author | martin |
Thu, 30 Oct 2014 07:31:41 -0700 | |
changeset 28059 | e576535359cc |
parent 25859 | 3317bb8137f4 |
child 35667 | ed476aba94de |
permissions | -rw-r--r-- |
2 | 1 |
/* |
22584
eed64ee05369
8032733: Fix cast lint warnings in client libraries
darcy
parents:
21278
diff
changeset
|
2 |
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package java.awt.image; |
|
27 |
||
28 |
import java.awt.color.ColorSpace; |
|
29 |
import java.awt.color.ICC_ColorSpace; |
|
30 |
||
31 |
/** |
|
32 |
* A <CODE>ColorModel</CODE> class that works with pixel values that |
|
33 |
* represent color and alpha information as separate samples and that |
|
34 |
* store each sample in a separate data element. This class can be |
|
35 |
* used with an arbitrary <CODE>ColorSpace</CODE>. The number of |
|
36 |
* color samples in the pixel values must be same as the number of |
|
37 |
* color components in the <CODE>ColorSpace</CODE>. There may be a |
|
38 |
* single alpha sample. |
|
39 |
* <p> |
|
40 |
* For those methods that use |
|
41 |
* a primitive array pixel representation of type <CODE>transferType</CODE>, |
|
42 |
* the array length is the same as the number of color and alpha samples. |
|
43 |
* Color samples are stored first in the array followed by the alpha |
|
44 |
* sample, if present. The order of the color samples is specified |
|
45 |
* by the <CODE>ColorSpace</CODE>. Typically, this order reflects the |
|
46 |
* name of the color space type. For example, for <CODE>TYPE_RGB</CODE>, |
|
47 |
* index 0 corresponds to red, index 1 to green, and index 2 to blue. |
|
48 |
* <p> |
|
49 |
* The translation from pixel sample values to color/alpha components for |
|
50 |
* display or processing purposes is based on a one-to-one correspondence of |
|
51 |
* samples to components. |
|
52 |
* Depending on the transfer type used to create an instance of |
|
53 |
* <code>ComponentColorModel</code>, the pixel sample values |
|
54 |
* represented by that instance may be signed or unsigned and may |
|
55 |
* be of integral type or float or double (see below for details). |
|
56 |
* The translation from sample values to normalized color/alpha components |
|
57 |
* must follow certain rules. For float and double samples, the translation |
|
58 |
* is an identity, i.e. normalized component values are equal to the |
|
59 |
* corresponding sample values. For integral samples, the translation |
|
60 |
* should be only a simple scale and offset, where the scale and offset |
|
61 |
* constants may be different for each component. The result of |
|
62 |
* applying the scale and offset constants is a set of color/alpha |
|
63 |
* component values, which are guaranteed to fall within a certain |
|
64 |
* range. Typically, the range for a color component will be the range |
|
65 |
* defined by the <code>getMinValue</code> and <code>getMaxValue</code> |
|
66 |
* methods of the <code>ColorSpace</code> class. The range for an |
|
67 |
* alpha component should be 0.0 to 1.0. |
|
68 |
* <p> |
|
69 |
* Instances of <code>ComponentColorModel</code> created with transfer types |
|
70 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
71 |
* and <CODE>DataBuffer.TYPE_INT</CODE> have pixel sample values which |
|
72 |
* are treated as unsigned integral values. |
|
73 |
* The number of bits in a color or alpha sample of a pixel value might not |
|
74 |
* be the same as the number of bits for the corresponding color or alpha |
|
75 |
* sample passed to the |
|
76 |
* <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code> |
|
77 |
* constructor. In |
|
78 |
* that case, this class assumes that the least significant n bits of a sample |
|
79 |
* value hold the component value, where n is the number of significant bits |
|
80 |
* for the component passed to the constructor. It also assumes that |
|
81 |
* any higher-order bits in a sample value are zero. Thus, sample values |
|
82 |
* range from 0 to 2<sup>n</sup> - 1. This class maps these sample values |
|
83 |
* to normalized color component values such that 0 maps to the value |
|
84 |
* obtained from the <code>ColorSpace's</code> <code>getMinValue</code> |
|
85 |
* method for each component and 2<sup>n</sup> - 1 maps to the value |
|
86 |
* obtained from <code>getMaxValue</code>. To create a |
|
87 |
* <code>ComponentColorModel</code> with a different color sample mapping |
|
88 |
* requires subclassing this class and overriding the |
|
89 |
* <code>getNormalizedComponents(Object, float[], int)</code> method. |
|
90 |
* The mapping for an alpha sample always maps 0 to 0.0 and |
|
91 |
* 2<sup>n</sup> - 1 to 1.0. |
|
92 |
* <p> |
|
93 |
* For instances with unsigned sample values, |
|
94 |
* the unnormalized color/alpha component representation is only |
|
28059
e576535359cc
8067377: My hobby: caning, then then canning, the the can-can
martin
parents:
25859
diff
changeset
|
95 |
* supported if two conditions hold. First, sample value 0 must |
2 | 96 |
* map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1 |
97 |
* to 1.0. Second the min/max range of all color components of the |
|
98 |
* <code>ColorSpace</code> must be 0.0 to 1.0. In this case, the |
|
99 |
* component representation is the n least |
|
100 |
* significant bits of the corresponding sample. Thus each component is |
|
101 |
* an unsigned integral value between 0 and 2<sup>n</sup> - 1, where |
|
102 |
* n is the number of significant bits for a particular component. |
|
103 |
* If these conditions are not met, any method taking an unnormalized |
|
104 |
* component argument will throw an <code>IllegalArgumentException</code>. |
|
105 |
* <p> |
|
106 |
* Instances of <code>ComponentColorModel</code> created with transfer types |
|
107 |
* <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and |
|
108 |
* <CODE>DataBuffer.TYPE_DOUBLE</CODE> have pixel sample values which |
|
109 |
* are treated as signed short, float, or double values. |
|
110 |
* Such instances do not support the unnormalized color/alpha component |
|
111 |
* representation, so any methods taking such a representation as an argument |
|
112 |
* will throw an <code>IllegalArgumentException</code> when called on one |
|
113 |
* of these instances. The normalized component values of instances |
|
114 |
* of this class have a range which depends on the transfer |
|
115 |
* type as follows: for float samples, the full range of the float data |
|
116 |
* type; for double samples, the full range of the float data type |
|
117 |
* (resulting from casting double to float); for short samples, |
|
118 |
* from approximately -maxVal to +maxVal, where maxVal is the per |
|
119 |
* component maximum value for the <code>ColorSpace</code> |
|
120 |
* (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps |
|
121 |
* to +maxVal). A subclass may override the scaling for short sample |
|
122 |
* values to normalized component values by overriding the |
|
123 |
* <code>getNormalizedComponents(Object, float[], int)</code> method. |
|
124 |
* For float and double samples, the normalized component values are |
|
125 |
* taken to be equal to the corresponding sample values, and subclasses |
|
126 |
* should not attempt to add any non-identity scaling for these transfer |
|
127 |
* types. |
|
128 |
* <p> |
|
129 |
* Instances of <code>ComponentColorModel</code> created with transfer types |
|
130 |
* <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and |
|
131 |
* <CODE>DataBuffer.TYPE_DOUBLE</CODE> |
|
132 |
* use all the bits of all sample values. Thus all color/alpha components |
|
133 |
* have 16 bits when using <CODE>DataBuffer.TYPE_SHORT</CODE>, 32 bits when |
|
134 |
* using <CODE>DataBuffer.TYPE_FLOAT</CODE>, and 64 bits when using |
|
135 |
* <CODE>DataBuffer.TYPE_DOUBLE</CODE>. When the |
|
136 |
* <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code> |
|
137 |
* form of constructor is used with one of these transfer types, the |
|
138 |
* bits array argument is ignored. |
|
139 |
* <p> |
|
140 |
* It is possible to have color/alpha sample values |
|
141 |
* which cannot be reasonably interpreted as component values for rendering. |
|
142 |
* This can happen when <code>ComponentColorModel</code> is subclassed to |
|
143 |
* override the mapping of unsigned sample values to normalized color |
|
144 |
* component values or when signed sample values outside a certain range |
|
145 |
* are used. (As an example, specifying an alpha component as a signed |
|
146 |
* short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can |
|
147 |
* lead to unexpected results.) It is the |
|
148 |
* responsibility of applications to appropriately scale pixel data before |
|
149 |
* rendering such that color components fall within the normalized range |
|
150 |
* of the <code>ColorSpace</code> (obtained using the <code>getMinValue</code> |
|
151 |
* and <code>getMaxValue</code> methods of the <code>ColorSpace</code> class) |
|
152 |
* and the alpha component is between 0.0 and 1.0. If color or alpha |
|
153 |
* component values fall outside these ranges, rendering results are |
|
154 |
* indeterminate. |
|
155 |
* <p> |
|
156 |
* Methods that use a single int pixel representation throw |
|
157 |
* an <CODE>IllegalArgumentException</CODE>, unless the number of components |
|
158 |
* for the <CODE>ComponentColorModel</CODE> is one and the component |
|
159 |
* value is unsigned -- in other words, a single color component using |
|
160 |
* a transfer type of <CODE>DataBuffer.TYPE_BYTE</CODE>, |
|
161 |
* <CODE>DataBuffer.TYPE_USHORT</CODE>, or <CODE>DataBuffer.TYPE_INT</CODE> |
|
162 |
* and no alpha. |
|
163 |
* <p> |
|
164 |
* A <CODE>ComponentColorModel</CODE> can be used in conjunction with a |
|
165 |
* <CODE>ComponentSampleModel</CODE>, a <CODE>BandedSampleModel</CODE>, |
|
166 |
* or a <CODE>PixelInterleavedSampleModel</CODE> to construct a |
|
167 |
* <CODE>BufferedImage</CODE>. |
|
168 |
* |
|
169 |
* @see ColorModel |
|
170 |
* @see ColorSpace |
|
171 |
* @see ComponentSampleModel |
|
172 |
* @see BandedSampleModel |
|
173 |
* @see PixelInterleavedSampleModel |
|
174 |
* @see BufferedImage |
|
175 |
* |
|
176 |
*/ |
|
177 |
public class ComponentColorModel extends ColorModel { |
|
178 |
||
179 |
/** |
|
180 |
* <code>signed</code> is <code>true</code> for <code>short</code>, |
|
181 |
* <code>float</code>, and <code>double</code> transfer types; it |
|
182 |
* is <code>false</code> for <code>byte</code>, <code>ushort</code>, |
|
183 |
* and <code>int</code> transfer types. |
|
184 |
*/ |
|
185 |
private boolean signed; // true for transfer types short, float, double |
|
186 |
// false for byte, ushort, int |
|
187 |
private boolean is_sRGB_stdScale; |
|
188 |
private boolean is_LinearRGB_stdScale; |
|
189 |
private boolean is_LinearGray_stdScale; |
|
190 |
private boolean is_ICCGray_stdScale; |
|
191 |
private byte[] tosRGB8LUT; |
|
192 |
private byte[] fromsRGB8LUT8; |
|
193 |
private short[] fromsRGB8LUT16; |
|
194 |
private byte[] fromLinearGray16ToOtherGray8LUT; |
|
195 |
private short[] fromLinearGray16ToOtherGray16LUT; |
|
196 |
private boolean needScaleInit; |
|
197 |
private boolean noUnnorm; |
|
198 |
private boolean nonStdScale; |
|
199 |
private float[] min; |
|
200 |
private float[] diffMinMax; |
|
201 |
private float[] compOffset; |
|
202 |
private float[] compScale; |
|
203 |
||
204 |
/** |
|
205 |
* Constructs a <CODE>ComponentColorModel</CODE> from the specified |
|
206 |
* parameters. Color components will be in the specified |
|
207 |
* <CODE>ColorSpace</CODE>. The supported transfer types are |
|
208 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
209 |
* <CODE>DataBuffer.TYPE_INT</CODE>, |
|
210 |
* <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, |
|
211 |
* and <CODE>DataBuffer.TYPE_DOUBLE</CODE>. |
|
212 |
* If not null, the <CODE>bits</CODE> array specifies the |
|
213 |
* number of significant bits per color and alpha component and its |
|
214 |
* length should be at least the number of components in the |
|
215 |
* <CODE>ColorSpace</CODE> if there is no alpha |
|
216 |
* information in the pixel values, or one more than this number if |
|
217 |
* there is alpha information. When the <CODE>transferType</CODE> is |
|
218 |
* <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, |
|
219 |
* or <CODE>DataBuffer.TYPE_DOUBLE</CODE> the <CODE>bits</CODE> array |
|
220 |
* argument is ignored. <CODE>hasAlpha</CODE> indicates whether alpha |
|
221 |
* information is present. If <CODE>hasAlpha</CODE> is true, then |
|
222 |
* the boolean <CODE>isAlphaPremultiplied</CODE> |
|
223 |
* specifies how to interpret color and alpha samples in pixel values. |
|
224 |
* If the boolean is true, color samples are assumed to have been |
|
225 |
* multiplied by the alpha sample. The <CODE>transparency</CODE> |
|
226 |
* specifies what alpha values can be represented by this color model. |
|
227 |
* The acceptable <code>transparency</code> values are |
|
228 |
* <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>. |
|
229 |
* The <CODE>transferType</CODE> is the type of primitive array used |
|
230 |
* to represent pixel values. |
|
231 |
* |
|
232 |
* @param colorSpace The <CODE>ColorSpace</CODE> associated |
|
233 |
* with this color model. |
|
234 |
* @param bits The number of significant bits per component. |
|
235 |
* May be null, in which case all bits of all |
|
236 |
* component samples will be significant. |
|
237 |
* Ignored if transferType is one of |
|
238 |
* <CODE>DataBuffer.TYPE_SHORT</CODE>, |
|
239 |
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or |
|
240 |
* <CODE>DataBuffer.TYPE_DOUBLE</CODE>, |
|
241 |
* in which case all bits of all component |
|
242 |
* samples will be significant. |
|
243 |
* @param hasAlpha If true, this color model supports alpha. |
|
244 |
* @param isAlphaPremultiplied If true, alpha is premultiplied. |
|
245 |
* @param transparency Specifies what alpha values can be represented |
|
246 |
* by this color model. |
|
247 |
* @param transferType Specifies the type of primitive array used to |
|
248 |
* represent pixel values. |
|
249 |
* |
|
250 |
* @throws IllegalArgumentException If the <CODE>bits</CODE> array |
|
251 |
* argument is not null, its length is less than the number of |
|
252 |
* color and alpha components, and transferType is one of |
|
253 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, |
|
254 |
* <CODE>DataBuffer.TYPE_USHORT</CODE>, or |
|
255 |
* <CODE>DataBuffer.TYPE_INT</CODE>. |
|
256 |
* @throws IllegalArgumentException If transferType is not one of |
|
257 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, |
|
258 |
* <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
259 |
* <CODE>DataBuffer.TYPE_INT</CODE>, |
|
260 |
* <CODE>DataBuffer.TYPE_SHORT</CODE>, |
|
261 |
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or |
|
262 |
* <CODE>DataBuffer.TYPE_DOUBLE</CODE>. |
|
263 |
* |
|
264 |
* @see ColorSpace |
|
265 |
* @see java.awt.Transparency |
|
266 |
*/ |
|
267 |
public ComponentColorModel (ColorSpace colorSpace, |
|
268 |
int[] bits, |
|
269 |
boolean hasAlpha, |
|
270 |
boolean isAlphaPremultiplied, |
|
271 |
int transparency, |
|
272 |
int transferType) { |
|
273 |
super (bitsHelper(transferType, colorSpace, hasAlpha), |
|
274 |
bitsArrayHelper(bits, transferType, colorSpace, hasAlpha), |
|
275 |
colorSpace, hasAlpha, isAlphaPremultiplied, transparency, |
|
276 |
transferType); |
|
277 |
switch(transferType) { |
|
278 |
case DataBuffer.TYPE_BYTE: |
|
279 |
case DataBuffer.TYPE_USHORT: |
|
280 |
case DataBuffer.TYPE_INT: |
|
281 |
signed = false; |
|
282 |
needScaleInit = true; |
|
283 |
break; |
|
284 |
case DataBuffer.TYPE_SHORT: |
|
285 |
signed = true; |
|
286 |
needScaleInit = true; |
|
287 |
break; |
|
288 |
case DataBuffer.TYPE_FLOAT: |
|
289 |
case DataBuffer.TYPE_DOUBLE: |
|
290 |
signed = true; |
|
291 |
needScaleInit = false; |
|
292 |
noUnnorm = true; |
|
293 |
nonStdScale = false; |
|
294 |
break; |
|
295 |
default: |
|
296 |
throw new IllegalArgumentException("This constructor is not "+ |
|
297 |
"compatible with transferType " + transferType); |
|
298 |
} |
|
299 |
setupLUTs(); |
|
300 |
} |
|
301 |
||
302 |
/** |
|
303 |
* Constructs a <CODE>ComponentColorModel</CODE> from the specified |
|
304 |
* parameters. Color components will be in the specified |
|
305 |
* <CODE>ColorSpace</CODE>. The supported transfer types are |
|
306 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
307 |
* <CODE>DataBuffer.TYPE_INT</CODE>, |
|
308 |
* <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, |
|
309 |
* and <CODE>DataBuffer.TYPE_DOUBLE</CODE>. The number of significant |
|
310 |
* bits per color and alpha component will be 8, 16, 32, 16, 32, or 64, |
|
311 |
* respectively. The number of color components will be the |
|
312 |
* number of components in the <CODE>ColorSpace</CODE>. There will be |
|
313 |
* an alpha component if <CODE>hasAlpha</CODE> is <CODE>true</CODE>. |
|
314 |
* If <CODE>hasAlpha</CODE> is true, then |
|
315 |
* the boolean <CODE>isAlphaPremultiplied</CODE> |
|
316 |
* specifies how to interpret color and alpha samples in pixel values. |
|
317 |
* If the boolean is true, color samples are assumed to have been |
|
318 |
* multiplied by the alpha sample. The <CODE>transparency</CODE> |
|
319 |
* specifies what alpha values can be represented by this color model. |
|
320 |
* The acceptable <code>transparency</code> values are |
|
321 |
* <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>. |
|
322 |
* The <CODE>transferType</CODE> is the type of primitive array used |
|
323 |
* to represent pixel values. |
|
324 |
* |
|
325 |
* @param colorSpace The <CODE>ColorSpace</CODE> associated |
|
326 |
* with this color model. |
|
327 |
* @param hasAlpha If true, this color model supports alpha. |
|
328 |
* @param isAlphaPremultiplied If true, alpha is premultiplied. |
|
329 |
* @param transparency Specifies what alpha values can be represented |
|
330 |
* by this color model. |
|
331 |
* @param transferType Specifies the type of primitive array used to |
|
332 |
* represent pixel values. |
|
333 |
* |
|
334 |
* @throws IllegalArgumentException If transferType is not one of |
|
335 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, |
|
336 |
* <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
337 |
* <CODE>DataBuffer.TYPE_INT</CODE>, |
|
338 |
* <CODE>DataBuffer.TYPE_SHORT</CODE>, |
|
339 |
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or |
|
340 |
* <CODE>DataBuffer.TYPE_DOUBLE</CODE>. |
|
341 |
* |
|
342 |
* @see ColorSpace |
|
343 |
* @see java.awt.Transparency |
|
344 |
* @since 1.4 |
|
345 |
*/ |
|
346 |
public ComponentColorModel (ColorSpace colorSpace, |
|
347 |
boolean hasAlpha, |
|
348 |
boolean isAlphaPremultiplied, |
|
349 |
int transparency, |
|
350 |
int transferType) { |
|
351 |
this(colorSpace, null, hasAlpha, isAlphaPremultiplied, |
|
352 |
transparency, transferType); |
|
353 |
} |
|
354 |
||
355 |
private static int bitsHelper(int transferType, |
|
356 |
ColorSpace colorSpace, |
|
357 |
boolean hasAlpha) { |
|
358 |
int numBits = DataBuffer.getDataTypeSize(transferType); |
|
359 |
int numComponents = colorSpace.getNumComponents(); |
|
360 |
if (hasAlpha) { |
|
361 |
++numComponents; |
|
362 |
} |
|
363 |
return numBits * numComponents; |
|
364 |
} |
|
365 |
||
366 |
private static int[] bitsArrayHelper(int[] origBits, |
|
367 |
int transferType, |
|
368 |
ColorSpace colorSpace, |
|
369 |
boolean hasAlpha) { |
|
370 |
switch(transferType) { |
|
371 |
case DataBuffer.TYPE_BYTE: |
|
372 |
case DataBuffer.TYPE_USHORT: |
|
373 |
case DataBuffer.TYPE_INT: |
|
374 |
if (origBits != null) { |
|
375 |
return origBits; |
|
376 |
} |
|
377 |
break; |
|
378 |
default: |
|
379 |
break; |
|
380 |
} |
|
381 |
int numBits = DataBuffer.getDataTypeSize(transferType); |
|
382 |
int numComponents = colorSpace.getNumComponents(); |
|
383 |
if (hasAlpha) { |
|
384 |
++numComponents; |
|
385 |
} |
|
386 |
int[] bits = new int[numComponents]; |
|
387 |
for (int i = 0; i < numComponents; i++) { |
|
388 |
bits[i] = numBits; |
|
389 |
} |
|
390 |
return bits; |
|
391 |
} |
|
392 |
||
393 |
private void setupLUTs() { |
|
394 |
// REMIND: there is potential to accelerate sRGB, LinearRGB, |
|
395 |
// LinearGray, ICCGray, and non-ICC Gray spaces with non-standard |
|
396 |
// scaling, if that becomes important |
|
397 |
// |
|
398 |
// NOTE: The is_xxx_stdScale and nonStdScale booleans are provisionally |
|
399 |
// set here when this method is called at construction time. These |
|
400 |
// variables may be set again when initScale is called later. |
|
401 |
// When setupLUTs returns, nonStdScale is true if (the transferType |
|
402 |
// is not float or double) AND (some minimum ColorSpace component |
|
403 |
// value is not 0.0 OR some maximum ColorSpace component value |
|
404 |
// is not 1.0). This is correct for the calls to |
|
405 |
// getNormalizedComponents(Object, float[], int) from initScale(). |
|
406 |
// initScale() may change the value nonStdScale based on the |
|
407 |
// return value of getNormalizedComponents() - this will only |
|
408 |
// happen if getNormalizedComponents() has been overridden by a |
|
409 |
// subclass to make the mapping of min/max pixel sample values |
|
410 |
// something different from min/max color component values. |
|
411 |
if (is_sRGB) { |
|
412 |
is_sRGB_stdScale = true; |
|
413 |
nonStdScale = false; |
|
414 |
} else if (ColorModel.isLinearRGBspace(colorSpace)) { |
|
415 |
// Note that the built-in Linear RGB space has a normalized |
|
416 |
// range of 0.0 - 1.0 for each coordinate. Usage of these |
|
417 |
// LUTs makes that assumption. |
|
418 |
is_LinearRGB_stdScale = true; |
|
419 |
nonStdScale = false; |
|
420 |
if (transferType == DataBuffer.TYPE_BYTE) { |
|
421 |
tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT(); |
|
422 |
fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT(); |
|
423 |
} else { |
|
424 |
tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT(); |
|
425 |
fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT(); |
|
426 |
} |
|
427 |
} else if ((colorSpaceType == ColorSpace.TYPE_GRAY) && |
|
428 |
(colorSpace instanceof ICC_ColorSpace) && |
|
429 |
(colorSpace.getMinValue(0) == 0.0f) && |
|
430 |
(colorSpace.getMaxValue(0) == 1.0f)) { |
|
431 |
// Note that a normalized range of 0.0 - 1.0 for the gray |
|
432 |
// component is required, because usage of these LUTs makes |
|
433 |
// that assumption. |
|
434 |
ICC_ColorSpace ics = (ICC_ColorSpace) colorSpace; |
|
435 |
is_ICCGray_stdScale = true; |
|
436 |
nonStdScale = false; |
|
437 |
fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT(); |
|
438 |
if (ColorModel.isLinearGRAYspace(ics)) { |
|
439 |
is_LinearGray_stdScale = true; |
|
440 |
if (transferType == DataBuffer.TYPE_BYTE) { |
|
441 |
tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics); |
|
442 |
} else { |
|
443 |
tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics); |
|
444 |
} |
|
445 |
} else { |
|
446 |
if (transferType == DataBuffer.TYPE_BYTE) { |
|
447 |
tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics); |
|
448 |
fromLinearGray16ToOtherGray8LUT = |
|
449 |
ColorModel.getLinearGray16ToOtherGray8LUT(ics); |
|
450 |
} else { |
|
451 |
tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics); |
|
452 |
fromLinearGray16ToOtherGray16LUT = |
|
453 |
ColorModel.getLinearGray16ToOtherGray16LUT(ics); |
|
454 |
} |
|
455 |
} |
|
456 |
} else if (needScaleInit) { |
|
457 |
// if transferType is byte, ushort, int, or short and we |
|
458 |
// don't already know the ColorSpace has minVlaue == 0.0f and |
|
459 |
// maxValue == 1.0f for all components, we need to check that |
|
460 |
// now and setup the min[] and diffMinMax[] arrays if necessary. |
|
461 |
nonStdScale = false; |
|
462 |
for (int i = 0; i < numColorComponents; i++) { |
|
463 |
if ((colorSpace.getMinValue(i) != 0.0f) || |
|
464 |
(colorSpace.getMaxValue(i) != 1.0f)) { |
|
465 |
nonStdScale = true; |
|
466 |
break; |
|
467 |
} |
|
468 |
} |
|
469 |
if (nonStdScale) { |
|
470 |
min = new float[numColorComponents]; |
|
471 |
diffMinMax = new float[numColorComponents]; |
|
472 |
for (int i = 0; i < numColorComponents; i++) { |
|
473 |
min[i] = colorSpace.getMinValue(i); |
|
474 |
diffMinMax[i] = colorSpace.getMaxValue(i) - min[i]; |
|
475 |
} |
|
476 |
} |
|
477 |
} |
|
478 |
} |
|
479 |
||
480 |
private void initScale() { |
|
481 |
// This method is called the first time any method which uses |
|
482 |
// pixel sample value to color component value scaling information |
|
483 |
// is called if the transferType supports non-standard scaling |
|
484 |
// as defined above (byte, ushort, int, and short), unless the |
|
485 |
// method is getNormalizedComponents(Object, float[], int) (that |
|
486 |
// method must be overridden to use non-standard scaling). This |
|
487 |
// method also sets up the noUnnorm boolean variable for these |
|
488 |
// transferTypes. After this method is called, the nonStdScale |
|
489 |
// variable will be true if getNormalizedComponents() maps a |
|
490 |
// sample value of 0 to anything other than 0.0f OR maps a |
|
491 |
// sample value of 2^^n - 1 (2^^15 - 1 for short transferType) |
|
492 |
// to anything other than 1.0f. Note that this can be independent |
|
493 |
// of the colorSpace min/max component values, if the |
|
494 |
// getNormalizedComponents() method has been overridden for some |
|
495 |
// reason, e.g. to provide greater dynamic range in the sample |
|
496 |
// values than in the color component values. Unfortunately, |
|
497 |
// this method can't be called at construction time, since a |
|
498 |
// subclass may still have uninitialized state that would cause |
|
499 |
// getNormalizedComponents() to return an incorrect result. |
|
500 |
needScaleInit = false; // only needs to called once |
|
501 |
if (nonStdScale || signed) { |
|
502 |
// The unnormalized form is only supported for unsigned |
|
503 |
// transferTypes and when the ColorSpace min/max values |
|
504 |
// are 0.0/1.0. When this method is called nonStdScale is |
|
505 |
// true if the latter condition does not hold. In addition, |
|
506 |
// the unnormalized form requires that the full range of |
|
507 |
// the pixel sample values map to the full 0.0 - 1.0 range |
|
508 |
// of color component values. That condition is checked |
|
509 |
// later in this method. |
|
510 |
noUnnorm = true; |
|
511 |
} else { |
|
512 |
noUnnorm = false; |
|
513 |
} |
|
514 |
float[] lowVal, highVal; |
|
515 |
switch (transferType) { |
|
516 |
case DataBuffer.TYPE_BYTE: |
|
517 |
{ |
|
518 |
byte[] bpixel = new byte[numComponents]; |
|
519 |
for (int i = 0; i < numColorComponents; i++) { |
|
520 |
bpixel[i] = 0; |
|
521 |
} |
|
522 |
if (supportsAlpha) { |
|
523 |
bpixel[numColorComponents] = |
|
524 |
(byte) ((1 << nBits[numColorComponents]) - 1); |
|
525 |
} |
|
526 |
lowVal = getNormalizedComponents(bpixel, null, 0); |
|
527 |
for (int i = 0; i < numColorComponents; i++) { |
|
528 |
bpixel[i] = (byte) ((1 << nBits[i]) - 1); |
|
529 |
} |
|
530 |
highVal = getNormalizedComponents(bpixel, null, 0); |
|
531 |
} |
|
532 |
break; |
|
533 |
case DataBuffer.TYPE_USHORT: |
|
534 |
{ |
|
535 |
short[] uspixel = new short[numComponents]; |
|
536 |
for (int i = 0; i < numColorComponents; i++) { |
|
537 |
uspixel[i] = 0; |
|
538 |
} |
|
539 |
if (supportsAlpha) { |
|
540 |
uspixel[numColorComponents] = |
|
541 |
(short) ((1 << nBits[numColorComponents]) - 1); |
|
542 |
} |
|
543 |
lowVal = getNormalizedComponents(uspixel, null, 0); |
|
544 |
for (int i = 0; i < numColorComponents; i++) { |
|
545 |
uspixel[i] = (short) ((1 << nBits[i]) - 1); |
|
546 |
} |
|
547 |
highVal = getNormalizedComponents(uspixel, null, 0); |
|
548 |
} |
|
549 |
break; |
|
550 |
case DataBuffer.TYPE_INT: |
|
551 |
{ |
|
552 |
int[] ipixel = new int[numComponents]; |
|
553 |
for (int i = 0; i < numColorComponents; i++) { |
|
554 |
ipixel[i] = 0; |
|
555 |
} |
|
556 |
if (supportsAlpha) { |
|
557 |
ipixel[numColorComponents] = |
|
558 |
((1 << nBits[numColorComponents]) - 1); |
|
559 |
} |
|
560 |
lowVal = getNormalizedComponents(ipixel, null, 0); |
|
561 |
for (int i = 0; i < numColorComponents; i++) { |
|
562 |
ipixel[i] = ((1 << nBits[i]) - 1); |
|
563 |
} |
|
564 |
highVal = getNormalizedComponents(ipixel, null, 0); |
|
565 |
} |
|
566 |
break; |
|
567 |
case DataBuffer.TYPE_SHORT: |
|
568 |
{ |
|
569 |
short[] spixel = new short[numComponents]; |
|
570 |
for (int i = 0; i < numColorComponents; i++) { |
|
571 |
spixel[i] = 0; |
|
572 |
} |
|
573 |
if (supportsAlpha) { |
|
574 |
spixel[numColorComponents] = 32767; |
|
575 |
} |
|
576 |
lowVal = getNormalizedComponents(spixel, null, 0); |
|
577 |
for (int i = 0; i < numColorComponents; i++) { |
|
578 |
spixel[i] = 32767; |
|
579 |
} |
|
580 |
highVal = getNormalizedComponents(spixel, null, 0); |
|
581 |
} |
|
582 |
break; |
|
583 |
default: |
|
584 |
lowVal = highVal = null; // to keep the compiler from complaining |
|
585 |
break; |
|
586 |
} |
|
587 |
nonStdScale = false; |
|
588 |
for (int i = 0; i < numColorComponents; i++) { |
|
589 |
if ((lowVal[i] != 0.0f) || (highVal[i] != 1.0f)) { |
|
590 |
nonStdScale = true; |
|
591 |
break; |
|
592 |
} |
|
593 |
} |
|
594 |
if (nonStdScale) { |
|
595 |
noUnnorm = true; |
|
596 |
is_sRGB_stdScale = false; |
|
597 |
is_LinearRGB_stdScale = false; |
|
598 |
is_LinearGray_stdScale = false; |
|
599 |
is_ICCGray_stdScale = false; |
|
600 |
compOffset = new float[numColorComponents]; |
|
601 |
compScale = new float[numColorComponents]; |
|
602 |
for (int i = 0; i < numColorComponents; i++) { |
|
603 |
compOffset[i] = lowVal[i]; |
|
604 |
compScale[i] = 1.0f / (highVal[i] - lowVal[i]); |
|
605 |
} |
|
606 |
} |
|
607 |
} |
|
608 |
||
609 |
private int getRGBComponent(int pixel, int idx) { |
|
610 |
if (numComponents > 1) { |
|
611 |
throw new |
|
612 |
IllegalArgumentException("More than one component per pixel"); |
|
613 |
} |
|
614 |
if (signed) { |
|
615 |
throw new |
|
616 |
IllegalArgumentException("Component value is signed"); |
|
617 |
} |
|
618 |
if (needScaleInit) { |
|
619 |
initScale(); |
|
620 |
} |
|
621 |
// Since there is only 1 component, there is no alpha |
|
622 |
||
623 |
// Normalize the pixel in order to convert it |
|
624 |
Object opixel = null; |
|
625 |
switch (transferType) { |
|
626 |
case DataBuffer.TYPE_BYTE: |
|
627 |
{ |
|
628 |
byte[] bpixel = { (byte) pixel }; |
|
629 |
opixel = bpixel; |
|
630 |
} |
|
631 |
break; |
|
632 |
case DataBuffer.TYPE_USHORT: |
|
633 |
{ |
|
634 |
short[] spixel = { (short) pixel }; |
|
635 |
opixel = spixel; |
|
636 |
} |
|
637 |
break; |
|
638 |
case DataBuffer.TYPE_INT: |
|
639 |
{ |
|
640 |
int[] ipixel = { pixel }; |
|
641 |
opixel = ipixel; |
|
642 |
} |
|
643 |
break; |
|
644 |
} |
|
645 |
float[] norm = getNormalizedComponents(opixel, null, 0); |
|
646 |
float[] rgb = colorSpace.toRGB(norm); |
|
647 |
||
648 |
return (int) (rgb[idx] * 255.0f + 0.5f); |
|
649 |
} |
|
650 |
||
651 |
/** |
|
652 |
* Returns the red color component for the specified pixel, scaled |
|
653 |
* from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion |
|
654 |
* is done if necessary. The pixel value is specified as an int. |
|
655 |
* The returned value will be a non pre-multiplied value. |
|
656 |
* If the alpha is premultiplied, this method divides |
|
657 |
* it out before returning the value (if the alpha value is 0, |
|
658 |
* the red value will be 0). |
|
659 |
* |
|
660 |
* @param pixel The pixel from which you want to get the red color component. |
|
661 |
* |
|
662 |
* @return The red color component for the specified pixel, as an int. |
|
663 |
* |
|
664 |
* @throws IllegalArgumentException If there is more than |
|
665 |
* one component in this <CODE>ColorModel</CODE>. |
|
666 |
* @throws IllegalArgumentException If the component value for this |
|
667 |
* <CODE>ColorModel</CODE> is signed |
|
668 |
*/ |
|
669 |
public int getRed(int pixel) { |
|
670 |
return getRGBComponent(pixel, 0); |
|
671 |
} |
|
672 |
||
673 |
/** |
|
674 |
* Returns the green color component for the specified pixel, scaled |
|
675 |
* from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion |
|
676 |
* is done if necessary. The pixel value is specified as an int. |
|
677 |
* The returned value will be a non |
|
678 |
* pre-multiplied value. If the alpha is premultiplied, this method |
|
679 |
* divides it out before returning the value (if the alpha value is 0, |
|
680 |
* the green value will be 0). |
|
681 |
* |
|
682 |
* @param pixel The pixel from which you want to get the green color component. |
|
683 |
* |
|
684 |
* @return The green color component for the specified pixel, as an int. |
|
685 |
* |
|
686 |
* @throws IllegalArgumentException If there is more than |
|
687 |
* one component in this <CODE>ColorModel</CODE>. |
|
688 |
* @throws IllegalArgumentException If the component value for this |
|
689 |
* <CODE>ColorModel</CODE> is signed |
|
690 |
*/ |
|
691 |
public int getGreen(int pixel) { |
|
692 |
return getRGBComponent(pixel, 1); |
|
693 |
} |
|
694 |
||
695 |
/** |
|
696 |
* Returns the blue color component for the specified pixel, scaled |
|
697 |
* from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion |
|
698 |
* is done if necessary. The pixel value is specified as an int. |
|
699 |
* The returned value will be a non |
|
700 |
* pre-multiplied value. If the alpha is premultiplied, this method |
|
701 |
* divides it out before returning the value (if the alpha value is 0, |
|
702 |
* the blue value will be 0). |
|
703 |
* |
|
704 |
* @param pixel The pixel from which you want to get the blue color component. |
|
705 |
* |
|
706 |
* @return The blue color component for the specified pixel, as an int. |
|
707 |
* |
|
708 |
* @throws IllegalArgumentException If there is more than |
|
709 |
* one component in this <CODE>ColorModel</CODE>. |
|
710 |
* @throws IllegalArgumentException If the component value for this |
|
711 |
* <CODE>ColorModel</CODE> is signed |
|
712 |
*/ |
|
713 |
public int getBlue(int pixel) { |
|
714 |
return getRGBComponent(pixel, 2); |
|
715 |
} |
|
716 |
||
717 |
/** |
|
718 |
* Returns the alpha component for the specified pixel, scaled |
|
719 |
* from 0 to 255. The pixel value is specified as an int. |
|
720 |
* |
|
721 |
* @param pixel The pixel from which you want to get the alpha component. |
|
722 |
* |
|
723 |
* @return The alpha component for the specified pixel, as an int. |
|
724 |
* |
|
725 |
* @throws IllegalArgumentException If there is more than |
|
726 |
* one component in this <CODE>ColorModel</CODE>. |
|
727 |
* @throws IllegalArgumentException If the component value for this |
|
728 |
* <CODE>ColorModel</CODE> is signed |
|
729 |
*/ |
|
730 |
public int getAlpha(int pixel) { |
|
731 |
if (supportsAlpha == false) { |
|
732 |
return 255; |
|
733 |
} |
|
734 |
if (numComponents > 1) { |
|
735 |
throw new |
|
736 |
IllegalArgumentException("More than one component per pixel"); |
|
737 |
} |
|
738 |
if (signed) { |
|
739 |
throw new |
|
740 |
IllegalArgumentException("Component value is signed"); |
|
741 |
} |
|
742 |
||
743 |
return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f); |
|
744 |
} |
|
745 |
||
746 |
/** |
|
747 |
* Returns the color/alpha components of the pixel in the default |
|
748 |
* RGB color model format. A color conversion is done if necessary. |
|
749 |
* The returned value will be in a non pre-multiplied format. If |
|
750 |
* the alpha is premultiplied, this method divides it out of the |
|
751 |
* color components (if the alpha value is 0, the color values will be 0). |
|
752 |
* |
|
753 |
* @param pixel The pixel from which you want to get the color/alpha components. |
|
754 |
* |
|
755 |
* @return The color/alpha components for the specified pixel, as an int. |
|
756 |
* |
|
757 |
* @throws IllegalArgumentException If there is more than |
|
758 |
* one component in this <CODE>ColorModel</CODE>. |
|
759 |
* @throws IllegalArgumentException If the component value for this |
|
760 |
* <CODE>ColorModel</CODE> is signed |
|
761 |
*/ |
|
762 |
public int getRGB(int pixel) { |
|
763 |
if (numComponents > 1) { |
|
764 |
throw new |
|
765 |
IllegalArgumentException("More than one component per pixel"); |
|
766 |
} |
|
767 |
if (signed) { |
|
768 |
throw new |
|
769 |
IllegalArgumentException("Component value is signed"); |
|
770 |
} |
|
771 |
||
772 |
return (getAlpha(pixel) << 24) |
|
773 |
| (getRed(pixel) << 16) |
|
774 |
| (getGreen(pixel) << 8) |
|
775 |
| (getBlue(pixel) << 0); |
|
776 |
} |
|
777 |
||
778 |
private int extractComponent(Object inData, int idx, int precision) { |
|
779 |
// Extract component idx from inData. The precision argument |
|
780 |
// should be either 8 or 16. If it's 8, this method will return |
|
781 |
// an 8-bit value. If it's 16, this method will return a 16-bit |
|
782 |
// value for transferTypes other than TYPE_BYTE. For TYPE_BYTE, |
|
783 |
// an 8-bit value will be returned. |
|
784 |
||
785 |
// This method maps the input value corresponding to a |
|
786 |
// normalized ColorSpace component value of 0.0 to 0, and the |
|
787 |
// input value corresponding to a normalized ColorSpace |
|
788 |
// component value of 1.0 to 2^n - 1 (where n is 8 or 16), so |
|
789 |
// it is appropriate only for ColorSpaces with min/max component |
|
790 |
// values of 0.0/1.0. This will be true for sRGB, the built-in |
|
791 |
// Linear RGB and Linear Gray spaces, and any other ICC grayscale |
|
792 |
// spaces for which we have precomputed LUTs. |
|
793 |
||
794 |
boolean needAlpha = (supportsAlpha && isAlphaPremultiplied); |
|
795 |
int alp = 0; |
|
796 |
int comp; |
|
797 |
int mask = (1 << nBits[idx]) - 1; |
|
798 |
||
799 |
switch (transferType) { |
|
800 |
// Note: we do no clamping of the pixel data here - we |
|
801 |
// assume that the data is scaled properly |
|
802 |
case DataBuffer.TYPE_SHORT: { |
|
803 |
short sdata[] = (short[]) inData; |
|
804 |
float scalefactor = (float) ((1 << precision) - 1); |
|
805 |
if (needAlpha) { |
|
806 |
short s = sdata[numColorComponents]; |
|
807 |
if (s != (short) 0) { |
|
808 |
return (int) ((((float) sdata[idx]) / |
|
809 |
((float) s)) * scalefactor + 0.5f); |
|
810 |
} else { |
|
811 |
return 0; |
|
812 |
} |
|
813 |
} else { |
|
814 |
return (int) ((sdata[idx] / 32767.0f) * scalefactor + 0.5f); |
|
815 |
} |
|
816 |
} |
|
817 |
case DataBuffer.TYPE_FLOAT: { |
|
818 |
float fdata[] = (float[]) inData; |
|
819 |
float scalefactor = (float) ((1 << precision) - 1); |
|
820 |
if (needAlpha) { |
|
821 |
float f = fdata[numColorComponents]; |
|
822 |
if (f != 0.0f) { |
|
823 |
return (int) (((fdata[idx] / f) * scalefactor) + 0.5f); |
|
824 |
} else { |
|
825 |
return 0; |
|
826 |
} |
|
827 |
} else { |
|
828 |
return (int) (fdata[idx] * scalefactor + 0.5f); |
|
829 |
} |
|
830 |
} |
|
831 |
case DataBuffer.TYPE_DOUBLE: { |
|
832 |
double ddata[] = (double[]) inData; |
|
833 |
double scalefactor = (double) ((1 << precision) - 1); |
|
834 |
if (needAlpha) { |
|
835 |
double d = ddata[numColorComponents]; |
|
836 |
if (d != 0.0) { |
|
837 |
return (int) (((ddata[idx] / d) * scalefactor) + 0.5); |
|
838 |
} else { |
|
839 |
return 0; |
|
840 |
} |
|
841 |
} else { |
|
842 |
return (int) (ddata[idx] * scalefactor + 0.5); |
|
843 |
} |
|
844 |
} |
|
845 |
case DataBuffer.TYPE_BYTE: |
|
846 |
byte bdata[] = (byte[])inData; |
|
847 |
comp = bdata[idx] & mask; |
|
848 |
precision = 8; |
|
849 |
if (needAlpha) { |
|
850 |
alp = bdata[numColorComponents] & mask; |
|
851 |
} |
|
852 |
break; |
|
853 |
case DataBuffer.TYPE_USHORT: |
|
854 |
short usdata[] = (short[])inData; |
|
855 |
comp = usdata[idx] & mask; |
|
856 |
if (needAlpha) { |
|
857 |
alp = usdata[numColorComponents] & mask; |
|
858 |
} |
|
859 |
break; |
|
860 |
case DataBuffer.TYPE_INT: |
|
861 |
int idata[] = (int[])inData; |
|
862 |
comp = idata[idx]; |
|
863 |
if (needAlpha) { |
|
864 |
alp = idata[numColorComponents]; |
|
865 |
} |
|
866 |
break; |
|
867 |
default: |
|
868 |
throw new |
|
869 |
UnsupportedOperationException("This method has not "+ |
|
870 |
"been implemented for transferType " + transferType); |
|
871 |
} |
|
872 |
if (needAlpha) { |
|
873 |
if (alp != 0) { |
|
874 |
float scalefactor = (float) ((1 << precision) - 1); |
|
875 |
float fcomp = ((float) comp) / ((float)mask); |
|
876 |
float invalp = ((float) ((1<<nBits[numColorComponents]) - 1)) / |
|
877 |
((float) alp); |
|
878 |
return (int) (fcomp * invalp * scalefactor + 0.5f); |
|
879 |
} else { |
|
880 |
return 0; |
|
881 |
} |
|
882 |
} else { |
|
883 |
if (nBits[idx] != precision) { |
|
884 |
float scalefactor = (float) ((1 << precision) - 1); |
|
885 |
float fcomp = ((float) comp) / ((float)mask); |
|
886 |
return (int) (fcomp * scalefactor + 0.5f); |
|
887 |
} |
|
888 |
return comp; |
|
889 |
} |
|
890 |
} |
|
891 |
||
892 |
private int getRGBComponent(Object inData, int idx) { |
|
893 |
if (needScaleInit) { |
|
894 |
initScale(); |
|
895 |
} |
|
896 |
if (is_sRGB_stdScale) { |
|
897 |
return extractComponent(inData, idx, 8); |
|
898 |
} else if (is_LinearRGB_stdScale) { |
|
899 |
int lutidx = extractComponent(inData, idx, 16); |
|
900 |
return tosRGB8LUT[lutidx] & 0xff; |
|
901 |
} else if (is_ICCGray_stdScale) { |
|
902 |
int lutidx = extractComponent(inData, 0, 16); |
|
903 |
return tosRGB8LUT[lutidx] & 0xff; |
|
904 |
} |
|
905 |
||
906 |
// Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace |
|
907 |
float[] norm = getNormalizedComponents(inData, null, 0); |
|
908 |
// Note that getNormalizedComponents returns non-premultiplied values |
|
909 |
float[] rgb = colorSpace.toRGB(norm); |
|
910 |
return (int) (rgb[idx] * 255.0f + 0.5f); |
|
911 |
} |
|
912 |
||
913 |
/** |
|
914 |
* Returns the red color component for the specified pixel, scaled |
|
915 |
* from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion |
|
916 |
* is done if necessary. The <CODE>pixel</CODE> value is specified by an array |
|
917 |
* of data elements of type <CODE>transferType</CODE> passed in as an object |
|
918 |
* reference. The returned value will be a non pre-multiplied value. If the |
|
919 |
* alpha is premultiplied, this method divides it out before returning |
|
920 |
* the value (if the alpha value is 0, the red value will be 0). Since |
|
921 |
* <code>ComponentColorModel</code> can be subclassed, subclasses |
|
922 |
* inherit the implementation of this method and if they don't override |
|
923 |
* it then they throw an exception if they use an unsupported |
|
924 |
* <code>transferType</code>. |
|
925 |
* |
|
926 |
* @param inData The pixel from which you want to get the red color component, |
|
927 |
* specified by an array of data elements of type <CODE>transferType</CODE>. |
|
928 |
* |
|
929 |
* @return The red color component for the specified pixel, as an int. |
|
930 |
* |
|
931 |
* @throws ClassCastException If <CODE>inData</CODE> is not a primitive array |
|
932 |
* of type <CODE>transferType</CODE>. |
|
933 |
* @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not |
|
934 |
* large enough to hold a pixel value for this |
|
935 |
* <CODE>ColorModel</CODE>. |
|
936 |
* @throws UnsupportedOperationException If the transfer type of |
|
937 |
* this <CODE>ComponentColorModel</CODE> |
|
938 |
* is not one of the supported transfer types: |
|
939 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
940 |
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, |
|
941 |
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. |
|
942 |
*/ |
|
943 |
public int getRed(Object inData) { |
|
944 |
return getRGBComponent(inData, 0); |
|
945 |
} |
|
946 |
||
947 |
||
948 |
/** |
|
949 |
* Returns the green color component for the specified pixel, scaled |
|
950 |
* from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB. |
|
951 |
* A color conversion is done if necessary. The <CODE>pixel</CODE> value |
|
952 |
* is specified by an array of data elements of type <CODE>transferType</CODE> |
|
953 |
* passed in as an object reference. The returned value is a non pre-multiplied |
|
954 |
* value. If the alpha is premultiplied, this method divides it out before |
|
955 |
* returning the value (if the alpha value is 0, the green value will be 0). |
|
956 |
* Since <code>ComponentColorModel</code> can be subclassed, |
|
957 |
* subclasses inherit the implementation of this method and if they |
|
958 |
* don't override it then they throw an exception if they use an |
|
959 |
* unsupported <code>transferType</code>. |
|
960 |
* |
|
961 |
* @param inData The pixel from which you want to get the green color component, |
|
962 |
* specified by an array of data elements of type <CODE>transferType</CODE>. |
|
963 |
* |
|
964 |
* @return The green color component for the specified pixel, as an int. |
|
965 |
* |
|
966 |
* @throws ClassCastException If <CODE>inData</CODE> is not a primitive array |
|
967 |
* of type <CODE>transferType</CODE>. |
|
968 |
* @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not |
|
969 |
* large enough to hold a pixel value for this |
|
970 |
* <CODE>ColorModel</CODE>. |
|
971 |
* @throws UnsupportedOperationException If the transfer type of |
|
972 |
* this <CODE>ComponentColorModel</CODE> |
|
973 |
* is not one of the supported transfer types: |
|
974 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
975 |
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, |
|
976 |
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. |
|
977 |
*/ |
|
978 |
public int getGreen(Object inData) { |
|
979 |
return getRGBComponent(inData, 1); |
|
980 |
} |
|
981 |
||
982 |
||
983 |
/** |
|
984 |
* Returns the blue color component for the specified pixel, scaled |
|
985 |
* from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB. |
|
986 |
* A color conversion is done if necessary. The <CODE>pixel</CODE> value is |
|
987 |
* specified by an array of data elements of type <CODE>transferType</CODE> |
|
988 |
* passed in as an object reference. The returned value is a non pre-multiplied |
|
989 |
* value. If the alpha is premultiplied, this method divides it out before |
|
990 |
* returning the value (if the alpha value is 0, the blue value will be 0). |
|
991 |
* Since <code>ComponentColorModel</code> can be subclassed, |
|
992 |
* subclasses inherit the implementation of this method and if they |
|
993 |
* don't override it then they throw an exception if they use an |
|
994 |
* unsupported <code>transferType</code>. |
|
995 |
* |
|
996 |
* @param inData The pixel from which you want to get the blue color component, |
|
997 |
* specified by an array of data elements of type <CODE>transferType</CODE>. |
|
998 |
* |
|
999 |
* @return The blue color component for the specified pixel, as an int. |
|
1000 |
* |
|
1001 |
* @throws ClassCastException If <CODE>inData</CODE> is not a primitive array |
|
1002 |
* of type <CODE>transferType</CODE>. |
|
1003 |
* @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not |
|
1004 |
* large enough to hold a pixel value for this |
|
1005 |
* <CODE>ColorModel</CODE>. |
|
1006 |
* @throws UnsupportedOperationException If the transfer type of |
|
1007 |
* this <CODE>ComponentColorModel</CODE> |
|
1008 |
* is not one of the supported transfer types: |
|
1009 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
1010 |
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, |
|
1011 |
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. |
|
1012 |
*/ |
|
1013 |
public int getBlue(Object inData) { |
|
1014 |
return getRGBComponent(inData, 2); |
|
1015 |
} |
|
1016 |
||
1017 |
/** |
|
1018 |
* Returns the alpha component for the specified pixel, scaled from |
|
1019 |
* 0 to 255. The pixel value is specified by an array of data |
|
1020 |
* elements of type <CODE>transferType</CODE> passed in as an |
|
1021 |
* object reference. Since <code>ComponentColorModel</code> can be |
|
1022 |
* subclassed, subclasses inherit the |
|
1023 |
* implementation of this method and if they don't override it then |
|
1024 |
* they throw an exception if they use an unsupported |
|
1025 |
* <code>transferType</code>. |
|
1026 |
* |
|
1027 |
* @param inData The pixel from which you want to get the alpha component, |
|
1028 |
* specified by an array of data elements of type <CODE>transferType</CODE>. |
|
1029 |
* |
|
1030 |
* @return The alpha component for the specified pixel, as an int. |
|
1031 |
* |
|
1032 |
* @throws ClassCastException If <CODE>inData</CODE> is not a primitive array |
|
1033 |
* of type <CODE>transferType</CODE>. |
|
1034 |
* @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not |
|
1035 |
* large enough to hold a pixel value for this |
|
1036 |
* <CODE>ColorModel</CODE>. |
|
1037 |
* @throws UnsupportedOperationException If the transfer type of |
|
1038 |
* this <CODE>ComponentColorModel</CODE> |
|
1039 |
* is not one of the supported transfer types: |
|
1040 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
1041 |
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, |
|
1042 |
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. |
|
1043 |
*/ |
|
1044 |
public int getAlpha(Object inData) { |
|
1045 |
if (supportsAlpha == false) { |
|
1046 |
return 255; |
|
1047 |
} |
|
1048 |
||
1049 |
int alpha = 0; |
|
1050 |
int aIdx = numColorComponents; |
|
1051 |
int mask = (1 << nBits[aIdx]) - 1; |
|
1052 |
||
1053 |
switch (transferType) { |
|
1054 |
case DataBuffer.TYPE_SHORT: |
|
1055 |
short sdata[] = (short[])inData; |
|
1056 |
alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f); |
|
1057 |
return alpha; |
|
1058 |
case DataBuffer.TYPE_FLOAT: |
|
1059 |
float fdata[] = (float[])inData; |
|
1060 |
alpha = (int) (fdata[aIdx] * 255.0f + 0.5f); |
|
1061 |
return alpha; |
|
1062 |
case DataBuffer.TYPE_DOUBLE: |
|
1063 |
double ddata[] = (double[])inData; |
|
1064 |
alpha = (int) (ddata[aIdx] * 255.0 + 0.5); |
|
1065 |
return alpha; |
|
1066 |
case DataBuffer.TYPE_BYTE: |
|
1067 |
byte bdata[] = (byte[])inData; |
|
1068 |
alpha = bdata[aIdx] & mask; |
|
1069 |
break; |
|
1070 |
case DataBuffer.TYPE_USHORT: |
|
1071 |
short usdata[] = (short[])inData; |
|
1072 |
alpha = usdata[aIdx] & mask; |
|
1073 |
break; |
|
1074 |
case DataBuffer.TYPE_INT: |
|
1075 |
int idata[] = (int[])inData; |
|
1076 |
alpha = idata[aIdx]; |
|
1077 |
break; |
|
1078 |
default: |
|
1079 |
throw new |
|
1080 |
UnsupportedOperationException("This method has not "+ |
|
1081 |
"been implemented for transferType " + transferType); |
|
1082 |
} |
|
1083 |
||
1084 |
if (nBits[aIdx] == 8) { |
|
1085 |
return alpha; |
|
1086 |
} else { |
|
1087 |
return (int) |
|
1088 |
((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) * |
|
1089 |
255.0f + 0.5f); |
|
1090 |
} |
|
1091 |
} |
|
1092 |
||
1093 |
/** |
|
1094 |
* Returns the color/alpha components for the specified pixel in the |
|
1095 |
* default RGB color model format. A color conversion is done if |
|
1096 |
* necessary. The pixel value is specified by an |
|
1097 |
* array of data elements of type <CODE>transferType</CODE> passed |
|
1098 |
* in as an object reference. |
|
1099 |
* The returned value is in a non pre-multiplied format. If |
|
1100 |
* the alpha is premultiplied, this method divides it out of the |
|
1101 |
* color components (if the alpha value is 0, the color values will be 0). |
|
1102 |
* Since <code>ComponentColorModel</code> can be subclassed, |
|
1103 |
* subclasses inherit the implementation of this method and if they |
|
1104 |
* don't override it then they throw an exception if they use an |
|
1105 |
* unsupported <code>transferType</code>. |
|
1106 |
* |
|
1107 |
* @param inData The pixel from which you want to get the color/alpha components, |
|
1108 |
* specified by an array of data elements of type <CODE>transferType</CODE>. |
|
1109 |
* |
|
1110 |
* @return The color/alpha components for the specified pixel, as an int. |
|
1111 |
* |
|
1112 |
* @throws ClassCastException If <CODE>inData</CODE> is not a primitive array |
|
1113 |
* of type <CODE>transferType</CODE>. |
|
1114 |
* @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not |
|
1115 |
* large enough to hold a pixel value for this |
|
1116 |
* <CODE>ColorModel</CODE>. |
|
1117 |
* @throws UnsupportedOperationException If the transfer type of |
|
1118 |
* this <CODE>ComponentColorModel</CODE> |
|
1119 |
* is not one of the supported transfer types: |
|
1120 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
1121 |
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, |
|
1122 |
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. |
|
1123 |
* @see ColorModel#getRGBdefault |
|
1124 |
*/ |
|
1125 |
public int getRGB(Object inData) { |
|
1126 |
if (needScaleInit) { |
|
1127 |
initScale(); |
|
1128 |
} |
|
1129 |
if (is_sRGB_stdScale || is_LinearRGB_stdScale) { |
|
1130 |
return (getAlpha(inData) << 24) |
|
1131 |
| (getRed(inData) << 16) |
|
1132 |
| (getGreen(inData) << 8) |
|
1133 |
| (getBlue(inData)); |
|
1134 |
} else if (colorSpaceType == ColorSpace.TYPE_GRAY) { |
|
1135 |
int gray = getRed(inData); // Red sRGB component should equal |
|
1136 |
// green and blue components |
|
1137 |
return (getAlpha(inData) << 24) |
|
1138 |
| (gray << 16) |
|
1139 |
| (gray << 8) |
|
1140 |
| gray; |
|
1141 |
} |
|
1142 |
float[] norm = getNormalizedComponents(inData, null, 0); |
|
1143 |
// Note that getNormalizedComponents returns non-premult values |
|
1144 |
float[] rgb = colorSpace.toRGB(norm); |
|
1145 |
return (getAlpha(inData) << 24) |
|
1146 |
| (((int) (rgb[0] * 255.0f + 0.5f)) << 16) |
|
1147 |
| (((int) (rgb[1] * 255.0f + 0.5f)) << 8) |
|
1148 |
| (((int) (rgb[2] * 255.0f + 0.5f)) << 0); |
|
1149 |
} |
|
1150 |
||
1151 |
/** |
|
1152 |
* Returns a data element array representation of a pixel in this |
|
1153 |
* <CODE>ColorModel</CODE>, given an integer pixel representation |
|
1154 |
* in the default RGB color model. |
|
1155 |
* This array can then be passed to the <CODE>setDataElements</CODE> |
|
1156 |
* method of a <CODE>WritableRaster</CODE> object. If the |
|
1157 |
* <CODE>pixel</CODE> |
|
1158 |
* parameter is null, a new array is allocated. Since |
|
1159 |
* <code>ComponentColorModel</code> can be subclassed, subclasses |
|
1160 |
* inherit the implementation of this method and if they don't |
|
1161 |
* override it then |
|
1162 |
* they throw an exception if they use an unsupported |
|
1163 |
* <code>transferType</code>. |
|
1164 |
* |
|
1165 |
* @param rgb the integer representation of the pixel in the RGB |
|
1166 |
* color model |
|
1167 |
* @param pixel the specified pixel |
|
1168 |
* @return The data element array representation of a pixel |
|
1169 |
* in this <CODE>ColorModel</CODE>. |
|
1170 |
* @throws ClassCastException If <CODE>pixel</CODE> is not null and |
|
1171 |
* is not a primitive array of type <CODE>transferType</CODE>. |
|
1172 |
* @throws ArrayIndexOutOfBoundsException If <CODE>pixel</CODE> is |
|
1173 |
* not large enough to hold a pixel value for this |
|
1174 |
* <CODE>ColorModel</CODE>. |
|
1175 |
* @throws UnsupportedOperationException If the transfer type of |
|
1176 |
* this <CODE>ComponentColorModel</CODE> |
|
1177 |
* is not one of the supported transfer types: |
|
1178 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
1179 |
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, |
|
1180 |
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. |
|
1181 |
* |
|
1182 |
* @see WritableRaster#setDataElements |
|
1183 |
* @see SampleModel#setDataElements |
|
1184 |
*/ |
|
1185 |
public Object getDataElements(int rgb, Object pixel) { |
|
1186 |
// REMIND: Use rendering hints? |
|
1187 |
||
1188 |
int red, grn, blu, alp; |
|
1189 |
red = (rgb>>16) & 0xff; |
|
1190 |
grn = (rgb>>8) & 0xff; |
|
1191 |
blu = rgb & 0xff; |
|
1192 |
||
1193 |
if (needScaleInit) { |
|
1194 |
initScale(); |
|
1195 |
} |
|
1196 |
if (signed) { |
|
1197 |
// Handle SHORT, FLOAT, & DOUBLE here |
|
1198 |
||
1199 |
switch(transferType) { |
|
1200 |
case DataBuffer.TYPE_SHORT: |
|
1201 |
{ |
|
1202 |
short sdata[]; |
|
1203 |
if (pixel == null) { |
|
1204 |
sdata = new short[numComponents]; |
|
1205 |
} else { |
|
1206 |
sdata = (short[])pixel; |
|
1207 |
} |
|
1208 |
float factor; |
|
1209 |
if (is_sRGB_stdScale || is_LinearRGB_stdScale) { |
|
1210 |
factor = 32767.0f / 255.0f; |
|
1211 |
if (is_LinearRGB_stdScale) { |
|
1212 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1213 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1214 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1215 |
factor = 32767.0f / 65535.0f; |
|
1216 |
} |
|
1217 |
if (supportsAlpha) { |
|
1218 |
alp = (rgb>>24) & 0xff; |
|
1219 |
sdata[3] = |
|
1220 |
(short) (alp * (32767.0f / 255.0f) + 0.5f); |
|
1221 |
if (isAlphaPremultiplied) { |
|
1222 |
factor = alp * factor * (1.0f / 255.0f); |
|
1223 |
} |
|
1224 |
} |
|
1225 |
sdata[0] = (short) (red * factor + 0.5f); |
|
1226 |
sdata[1] = (short) (grn * factor + 0.5f); |
|
1227 |
sdata[2] = (short) (blu * factor + 0.5f); |
|
1228 |
} else if (is_LinearGray_stdScale) { |
|
1229 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1230 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1231 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1232 |
float gray = ((0.2125f * red) + |
|
1233 |
(0.7154f * grn) + |
|
1234 |
(0.0721f * blu)) / 65535.0f; |
|
1235 |
factor = 32767.0f; |
|
1236 |
if (supportsAlpha) { |
|
1237 |
alp = (rgb>>24) & 0xff; |
|
1238 |
sdata[1] = |
|
1239 |
(short) (alp * (32767.0f / 255.0f) + 0.5f); |
|
1240 |
if (isAlphaPremultiplied) { |
|
1241 |
factor = alp * factor * (1.0f / 255.0f); |
|
1242 |
} |
|
1243 |
} |
|
1244 |
sdata[0] = (short) (gray * factor + 0.5f); |
|
1245 |
} else if (is_ICCGray_stdScale) { |
|
1246 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1247 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1248 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1249 |
int gray = (int) ((0.2125f * red) + |
|
1250 |
(0.7154f * grn) + |
|
1251 |
(0.0721f * blu) + 0.5f); |
|
1252 |
gray = fromLinearGray16ToOtherGray16LUT[gray] & 0xffff; |
|
1253 |
factor = 32767.0f / 65535.0f; |
|
1254 |
if (supportsAlpha) { |
|
1255 |
alp = (rgb>>24) & 0xff; |
|
1256 |
sdata[1] = |
|
1257 |
(short) (alp * (32767.0f / 255.0f) + 0.5f); |
|
1258 |
if (isAlphaPremultiplied) { |
|
1259 |
factor = alp * factor * (1.0f / 255.0f); |
|
1260 |
} |
|
1261 |
} |
|
1262 |
sdata[0] = (short) (gray * factor + 0.5f); |
|
1263 |
} else { |
|
1264 |
factor = 1.0f / 255.0f; |
|
1265 |
float norm[] = new float[3]; |
|
1266 |
norm[0] = red * factor; |
|
1267 |
norm[1] = grn * factor; |
|
1268 |
norm[2] = blu * factor; |
|
1269 |
norm = colorSpace.fromRGB(norm); |
|
1270 |
if (nonStdScale) { |
|
1271 |
for (int i = 0; i < numColorComponents; i++) { |
|
1272 |
norm[i] = (norm[i] - compOffset[i]) * |
|
1273 |
compScale[i]; |
|
1274 |
// REMIND: need to analyze whether this |
|
1275 |
// clamping is necessary |
|
1276 |
if (norm[i] < 0.0f) { |
|
1277 |
norm[i] = 0.0f; |
|
1278 |
} |
|
1279 |
if (norm[i] > 1.0f) { |
|
1280 |
norm[i] = 1.0f; |
|
1281 |
} |
|
1282 |
} |
|
1283 |
} |
|
1284 |
factor = 32767.0f; |
|
1285 |
if (supportsAlpha) { |
|
1286 |
alp = (rgb>>24) & 0xff; |
|
1287 |
sdata[numColorComponents] = |
|
1288 |
(short) (alp * (32767.0f / 255.0f) + 0.5f); |
|
1289 |
if (isAlphaPremultiplied) { |
|
1290 |
factor *= alp * (1.0f / 255.0f); |
|
1291 |
} |
|
1292 |
} |
|
1293 |
for (int i = 0; i < numColorComponents; i++) { |
|
1294 |
sdata[i] = (short) (norm[i] * factor + 0.5f); |
|
1295 |
} |
|
1296 |
} |
|
1297 |
return sdata; |
|
1298 |
} |
|
1299 |
case DataBuffer.TYPE_FLOAT: |
|
1300 |
{ |
|
1301 |
float fdata[]; |
|
1302 |
if (pixel == null) { |
|
1303 |
fdata = new float[numComponents]; |
|
1304 |
} else { |
|
1305 |
fdata = (float[])pixel; |
|
1306 |
} |
|
1307 |
float factor; |
|
1308 |
if (is_sRGB_stdScale || is_LinearRGB_stdScale) { |
|
1309 |
if (is_LinearRGB_stdScale) { |
|
1310 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1311 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1312 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1313 |
factor = 1.0f / 65535.0f; |
|
1314 |
} else { |
|
1315 |
factor = 1.0f / 255.0f; |
|
1316 |
} |
|
1317 |
if (supportsAlpha) { |
|
1318 |
alp = (rgb>>24) & 0xff; |
|
1319 |
fdata[3] = alp * (1.0f / 255.0f); |
|
1320 |
if (isAlphaPremultiplied) { |
|
1321 |
factor *= fdata[3]; |
|
1322 |
} |
|
1323 |
} |
|
1324 |
fdata[0] = red * factor; |
|
1325 |
fdata[1] = grn * factor; |
|
1326 |
fdata[2] = blu * factor; |
|
1327 |
} else if (is_LinearGray_stdScale) { |
|
1328 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1329 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1330 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1331 |
fdata[0] = ((0.2125f * red) + |
|
1332 |
(0.7154f * grn) + |
|
1333 |
(0.0721f * blu)) / 65535.0f; |
|
1334 |
if (supportsAlpha) { |
|
1335 |
alp = (rgb>>24) & 0xff; |
|
1336 |
fdata[1] = alp * (1.0f / 255.0f); |
|
1337 |
if (isAlphaPremultiplied) { |
|
1338 |
fdata[0] *= fdata[1]; |
|
1339 |
} |
|
1340 |
} |
|
1341 |
} else if (is_ICCGray_stdScale) { |
|
1342 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1343 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1344 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1345 |
int gray = (int) ((0.2125f * red) + |
|
1346 |
(0.7154f * grn) + |
|
1347 |
(0.0721f * blu) + 0.5f); |
|
1348 |
fdata[0] = (fromLinearGray16ToOtherGray16LUT[gray] & |
|
1349 |
0xffff) / 65535.0f; |
|
1350 |
if (supportsAlpha) { |
|
1351 |
alp = (rgb>>24) & 0xff; |
|
1352 |
fdata[1] = alp * (1.0f / 255.0f); |
|
1353 |
if (isAlphaPremultiplied) { |
|
1354 |
fdata[0] *= fdata[1]; |
|
1355 |
} |
|
1356 |
} |
|
1357 |
} else { |
|
1358 |
float norm[] = new float[3]; |
|
1359 |
factor = 1.0f / 255.0f; |
|
1360 |
norm[0] = red * factor; |
|
1361 |
norm[1] = grn * factor; |
|
1362 |
norm[2] = blu * factor; |
|
1363 |
norm = colorSpace.fromRGB(norm); |
|
1364 |
if (supportsAlpha) { |
|
1365 |
alp = (rgb>>24) & 0xff; |
|
1366 |
fdata[numColorComponents] = alp * factor; |
|
1367 |
if (isAlphaPremultiplied) { |
|
1368 |
factor *= alp; |
|
1369 |
for (int i = 0; i < numColorComponents; i++) { |
|
1370 |
norm[i] *= factor; |
|
1371 |
} |
|
1372 |
} |
|
1373 |
} |
|
1374 |
for (int i = 0; i < numColorComponents; i++) { |
|
1375 |
fdata[i] = norm[i]; |
|
1376 |
} |
|
1377 |
} |
|
1378 |
return fdata; |
|
1379 |
} |
|
1380 |
case DataBuffer.TYPE_DOUBLE: |
|
1381 |
{ |
|
1382 |
double ddata[]; |
|
1383 |
if (pixel == null) { |
|
1384 |
ddata = new double[numComponents]; |
|
1385 |
} else { |
|
1386 |
ddata = (double[])pixel; |
|
1387 |
} |
|
1388 |
if (is_sRGB_stdScale || is_LinearRGB_stdScale) { |
|
1389 |
double factor; |
|
1390 |
if (is_LinearRGB_stdScale) { |
|
1391 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1392 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1393 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1394 |
factor = 1.0 / 65535.0; |
|
1395 |
} else { |
|
1396 |
factor = 1.0 / 255.0; |
|
1397 |
} |
|
1398 |
if (supportsAlpha) { |
|
1399 |
alp = (rgb>>24) & 0xff; |
|
1400 |
ddata[3] = alp * (1.0 / 255.0); |
|
1401 |
if (isAlphaPremultiplied) { |
|
1402 |
factor *= ddata[3]; |
|
1403 |
} |
|
1404 |
} |
|
1405 |
ddata[0] = red * factor; |
|
1406 |
ddata[1] = grn * factor; |
|
1407 |
ddata[2] = blu * factor; |
|
1408 |
} else if (is_LinearGray_stdScale) { |
|
1409 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1410 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1411 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1412 |
ddata[0] = ((0.2125 * red) + |
|
1413 |
(0.7154 * grn) + |
|
1414 |
(0.0721 * blu)) / 65535.0; |
|
1415 |
if (supportsAlpha) { |
|
1416 |
alp = (rgb>>24) & 0xff; |
|
1417 |
ddata[1] = alp * (1.0 / 255.0); |
|
1418 |
if (isAlphaPremultiplied) { |
|
1419 |
ddata[0] *= ddata[1]; |
|
1420 |
} |
|
1421 |
} |
|
1422 |
} else if (is_ICCGray_stdScale) { |
|
1423 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1424 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1425 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1426 |
int gray = (int) ((0.2125f * red) + |
|
1427 |
(0.7154f * grn) + |
|
1428 |
(0.0721f * blu) + 0.5f); |
|
1429 |
ddata[0] = (fromLinearGray16ToOtherGray16LUT[gray] & |
|
1430 |
0xffff) / 65535.0; |
|
1431 |
if (supportsAlpha) { |
|
1432 |
alp = (rgb>>24) & 0xff; |
|
1433 |
ddata[1] = alp * (1.0 / 255.0); |
|
1434 |
if (isAlphaPremultiplied) { |
|
1435 |
ddata[0] *= ddata[1]; |
|
1436 |
} |
|
1437 |
} |
|
1438 |
} else { |
|
1439 |
float factor = 1.0f / 255.0f; |
|
1440 |
float norm[] = new float[3]; |
|
1441 |
norm[0] = red * factor; |
|
1442 |
norm[1] = grn * factor; |
|
1443 |
norm[2] = blu * factor; |
|
1444 |
norm = colorSpace.fromRGB(norm); |
|
1445 |
if (supportsAlpha) { |
|
1446 |
alp = (rgb>>24) & 0xff; |
|
1447 |
ddata[numColorComponents] = alp * (1.0 / 255.0); |
|
1448 |
if (isAlphaPremultiplied) { |
|
1449 |
factor *= alp; |
|
1450 |
for (int i = 0; i < numColorComponents; i++) { |
|
1451 |
norm[i] *= factor; |
|
1452 |
} |
|
1453 |
} |
|
1454 |
} |
|
1455 |
for (int i = 0; i < numColorComponents; i++) { |
|
1456 |
ddata[i] = norm[i]; |
|
1457 |
} |
|
1458 |
} |
|
1459 |
return ddata; |
|
1460 |
} |
|
1461 |
} |
|
1462 |
} |
|
1463 |
||
1464 |
// Handle BYTE, USHORT, & INT here |
|
1465 |
//REMIND: maybe more efficient not to use int array for |
|
1466 |
//DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT |
|
1467 |
int intpixel[]; |
|
1468 |
if (transferType == DataBuffer.TYPE_INT && |
|
1469 |
pixel != null) { |
|
1470 |
intpixel = (int[])pixel; |
|
1471 |
} else { |
|
1472 |
intpixel = new int[numComponents]; |
|
1473 |
} |
|
1474 |
||
1475 |
if (is_sRGB_stdScale || is_LinearRGB_stdScale) { |
|
1476 |
int precision; |
|
1477 |
float factor; |
|
1478 |
if (is_LinearRGB_stdScale) { |
|
1479 |
if (transferType == DataBuffer.TYPE_BYTE) { |
|
1480 |
red = fromsRGB8LUT8[red] & 0xff; |
|
1481 |
grn = fromsRGB8LUT8[grn] & 0xff; |
|
1482 |
blu = fromsRGB8LUT8[blu] & 0xff; |
|
1483 |
precision = 8; |
|
1484 |
factor = 1.0f / 255.0f; |
|
1485 |
} else { |
|
1486 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1487 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1488 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1489 |
precision = 16; |
|
1490 |
factor = 1.0f / 65535.0f; |
|
1491 |
} |
|
1492 |
} else { |
|
1493 |
precision = 8; |
|
1494 |
factor = 1.0f / 255.0f; |
|
1495 |
} |
|
1496 |
if (supportsAlpha) { |
|
1497 |
alp = (rgb>>24)&0xff; |
|
1498 |
if (nBits[3] == 8) { |
|
1499 |
intpixel[3] = alp; |
|
1500 |
} |
|
1501 |
else { |
|
1502 |
intpixel[3] = (int) |
|
1503 |
(alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1) + 0.5f); |
|
1504 |
} |
|
1505 |
if (isAlphaPremultiplied) { |
|
1506 |
factor *= (alp * (1.0f / 255.0f)); |
|
1507 |
precision = -1; // force component calculations below |
|
1508 |
} |
|
1509 |
} |
|
1510 |
if (nBits[0] == precision) { |
|
1511 |
intpixel[0] = red; |
|
1512 |
} |
|
1513 |
else { |
|
1514 |
intpixel[0] = (int) (red * factor * ((1<<nBits[0]) - 1) + 0.5f); |
|
1515 |
} |
|
1516 |
if (nBits[1] == precision) { |
|
22584
eed64ee05369
8032733: Fix cast lint warnings in client libraries
darcy
parents:
21278
diff
changeset
|
1517 |
intpixel[1] = grn; |
2 | 1518 |
} |
1519 |
else { |
|
1520 |
intpixel[1] = (int) (grn * factor * ((1<<nBits[1]) - 1) + 0.5f); |
|
1521 |
} |
|
1522 |
if (nBits[2] == precision) { |
|
22584
eed64ee05369
8032733: Fix cast lint warnings in client libraries
darcy
parents:
21278
diff
changeset
|
1523 |
intpixel[2] = blu; |
2 | 1524 |
} |
1525 |
else { |
|
1526 |
intpixel[2] = (int) (blu * factor * ((1<<nBits[2]) - 1) + 0.5f); |
|
1527 |
} |
|
1528 |
} else if (is_LinearGray_stdScale) { |
|
1529 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1530 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1531 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1532 |
float gray = ((0.2125f * red) + |
|
1533 |
(0.7154f * grn) + |
|
1534 |
(0.0721f * blu)) / 65535.0f; |
|
1535 |
if (supportsAlpha) { |
|
1536 |
alp = (rgb>>24) & 0xff; |
|
1537 |
if (nBits[1] == 8) { |
|
1538 |
intpixel[1] = alp; |
|
1539 |
} else { |
|
1540 |
intpixel[1] = (int) (alp * (1.0f / 255.0f) * |
|
1541 |
((1 << nBits[1]) - 1) + 0.5f); |
|
1542 |
} |
|
1543 |
if (isAlphaPremultiplied) { |
|
1544 |
gray *= (alp * (1.0f / 255.0f)); |
|
1545 |
} |
|
1546 |
} |
|
1547 |
intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f); |
|
1548 |
} else if (is_ICCGray_stdScale) { |
|
1549 |
red = fromsRGB8LUT16[red] & 0xffff; |
|
1550 |
grn = fromsRGB8LUT16[grn] & 0xffff; |
|
1551 |
blu = fromsRGB8LUT16[blu] & 0xffff; |
|
1552 |
int gray16 = (int) ((0.2125f * red) + |
|
1553 |
(0.7154f * grn) + |
|
1554 |
(0.0721f * blu) + 0.5f); |
|
1555 |
float gray = (fromLinearGray16ToOtherGray16LUT[gray16] & |
|
1556 |
0xffff) / 65535.0f; |
|
1557 |
if (supportsAlpha) { |
|
1558 |
alp = (rgb>>24) & 0xff; |
|
1559 |
if (nBits[1] == 8) { |
|
1560 |
intpixel[1] = alp; |
|
1561 |
} else { |
|
1562 |
intpixel[1] = (int) (alp * (1.0f / 255.0f) * |
|
1563 |
((1 << nBits[1]) - 1) + 0.5f); |
|
1564 |
} |
|
1565 |
if (isAlphaPremultiplied) { |
|
1566 |
gray *= (alp * (1.0f / 255.0f)); |
|
1567 |
} |
|
1568 |
} |
|
1569 |
intpixel[0] = (int) (gray * ((1 << nBits[0]) - 1) + 0.5f); |
|
1570 |
} else { |
|
1571 |
// Need to convert the color |
|
1572 |
float[] norm = new float[3]; |
|
1573 |
float factor = 1.0f / 255.0f; |
|
1574 |
norm[0] = red * factor; |
|
1575 |
norm[1] = grn * factor; |
|
1576 |
norm[2] = blu * factor; |
|
1577 |
norm = colorSpace.fromRGB(norm); |
|
1578 |
if (nonStdScale) { |
|
1579 |
for (int i = 0; i < numColorComponents; i++) { |
|
1580 |
norm[i] = (norm[i] - compOffset[i]) * |
|
1581 |
compScale[i]; |
|
1582 |
// REMIND: need to analyze whether this |
|
1583 |
// clamping is necessary |
|
1584 |
if (norm[i] < 0.0f) { |
|
1585 |
norm[i] = 0.0f; |
|
1586 |
} |
|
1587 |
if (norm[i] > 1.0f) { |
|
1588 |
norm[i] = 1.0f; |
|
1589 |
} |
|
1590 |
} |
|
1591 |
} |
|
1592 |
if (supportsAlpha) { |
|
1593 |
alp = (rgb>>24) & 0xff; |
|
1594 |
if (nBits[numColorComponents] == 8) { |
|
1595 |
intpixel[numColorComponents] = alp; |
|
1596 |
} |
|
1597 |
else { |
|
1598 |
intpixel[numColorComponents] = |
|
1599 |
(int) (alp * factor * |
|
1600 |
((1<<nBits[numColorComponents]) - 1) + 0.5f); |
|
1601 |
} |
|
1602 |
if (isAlphaPremultiplied) { |
|
1603 |
factor *= alp; |
|
1604 |
for (int i = 0; i < numColorComponents; i++) { |
|
1605 |
norm[i] *= factor; |
|
1606 |
} |
|
1607 |
} |
|
1608 |
} |
|
1609 |
for (int i = 0; i < numColorComponents; i++) { |
|
1610 |
intpixel[i] = (int) (norm[i] * ((1<<nBits[i]) - 1) + 0.5f); |
|
1611 |
} |
|
1612 |
} |
|
1613 |
||
1614 |
switch (transferType) { |
|
1615 |
case DataBuffer.TYPE_BYTE: { |
|
1616 |
byte bdata[]; |
|
1617 |
if (pixel == null) { |
|
1618 |
bdata = new byte[numComponents]; |
|
1619 |
} else { |
|
1620 |
bdata = (byte[])pixel; |
|
1621 |
} |
|
1622 |
for (int i = 0; i < numComponents; i++) { |
|
1623 |
bdata[i] = (byte)(0xff&intpixel[i]); |
|
1624 |
} |
|
1625 |
return bdata; |
|
1626 |
} |
|
1627 |
case DataBuffer.TYPE_USHORT:{ |
|
1628 |
short sdata[]; |
|
1629 |
if (pixel == null) { |
|
1630 |
sdata = new short[numComponents]; |
|
1631 |
} else { |
|
1632 |
sdata = (short[])pixel; |
|
1633 |
} |
|
1634 |
for (int i = 0; i < numComponents; i++) { |
|
1635 |
sdata[i] = (short)(intpixel[i]&0xffff); |
|
1636 |
} |
|
1637 |
return sdata; |
|
1638 |
} |
|
1639 |
case DataBuffer.TYPE_INT: |
|
1640 |
if (maxBits > 23) { |
|
1641 |
// fix 4412670 - for components of 24 or more bits |
|
1642 |
// some calculations done above with float precision |
|
1643 |
// may lose enough precision that the integer result |
|
1644 |
// overflows nBits, so we need to clamp. |
|
1645 |
for (int i = 0; i < numComponents; i++) { |
|
1646 |
if (intpixel[i] > ((1<<nBits[i]) - 1)) { |
|
1647 |
intpixel[i] = (1<<nBits[i]) - 1; |
|
1648 |
} |
|
1649 |
} |
|
1650 |
} |
|
1651 |
return intpixel; |
|
1652 |
} |
|
1653 |
throw new IllegalArgumentException("This method has not been "+ |
|
1654 |
"implemented for transferType " + transferType); |
|
1655 |
} |
|
1656 |
||
1657 |
/** Returns an array of unnormalized color/alpha components given a pixel |
|
1658 |
* in this <CODE>ColorModel</CODE>. |
|
1659 |
* An IllegalArgumentException is thrown if the component value for this |
|
1660 |
* <CODE>ColorModel</CODE> is not conveniently representable in the |
|
1661 |
* unnormalized form. Color/alpha components are stored |
|
1662 |
* in the <CODE>components</CODE> array starting at <CODE>offset</CODE> |
|
1663 |
* (even if the array is allocated by this method). |
|
1664 |
* |
|
1665 |
* @param pixel The pixel value specified as an integer. |
|
1666 |
* @param components An integer array in which to store the unnormalized |
|
1667 |
* color/alpha components. If the <CODE>components</CODE> array is null, |
|
1668 |
* a new array is allocated. |
|
1669 |
* @param offset An offset into the <CODE>components</CODE> array. |
|
1670 |
* |
|
1671 |
* @return The components array. |
|
1672 |
* |
|
1673 |
* @throws IllegalArgumentException If there is more than one |
|
1674 |
* component in this <CODE>ColorModel</CODE>. |
|
1675 |
* @throws IllegalArgumentException If this |
|
1676 |
* <CODE>ColorModel</CODE> does not support the unnormalized form |
|
1677 |
* @throws ArrayIndexOutOfBoundsException If the <CODE>components</CODE> |
|
1678 |
* array is not null and is not large enough to hold all the color and |
|
1679 |
* alpha components (starting at offset). |
|
1680 |
*/ |
|
1681 |
public int[] getComponents(int pixel, int[] components, int offset) { |
|
1682 |
if (numComponents > 1) { |
|
1683 |
throw new |
|
1684 |
IllegalArgumentException("More than one component per pixel"); |
|
1685 |
} |
|
1686 |
if (needScaleInit) { |
|
1687 |
initScale(); |
|
1688 |
} |
|
1689 |
if (noUnnorm) { |
|
1690 |
throw new |
|
1691 |
IllegalArgumentException( |
|
1692 |
"This ColorModel does not support the unnormalized form"); |
|
1693 |
} |
|
1694 |
if (components == null) { |
|
1695 |
components = new int[offset+1]; |
|
1696 |
} |
|
1697 |
||
1698 |
components[offset+0] = (pixel & ((1<<nBits[0]) - 1)); |
|
1699 |
return components; |
|
1700 |
} |
|
1701 |
||
1702 |
/** |
|
1703 |
* Returns an array of unnormalized color/alpha components given a pixel |
|
1704 |
* in this <CODE>ColorModel</CODE>. The pixel value is specified by an |
|
1705 |
* array of data elements of type <CODE>transferType</CODE> passed in as |
|
1706 |
* an object reference. |
|
1707 |
* An IllegalArgumentException is thrown if the component values for this |
|
1708 |
* <CODE>ColorModel</CODE> are not conveniently representable in the |
|
1709 |
* unnormalized form. |
|
1710 |
* Color/alpha components are stored in the <CODE>components</CODE> array |
|
1711 |
* starting at <CODE>offset</CODE> (even if the array is allocated by |
|
1712 |
* this method). Since <code>ComponentColorModel</code> can be |
|
1713 |
* subclassed, subclasses inherit the |
|
1714 |
* implementation of this method and if they don't override it then |
|
1715 |
* this method might throw an exception if they use an unsupported |
|
1716 |
* <code>transferType</code>. |
|
1717 |
* |
|
1718 |
* @param pixel A pixel value specified by an array of data elements of |
|
1719 |
* type <CODE>transferType</CODE>. |
|
1720 |
* @param components An integer array in which to store the unnormalized |
|
1721 |
* color/alpha components. If the <CODE>components</CODE> array is null, |
|
1722 |
* a new array is allocated. |
|
1723 |
* @param offset An offset into the <CODE>components</CODE> array. |
|
1724 |
* |
|
1725 |
* @return The <CODE>components</CODE> array. |
|
1726 |
* |
|
1727 |
* @throws IllegalArgumentException If this |
|
1728 |
* <CODE>ComponentColorModel</CODE> does not support the unnormalized form |
|
1729 |
* @throws UnsupportedOperationException in some cases iff the |
|
1730 |
* transfer type of this <CODE>ComponentColorModel</CODE> |
|
1731 |
* is not one of the following transfer types: |
|
1732 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
1733 |
* or <CODE>DataBuffer.TYPE_INT</CODE>. |
|
1734 |
* @throws ClassCastException If <CODE>pixel</CODE> is not a primitive |
|
1735 |
* array of type <CODE>transferType</CODE>. |
|
1736 |
* @throws IllegalArgumentException If the <CODE>components</CODE> array is |
|
1737 |
* not null and is not large enough to hold all the color and alpha |
|
1738 |
* components (starting at offset), or if <CODE>pixel</CODE> is not large |
|
1739 |
* enough to hold a pixel value for this ColorModel. |
|
1740 |
*/ |
|
1741 |
public int[] getComponents(Object pixel, int[] components, int offset) { |
|
1742 |
int intpixel[]; |
|
1743 |
if (needScaleInit) { |
|
1744 |
initScale(); |
|
1745 |
} |
|
1746 |
if (noUnnorm) { |
|
1747 |
throw new |
|
1748 |
IllegalArgumentException( |
|
1749 |
"This ColorModel does not support the unnormalized form"); |
|
1750 |
} |
|
1751 |
if (pixel instanceof int[]) { |
|
1752 |
intpixel = (int[])pixel; |
|
1753 |
} else { |
|
1754 |
intpixel = DataBuffer.toIntArray(pixel); |
|
1755 |
if (intpixel == null) { |
|
1756 |
throw new UnsupportedOperationException("This method has not been "+ |
|
1757 |
"implemented for transferType " + transferType); |
|
1758 |
} |
|
1759 |
} |
|
1760 |
if (intpixel.length < numComponents) { |
|
1761 |
throw new IllegalArgumentException |
|
1762 |
("Length of pixel array < number of components in model"); |
|
1763 |
} |
|
1764 |
if (components == null) { |
|
1765 |
components = new int[offset+numComponents]; |
|
1766 |
} |
|
1767 |
else if ((components.length-offset) < numComponents) { |
|
1768 |
throw new IllegalArgumentException |
|
1769 |
("Length of components array < number of components in model"); |
|
1770 |
} |
|
1771 |
System.arraycopy(intpixel, 0, components, offset, numComponents); |
|
1772 |
||
1773 |
return components; |
|
1774 |
} |
|
1775 |
||
1776 |
/** |
|
1777 |
* Returns an array of all of the color/alpha components in unnormalized |
|
1778 |
* form, given a normalized component array. Unnormalized components |
|
1779 |
* are unsigned integral values between 0 and 2<sup>n</sup> - 1, where |
|
1780 |
* n is the number of bits for a particular component. Normalized |
|
1781 |
* components are float values between a per component minimum and |
|
1782 |
* maximum specified by the <code>ColorSpace</code> object for this |
|
1783 |
* <code>ColorModel</code>. An <code>IllegalArgumentException</code> |
|
1784 |
* will be thrown if color component values for this |
|
1785 |
* <code>ColorModel</code> are not conveniently representable in the |
|
1786 |
* unnormalized form. If the |
|
1787 |
* <code>components</code> array is <code>null</code>, a new array |
|
1788 |
* will be allocated. The <code>components</code> array will |
|
1789 |
* be returned. Color/alpha components are stored in the |
|
1790 |
* <code>components</code> array starting at <code>offset</code> (even |
|
1791 |
* if the array is allocated by this method). An |
|
1792 |
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the |
|
1793 |
* <code>components</code> array is not <code>null</code> and is not |
|
1794 |
* large enough to hold all the color and alpha |
|
1795 |
* components (starting at <code>offset</code>). An |
|
1796 |
* <code>IllegalArgumentException</code> is thrown if the |
|
1797 |
* <code>normComponents</code> array is not large enough to hold |
|
1798 |
* all the color and alpha components starting at |
|
1799 |
* <code>normOffset</code>. |
|
1800 |
* @param normComponents an array containing normalized components |
|
1801 |
* @param normOffset the offset into the <code>normComponents</code> |
|
1802 |
* array at which to start retrieving normalized components |
|
1803 |
* @param components an array that receives the components from |
|
1804 |
* <code>normComponents</code> |
|
1805 |
* @param offset the index into <code>components</code> at which to |
|
1806 |
* begin storing normalized components from |
|
1807 |
* <code>normComponents</code> |
|
1808 |
* @return an array containing unnormalized color and alpha |
|
1809 |
* components. |
|
1810 |
* @throws IllegalArgumentException If this |
|
1811 |
* <CODE>ComponentColorModel</CODE> does not support the unnormalized form |
|
1812 |
* @throws IllegalArgumentException if the length of |
|
1813 |
* <code>normComponents</code> minus <code>normOffset</code> |
|
1814 |
* is less than <code>numComponents</code> |
|
1815 |
*/ |
|
1816 |
public int[] getUnnormalizedComponents(float[] normComponents, |
|
1817 |
int normOffset, |
|
1818 |
int[] components, int offset) { |
|
1819 |
if (needScaleInit) { |
|
1820 |
initScale(); |
|
1821 |
} |
|
1822 |
if (noUnnorm) { |
|
1823 |
throw new |
|
1824 |
IllegalArgumentException( |
|
1825 |
"This ColorModel does not support the unnormalized form"); |
|
1826 |
} |
|
1827 |
return super.getUnnormalizedComponents(normComponents, normOffset, |
|
1828 |
components, offset); |
|
1829 |
} |
|
1830 |
||
1831 |
/** |
|
1832 |
* Returns an array of all of the color/alpha components in normalized |
|
1833 |
* form, given an unnormalized component array. Unnormalized components |
|
1834 |
* are unsigned integral values between 0 and 2<sup>n</sup> - 1, where |
|
1835 |
* n is the number of bits for a particular component. Normalized |
|
1836 |
* components are float values between a per component minimum and |
|
1837 |
* maximum specified by the <code>ColorSpace</code> object for this |
|
1838 |
* <code>ColorModel</code>. An <code>IllegalArgumentException</code> |
|
1839 |
* will be thrown if color component values for this |
|
1840 |
* <code>ColorModel</code> are not conveniently representable in the |
|
1841 |
* unnormalized form. If the |
|
1842 |
* <code>normComponents</code> array is <code>null</code>, a new array |
|
1843 |
* will be allocated. The <code>normComponents</code> array |
|
1844 |
* will be returned. Color/alpha components are stored in the |
|
1845 |
* <code>normComponents</code> array starting at |
|
1846 |
* <code>normOffset</code> (even if the array is allocated by this |
|
1847 |
* method). An <code>ArrayIndexOutOfBoundsException</code> is thrown |
|
1848 |
* if the <code>normComponents</code> array is not <code>null</code> |
|
1849 |
* and is not large enough to hold all the color and alpha components |
|
1850 |
* (starting at <code>normOffset</code>). An |
|
1851 |
* <code>IllegalArgumentException</code> is thrown if the |
|
1852 |
* <code>components</code> array is not large enough to hold all the |
|
1853 |
* color and alpha components starting at <code>offset</code>. |
|
1854 |
* @param components an array containing unnormalized components |
|
1855 |
* @param offset the offset into the <code>components</code> array at |
|
1856 |
* which to start retrieving unnormalized components |
|
1857 |
* @param normComponents an array that receives the normalized components |
|
1858 |
* @param normOffset the index into <code>normComponents</code> at |
|
1859 |
* which to begin storing normalized components |
|
1860 |
* @return an array containing normalized color and alpha |
|
1861 |
* components. |
|
1862 |
* @throws IllegalArgumentException If this |
|
1863 |
* <CODE>ComponentColorModel</CODE> does not support the unnormalized form |
|
1864 |
*/ |
|
1865 |
public float[] getNormalizedComponents(int[] components, int offset, |
|
1866 |
float[] normComponents, |
|
1867 |
int normOffset) { |
|
1868 |
if (needScaleInit) { |
|
1869 |
initScale(); |
|
1870 |
} |
|
1871 |
if (noUnnorm) { |
|
1872 |
throw new |
|
1873 |
IllegalArgumentException( |
|
1874 |
"This ColorModel does not support the unnormalized form"); |
|
1875 |
} |
|
1876 |
return super.getNormalizedComponents(components, offset, |
|
1877 |
normComponents, normOffset); |
|
1878 |
} |
|
1879 |
||
1880 |
/** |
|
1881 |
* Returns a pixel value represented as an int in this <CODE>ColorModel</CODE>, |
|
1882 |
* given an array of unnormalized color/alpha components. |
|
1883 |
* |
|
1884 |
* @param components An array of unnormalized color/alpha components. |
|
1885 |
* @param offset An offset into the <CODE>components</CODE> array. |
|
1886 |
* |
|
1887 |
* @return A pixel value represented as an int. |
|
1888 |
* |
|
1889 |
* @throws IllegalArgumentException If there is more than one component |
|
1890 |
* in this <CODE>ColorModel</CODE>. |
|
1891 |
* @throws IllegalArgumentException If this |
|
1892 |
* <CODE>ComponentColorModel</CODE> does not support the unnormalized form |
|
1893 |
*/ |
|
1894 |
public int getDataElement(int[] components, int offset) { |
|
1895 |
if (needScaleInit) { |
|
1896 |
initScale(); |
|
1897 |
} |
|
1898 |
if (numComponents == 1) { |
|
1899 |
if (noUnnorm) { |
|
1900 |
throw new |
|
1901 |
IllegalArgumentException( |
|
1902 |
"This ColorModel does not support the unnormalized form"); |
|
1903 |
} |
|
1904 |
return components[offset+0]; |
|
1905 |
} |
|
1906 |
throw new IllegalArgumentException("This model returns "+ |
|
1907 |
numComponents+ |
|
1908 |
" elements in the pixel array."); |
|
1909 |
} |
|
1910 |
||
1911 |
/** |
|
1912 |
* Returns a data element array representation of a pixel in this |
|
1913 |
* <CODE>ColorModel</CODE>, given an array of unnormalized color/alpha |
|
1914 |
* components. This array can then be passed to the <CODE>setDataElements</CODE> |
|
1915 |
* method of a <CODE>WritableRaster</CODE> object. |
|
1916 |
* |
|
1917 |
* @param components An array of unnormalized color/alpha components. |
|
1918 |
* @param offset The integer offset into the <CODE>components</CODE> array. |
|
1919 |
* @param obj The object in which to store the data element array |
|
1920 |
* representation of the pixel. If <CODE>obj</CODE> variable is null, |
|
1921 |
* a new array is allocated. If <CODE>obj</CODE> is not null, it must |
|
1922 |
* be a primitive array of type <CODE>transferType</CODE>. An |
|
1923 |
* <CODE>ArrayIndexOutOfBoundsException</CODE> is thrown if |
|
1924 |
* <CODE>obj</CODE> is not large enough to hold a pixel value |
|
1925 |
* for this <CODE>ColorModel</CODE>. Since |
|
1926 |
* <code>ComponentColorModel</code> can be subclassed, subclasses |
|
1927 |
* inherit the implementation of this method and if they don't |
|
1928 |
* override it then they throw an exception if they use an |
|
1929 |
* unsupported <code>transferType</code>. |
|
1930 |
* |
|
1931 |
* @return The data element array representation of a pixel |
|
1932 |
* in this <CODE>ColorModel</CODE>. |
|
1933 |
* |
|
1934 |
* @throws IllegalArgumentException If the components array |
|
1935 |
* is not large enough to hold all the color and alpha components |
|
1936 |
* (starting at offset). |
|
1937 |
* @throws ClassCastException If <CODE>obj</CODE> is not null and is not a |
|
1938 |
* primitive array of type <CODE>transferType</CODE>. |
|
1939 |
* @throws ArrayIndexOutOfBoundsException If <CODE>obj</CODE> is not large |
|
1940 |
* enough to hold a pixel value for this <CODE>ColorModel</CODE>. |
|
1941 |
* @throws IllegalArgumentException If this |
|
1942 |
* <CODE>ComponentColorModel</CODE> does not support the unnormalized form |
|
1943 |
* @throws UnsupportedOperationException If the transfer type of |
|
1944 |
* this <CODE>ComponentColorModel</CODE> |
|
1945 |
* is not one of the following transfer types: |
|
1946 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
1947 |
* or <CODE>DataBuffer.TYPE_INT</CODE>. |
|
1948 |
* |
|
1949 |
* @see WritableRaster#setDataElements |
|
1950 |
* @see SampleModel#setDataElements |
|
1951 |
*/ |
|
1952 |
public Object getDataElements(int[] components, int offset, Object obj) { |
|
1953 |
if (needScaleInit) { |
|
1954 |
initScale(); |
|
1955 |
} |
|
1956 |
if (noUnnorm) { |
|
1957 |
throw new |
|
1958 |
IllegalArgumentException( |
|
1959 |
"This ColorModel does not support the unnormalized form"); |
|
1960 |
} |
|
1961 |
if ((components.length-offset) < numComponents) { |
|
1962 |
throw new IllegalArgumentException("Component array too small"+ |
|
1963 |
" (should be "+numComponents); |
|
1964 |
} |
|
1965 |
switch(transferType) { |
|
1966 |
case DataBuffer.TYPE_INT: |
|
1967 |
{ |
|
1968 |
int[] pixel; |
|
1969 |
if (obj == null) { |
|
1970 |
pixel = new int[numComponents]; |
|
1971 |
} |
|
1972 |
else { |
|
1973 |
pixel = (int[]) obj; |
|
1974 |
} |
|
1975 |
System.arraycopy(components, offset, pixel, 0, |
|
1976 |
numComponents); |
|
1977 |
return pixel; |
|
1978 |
} |
|
1979 |
||
1980 |
case DataBuffer.TYPE_BYTE: |
|
1981 |
{ |
|
1982 |
byte[] pixel; |
|
1983 |
if (obj == null) { |
|
1984 |
pixel = new byte[numComponents]; |
|
1985 |
} |
|
1986 |
else { |
|
1987 |
pixel = (byte[]) obj; |
|
1988 |
} |
|
1989 |
for (int i=0; i < numComponents; i++) { |
|
1990 |
pixel[i] = (byte) (components[offset+i]&0xff); |
|
1991 |
} |
|
1992 |
return pixel; |
|
1993 |
} |
|
1994 |
||
1995 |
case DataBuffer.TYPE_USHORT: |
|
1996 |
{ |
|
1997 |
short[] pixel; |
|
1998 |
if (obj == null) { |
|
1999 |
pixel = new short[numComponents]; |
|
2000 |
} |
|
2001 |
else { |
|
2002 |
pixel = (short[]) obj; |
|
2003 |
} |
|
2004 |
for (int i=0; i < numComponents; i++) { |
|
2005 |
pixel[i] = (short) (components[offset+i]&0xffff); |
|
2006 |
} |
|
2007 |
return pixel; |
|
2008 |
} |
|
2009 |
||
2010 |
default: |
|
2011 |
throw new UnsupportedOperationException("This method has not been "+ |
|
2012 |
"implemented for transferType " + |
|
2013 |
transferType); |
|
2014 |
} |
|
2015 |
} |
|
2016 |
||
2017 |
/** |
|
2018 |
* Returns a pixel value represented as an <code>int</code> in this |
|
2019 |
* <code>ColorModel</code>, given an array of normalized color/alpha |
|
2020 |
* components. This method will throw an |
|
2021 |
* <code>IllegalArgumentException</code> if pixel values for this |
|
2022 |
* <code>ColorModel</code> are not conveniently representable as a |
|
2023 |
* single <code>int</code>. An |
|
2024 |
* <code>ArrayIndexOutOfBoundsException</code> is thrown if the |
|
2025 |
* <code>normComponents</code> array is not large enough to hold all the |
|
2026 |
* color and alpha components (starting at <code>normOffset</code>). |
|
2027 |
* @param normComponents an array of normalized color and alpha |
|
2028 |
* components |
|
2029 |
* @param normOffset the index into <code>normComponents</code> at which to |
|
2030 |
* begin retrieving the color and alpha components |
|
2031 |
* @return an <code>int</code> pixel value in this |
|
2032 |
* <code>ColorModel</code> corresponding to the specified components. |
|
2033 |
* @throws IllegalArgumentException if |
|
2034 |
* pixel values for this <code>ColorModel</code> are not |
|
2035 |
* conveniently representable as a single <code>int</code> |
|
2036 |
* @throws ArrayIndexOutOfBoundsException if |
|
2037 |
* the <code>normComponents</code> array is not large enough to |
|
2038 |
* hold all of the color and alpha components starting at |
|
2039 |
* <code>normOffset</code> |
|
2040 |
* @since 1.4 |
|
2041 |
*/ |
|
2042 |
public int getDataElement(float[] normComponents, int normOffset) { |
|
2043 |
if (numComponents > 1) { |
|
2044 |
throw new |
|
2045 |
IllegalArgumentException("More than one component per pixel"); |
|
2046 |
} |
|
2047 |
if (signed) { |
|
2048 |
throw new |
|
2049 |
IllegalArgumentException("Component value is signed"); |
|
2050 |
} |
|
2051 |
if (needScaleInit) { |
|
2052 |
initScale(); |
|
2053 |
} |
|
2054 |
Object pixel = getDataElements(normComponents, normOffset, null); |
|
2055 |
switch (transferType) { |
|
2056 |
case DataBuffer.TYPE_BYTE: |
|
2057 |
{ |
|
2058 |
byte bpixel[] = (byte[]) pixel; |
|
2059 |
return bpixel[0] & 0xff; |
|
2060 |
} |
|
2061 |
case DataBuffer.TYPE_USHORT: |
|
2062 |
{ |
|
2063 |
short[] uspixel = (short[]) pixel; |
|
2064 |
return uspixel[0] & 0xffff; |
|
2065 |
} |
|
2066 |
case DataBuffer.TYPE_INT: |
|
2067 |
{ |
|
2068 |
int[] ipixel = (int[]) pixel; |
|
2069 |
return ipixel[0]; |
|
2070 |
} |
|
2071 |
default: |
|
2072 |
throw new UnsupportedOperationException("This method has not been " |
|
2073 |
+ "implemented for transferType " + transferType); |
|
2074 |
} |
|
2075 |
} |
|
2076 |
||
2077 |
/** |
|
2078 |
* Returns a data element array representation of a pixel in this |
|
2079 |
* <code>ColorModel</code>, given an array of normalized color/alpha |
|
2080 |
* components. This array can then be passed to the |
|
2081 |
* <code>setDataElements</code> method of a <code>WritableRaster</code> |
|
2082 |
* object. An <code>ArrayIndexOutOfBoundsException</code> is thrown |
|
2083 |
* if the <code>normComponents</code> array is not large enough to hold |
|
2084 |
* all the color and alpha components (starting at |
|
2085 |
* <code>normOffset</code>). If the <code>obj</code> variable is |
|
2086 |
* <code>null</code>, a new array will be allocated. If |
|
2087 |
* <code>obj</code> is not <code>null</code>, it must be a primitive |
|
2088 |
* array of type transferType; otherwise, a |
|
2089 |
* <code>ClassCastException</code> is thrown. An |
|
2090 |
* <code>ArrayIndexOutOfBoundsException</code> is thrown if |
|
2091 |
* <code>obj</code> is not large enough to hold a pixel value for this |
|
2092 |
* <code>ColorModel</code>. |
|
2093 |
* @param normComponents an array of normalized color and alpha |
|
2094 |
* components |
|
2095 |
* @param normOffset the index into <code>normComponents</code> at which to |
|
2096 |
* begin retrieving color and alpha components |
|
2097 |
* @param obj a primitive data array to hold the returned pixel |
|
2098 |
* @return an <code>Object</code> which is a primitive data array |
|
2099 |
* representation of a pixel |
|
2100 |
* @throws ClassCastException if <code>obj</code> |
|
2101 |
* is not a primitive array of type <code>transferType</code> |
|
2102 |
* @throws ArrayIndexOutOfBoundsException if |
|
2103 |
* <code>obj</code> is not large enough to hold a pixel value |
|
2104 |
* for this <code>ColorModel</code> or the <code>normComponents</code> |
|
2105 |
* array is not large enough to hold all of the color and alpha |
|
2106 |
* components starting at <code>normOffset</code> |
|
2107 |
* @see WritableRaster#setDataElements |
|
2108 |
* @see SampleModel#setDataElements |
|
2109 |
* @since 1.4 |
|
2110 |
*/ |
|
2111 |
public Object getDataElements(float[] normComponents, int normOffset, |
|
2112 |
Object obj) { |
|
2113 |
boolean needAlpha = supportsAlpha && isAlphaPremultiplied; |
|
2114 |
float[] stdNormComponents; |
|
2115 |
if (needScaleInit) { |
|
2116 |
initScale(); |
|
2117 |
} |
|
2118 |
if (nonStdScale) { |
|
2119 |
stdNormComponents = new float[numComponents]; |
|
2120 |
for (int c = 0, nc = normOffset; c < numColorComponents; |
|
2121 |
c++, nc++) { |
|
2122 |
stdNormComponents[c] = (normComponents[nc] - compOffset[c]) * |
|
2123 |
compScale[c]; |
|
2124 |
// REMIND: need to analyze whether this |
|
2125 |
// clamping is necessary |
|
2126 |
if (stdNormComponents[c] < 0.0f) { |
|
2127 |
stdNormComponents[c] = 0.0f; |
|
2128 |
} |
|
2129 |
if (stdNormComponents[c] > 1.0f) { |
|
2130 |
stdNormComponents[c] = 1.0f; |
|
2131 |
} |
|
2132 |
} |
|
2133 |
if (supportsAlpha) { |
|
2134 |
stdNormComponents[numColorComponents] = |
|
2135 |
normComponents[numColorComponents + normOffset]; |
|
2136 |
} |
|
2137 |
normOffset = 0; |
|
2138 |
} else { |
|
2139 |
stdNormComponents = normComponents; |
|
2140 |
} |
|
2141 |
switch (transferType) { |
|
2142 |
case DataBuffer.TYPE_BYTE: |
|
2143 |
byte[] bpixel; |
|
2144 |
if (obj == null) { |
|
2145 |
bpixel = new byte[numComponents]; |
|
2146 |
} else { |
|
2147 |
bpixel = (byte[]) obj; |
|
2148 |
} |
|
2149 |
if (needAlpha) { |
|
2150 |
float alpha = |
|
2151 |
stdNormComponents[numColorComponents + normOffset]; |
|
2152 |
for (int c = 0, nc = normOffset; c < numColorComponents; |
|
2153 |
c++, nc++) { |
|
2154 |
bpixel[c] = (byte) ((stdNormComponents[nc] * alpha) * |
|
2155 |
((float) ((1 << nBits[c]) - 1)) + 0.5f); |
|
2156 |
} |
|
2157 |
bpixel[numColorComponents] = |
|
2158 |
(byte) (alpha * |
|
2159 |
((float) ((1 << nBits[numColorComponents]) - 1)) + |
|
2160 |
0.5f); |
|
2161 |
} else { |
|
2162 |
for (int c = 0, nc = normOffset; c < numComponents; |
|
2163 |
c++, nc++) { |
|
2164 |
bpixel[c] = (byte) (stdNormComponents[nc] * |
|
2165 |
((float) ((1 << nBits[c]) - 1)) + 0.5f); |
|
2166 |
} |
|
2167 |
} |
|
2168 |
return bpixel; |
|
2169 |
case DataBuffer.TYPE_USHORT: |
|
2170 |
short[] uspixel; |
|
2171 |
if (obj == null) { |
|
2172 |
uspixel = new short[numComponents]; |
|
2173 |
} else { |
|
2174 |
uspixel = (short[]) obj; |
|
2175 |
} |
|
2176 |
if (needAlpha) { |
|
2177 |
float alpha = |
|
2178 |
stdNormComponents[numColorComponents + normOffset]; |
|
2179 |
for (int c = 0, nc = normOffset; c < numColorComponents; |
|
2180 |
c++, nc++) { |
|
2181 |
uspixel[c] = (short) ((stdNormComponents[nc] * alpha) * |
|
2182 |
((float) ((1 << nBits[c]) - 1)) + |
|
2183 |
0.5f); |
|
2184 |
} |
|
2185 |
uspixel[numColorComponents] = |
|
2186 |
(short) (alpha * |
|
2187 |
((float) ((1 << nBits[numColorComponents]) - 1)) + |
|
2188 |
0.5f); |
|
2189 |
} else { |
|
2190 |
for (int c = 0, nc = normOffset; c < numComponents; |
|
2191 |
c++, nc++) { |
|
2192 |
uspixel[c] = (short) (stdNormComponents[nc] * |
|
2193 |
((float) ((1 << nBits[c]) - 1)) + |
|
2194 |
0.5f); |
|
2195 |
} |
|
2196 |
} |
|
2197 |
return uspixel; |
|
2198 |
case DataBuffer.TYPE_INT: |
|
2199 |
int[] ipixel; |
|
2200 |
if (obj == null) { |
|
2201 |
ipixel = new int[numComponents]; |
|
2202 |
} else { |
|
2203 |
ipixel = (int[]) obj; |
|
2204 |
} |
|
2205 |
if (needAlpha) { |
|
2206 |
float alpha = |
|
2207 |
stdNormComponents[numColorComponents + normOffset]; |
|
2208 |
for (int c = 0, nc = normOffset; c < numColorComponents; |
|
2209 |
c++, nc++) { |
|
2210 |
ipixel[c] = (int) ((stdNormComponents[nc] * alpha) * |
|
2211 |
((float) ((1 << nBits[c]) - 1)) + 0.5f); |
|
2212 |
} |
|
2213 |
ipixel[numColorComponents] = |
|
2214 |
(int) (alpha * |
|
2215 |
((float) ((1 << nBits[numColorComponents]) - 1)) + |
|
2216 |
0.5f); |
|
2217 |
} else { |
|
2218 |
for (int c = 0, nc = normOffset; c < numComponents; |
|
2219 |
c++, nc++) { |
|
2220 |
ipixel[c] = (int) (stdNormComponents[nc] * |
|
2221 |
((float) ((1 << nBits[c]) - 1)) + 0.5f); |
|
2222 |
} |
|
2223 |
} |
|
2224 |
return ipixel; |
|
2225 |
case DataBuffer.TYPE_SHORT: |
|
2226 |
short[] spixel; |
|
2227 |
if (obj == null) { |
|
2228 |
spixel = new short[numComponents]; |
|
2229 |
} else { |
|
2230 |
spixel = (short[]) obj; |
|
2231 |
} |
|
2232 |
if (needAlpha) { |
|
2233 |
float alpha = |
|
2234 |
stdNormComponents[numColorComponents + normOffset]; |
|
2235 |
for (int c = 0, nc = normOffset; c < numColorComponents; |
|
2236 |
c++, nc++) { |
|
2237 |
spixel[c] = (short) |
|
2238 |
(stdNormComponents[nc] * alpha * 32767.0f + 0.5f); |
|
2239 |
} |
|
2240 |
spixel[numColorComponents] = (short) (alpha * 32767.0f + 0.5f); |
|
2241 |
} else { |
|
2242 |
for (int c = 0, nc = normOffset; c < numComponents; |
|
2243 |
c++, nc++) { |
|
2244 |
spixel[c] = (short) |
|
2245 |
(stdNormComponents[nc] * 32767.0f + 0.5f); |
|
2246 |
} |
|
2247 |
} |
|
2248 |
return spixel; |
|
2249 |
case DataBuffer.TYPE_FLOAT: |
|
2250 |
float[] fpixel; |
|
2251 |
if (obj == null) { |
|
2252 |
fpixel = new float[numComponents]; |
|
2253 |
} else { |
|
2254 |
fpixel = (float[]) obj; |
|
2255 |
} |
|
2256 |
if (needAlpha) { |
|
2257 |
float alpha = normComponents[numColorComponents + normOffset]; |
|
2258 |
for (int c = 0, nc = normOffset; c < numColorComponents; |
|
2259 |
c++, nc++) { |
|
2260 |
fpixel[c] = normComponents[nc] * alpha; |
|
2261 |
} |
|
2262 |
fpixel[numColorComponents] = alpha; |
|
2263 |
} else { |
|
2264 |
for (int c = 0, nc = normOffset; c < numComponents; |
|
2265 |
c++, nc++) { |
|
2266 |
fpixel[c] = normComponents[nc]; |
|
2267 |
} |
|
2268 |
} |
|
2269 |
return fpixel; |
|
2270 |
case DataBuffer.TYPE_DOUBLE: |
|
2271 |
double[] dpixel; |
|
2272 |
if (obj == null) { |
|
2273 |
dpixel = new double[numComponents]; |
|
2274 |
} else { |
|
2275 |
dpixel = (double[]) obj; |
|
2276 |
} |
|
2277 |
if (needAlpha) { |
|
2278 |
double alpha = |
|
2279 |
(double) (normComponents[numColorComponents + normOffset]); |
|
2280 |
for (int c = 0, nc = normOffset; c < numColorComponents; |
|
2281 |
c++, nc++) { |
|
2282 |
dpixel[c] = normComponents[nc] * alpha; |
|
2283 |
} |
|
2284 |
dpixel[numColorComponents] = alpha; |
|
2285 |
} else { |
|
2286 |
for (int c = 0, nc = normOffset; c < numComponents; |
|
2287 |
c++, nc++) { |
|
2288 |
dpixel[c] = (double) normComponents[nc]; |
|
2289 |
} |
|
2290 |
} |
|
2291 |
return dpixel; |
|
2292 |
default: |
|
2293 |
throw new UnsupportedOperationException("This method has not been "+ |
|
2294 |
"implemented for transferType " + |
|
2295 |
transferType); |
|
2296 |
} |
|
2297 |
} |
|
2298 |
||
2299 |
/** |
|
2300 |
* Returns an array of all of the color/alpha components in normalized |
|
2301 |
* form, given a pixel in this <code>ColorModel</code>. The pixel |
|
2302 |
* value is specified by an array of data elements of type transferType |
|
2303 |
* passed in as an object reference. If pixel is not a primitive array |
|
2304 |
* of type transferType, a <code>ClassCastException</code> is thrown. |
|
2305 |
* An <code>ArrayIndexOutOfBoundsException</code> is thrown if |
|
2306 |
* <code>pixel</code> is not large enough to hold a pixel value for this |
|
2307 |
* <code>ColorModel</code>. |
|
2308 |
* Normalized components are float values between a per component minimum |
|
2309 |
* and maximum specified by the <code>ColorSpace</code> object for this |
|
2310 |
* <code>ColorModel</code>. If the |
|
2311 |
* <code>normComponents</code> array is <code>null</code>, a new array |
|
2312 |
* will be allocated. The <code>normComponents</code> array |
|
2313 |
* will be returned. Color/alpha components are stored in the |
|
2314 |
* <code>normComponents</code> array starting at |
|
2315 |
* <code>normOffset</code> (even if the array is allocated by this |
|
2316 |
* method). An <code>ArrayIndexOutOfBoundsException</code> is thrown |
|
2317 |
* if the <code>normComponents</code> array is not <code>null</code> |
|
2318 |
* and is not large enough to hold all the color and alpha components |
|
2319 |
* (starting at <code>normOffset</code>). |
|
2320 |
* <p> |
|
21278 | 2321 |
* This method must be overridden by a subclass if that subclass |
2 | 2322 |
* is designed to translate pixel sample values to color component values |
2323 |
* in a non-default way. The default translations implemented by this |
|
2324 |
* class is described in the class comments. Any subclass implementing |
|
2325 |
* a non-default translation must follow the constraints on allowable |
|
2326 |
* translations defined there. |
|
2327 |
* @param pixel the specified pixel |
|
2328 |
* @param normComponents an array to receive the normalized components |
|
2329 |
* @param normOffset the offset into the <code>normComponents</code> |
|
2330 |
* array at which to start storing normalized components |
|
2331 |
* @return an array containing normalized color and alpha |
|
2332 |
* components. |
|
2333 |
* @throws ClassCastException if <code>pixel</code> is not a primitive |
|
2334 |
* array of type transferType |
|
2335 |
* @throws ArrayIndexOutOfBoundsException if |
|
2336 |
* <code>normComponents</code> is not large enough to hold all |
|
2337 |
* color and alpha components starting at <code>normOffset</code> |
|
2338 |
* @throws ArrayIndexOutOfBoundsException if |
|
2339 |
* <code>pixel</code> is not large enough to hold a pixel |
|
2340 |
* value for this <code>ColorModel</code>. |
|
2341 |
* @since 1.4 |
|
2342 |
*/ |
|
2343 |
public float[] getNormalizedComponents(Object pixel, |
|
2344 |
float[] normComponents, |
|
2345 |
int normOffset) { |
|
2346 |
if (normComponents == null) { |
|
2347 |
normComponents = new float[numComponents+normOffset]; |
|
2348 |
} |
|
2349 |
switch (transferType) { |
|
2350 |
case DataBuffer.TYPE_BYTE: |
|
2351 |
byte[] bpixel = (byte[]) pixel; |
|
2352 |
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { |
|
2353 |
normComponents[nc] = ((float) (bpixel[c] & 0xff)) / |
|
2354 |
((float) ((1 << nBits[c]) - 1)); |
|
2355 |
} |
|
2356 |
break; |
|
2357 |
case DataBuffer.TYPE_USHORT: |
|
2358 |
short[] uspixel = (short[]) pixel; |
|
2359 |
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { |
|
2360 |
normComponents[nc] = ((float) (uspixel[c] & 0xffff)) / |
|
2361 |
((float) ((1 << nBits[c]) - 1)); |
|
2362 |
} |
|
2363 |
break; |
|
2364 |
case DataBuffer.TYPE_INT: |
|
2365 |
int[] ipixel = (int[]) pixel; |
|
2366 |
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { |
|
2367 |
normComponents[nc] = ((float) ipixel[c]) / |
|
2368 |
((float) ((1 << nBits[c]) - 1)); |
|
2369 |
} |
|
2370 |
break; |
|
2371 |
case DataBuffer.TYPE_SHORT: |
|
2372 |
short[] spixel = (short[]) pixel; |
|
2373 |
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { |
|
2374 |
normComponents[nc] = ((float) spixel[c]) / 32767.0f; |
|
2375 |
} |
|
2376 |
break; |
|
2377 |
case DataBuffer.TYPE_FLOAT: |
|
2378 |
float[] fpixel = (float[]) pixel; |
|
2379 |
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { |
|
2380 |
normComponents[nc] = fpixel[c]; |
|
2381 |
} |
|
2382 |
break; |
|
2383 |
case DataBuffer.TYPE_DOUBLE: |
|
2384 |
double[] dpixel = (double[]) pixel; |
|
2385 |
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { |
|
2386 |
normComponents[nc] = (float) dpixel[c]; |
|
2387 |
} |
|
2388 |
break; |
|
2389 |
default: |
|
2390 |
throw new UnsupportedOperationException("This method has not been "+ |
|
2391 |
"implemented for transferType " + |
|
2392 |
transferType); |
|
2393 |
} |
|
2394 |
||
2395 |
if (supportsAlpha && isAlphaPremultiplied) { |
|
2396 |
float alpha = normComponents[numColorComponents + normOffset]; |
|
2397 |
if (alpha != 0.0f) { |
|
2398 |
float invAlpha = 1.0f / alpha; |
|
2399 |
for (int c = normOffset; c < numColorComponents + normOffset; |
|
2400 |
c++) { |
|
2401 |
normComponents[c] *= invAlpha; |
|
2402 |
} |
|
2403 |
} |
|
2404 |
} |
|
2405 |
if (min != null) { |
|
2406 |
// Normally (i.e. when this class is not subclassed to override |
|
2407 |
// this method), the test (min != null) will be equivalent to |
|
2408 |
// the test (nonStdScale). However, there is an unlikely, but |
|
2409 |
// possible case, in which this method is overridden, nonStdScale |
|
2410 |
// is set true by initScale(), the subclass method for some |
|
2411 |
// reason calls this superclass method, but the min and |
|
2412 |
// diffMinMax arrays were never initialized by setupLUTs(). In |
|
2413 |
// that case, the right thing to do is follow the intended |
|
2414 |
// semantics of this method, and rescale the color components |
|
2415 |
// only if the ColorSpace min/max were detected to be other |
|
2416 |
// than 0.0/1.0 by setupLUTs(). Note that this implies the |
|
2417 |
// transferType is byte, ushort, int, or short - i.e. components |
|
2418 |
// derived from float and double pixel data are never rescaled. |
|
2419 |
for (int c = 0; c < numColorComponents; c++) { |
|
2420 |
normComponents[c + normOffset] = min[c] + |
|
2421 |
diffMinMax[c] * normComponents[c + normOffset]; |
|
2422 |
} |
|
2423 |
} |
|
2424 |
return normComponents; |
|
2425 |
} |
|
2426 |
||
2427 |
/** |
|
2428 |
* Forces the raster data to match the state specified in the |
|
2429 |
* <CODE>isAlphaPremultiplied</CODE> variable, assuming the data |
|
2430 |
* is currently correctly described by this <CODE>ColorModel</CODE>. |
|
2431 |
* It may multiply or divide the color raster data by alpha, or |
|
2432 |
* do nothing if the data is in the correct state. If the data needs |
|
2433 |
* to be coerced, this method also returns an instance of |
|
2434 |
* this <CODE>ColorModel</CODE> with |
|
2435 |
* the <CODE>isAlphaPremultiplied</CODE> flag set appropriately. |
|
2436 |
* Since <code>ColorModel</code> can be subclassed, subclasses inherit |
|
2437 |
* the implementation of this method and if they don't override it |
|
2438 |
* then they throw an exception if they use an unsupported |
|
2439 |
* <code>transferType</code>. |
|
2440 |
* |
|
2441 |
* @throws NullPointerException if <code>raster</code> is |
|
2442 |
* <code>null</code> and data coercion is required. |
|
2443 |
* @throws UnsupportedOperationException if the transfer type of |
|
2444 |
* this <CODE>ComponentColorModel</CODE> |
|
2445 |
* is not one of the supported transfer types: |
|
2446 |
* <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, |
|
2447 |
* <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, |
|
2448 |
* <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. |
|
2449 |
*/ |
|
2450 |
public ColorModel coerceData (WritableRaster raster, |
|
2451 |
boolean isAlphaPremultiplied) { |
|
2452 |
if ((supportsAlpha == false) || |
|
2453 |
(this.isAlphaPremultiplied == isAlphaPremultiplied)) |
|
2454 |
{ |
|
2455 |
// Nothing to do |
|
2456 |
return this; |
|
2457 |
} |
|
2458 |
||
2459 |
int w = raster.getWidth(); |
|
2460 |
int h = raster.getHeight(); |
|
2461 |
int aIdx = raster.getNumBands() - 1; |
|
2462 |
float normAlpha; |
|
2463 |
int rminX = raster.getMinX(); |
|
2464 |
int rY = raster.getMinY(); |
|
2465 |
int rX; |
|
2466 |
if (isAlphaPremultiplied) { |
|
2467 |
switch (transferType) { |
|
2468 |
case DataBuffer.TYPE_BYTE: { |
|
2469 |
byte pixel[] = null; |
|
2470 |
byte zpixel[] = null; |
|
2471 |
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); |
|
2472 |
for (int y = 0; y < h; y++, rY++) { |
|
2473 |
rX = rminX; |
|
2474 |
for (int x = 0; x < w; x++, rX++) { |
|
2475 |
pixel = (byte[])raster.getDataElements(rX, rY, |
|
2476 |
pixel); |
|
2477 |
normAlpha = (pixel[aIdx] & 0xff) * alphaScale; |
|
2478 |
if (normAlpha != 0.0f) { |
|
2479 |
for (int c=0; c < aIdx; c++) { |
|
2480 |
pixel[c] = (byte)((pixel[c] & 0xff) * |
|
2481 |
normAlpha + 0.5f); |
|
2482 |
} |
|
2483 |
raster.setDataElements(rX, rY, pixel); |
|
2484 |
} else { |
|
2485 |
if (zpixel == null) { |
|
2486 |
zpixel = new byte[numComponents]; |
|
2487 |
java.util.Arrays.fill(zpixel, (byte) 0); |
|
2488 |
} |
|
2489 |
raster.setDataElements(rX, rY, zpixel); |
|
2490 |
} |
|
2491 |
} |
|
2492 |
} |
|
2493 |
} |
|
2494 |
break; |
|
2495 |
case DataBuffer.TYPE_USHORT: { |
|
2496 |
short pixel[] = null; |
|
2497 |
short zpixel[] = null; |
|
2498 |
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); |
|
2499 |
for (int y = 0; y < h; y++, rY++) { |
|
2500 |
rX = rminX; |
|
2501 |
for (int x = 0; x < w; x++, rX++) { |
|
2502 |
pixel = (short[])raster.getDataElements(rX, rY, |
|
2503 |
pixel); |
|
2504 |
normAlpha = (pixel[aIdx] & 0xffff) * alphaScale; |
|
2505 |
if (normAlpha != 0.0f) { |
|
2506 |
for (int c=0; c < aIdx; c++) { |
|
2507 |
pixel[c] = (short) |
|
2508 |
((pixel[c] & 0xffff) * normAlpha + |
|
2509 |
0.5f); |
|
2510 |
} |
|
2511 |
raster.setDataElements(rX, rY, pixel); |
|
2512 |
} else { |
|
2513 |
if (zpixel == null) { |
|
2514 |
zpixel = new short[numComponents]; |
|
2515 |
java.util.Arrays.fill(zpixel, (short) 0); |
|
2516 |
} |
|
2517 |
raster.setDataElements(rX, rY, zpixel); |
|
2518 |
} |
|
2519 |
} |
|
2520 |
} |
|
2521 |
} |
|
2522 |
break; |
|
2523 |
case DataBuffer.TYPE_INT: { |
|
2524 |
int pixel[] = null; |
|
2525 |
int zpixel[] = null; |
|
2526 |
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); |
|
2527 |
for (int y = 0; y < h; y++, rY++) { |
|
2528 |
rX = rminX; |
|
2529 |
for (int x = 0; x < w; x++, rX++) { |
|
2530 |
pixel = (int[])raster.getDataElements(rX, rY, |
|
2531 |
pixel); |
|
2532 |
normAlpha = pixel[aIdx] * alphaScale; |
|
2533 |
if (normAlpha != 0.0f) { |
|
2534 |
for (int c=0; c < aIdx; c++) { |
|
2535 |
pixel[c] = (int) (pixel[c] * normAlpha + |
|
2536 |
0.5f); |
|
2537 |
} |
|
2538 |
raster.setDataElements(rX, rY, pixel); |
|
2539 |
} else { |
|
2540 |
if (zpixel == null) { |
|
2541 |
zpixel = new int[numComponents]; |
|
2542 |
java.util.Arrays.fill(zpixel, 0); |
|
2543 |
} |
|
2544 |
raster.setDataElements(rX, rY, zpixel); |
|
2545 |
} |
|
2546 |
} |
|
2547 |
} |
|
2548 |
} |
|
2549 |
break; |
|
2550 |
case DataBuffer.TYPE_SHORT: { |
|
2551 |
short pixel[] = null; |
|
2552 |
short zpixel[] = null; |
|
2553 |
float alphaScale = 1.0f / 32767.0f; |
|
2554 |
for (int y = 0; y < h; y++, rY++) { |
|
2555 |
rX = rminX; |
|
2556 |
for (int x = 0; x < w; x++, rX++) { |
|
2557 |
pixel = (short[]) raster.getDataElements(rX, rY, |
|
2558 |
pixel); |
|
2559 |
normAlpha = pixel[aIdx] * alphaScale; |
|
2560 |
if (normAlpha != 0.0f) { |
|
2561 |
for (int c=0; c < aIdx; c++) { |
|
2562 |
pixel[c] = (short) (pixel[c] * normAlpha + |
|
2563 |
0.5f); |
|
2564 |
} |
|
2565 |
raster.setDataElements(rX, rY, pixel); |
|
2566 |
} else { |
|
2567 |
if (zpixel == null) { |
|
2568 |
zpixel = new short[numComponents]; |
|
2569 |
java.util.Arrays.fill(zpixel, (short) 0); |
|
2570 |
} |
|
2571 |
raster.setDataElements(rX, rY, zpixel); |
|
2572 |
} |
|
2573 |
} |
|
2574 |
} |
|
2575 |
} |
|
2576 |
break; |
|
2577 |
case DataBuffer.TYPE_FLOAT: { |
|
2578 |
float pixel[] = null; |
|
2579 |
float zpixel[] = null; |
|
2580 |
for (int y = 0; y < h; y++, rY++) { |
|
2581 |
rX = rminX; |
|
2582 |
for (int x = 0; x < w; x++, rX++) { |
|
2583 |
pixel = (float[]) raster.getDataElements(rX, rY, |
|
2584 |
pixel); |
|
2585 |
normAlpha = pixel[aIdx]; |
|
2586 |
if (normAlpha != 0.0f) { |
|
2587 |
for (int c=0; c < aIdx; c++) { |
|
2588 |
pixel[c] *= normAlpha; |
|
2589 |
} |
|
2590 |
raster.setDataElements(rX, rY, pixel); |
|
2591 |
} else { |
|
2592 |
if (zpixel == null) { |
|
2593 |
zpixel = new float[numComponents]; |
|
2594 |
java.util.Arrays.fill(zpixel, 0.0f); |
|
2595 |
} |
|
2596 |
raster.setDataElements(rX, rY, zpixel); |
|
2597 |
} |
|
2598 |
} |
|
2599 |
} |
|
2600 |
} |
|
2601 |
break; |
|
2602 |
case DataBuffer.TYPE_DOUBLE: { |
|
2603 |
double pixel[] = null; |
|
2604 |
double zpixel[] = null; |
|
2605 |
for (int y = 0; y < h; y++, rY++) { |
|
2606 |
rX = rminX; |
|
2607 |
for (int x = 0; x < w; x++, rX++) { |
|
2608 |
pixel = (double[]) raster.getDataElements(rX, rY, |
|
2609 |
pixel); |
|
2610 |
double dnormAlpha = pixel[aIdx]; |
|
2611 |
if (dnormAlpha != 0.0) { |
|
2612 |
for (int c=0; c < aIdx; c++) { |
|
2613 |
pixel[c] *= dnormAlpha; |
|
2614 |
} |
|
2615 |
raster.setDataElements(rX, rY, pixel); |
|
2616 |
} else { |
|
2617 |
if (zpixel == null) { |
|
2618 |
zpixel = new double[numComponents]; |
|
2619 |
java.util.Arrays.fill(zpixel, 0.0); |
|
2620 |
} |
|
2621 |
raster.setDataElements(rX, rY, zpixel); |
|
2622 |
} |
|
2623 |
} |
|
2624 |
} |
|
2625 |
} |
|
2626 |
break; |
|
2627 |
default: |
|
2628 |
throw new UnsupportedOperationException("This method has not been "+ |
|
2629 |
"implemented for transferType " + transferType); |
|
2630 |
} |
|
2631 |
} |
|
2632 |
else { |
|
2633 |
// We are premultiplied and want to divide it out |
|
2634 |
switch (transferType) { |
|
2635 |
case DataBuffer.TYPE_BYTE: { |
|
2636 |
byte pixel[] = null; |
|
2637 |
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); |
|
2638 |
for (int y = 0; y < h; y++, rY++) { |
|
2639 |
rX = rminX; |
|
2640 |
for (int x = 0; x < w; x++, rX++) { |
|
2641 |
pixel = (byte[])raster.getDataElements(rX, rY, |
|
2642 |
pixel); |
|
2643 |
normAlpha = (pixel[aIdx] & 0xff) * alphaScale; |
|
2644 |
if (normAlpha != 0.0f) { |
|
2645 |
float invAlpha = 1.0f / normAlpha; |
|
2646 |
for (int c=0; c < aIdx; c++) { |
|
2647 |
pixel[c] = (byte) |
|
2648 |
((pixel[c] & 0xff) * invAlpha + 0.5f); |
|
2649 |
} |
|
2650 |
raster.setDataElements(rX, rY, pixel); |
|
2651 |
} |
|
2652 |
} |
|
2653 |
} |
|
2654 |
} |
|
2655 |
break; |
|
2656 |
case DataBuffer.TYPE_USHORT: { |
|
2657 |
short pixel[] = null; |
|
2658 |
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); |
|
2659 |
for (int y = 0; y < h; y++, rY++) { |
|
2660 |
rX = rminX; |
|
2661 |
for (int x = 0; x < w; x++, rX++) { |
|
2662 |
pixel = (short[])raster.getDataElements(rX, rY, |
|
2663 |
pixel); |
|
2664 |
normAlpha = (pixel[aIdx] & 0xffff) * alphaScale; |
|
2665 |
if (normAlpha != 0.0f) { |
|
2666 |
float invAlpha = 1.0f / normAlpha; |
|
2667 |
for (int c=0; c < aIdx; c++) { |
|
2668 |
pixel[c] = (short) |
|
2669 |
((pixel[c] & 0xffff) * invAlpha + 0.5f); |
|
2670 |
} |
|
2671 |
raster.setDataElements(rX, rY, pixel); |
|
2672 |
} |
|
2673 |
} |
|
2674 |
} |
|
2675 |
} |
|
2676 |
break; |
|
2677 |
case DataBuffer.TYPE_INT: { |
|
2678 |
int pixel[] = null; |
|
2679 |
float alphaScale = 1.0f / ((float) ((1<<nBits[aIdx]) - 1)); |
|
2680 |
for (int y = 0; y < h; y++, rY++) { |
|
2681 |
rX = rminX; |
|
2682 |
for (int x = 0; x < w; x++, rX++) { |
|
2683 |
pixel = (int[])raster.getDataElements(rX, rY, |
|
2684 |
pixel); |
|
2685 |
normAlpha = pixel[aIdx] * alphaScale; |
|
2686 |
if (normAlpha != 0.0f) { |
|
2687 |
float invAlpha = 1.0f / normAlpha; |
|
2688 |
for (int c=0; c < aIdx; c++) { |
|
2689 |
pixel[c] = (int) |
|
2690 |
(pixel[c] * invAlpha + 0.5f); |
|
2691 |
} |
|
2692 |
raster.setDataElements(rX, rY, pixel); |
|
2693 |
} |
|
2694 |
} |
|
2695 |
} |
|
2696 |
} |
|
2697 |
break; |
|
2698 |
case DataBuffer.TYPE_SHORT: { |
|
2699 |
short pixel[] = null; |
|
2700 |
float alphaScale = 1.0f / 32767.0f; |
|
2701 |
for (int y = 0; y < h; y++, rY++) { |
|
2702 |
rX = rminX; |
|
2703 |
for (int x = 0; x < w; x++, rX++) { |
|
2704 |
pixel = (short[])raster.getDataElements(rX, rY, |
|
2705 |
pixel); |
|
2706 |
normAlpha = pixel[aIdx] * alphaScale; |
|
2707 |
if (normAlpha != 0.0f) { |
|
2708 |
float invAlpha = 1.0f / normAlpha; |
|
2709 |
for (int c=0; c < aIdx; c++) { |
|
2710 |
pixel[c] = (short) |
|
2711 |
(pixel[c] * invAlpha + 0.5f); |
|
2712 |
} |
|
2713 |
raster.setDataElements(rX, rY, pixel); |
|
2714 |
} |
|
2715 |
} |
|
2716 |
} |
|
2717 |
} |
|
2718 |
break; |
|
2719 |
case DataBuffer.TYPE_FLOAT: { |
|
2720 |
float pixel[] = null; |
|
2721 |
for (int y = 0; y < h; y++, rY++) { |
|
2722 |
rX = rminX; |
|
2723 |
for (int x = 0; x < w; x++, rX++) { |
|
2724 |
pixel = (float[])raster.getDataElements(rX, rY, |
|
2725 |
pixel); |
|
2726 |
normAlpha = pixel[aIdx]; |
|
2727 |
if (normAlpha != 0.0f) { |
|
2728 |
float invAlpha = 1.0f / normAlpha; |
|
2729 |
for (int c=0; c < aIdx; c++) { |
|
2730 |
pixel[c] *= invAlpha; |
|
2731 |
} |
|
2732 |
raster.setDataElements(rX, rY, pixel); |
|
2733 |
} |
|
2734 |
} |
|
2735 |
} |
|
2736 |
} |
|
2737 |
break; |
|
2738 |
case DataBuffer.TYPE_DOUBLE: { |
|
2739 |
double pixel[] = null; |
|
2740 |
for (int y = 0; y < h; y++, rY++) { |
|
2741 |
rX = rminX; |
|
2742 |
for (int x = 0; x < w; x++, rX++) { |
|
2743 |
pixel = (double[])raster.getDataElements(rX, rY, |
|
2744 |
pixel); |
|
2745 |
double dnormAlpha = pixel[aIdx]; |
|
2746 |
if (dnormAlpha != 0.0) { |
|
2747 |
double invAlpha = 1.0 / dnormAlpha; |
|
2748 |
for (int c=0; c < aIdx; c++) { |
|
2749 |
pixel[c] *= invAlpha; |
|
2750 |
} |
|
2751 |
raster.setDataElements(rX, rY, pixel); |
|
2752 |
} |
|
2753 |
} |
|
2754 |
} |
|
2755 |
} |
|
2756 |
break; |
|
2757 |
default: |
|
2758 |
throw new UnsupportedOperationException("This method has not been "+ |
|
2759 |
"implemented for transferType " + transferType); |
|
2760 |
} |
|
2761 |
} |
|
2762 |
||
2763 |
// Return a new color model |
|
2764 |
if (!signed) { |
|
2765 |
return new ComponentColorModel(colorSpace, nBits, supportsAlpha, |
|
2766 |
isAlphaPremultiplied, transparency, |
|
2767 |
transferType); |
|
2768 |
} else { |
|
2769 |
return new ComponentColorModel(colorSpace, supportsAlpha, |
|
2770 |
isAlphaPremultiplied, transparency, |
|
2771 |
transferType); |
|
2772 |
} |
|
2773 |
||
2774 |
} |
|
2775 |
||
2776 |
/** |
|
2777 |
* Returns true if <CODE>raster</CODE> is compatible with this |
|
2778 |
* <CODE>ColorModel</CODE>; false if it is not. |
|
2779 |
* |
|
2780 |
* @param raster The <CODE>Raster</CODE> object to test for compatibility. |
|
2781 |
* |
|
2782 |
* @return <CODE>true</CODE> if <CODE>raster</CODE> is compatible with this |
|
2783 |
* <CODE>ColorModel</CODE>, <CODE>false</CODE> if it is not. |
|
2784 |
*/ |
|
2785 |
public boolean isCompatibleRaster(Raster raster) { |
|
2786 |
||
2787 |
SampleModel sm = raster.getSampleModel(); |
|
2788 |
||
2789 |
if (sm instanceof ComponentSampleModel) { |
|
2790 |
if (sm.getNumBands() != getNumComponents()) { |
|
2791 |
return false; |
|
2792 |
} |
|
2793 |
for (int i=0; i<nBits.length; i++) { |
|
2794 |
if (sm.getSampleSize(i) < nBits[i]) { |
|
2795 |
return false; |
|
2796 |
} |
|
2797 |
} |
|
2798 |
return (raster.getTransferType() == transferType); |
|
2799 |
} |
|
2800 |
else { |
|
2801 |
return false; |
|
2802 |
} |
|
2803 |
} |
|
2804 |
||
2805 |
/** |
|
2806 |
* Creates a <CODE>WritableRaster</CODE> with the specified width and height, |
|
2807 |
* that has a data layout (<CODE>SampleModel</CODE>) compatible with |
|
2808 |
* this <CODE>ColorModel</CODE>. |
|
2809 |
* |
|
2810 |
* @param w The width of the <CODE>WritableRaster</CODE> you want to create. |
|
2811 |
* @param h The height of the <CODE>WritableRaster</CODE> you want to create. |
|
2812 |
* |
|
2813 |
* @return A <CODE>WritableRaster</CODE> that is compatible with |
|
2814 |
* this <CODE>ColorModel</CODE>. |
|
2815 |
* @see WritableRaster |
|
2816 |
* @see SampleModel |
|
2817 |
*/ |
|
2818 |
public WritableRaster createCompatibleWritableRaster (int w, int h) { |
|
2819 |
int dataSize = w*h*numComponents; |
|
2820 |
WritableRaster raster = null; |
|
2821 |
||
2822 |
switch (transferType) { |
|
2823 |
case DataBuffer.TYPE_BYTE: |
|
2824 |
case DataBuffer.TYPE_USHORT: |
|
2825 |
raster = Raster.createInterleavedRaster(transferType, |
|
2826 |
w, h, |
|
2827 |
numComponents, null); |
|
2828 |
break; |
|
2829 |
default: |
|
2830 |
SampleModel sm = createCompatibleSampleModel(w, h); |
|
2831 |
DataBuffer db = sm.createDataBuffer(); |
|
2832 |
raster = Raster.createWritableRaster(sm, db, null); |
|
2833 |
} |
|
2834 |
||
2835 |
return raster; |
|
2836 |
} |
|
2837 |
||
2838 |
/** |
|
2839 |
* Creates a <CODE>SampleModel</CODE> with the specified width and height, |
|
2840 |
* that has a data layout compatible with this <CODE>ColorModel</CODE>. |
|
2841 |
* |
|
2842 |
* @param w The width of the <CODE>SampleModel</CODE> you want to create. |
|
2843 |
* @param h The height of the <CODE>SampleModel</CODE> you want to create. |
|
2844 |
* |
|
2845 |
* @return A <CODE>SampleModel</CODE> that is compatible with this |
|
2846 |
* <CODE>ColorModel</CODE>. |
|
2847 |
* |
|
2848 |
* @see SampleModel |
|
2849 |
*/ |
|
2850 |
public SampleModel createCompatibleSampleModel(int w, int h) { |
|
2851 |
int[] bandOffsets = new int[numComponents]; |
|
2852 |
for (int i=0; i < numComponents; i++) { |
|
2853 |
bandOffsets[i] = i; |
|
2854 |
} |
|
2855 |
switch (transferType) { |
|
2856 |
case DataBuffer.TYPE_BYTE: |
|
2857 |
case DataBuffer.TYPE_USHORT: |
|
2858 |
return new PixelInterleavedSampleModel(transferType, w, h, |
|
2859 |
numComponents, |
|
2860 |
w*numComponents, |
|
2861 |
bandOffsets); |
|
2862 |
default: |
|
2863 |
return new ComponentSampleModel(transferType, w, h, |
|
2864 |
numComponents, |
|
2865 |
w*numComponents, |
|
2866 |
bandOffsets); |
|
2867 |
} |
|
2868 |
} |
|
2869 |
||
2870 |
/** |
|
2871 |
* Checks whether or not the specified <CODE>SampleModel</CODE> |
|
2872 |
* is compatible with this <CODE>ColorModel</CODE>. |
|
2873 |
* |
|
2874 |
* @param sm The <CODE>SampleModel</CODE> to test for compatibility. |
|
2875 |
* |
|
2876 |
* @return <CODE>true</CODE> if the <CODE>SampleModel</CODE> is |
|
2877 |
* compatible with this <CODE>ColorModel</CODE>, <CODE>false</CODE> |
|
2878 |
* if it is not. |
|
2879 |
* |
|
2880 |
* @see SampleModel |
|
2881 |
*/ |
|
2882 |
public boolean isCompatibleSampleModel(SampleModel sm) { |
|
2883 |
if (!(sm instanceof ComponentSampleModel)) { |
|
2884 |
return false; |
|
2885 |
} |
|
2886 |
||
2887 |
// Must have the same number of components |
|
2888 |
if (numComponents != sm.getNumBands()) { |
|
2889 |
return false; |
|
2890 |
} |
|
2891 |
||
2892 |
if (sm.getTransferType() != transferType) { |
|
2893 |
return false; |
|
2894 |
} |
|
2895 |
||
2896 |
return true; |
|
2897 |
} |
|
2898 |
||
2899 |
/** |
|
2900 |
* Returns a <CODE>Raster</CODE> representing the alpha channel of an image, |
|
2901 |
* extracted from the input <CODE>Raster</CODE>. |
|
2902 |
* This method assumes that <CODE>Raster</CODE> objects associated with |
|
2903 |
* this <CODE>ColorModel</CODE> store the alpha band, if present, as |
|
2904 |
* the last band of image data. Returns null if there is no separate spatial |
|
2905 |
* alpha channel associated with this <CODE>ColorModel</CODE>. |
|
2906 |
* This method creates a new <CODE>Raster</CODE>, but will share the data |
|
2907 |
* array. |
|
2908 |
* |
|
2909 |
* @param raster The <CODE>WritableRaster</CODE> from which to extract the |
|
2910 |
* alpha channel. |
|
2911 |
* |
|
2912 |
* @return A <CODE>WritableRaster</CODE> containing the image's alpha channel. |
|
2913 |
* |
|
2914 |
*/ |
|
2915 |
public WritableRaster getAlphaRaster(WritableRaster raster) { |
|
2916 |
if (hasAlpha() == false) { |
|
2917 |
return null; |
|
2918 |
} |
|
2919 |
||
2920 |
int x = raster.getMinX(); |
|
2921 |
int y = raster.getMinY(); |
|
2922 |
int[] band = new int[1]; |
|
2923 |
band[0] = raster.getNumBands() - 1; |
|
2924 |
return raster.createWritableChild(x, y, raster.getWidth(), |
|
2925 |
raster.getHeight(), x, y, |
|
2926 |
band); |
|
2927 |
} |
|
2928 |
||
2929 |
/** |
|
2930 |
* Compares this color model with another for equality. |
|
2931 |
* |
|
2932 |
* @param obj The object to compare with this color model. |
|
2933 |
* @return <CODE>true</CODE> if the color model objects are equal, |
|
2934 |
* <CODE>false</CODE> if they are not. |
|
2935 |
*/ |
|
2936 |
public boolean equals(Object obj) { |
|
2937 |
if (!super.equals(obj)) { |
|
2938 |
return false; |
|
2939 |
} |
|
2940 |
||
2941 |
if (obj.getClass() != getClass()) { |
|
2942 |
return false; |
|
2943 |
} |
|
2944 |
||
2945 |
return true; |
|
2946 |
} |
|
2947 |
||
2948 |
} |