History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/image (123 of 18352 files). Show all

Unified · Split

123 files
  1. java/pkg/java/awt/image/AffineTransformOp.class +0 −0
  2. java/pkg/java/awt/image/AffineTransformOp.java +560 −0
  3. java/pkg/java/awt/image/AreaAveragingScaleFilter.class +0 −0
  4. java/pkg/java/awt/image/AreaAveragingScaleFilter.java +281 −0
  5. java/pkg/java/awt/image/BandCombineOp.class +0 −0
  6. java/pkg/java/awt/image/BandCombineOp.java +289 −0
  7. java/pkg/java/awt/image/BandedSampleModel.class +0 −0
  8. java/pkg/java/awt/image/BandedSampleModel.java +849 −0
  9. java/pkg/java/awt/image/BufferStrategy.class +0 −0
  10. java/pkg/java/awt/image/BufferStrategy.java +205 −0
  11. java/pkg/java/awt/image/BufferedImage.class +0 −0
  12. java/pkg/java/awt/image/BufferedImage.java +1609 −0
  13. java/pkg/java/awt/image/BufferedImageFilter.class +0 −0
  14. java/pkg/java/awt/image/BufferedImageFilter.java +417 −0
  15. java/pkg/java/awt/image/BufferedImageOp.class +0 −0
  16. java/pkg/java/awt/image/BufferedImageOp.java +136 −0
  17. java/pkg/java/awt/image/ByteLookupTable.class +0 −0
  18. java/pkg/java/awt/image/ByteLookupTable.java +210 −0
  19. java/pkg/java/awt/image/ColorConvertOp.class +0 −0
  20. java/pkg/java/awt/image/ColorConvertOp.java +1109 −0
  21. java/pkg/java/awt/image/ColorModel.class +0 −0
  22. java/pkg/java/awt/image/ColorModel.java +1959 −0
  23. java/pkg/java/awt/image/ComponentColorModel.class +0 −0
  24. java/pkg/java/awt/image/ComponentColorModel.java +2948 −0
  25. java/pkg/java/awt/image/ComponentSampleModel.class +0 −0
  26. java/pkg/java/awt/image/ComponentSampleModel.java +1212 −0
  27. java/pkg/java/awt/image/ConvolveOp.class +0 −0
  28. java/pkg/java/awt/image/ConvolveOp.java +347 −0
  29. java/pkg/java/awt/image/CropImageFilter.class +0 −0
  30. java/pkg/java/awt/image/CropImageFilter.java +193 −0
  31. java/pkg/java/awt/image/DataBuffer$1.class +0 −0
  32. java/pkg/java/awt/image/DataBuffer.class +0 −0
  33. java/pkg/java/awt/image/DataBuffer.java +541 −0
  34. java/pkg/java/awt/image/DataBufferByte.class +0 −0
  35. java/pkg/java/awt/image/DataBufferByte.java +286 −0
  36. java/pkg/java/awt/image/DataBufferDouble.class +0 −0
  37. java/pkg/java/awt/image/DataBufferDouble.java +403 −0
  38. java/pkg/java/awt/image/DataBufferFloat.class +0 −0
  39. java/pkg/java/awt/image/DataBufferFloat.java +406 −0
  40. java/pkg/java/awt/image/DataBufferInt.class +0 −0
  41. java/pkg/java/awt/image/DataBufferInt.java +284 −0
  42. java/pkg/java/awt/image/DataBufferShort.class +0 −0
  43. java/pkg/java/awt/image/DataBufferShort.java +283 −0
  44. java/pkg/java/awt/image/DataBufferUShort.class +0 −0
  45. java/pkg/java/awt/image/DataBufferUShort.java +318 −0
  46. java/pkg/java/awt/image/DirectColorModel.class +0 −0
  47. java/pkg/java/awt/image/DirectColorModel.java +1416 −0
  48. java/pkg/java/awt/image/FilteredImageSource.class +0 −0
  49. java/pkg/java/awt/image/FilteredImageSource.java +209 −0
  50. java/pkg/java/awt/image/ImageConsumer.class +0 −0
  51. java/pkg/java/awt/image/ImageConsumer.java +226 −0
  52. java/pkg/java/awt/image/ImageFilter.class +0 −0
  53. java/pkg/java/awt/image/ImageFilter.java +258 −0
  54. java/pkg/java/awt/image/ImageObserver.class +0 −0
  55. java/pkg/java/awt/image/ImageObserver.java +170 −0
  56. java/pkg/java/awt/image/ImageProducer.class +0 −0
  57. java/pkg/java/awt/image/ImageProducer.java +112 −0
  58. java/pkg/java/awt/image/ImagingOpException.class +0 −0
  59. java/pkg/java/awt/image/ImagingOpException.java +45 −0
  60. java/pkg/java/awt/image/IndexColorModel.class +0 −0
  61. java/pkg/java/awt/image/IndexColorModel.java +1534 −0
  62. java/pkg/java/awt/image/Kernel.class +0 −0
  63. java/pkg/java/awt/image/Kernel.java +153 −0
  64. java/pkg/java/awt/image/LookupOp.class +0 −0
  65. java/pkg/java/awt/image/LookupOp.java +567 −0
  66. java/pkg/java/awt/image/LookupTable.class +0 −0
  67. java/pkg/java/awt/image/LookupTable.java +109 −0
  68. java/pkg/java/awt/image/MemoryImageSource.class +0 −0
  69. java/pkg/java/awt/image/MemoryImageSource.java +571 −0
  70. java/pkg/java/awt/image/MultiPixelPackedSampleModel.class +0 −0
  71. java/pkg/java/awt/image/MultiPixelPackedSampleModel.java +699 −0
  72. java/pkg/java/awt/image/PackedColorModel.class +0 −0
  73. java/pkg/java/awt/image/PackedColorModel.java +486 −0
  74. java/pkg/java/awt/image/PixelGrabber.class +0 −0
  75. java/pkg/java/awt/image/PixelGrabber.java +672 −0
  76. java/pkg/java/awt/image/PixelInterleavedSampleModel.class +0 −0
  77. java/pkg/java/awt/image/PixelInterleavedSampleModel.java +171 −0
  78. java/pkg/java/awt/image/RGBImageFilter.class +0 −0
  79. java/pkg/java/awt/image/RGBImageFilter.java +292 −0
  80. java/pkg/java/awt/image/Raster.class +0 −0
  81. java/pkg/java/awt/image/Raster.java +1777 −0
  82. java/pkg/java/awt/image/RasterFormatException.class +0 −0
  83. java/pkg/java/awt/image/RasterFormatException.java +44 −0
  84. java/pkg/java/awt/image/RasterOp.class +0 −0
  85. java/pkg/java/awt/image/RasterOp.java +107 −0
  86. java/pkg/java/awt/image/RenderedImage.class +0 −0
  87. java/pkg/java/awt/image/RenderedImage.java +217 −0
  88. java/pkg/java/awt/image/ReplicateScaleFilter.class +0 −0
  89. java/pkg/java/awt/image/ReplicateScaleFilter.java +255 −0
  90. java/pkg/java/awt/image/RescaleOp.class +0 −0
  91. java/pkg/java/awt/image/RescaleOp.java +666 −0
  92. java/pkg/java/awt/image/SampleModel.class +0 −0
  93. java/pkg/java/awt/image/SampleModel.java +1507 −0
  94. java/pkg/java/awt/image/ShortLookupTable.class +0 −0
  95. java/pkg/java/awt/image/ShortLookupTable.java +204 −0
  96. java/pkg/java/awt/image/SinglePixelPackedSampleModel.class +0 −0
  97. java/pkg/java/awt/image/SinglePixelPackedSampleModel.java +801 −0
  98. java/pkg/java/awt/image/TileObserver.class +0 −0
  99. java/pkg/java/awt/image/TileObserver.java +55 −0
  100. java/pkg/java/awt/image/VolatileImage.class +0 −0
  101. java/pkg/java/awt/image/VolatileImage.java +342 −0
  102. java/pkg/java/awt/image/WritableRaster.class +0 −0
  103. java/pkg/java/awt/image/WritableRaster.java +741 −0
  104. java/pkg/java/awt/image/WritableRenderedImage.class +0 −0
  105. java/pkg/java/awt/image/WritableRenderedImage.java +151 −0
  106. java/pkg/java/awt/image/mkfile +63 −0
  107. java/pkg/java/awt/image/package.html +57 −0
  108. java/pkg/java/awt/image/renderable/ContextualRenderedImageFactory.class +0 −0
  109. java/pkg/java/awt/image/renderable/ContextualRenderedImageFactory.java +143 −0
  110. java/pkg/java/awt/image/renderable/ParameterBlock.class +0 −0
  111. java/pkg/java/awt/image/renderable/ParameterBlock.java +725 −0
  112. java/pkg/java/awt/image/renderable/RenderContext.class +0 −0
  113. java/pkg/java/awt/image/renderable/RenderContext.java +272 −0
  114. java/pkg/java/awt/image/renderable/RenderableImage.class +0 −0
  115. java/pkg/java/awt/image/renderable/RenderableImage.java +198 −0
  116. java/pkg/java/awt/image/renderable/RenderableImageOp.class +0 −0
  117. java/pkg/java/awt/image/renderable/RenderableImageOp.java +350 −0
  118. java/pkg/java/awt/image/renderable/RenderableImageProducer.class +0 −0
  119. java/pkg/java/awt/image/renderable/RenderableImageProducer.java +219 −0
  120. java/pkg/java/awt/image/renderable/RenderedImageFactory.class +0 −0
  121. java/pkg/java/awt/image/renderable/RenderedImageFactory.java +78 −0
  122. java/pkg/java/awt/image/renderable/mkfile +14 −0
  123. java/pkg/java/awt/image/renderable/package.html +51 −0
java/pkg/java/awt/image/AffineTransformOp.class+0−0

Binary file not shown.

java/pkg/java/awt/image/AffineTransformOp.java+560−0
@@ -0,0 +1,560 @@
1/*
2 * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.geom.AffineTransform;
29import java.awt.geom.NoninvertibleTransformException;
30import java.awt.geom.Rectangle2D;
31import java.awt.geom.Point2D;
32import java.awt.AlphaComposite;
33import java.awt.GraphicsEnvironment;
34import java.awt.Rectangle;
35import java.awt.RenderingHints;
36import java.awt.Transparency;
37import sun.awt.image.ImagingLib;
38
39/**
40 * This class uses an affine transform to perform a linear mapping from
41 * 2D coordinates in the source image or <CODE>Raster</CODE> to 2D coordinates
42 * in the destination image or <CODE>Raster</CODE>.
43 * The type of interpolation that is used is specified through a constructor,
44 * either by a <CODE>RenderingHints</CODE> object or by one of the integer
45 * interpolation types defined in this class.
46 * <p>
47 * If a <CODE>RenderingHints</CODE> object is specified in the constructor, the
48 * interpolation hint and the rendering quality hint are used to set
49 * the interpolation type for this operation. The color rendering hint
50 * and the dithering hint can be used when color conversion is required.
51 * <p>
52 * Note that the following constraints have to be met:
53 * <ul>
54 * <li>The source and destination must be different.
55 * <li>For <CODE>Raster</CODE> objects, the number of bands in the source must
56 * be equal to the number of bands in the destination.
57 * </ul>
58 * @see AffineTransform
59 * @see BufferedImageFilter
60 * @see java.awt.RenderingHints#KEY_INTERPOLATION
61 * @see java.awt.RenderingHints#KEY_RENDERING
62 * @see java.awt.RenderingHints#KEY_COLOR_RENDERING
63 * @see java.awt.RenderingHints#KEY_DITHERING
64 */
65public class AffineTransformOp implements BufferedImageOp, RasterOp {
66 private AffineTransform xform;
67 RenderingHints hints;
68
69 /**
70 * Nearest-neighbor interpolation type.
71 */
72 public static final int TYPE_NEAREST_NEIGHBOR = 1;
73
74 /**
75 * Bilinear interpolation type.
76 */
77 public static final int TYPE_BILINEAR = 2;
78
79 /**
80 * Bicubic interpolation type.
81 */
82 public static final int TYPE_BICUBIC = 3;
83
84 int interpolationType = TYPE_NEAREST_NEIGHBOR;
85
86 /**
87 * Constructs an <CODE>AffineTransformOp</CODE> given an affine transform.
88 * The interpolation type is determined from the
89 * <CODE>RenderingHints</CODE> object. If the interpolation hint is
90 * defined, it will be used. Otherwise, if the rendering quality hint is
91 * defined, the interpolation type is determined from its value. If no
92 * hints are specified (<CODE>hints</CODE> is null),
93 * the interpolation type is {@link #TYPE_NEAREST_NEIGHBOR
94 * TYPE_NEAREST_NEIGHBOR}.
95 *
96 * @param xform The <CODE>AffineTransform</CODE> to use for the
97 * operation.
98 *
99 * @param hints The <CODE>RenderingHints</CODE> object used to specify
100 * the interpolation type for the operation.
101 *
102 * @throws ImagingOpException if the transform is non-invertible.
103 * @see java.awt.RenderingHints#KEY_INTERPOLATION
104 * @see java.awt.RenderingHints#KEY_RENDERING
105 */
106 public AffineTransformOp(AffineTransform xform, RenderingHints hints){
107 validateTransform(xform);
108 this.xform = (AffineTransform) xform.clone();
109 this.hints = hints;
110
111 if (hints != null) {
112 Object value = hints.get(hints.KEY_INTERPOLATION);
113 if (value == null) {
114 value = hints.get(hints.KEY_RENDERING);
115 if (value == hints.VALUE_RENDER_SPEED) {
116 interpolationType = TYPE_NEAREST_NEIGHBOR;
117 }
118 else if (value == hints.VALUE_RENDER_QUALITY) {
119 interpolationType = TYPE_BILINEAR;
120 }
121 }
122 else if (value == hints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR) {
123 interpolationType = TYPE_NEAREST_NEIGHBOR;
124 }
125 else if (value == hints.VALUE_INTERPOLATION_BILINEAR) {
126 interpolationType = TYPE_BILINEAR;
127 }
128 else if (value == hints.VALUE_INTERPOLATION_BICUBIC) {
129 interpolationType = TYPE_BICUBIC;
130 }
131 }
132 else {
133 interpolationType = TYPE_NEAREST_NEIGHBOR;
134 }
135 }
136
137 /**
138 * Constructs an <CODE>AffineTransformOp</CODE> given an affine transform
139 * and the interpolation type.
140 *
141 * @param xform The <CODE>AffineTransform</CODE> to use for the operation.
142 * @param interpolationType One of the integer
143 * interpolation type constants defined by this class:
144 * {@link #TYPE_NEAREST_NEIGHBOR TYPE_NEAREST_NEIGHBOR},
145 * {@link #TYPE_BILINEAR TYPE_BILINEAR},
146 * {@link #TYPE_BICUBIC TYPE_BICUBIC}.
147 * @throws ImagingOpException if the transform is non-invertible.
148 */
149 public AffineTransformOp(AffineTransform xform, int interpolationType) {
150 validateTransform(xform);
151 this.xform = (AffineTransform)xform.clone();
152 switch(interpolationType) {
153 case TYPE_NEAREST_NEIGHBOR:
154 case TYPE_BILINEAR:
155 case TYPE_BICUBIC:
156 break;
157 default:
158 throw new IllegalArgumentException("Unknown interpolation type: "+
159 interpolationType);
160 }
161 this.interpolationType = interpolationType;
162 }
163
164 /**
165 * Returns the interpolation type used by this op.
166 * @return the interpolation type.
167 * @see #TYPE_NEAREST_NEIGHBOR
168 * @see #TYPE_BILINEAR
169 * @see #TYPE_BICUBIC
170 */
171 public final int getInterpolationType() {
172 return interpolationType;
173 }
174
175 /**
176 * Transforms the source <CODE>BufferedImage</CODE> and stores the results
177 * in the destination <CODE>BufferedImage</CODE>.
178 * If the color models for the two images do not match, a color
179 * conversion into the destination color model is performed.
180 * If the destination image is null,
181 * a <CODE>BufferedImage</CODE> is created with the source
182 * <CODE>ColorModel</CODE>.
183 * <p>
184 * The coordinates of the rectangle returned by
185 * <code>getBounds2D(BufferedImage)</code>
186 * are not necessarily the same as the coordinates of the
187 * <code>BufferedImage</code> returned by this method. If the
188 * upper-left corner coordinates of the rectangle are
189 * negative then this part of the rectangle is not drawn. If the
190 * upper-left corner coordinates of the rectangle are positive
191 * then the filtered image is drawn at that position in the
192 * destination <code>BufferedImage</code>.
193 * <p>
194 * An <CODE>IllegalArgumentException</CODE> is thrown if the source is
195 * the same as the destination.
196 *
197 * @param src The <CODE>BufferedImage</CODE> to transform.
198 * @param dst The <CODE>BufferedImage</CODE> in which to store the results
199 * of the transformation.
200 *
201 * @return The filtered <CODE>BufferedImage</CODE>.
202 * @throws IllegalArgumentException if <code>src</code> and
203 * <code>dst</code> are the same
204 * @throws ImagingOpException if the image cannot be transformed
205 * because of a data-processing error that might be
206 * caused by an invalid image format, tile format, or
207 * image-processing operation, or any other unsupported
208 * operation.
209 */
210 public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
211
212 if (src == null) {
213 throw new NullPointerException("src image is null");
214 }
215 if (src == dst) {
216 throw new IllegalArgumentException("src image cannot be the "+
217 "same as the dst image");
218 }
219
220 boolean needToConvert = false;
221 ColorModel srcCM = src.getColorModel();
222 ColorModel dstCM;
223 BufferedImage origDst = dst;
224
225 if (dst == null) {
226 dst = createCompatibleDestImage(src, null);
227 dstCM = srcCM;
228 origDst = dst;
229 }
230 else {
231 dstCM = dst.getColorModel();
232 if (srcCM.getColorSpace().getType() !=
233 dstCM.getColorSpace().getType())
234 {
235 int type = xform.getType();
236 boolean needTrans = ((type&
237 (xform.TYPE_MASK_ROTATION|
238 xform.TYPE_GENERAL_TRANSFORM))
239 != 0);
240 if (! needTrans && type != xform.TYPE_TRANSLATION && type != xform.TYPE_IDENTITY)
241 {
242 double[] mtx = new double[4];
243 xform.getMatrix(mtx);
244 // Check out the matrix. A non-integral scale will force ARGB
245 // since the edge conditions can't be guaranteed.
246 needTrans = (mtx[0] != (int)mtx[0] || mtx[3] != (int)mtx[3]);
247 }
248
249 if (needTrans &&
250 srcCM.getTransparency() == Transparency.OPAQUE)
251 {
252 // Need to convert first
253 ColorConvertOp ccop = new ColorConvertOp(hints);
254 BufferedImage tmpSrc = null;
255 int sw = src.getWidth();
256 int sh = src.getHeight();
257 if (dstCM.getTransparency() == Transparency.OPAQUE) {
258 tmpSrc = new BufferedImage(sw, sh,
259 BufferedImage.TYPE_INT_ARGB);
260 }
261 else {
262 WritableRaster r =
263 dstCM.createCompatibleWritableRaster(sw, sh);
264 tmpSrc = new BufferedImage(dstCM, r,
265 dstCM.isAlphaPremultiplied(),
266 null);
267 }
268 src = ccop.filter(src, tmpSrc);
269 }
270 else {
271 needToConvert = true;
272 dst = createCompatibleDestImage(src, null);
273 }
274 }
275
276 }
277
278 if (interpolationType != TYPE_NEAREST_NEIGHBOR &&
279 dst.getColorModel() instanceof IndexColorModel) {
280 dst = new BufferedImage(dst.getWidth(), dst.getHeight(),
281 BufferedImage.TYPE_INT_ARGB);
282 }
283 if (ImagingLib.filter(this, src, dst) == null) {
284 throw new ImagingOpException ("Unable to transform src image");
285 }
286
287 if (needToConvert) {
288 ColorConvertOp ccop = new ColorConvertOp(hints);
289 ccop.filter(dst, origDst);
290 }
291 else if (origDst != dst) {
292 java.awt.Graphics2D g = origDst.createGraphics();
293 try {
294 g.setComposite(AlphaComposite.Src);
295 g.drawImage(dst, 0, 0, null);
296 } finally {
297 g.dispose();
298 }
299 }
300
301 return origDst;
302 }
303
304 /**
305 * Transforms the source <CODE>Raster</CODE> and stores the results in
306 * the destination <CODE>Raster</CODE>. This operation performs the
307 * transform band by band.
308 * <p>
309 * If the destination <CODE>Raster</CODE> is null, a new
310 * <CODE>Raster</CODE> is created.
311 * An <CODE>IllegalArgumentException</CODE> may be thrown if the source is
312 * the same as the destination or if the number of bands in
313 * the source is not equal to the number of bands in the
314 * destination.
315 * <p>
316 * The coordinates of the rectangle returned by
317 * <code>getBounds2D(Raster)</code>
318 * are not necessarily the same as the coordinates of the
319 * <code>WritableRaster</code> returned by this method. If the
320 * upper-left corner coordinates of rectangle are negative then
321 * this part of the rectangle is not drawn. If the coordinates
322 * of the rectangle are positive then the filtered image is drawn at
323 * that position in the destination <code>Raster</code>.
324 * <p>
325 * @param src The <CODE>Raster</CODE> to transform.
326 * @param dst The <CODE>Raster</CODE> in which to store the results of the
327 * transformation.
328 *
329 * @return The transformed <CODE>Raster</CODE>.
330 *
331 * @throws ImagingOpException if the raster cannot be transformed
332 * because of a data-processing error that might be
333 * caused by an invalid image format, tile format, or
334 * image-processing operation, or any other unsupported
335 * operation.
336 */
337 public final WritableRaster filter(Raster src, WritableRaster dst) {
338 if (src == null) {
339 throw new NullPointerException("src image is null");
340 }
341 if (dst == null) {
342 dst = createCompatibleDestRaster(src);
343 }
344 if (src == dst) {
345 throw new IllegalArgumentException("src image cannot be the "+
346 "same as the dst image");
347 }
348 if (src.getNumBands() != dst.getNumBands()) {
349 throw new IllegalArgumentException("Number of src bands ("+
350 src.getNumBands()+
351 ") does not match number of "+
352 " dst bands ("+
353 dst.getNumBands()+")");
354 }
355
356 if (ImagingLib.filter(this, src, dst) == null) {
357 throw new ImagingOpException ("Unable to transform src image");
358 }
359 return dst;
360 }
361
362 /**
363 * Returns the bounding box of the transformed destination. The
364 * rectangle returned is the actual bounding box of the
365 * transformed points. The coordinates of the upper-left corner
366 * of the returned rectangle might not be (0,&nbsp;0).
367 *
368 * @param src The <CODE>BufferedImage</CODE> to be transformed.
369 *
370 * @return The <CODE>Rectangle2D</CODE> representing the destination's
371 * bounding box.
372 */
373 public final Rectangle2D getBounds2D (BufferedImage src) {
374 return getBounds2D(src.getRaster());
375 }
376
377 /**
378 * Returns the bounding box of the transformed destination. The
379 * rectangle returned will be the actual bounding box of the
380 * transformed points. The coordinates of the upper-left corner
381 * of the returned rectangle might not be (0,&nbsp;0).
382 *
383 * @param src The <CODE>Raster</CODE> to be transformed.
384 *
385 * @return The <CODE>Rectangle2D</CODE> representing the destination's
386 * bounding box.
387 */
388 public final Rectangle2D getBounds2D (Raster src) {
389 int w = src.getWidth();
390 int h = src.getHeight();
391
392 // Get the bounding box of the src and transform the corners
393 float[] pts = {0, 0, w, 0, w, h, 0, h};
394 xform.transform(pts, 0, pts, 0, 4);
395
396 // Get the min, max of the dst
397 float fmaxX = pts[0];
398 float fmaxY = pts[1];
399 float fminX = pts[0];
400 float fminY = pts[1];
401 for (int i=2; i < 8; i+=2) {
402 if (pts[i] > fmaxX) {
403 fmaxX = pts[i];
404 }
405 else if (pts[i] < fminX) {
406 fminX = pts[i];
407 }
408 if (pts[i+1] > fmaxY) {
409 fmaxY = pts[i+1];
410 }
411 else if (pts[i+1] < fminY) {
412 fminY = pts[i+1];
413 }
414 }
415
416 return new Rectangle2D.Float(fminX, fminY, fmaxX-fminX, fmaxY-fminY);
417 }
418
419 /**
420 * Creates a zeroed destination image with the correct size and number of
421 * bands. A <CODE>RasterFormatException</CODE> may be thrown if the
422 * transformed width or height is equal to 0.
423 * <p>
424 * If <CODE>destCM</CODE> is null,
425 * an appropriate <CODE>ColorModel</CODE> is used; this
426 * <CODE>ColorModel</CODE> may have
427 * an alpha channel even if the source <CODE>ColorModel</CODE> is opaque.
428 *
429 * @param src The <CODE>BufferedImage</CODE> to be transformed.
430 * @param destCM <CODE>ColorModel</CODE> of the destination. If null,
431 * an appropriate <CODE>ColorModel</CODE> is used.
432 *
433 * @return The zeroed destination image.
434 */
435 public BufferedImage createCompatibleDestImage (BufferedImage src,
436 ColorModel destCM) {
437 BufferedImage image;
438 Rectangle r = getBounds2D(src).getBounds();
439
440 // If r.x (or r.y) is < 0, then we want to only create an image
441 // that is in the positive range.
442 // If r.x (or r.y) is > 0, then we need to create an image that
443 // includes the translation.
444 int w = r.x + r.width;
445 int h = r.y + r.height;
446 if (w <= 0) {
447 throw new RasterFormatException("Transformed width ("+w+
448 ") is less than or equal to 0.");
449 }
450 if (h <= 0) {
451 throw new RasterFormatException("Transformed height ("+h+
452 ") is less than or equal to 0.");
453 }
454
455 if (destCM == null) {
456 ColorModel cm = src.getColorModel();
457 if (interpolationType != TYPE_NEAREST_NEIGHBOR &&
458 (cm instanceof IndexColorModel ||
459 cm.getTransparency() == Transparency.OPAQUE))
460 {
461 image = new BufferedImage(w, h,
462 BufferedImage.TYPE_INT_ARGB);
463 }
464 else {
465 image = new BufferedImage(cm,
466 src.getRaster().createCompatibleWritableRaster(w,h),
467 cm.isAlphaPremultiplied(), null);
468 }
469 }
470 else {
471 image = new BufferedImage(destCM,
472 destCM.createCompatibleWritableRaster(w,h),
473 destCM.isAlphaPremultiplied(), null);
474 }
475
476 return image;
477 }
478
479 /**
480 * Creates a zeroed destination <CODE>Raster</CODE> with the correct size
481 * and number of bands. A <CODE>RasterFormatException</CODE> may be thrown
482 * if the transformed width or height is equal to 0.
483 *
484 * @param src The <CODE>Raster</CODE> to be transformed.
485 *
486 * @return The zeroed destination <CODE>Raster</CODE>.
487 */
488 public WritableRaster createCompatibleDestRaster (Raster src) {
489 Rectangle2D r = getBounds2D(src);
490
491 return src.createCompatibleWritableRaster((int)r.getX(),
492 (int)r.getY(),
493 (int)r.getWidth(),
494 (int)r.getHeight());
495 }
496
497 /**
498 * Returns the location of the corresponding destination point given a
499 * point in the source. If <CODE>dstPt</CODE> is specified, it
500 * is used to hold the return value.
501 *
502 * @param srcPt The <code>Point2D</code> that represents the source
503 * point.
504 * @param dstPt The <CODE>Point2D</CODE> in which to store the result.
505 *
506 * @return The <CODE>Point2D</CODE> in the destination that corresponds to
507 * the specified point in the source.
508 */
509 public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) {
510 return xform.transform (srcPt, dstPt);
511 }
512
513 /**
514 * Returns the affine transform used by this transform operation.
515 *
516 * @return The <CODE>AffineTransform</CODE> associated with this op.
517 */
518 public final AffineTransform getTransform() {
519 return (AffineTransform) xform.clone();
520 }
521
522 /**
523 * Returns the rendering hints used by this transform operation.
524 *
525 * @return The <CODE>RenderingHints</CODE> object associated with this op.
526 */
527 public final RenderingHints getRenderingHints() {
528 if (hints == null) {
529 Object val;
530 switch(interpolationType) {
531 case TYPE_NEAREST_NEIGHBOR:
532 val = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
533 break;
534 case TYPE_BILINEAR:
535 val = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
536 break;
537 case TYPE_BICUBIC:
538 val = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
539 break;
540 default:
541 // Should never get here
542 throw new InternalError("Unknown interpolation type "+
543 interpolationType);
544
545 }
546 hints = new RenderingHints(RenderingHints.KEY_INTERPOLATION, val);
547 }
548
549 return hints;
550 }
551
552 // We need to be able to invert the transform if we want to
553 // transform the image. If the determinant of the matrix is 0,
554 // then we can't invert the transform.
555 void validateTransform(AffineTransform xform) {
556 if (Math.abs(xform.getDeterminant()) <= Double.MIN_VALUE) {
557 throw new ImagingOpException("Unable to invert transform "+xform);
558 }
559 }
560}
java/pkg/java/awt/image/AreaAveragingScaleFilter.class+0−0

Binary file not shown.

java/pkg/java/awt/image/AreaAveragingScaleFilter.java+281−0
@@ -0,0 +1,281 @@
1/*
2 * Copyright (c) 1996, 2002, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.image.ImageConsumer;
29import java.awt.image.ColorModel;
30import java.util.Hashtable;
31import java.awt.Rectangle;
32
33/**
34 * An ImageFilter class for scaling images using a simple area averaging
35 * algorithm that produces smoother results than the nearest neighbor
36 * algorithm.
37 * <p>This class extends the basic ImageFilter Class to scale an existing
38 * image and provide a source for a new image containing the resampled
39 * image. The pixels in the source image are blended to produce pixels
40 * for an image of the specified size. The blending process is analogous
41 * to scaling up the source image to a multiple of the destination size
42 * using pixel replication and then scaling it back down to the destination
43 * size by simply averaging all the pixels in the supersized image that
44 * fall within a given pixel of the destination image. If the data from
45 * the source is not delivered in TopDownLeftRight order then the filter
46 * will back off to a simple pixel replication behavior and utilize the
47 * requestTopDownLeftRightResend() method to refilter the pixels in a
48 * better way at the end.
49 * <p>It is meant to be used in conjunction with a FilteredImageSource
50 * object to produce scaled versions of existing images. Due to
51 * implementation dependencies, there may be differences in pixel values
52 * of an image filtered on different platforms.
53 *
54 * @see FilteredImageSource
55 * @see ReplicateScaleFilter
56 * @see ImageFilter
57 *
58 * @author Jim Graham
59 */
60public class AreaAveragingScaleFilter extends ReplicateScaleFilter {
61 private static final ColorModel rgbmodel = ColorModel.getRGBdefault();
62 private static final int neededHints = (TOPDOWNLEFTRIGHT
63 | COMPLETESCANLINES);
64
65 private boolean passthrough;
66 private float reds[], greens[], blues[], alphas[];
67 private int savedy;
68 private int savedyrem;
69
70 /**
71 * Constructs an AreaAveragingScaleFilter that scales the pixels from
72 * its source Image as specified by the width and height parameters.
73 * @param width the target width to scale the image
74 * @param height the target height to scale the image
75 */
76 public AreaAveragingScaleFilter(int width, int height) {
77 super(width, height);
78 }
79
80 /**
81 * Detect if the data is being delivered with the necessary hints
82 * to allow the averaging algorithm to do its work.
83 * <p>
84 * Note: This method is intended to be called by the
85 * <code>ImageProducer</code> of the <code>Image</code> whose
86 * pixels are being filtered. Developers using
87 * this class to filter pixels from an image should avoid calling
88 * this method directly since that operation could interfere
89 * with the filtering operation.
90 * @see ImageConsumer#setHints
91 */
92 public void setHints(int hints) {
93 passthrough = ((hints & neededHints) != neededHints);
94 super.setHints(hints);
95 }
96
97 private void makeAccumBuffers() {
98 reds = new float[destWidth];
99 greens = new float[destWidth];
100 blues = new float[destWidth];
101 alphas = new float[destWidth];
102 }
103
104 private int[] calcRow() {
105 float origmult = ((float) srcWidth) * srcHeight;
106 if (outpixbuf == null || !(outpixbuf instanceof int[])) {
107 outpixbuf = new int[destWidth];
108 }
109 int[] outpix = (int[]) outpixbuf;
110 for (int x = 0; x < destWidth; x++) {
111 float mult = origmult;
112 int a = Math.round(alphas[x] / mult);
113 if (a <= 0) {
114 a = 0;
115 } else if (a >= 255) {
116 a = 255;
117 } else {
118 // un-premultiply the components (by modifying mult here, we
119 // are effectively doing the divide by mult and divide by
120 // alpha in the same step)
121 mult = alphas[x] / 255;
122 }
123 int r = Math.round(reds[x] / mult);
124 int g = Math.round(greens[x] / mult);
125 int b = Math.round(blues[x] / mult);
126 if (r < 0) {r = 0;} else if (r > 255) {r = 255;}
127 if (g < 0) {g = 0;} else if (g > 255) {g = 255;}
128 if (b < 0) {b = 0;} else if (b > 255) {b = 255;}
129 outpix[x] = (a << 24 | r << 16 | g << 8 | b);
130 }
131 return outpix;
132 }
133
134 private void accumPixels(int x, int y, int w, int h,
135 ColorModel model, Object pixels, int off,
136 int scansize) {
137 if (reds == null) {
138 makeAccumBuffers();
139 }
140 int sy = y;
141 int syrem = destHeight;
142 int dy, dyrem;
143 if (sy == 0) {
144 dy = 0;
145 dyrem = 0;
146 } else {
147 dy = savedy;
148 dyrem = savedyrem;
149 }
150 while (sy < y + h) {
151 int amty;
152 if (dyrem == 0) {
153 for (int i = 0; i < destWidth; i++) {
154 alphas[i] = reds[i] = greens[i] = blues[i] = 0f;
155 }
156 dyrem = srcHeight;
157 }
158 if (syrem < dyrem) {
159 amty = syrem;
160 } else {
161 amty = dyrem;
162 }
163 int sx = 0;
164 int dx = 0;
165 int sxrem = 0;
166 int dxrem = srcWidth;
167 float a = 0f, r = 0f, g = 0f, b = 0f;
168 while (sx < w) {
169 if (sxrem == 0) {
170 sxrem = destWidth;
171 int rgb;
172 if (pixels instanceof byte[]) {
173 rgb = ((byte[]) pixels)[off + sx] & 0xff;
174 } else {
175 rgb = ((int[]) pixels)[off + sx];
176 }
177 // getRGB() always returns non-premultiplied components
178 rgb = model.getRGB(rgb);
179 a = rgb >>> 24;
180 r = (rgb >> 16) & 0xff;
181 g = (rgb >> 8) & 0xff;
182 b = rgb & 0xff;
183 // premultiply the components if necessary
184 if (a != 255.0f) {
185 float ascale = a / 255.0f;
186 r *= ascale;
187 g *= ascale;
188 b *= ascale;
189 }
190 }
191 int amtx;
192 if (sxrem < dxrem) {
193 amtx = sxrem;
194 } else {
195 amtx = dxrem;
196 }
197 float mult = ((float) amtx) * amty;
198 alphas[dx] += mult * a;
199 reds[dx] += mult * r;
200 greens[dx] += mult * g;
201 blues[dx] += mult * b;
202 if ((sxrem -= amtx) == 0) {
203 sx++;
204 }
205 if ((dxrem -= amtx) == 0) {
206 dx++;
207 dxrem = srcWidth;
208 }
209 }
210 if ((dyrem -= amty) == 0) {
211 int outpix[] = calcRow();
212 do {
213 consumer.setPixels(0, dy, destWidth, 1,
214 rgbmodel, outpix, 0, destWidth);
215 dy++;
216 } while ((syrem -= amty) >= amty && amty == srcHeight);
217 } else {
218 syrem -= amty;
219 }
220 if (syrem == 0) {
221 syrem = destHeight;
222 sy++;
223 off += scansize;
224 }
225 }
226 savedyrem = dyrem;
227 savedy = dy;
228 }
229
230 /**
231 * Combine the components for the delivered byte pixels into the
232 * accumulation arrays and send on any averaged data for rows of
233 * pixels that are complete. If the correct hints were not
234 * specified in the setHints call then relay the work to our
235 * superclass which is capable of scaling pixels regardless of
236 * the delivery hints.
237 * <p>
238 * Note: This method is intended to be called by the
239 * <code>ImageProducer</code> of the <code>Image</code>
240 * whose pixels are being filtered. Developers using
241 * this class to filter pixels from an image should avoid calling
242 * this method directly since that operation could interfere
243 * with the filtering operation.
244 * @see ReplicateScaleFilter
245 */
246 public void setPixels(int x, int y, int w, int h,
247 ColorModel model, byte pixels[], int off,
248 int scansize) {
249 if (passthrough) {
250 super.setPixels(x, y, w, h, model, pixels, off, scansize);
251 } else {
252 accumPixels(x, y, w, h, model, pixels, off, scansize);
253 }
254 }
255
256 /**
257 * Combine the components for the delivered int pixels into the
258 * accumulation arrays and send on any averaged data for rows of
259 * pixels that are complete. If the correct hints were not
260 * specified in the setHints call then relay the work to our
261 * superclass which is capable of scaling pixels regardless of
262 * the delivery hints.
263 * <p>
264 * Note: This method is intended to be called by the
265 * <code>ImageProducer</code> of the <code>Image</code>
266 * whose pixels are being filtered. Developers using
267 * this class to filter pixels from an image should avoid calling
268 * this method directly since that operation could interfere
269 * with the filtering operation.
270 * @see ReplicateScaleFilter
271 */
272 public void setPixels(int x, int y, int w, int h,
273 ColorModel model, int pixels[], int off,
274 int scansize) {
275 if (passthrough) {
276 super.setPixels(x, y, w, h, model, pixels, off, scansize);
277 } else {
278 accumPixels(x, y, w, h, model, pixels, off, scansize);
279 }
280 }
281}
java/pkg/java/awt/image/BandCombineOp.class+0−0

Binary file not shown.

java/pkg/java/awt/image/BandCombineOp.java+289−0
@@ -0,0 +1,289 @@
1/*
2 * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.GraphicsEnvironment;
29import java.awt.color.ICC_Profile;
30import java.awt.geom.Rectangle2D;
31import java.awt.Rectangle;
32import java.awt.geom.Point2D;
33import java.awt.RenderingHints;
34import sun.awt.image.ImagingLib;
35import java.util.Arrays;
36
37/**
38 * This class performs an arbitrary linear combination of the bands
39 * in a <CODE>Raster</CODE>, using a specified matrix.
40 * <p>
41 * The width of the matrix must be equal to the number of bands in the
42 * source <CODE>Raster</CODE>, optionally plus one. If there is one more
43 * column in the matrix than the number of bands, there is an implied 1 at the
44 * end of the vector of band samples representing a pixel. The height
45 * of the matrix must be equal to the number of bands in the destination.
46 * <p>
47 * For example, a 3-banded <CODE>Raster</CODE> might have the following
48 * transformation applied to each pixel in order to invert the second band of
49 * the <CODE>Raster</CODE>.
50 * <pre>
51 * [ 1.0 0.0 0.0 0.0 ] [ b1 ]
52 * [ 0.0 -1.0 0.0 255.0 ] x [ b2 ]
53 * [ 0.0 0.0 1.0 0.0 ] [ b3 ]
54 * [ 1 ]
55 * </pre>
56 *
57 * <p>
58 * Note that the source and destination can be the same object.
59 */
60public class BandCombineOp implements RasterOp {
61 float[][] matrix;
62 int nrows = 0;
63 int ncols = 0;
64 RenderingHints hints;
65
66 /**
67 * Constructs a <CODE>BandCombineOp</CODE> with the specified matrix.
68 * The width of the matrix must be equal to the number of bands in
69 * the source <CODE>Raster</CODE>, optionally plus one. If there is one
70 * more column in the matrix than the number of bands, there is an implied
71 * 1 at the end of the vector of band samples representing a pixel. The
72 * height of the matrix must be equal to the number of bands in the
73 * destination.
74 * <p>
75 * The first subscript is the row index and the second
76 * is the column index. This operation uses none of the currently
77 * defined rendering hints; the <CODE>RenderingHints</CODE> argument can be
78 * null.
79 *
80 * @param matrix The matrix to use for the band combine operation.
81 * @param hints The <CODE>RenderingHints</CODE> object for this operation.
82 * Not currently used so it can be null.
83 */
84 public BandCombineOp (float[][] matrix, RenderingHints hints) {
85 nrows = matrix.length;
86 ncols = matrix[0].length;
87 this.matrix = new float[nrows][];
88 for (int i=0; i < nrows; i++) {
89 /* Arrays.copyOf is forgiving of the source array being
90 * too short, but it is also faster than other cloning
91 * methods, so we provide our own protection for short
92 * matrix rows.
93 */
94 if (ncols > matrix[i].length) {
95 throw new IndexOutOfBoundsException("row "+i+" too short");
96 }
97 this.matrix[i] = Arrays.copyOf(matrix[i], ncols);
98 }
99 this.hints = hints;
100 }
101
102 /**
103 * Returns a copy of the linear combination matrix.
104 *
105 * @return The matrix associated with this band combine operation.
106 */
107 public final float[][] getMatrix() {
108 float[][] ret = new float[nrows][];
109 for (int i = 0; i < nrows; i++) {
110 ret[i] = Arrays.copyOf(matrix[i], ncols);
111 }
112 return ret;
113 }
114
115 /**
116 * Transforms the <CODE>Raster</CODE> using the matrix specified in the
117 * constructor. An <CODE>IllegalArgumentException</CODE> may be thrown if
118 * the number of bands in the source or destination is incompatible with
119 * the matrix. See the class comments for more details.
120 * <p>
121 * If the destination is null, it will be created with a number of bands
122 * equalling the number of rows in the matrix. No exception is thrown
123 * if the operation causes a data overflow.
124 *
125 * @param src The <CODE>Raster</CODE> to be filtered.
126 * @param dst The <CODE>Raster</CODE> in which to store the results
127 * of the filter operation.
128 *
129 * @return The filtered <CODE>Raster</CODE>.
130 *
131 * @throws IllegalArgumentException If the number of bands in the
132 * source or destination is incompatible with the matrix.
133 */
134 public WritableRaster filter(Raster src, WritableRaster dst) {
135 int nBands = src.getNumBands();
136 if (ncols != nBands && ncols != (nBands+1)) {
137 throw new IllegalArgumentException("Number of columns in the "+
138 "matrix ("+ncols+
139 ") must be equal to the number"+
140 " of bands ([+1]) in src ("+
141 nBands+").");
142 }
143 if (dst == null) {
144 dst = createCompatibleDestRaster(src);
145 }
146 else if (nrows != dst.getNumBands()) {
147 throw new IllegalArgumentException("Number of rows in the "+
148 "matrix ("+nrows+
149 ") must be equal to the number"+
150 " of bands ([+1]) in dst ("+
151 nBands+").");
152 }
153
154 if (ImagingLib.filter(this, src, dst) != null) {
155 return dst;
156 }
157
158 int[] pixel = null;
159 int[] dstPixel = new int[dst.getNumBands()];
160 float accum;
161 int sminX = src.getMinX();
162 int sY = src.getMinY();
163 int dminX = dst.getMinX();
164 int dY = dst.getMinY();
165 int sX;
166 int dX;
167 if (ncols == nBands) {
168 for (int y=0; y < src.getHeight(); y++, sY++, dY++) {
169 dX = dminX;
170 sX = sminX;
171 for (int x=0; x < src.getWidth(); x++, sX++, dX++) {
172 pixel = src.getPixel(sX, sY, pixel);
173 for (int r=0; r < nrows; r++) {
174 accum = 0.f;
175 for (int c=0; c < ncols; c++) {
176 accum += matrix[r][c]*pixel[c];
177 }
178 dstPixel[r] = (int) accum;
179 }
180 dst.setPixel(dX, dY, dstPixel);
181 }
182 }
183 }
184 else {
185 // Need to add constant
186 for (int y=0; y < src.getHeight(); y++, sY++, dY++) {
187 dX = dminX;
188 sX = sminX;
189 for (int x=0; x < src.getWidth(); x++, sX++, dX++) {
190 pixel = src.getPixel(sX, sY, pixel);
191 for (int r=0; r < nrows; r++) {
192 accum = 0.f;
193 for (int c=0; c < nBands; c++) {
194 accum += matrix[r][c]*pixel[c];
195 }
196 dstPixel[r] = (int) (accum+matrix[r][nBands]);
197 }
198 dst.setPixel(dX, dY, dstPixel);
199 }
200 }
201 }
202
203 return dst;
204 }
205
206 /**
207 * Returns the bounding box of the transformed destination. Since
208 * this is not a geometric operation, the bounding box is the same for
209 * the source and destination.
210 * An <CODE>IllegalArgumentException</CODE> may be thrown if the number of
211 * bands in the source is incompatible with the matrix. See
212 * the class comments for more details.
213 *
214 * @param src The <CODE>Raster</CODE> to be filtered.
215 *
216 * @return The <CODE>Rectangle2D</CODE> representing the destination
217 * image's bounding box.
218 *
219 * @throws IllegalArgumentException If the number of bands in the source
220 * is incompatible with the matrix.
221 */
222 public final Rectangle2D getBounds2D (Raster src) {
223 return src.getBounds();
224 }
225
226
227 /**
228 * Creates a zeroed destination <CODE>Raster</CODE> with the correct size
229 * and number of bands.
230 * An <CODE>IllegalArgumentException</CODE> may be thrown if the number of
231 * bands in the source is incompatible with the matrix. See
232 * the class comments for more details.
233 *
234 * @param src The <CODE>Raster</CODE> to be filtered.
235 *
236 * @return The zeroed destination <CODE>Raster</CODE>.
237 */
238 public WritableRaster createCompatibleDestRaster (Raster src) {
239 int nBands = src.getNumBands();
240 if ((ncols != nBands) && (ncols != (nBands+1))) {
241 throw new IllegalArgumentException("Number of columns in the "+
242 "matrix ("+ncols+
243 ") must be equal to the number"+
244 " of bands ([+1]) in src ("+
245 nBands+").");
246 }
247 if (src.getNumBands() == nrows) {
248 return src.createCompatibleWritableRaster();
249 }
250 else {
251 throw new IllegalArgumentException("Don't know how to create a "+
252 " compatible Raster with "+
253 nrows+" bands.");
254 }
255 }
256
257 /**
258 * Returns the location of the corresponding destination point given a
259 * point in the source <CODE>Raster</CODE>. If <CODE>dstPt</CODE> is
260 * specified, it is used to hold the return value.
261 * Since this is not a geometric operation, the point returned
262 * is the same as the specified <CODE>srcPt</CODE>.
263 *
264 * @param srcPt The <code>Point2D</code> that represents the point in
265 * the source <code>Raster</code>
266 * @param dstPt The <CODE>Point2D</CODE> in which to store the result.
267 *
268 * @return The <CODE>Point2D</CODE> in the destination image that
269 * corresponds to the specified point in the source image.
270 */
271 public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) {
272 if (dstPt == null) {
273 dstPt = new Point2D.Float();
274 }
275 dstPt.setLocation(srcPt.getX(), srcPt.getY());
276
277 return dstPt;
278 }
279
280 /**
281 * Returns the rendering hints for this operation.
282 *
283 * @return The <CODE>RenderingHints</CODE> object associated with this
284 * operation. Returns null if no hints have been set.
285 */
286 public final RenderingHints getRenderingHints() {
287 return hints;
288 }
289}
java/pkg/java/awt/image/BandedSampleModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/BandedSampleModel.java+849−0
@@ -0,0 +1,849 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26/* ****************************************************************
27 ******************************************************************
28 ******************************************************************
29 *** COPYRIGHT (c) Eastman Kodak Company, 1997
30 *** As an unpublished work pursuant to Title 17 of the United
31 *** States Code. All rights reserved.
32 ******************************************************************
33 ******************************************************************
34 ******************************************************************/
35
36package java.awt.image;
37
38/**
39 * This class represents image data which is stored in a band interleaved
40 * fashion and for
41 * which each sample of a pixel occupies one data element of the DataBuffer.
42 * It subclasses ComponentSampleModel but provides a more efficent
43 * implementation for accessing band interleaved image data than is provided
44 * by ComponentSampleModel. This class should typically be used when working
45 * with images which store sample data for each band in a different bank of the
46 * DataBuffer. Accessor methods are provided so that image data can be
47 * manipulated directly. Pixel stride is the number of
48 * data array elements between two samples for the same band on the same
49 * scanline. The pixel stride for a BandedSampleModel is one.
50 * Scanline stride is the number of data array elements between
51 * a given sample and the corresponding sample in the same column of the next
52 * scanline. Band offsets denote the number
53 * of data array elements from the first data array element of the bank
54 * of the DataBuffer holding each band to the first sample of the band.
55 * The bands are numbered from 0 to N-1.
56 * Bank indices denote the correspondence between a bank of the data buffer
57 * and a band of image data. This class supports
58 * {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
59 * {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
60 * {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
61 * {@link DataBuffer#TYPE_INT TYPE_INT},
62 * {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT}, and
63 * {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE} datatypes
64 */
65
66
67public final class BandedSampleModel extends ComponentSampleModel
68{
69
70 /**
71 * Constructs a BandedSampleModel with the specified parameters.
72 * The pixel stride will be one data element. The scanline stride
73 * will be the same as the width. Each band will be stored in
74 * a separate bank and all band offsets will be zero.
75 * @param dataType The data type for storing samples.
76 * @param w The width (in pixels) of the region of
77 * image data described.
78 * @param h The height (in pixels) of the region of image
79 * data described.
80 * @param numBands The number of bands for the image data.
81 * @throws IllegalArgumentException if <code>dataType</code> is not
82 * one of the supported data types
83 */
84 public BandedSampleModel(int dataType, int w, int h, int numBands) {
85 super(dataType, w, h, 1, w,
86 BandedSampleModel.createIndicesArray(numBands),
87 BandedSampleModel.createOffsetArray(numBands));
88 }
89
90 /**
91 * Constructs a BandedSampleModel with the specified parameters.
92 * The number of bands will be inferred from the lengths of the
93 * bandOffsets bankIndices arrays, which must be equal. The pixel
94 * stride will be one data element.
95 * @param dataType The data type for storing samples.
96 * @param w The width (in pixels) of the region of
97 * image data described.
98 * @param h The height (in pixels) of the region of
99 * image data described.
100 * @param scanlineStride The line stride of the of the image data.
101 * @param bankIndices The bank index for each band.
102 * @param bandOffsets The band offset for each band.
103 * @throws IllegalArgumentException if <code>dataType</code> is not
104 * one of the supported data types
105 */
106 public BandedSampleModel(int dataType,
107 int w, int h,
108 int scanlineStride,
109 int bankIndices[],
110 int bandOffsets[]) {
111
112 super(dataType, w, h, 1,scanlineStride, bankIndices, bandOffsets);
113 }
114
115 /**
116 * Creates a new BandedSampleModel with the specified
117 * width and height. The new BandedSampleModel will have the same
118 * number of bands, storage data type, and bank indices
119 * as this BandedSampleModel. The band offsets will be compressed
120 * such that the offset between bands will be w*pixelStride and
121 * the minimum of all of the band offsets is zero.
122 * @param w the width of the resulting <code>BandedSampleModel</code>
123 * @param h the height of the resulting <code>BandedSampleModel</code>
124 * @return a new <code>BandedSampleModel</code> with the specified
125 * width and height.
126 * @throws IllegalArgumentException if <code>w</code> or
127 * <code>h</code> equals either
128 * <code>Integer.MAX_VALUE</code> or
129 * <code>Integer.MIN_VALUE</code>
130 * @throws IllegalArgumentException if <code>dataType</code> is not
131 * one of the supported data types
132 */
133 public SampleModel createCompatibleSampleModel(int w, int h) {
134 int[] bandOffs;
135
136 if (numBanks == 1) {
137 bandOffs = orderBands(bandOffsets, w*h);
138 }
139 else {
140 bandOffs = new int[bandOffsets.length];
141 }
142
143 SampleModel sampleModel =
144 new BandedSampleModel(dataType, w, h, w, bankIndices, bandOffs);
145 return sampleModel;
146 }
147
148 /**
149 * Creates a new BandedSampleModel with a subset of the bands of this
150 * BandedSampleModel. The new BandedSampleModel can be
151 * used with any DataBuffer that the existing BandedSampleModel
152 * can be used with. The new BandedSampleModel/DataBuffer
153 * combination will represent an image with a subset of the bands
154 * of the original BandedSampleModel/DataBuffer combination.
155 * @throws RasterFormatException if the number of bands is greater than
156 * the number of banks in this sample model.
157 * @throws IllegalArgumentException if <code>dataType</code> is not
158 * one of the supported data types
159 */
160 public SampleModel createSubsetSampleModel(int bands[]) {
161 if (bands.length > bankIndices.length)
162 throw new RasterFormatException("There are only " +
163 bankIndices.length +
164 " bands");
165 int newBankIndices[] = new int[bands.length];
166 int newBandOffsets[] = new int[bands.length];
167
168 for (int i=0; i<bands.length; i++) {
169 newBankIndices[i] = bankIndices[bands[i]];
170 newBandOffsets[i] = bandOffsets[bands[i]];
171 }
172
173 return new BandedSampleModel(this.dataType, width, height,
174 this.scanlineStride,
175 newBankIndices, newBandOffsets);
176 }
177
178 /**
179 * Creates a DataBuffer that corresponds to this BandedSampleModel,
180 * The DataBuffer's data type, number of banks, and size
181 * will be consistent with this BandedSampleModel.
182 * @throws IllegalArgumentException if <code>dataType</code> is not
183 * one of the supported types.
184 */
185 public DataBuffer createDataBuffer() {
186 DataBuffer dataBuffer = null;
187
188 int size = scanlineStride * height;
189 switch (dataType) {
190 case DataBuffer.TYPE_BYTE:
191 dataBuffer = new DataBufferByte(size, numBanks);
192 break;
193 case DataBuffer.TYPE_USHORT:
194 dataBuffer = new DataBufferUShort(size, numBanks);
195 break;
196 case DataBuffer.TYPE_SHORT:
197 dataBuffer = new DataBufferShort(size, numBanks);
198 break;
199 case DataBuffer.TYPE_INT:
200 dataBuffer = new DataBufferInt(size, numBanks);
201 break;
202 case DataBuffer.TYPE_FLOAT:
203 dataBuffer = new DataBufferFloat(size, numBanks);
204 break;
205 case DataBuffer.TYPE_DOUBLE:
206 dataBuffer = new DataBufferDouble(size, numBanks);
207 break;
208 default:
209 throw new IllegalArgumentException("dataType is not one " +
210 "of the supported types.");
211 }
212
213 return dataBuffer;
214 }
215
216
217 /**
218 * Returns data for a single pixel in a primitive array of type
219 * TransferType. For a BandedSampleModel, this will be the same
220 * as the data type, and samples will be returned one per array
221 * element. Generally, obj
222 * should be passed in as null, so that the Object will be created
223 * automatically and will be of the right primitive data type.
224 * <p>
225 * The following code illustrates transferring data for one pixel from
226 * DataBuffer <code>db1</code>, whose storage layout is described by
227 * BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
228 * whose storage layout is described by
229 * BandedSampleModel <code>bsm2</code>.
230 * The transfer will generally be more efficient than using
231 * getPixel/setPixel.
232 * <pre>
233 * BandedSampleModel bsm1, bsm2;
234 * DataBufferInt db1, db2;
235 * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
236 * db2);
237 * </pre>
238 * Using getDataElements/setDataElements to transfer between two
239 * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
240 * the same number of bands, corresponding bands have the same number of
241 * bits per sample, and the TransferTypes are the same.
242 * <p>
243 * If obj is non-null, it should be a primitive array of type TransferType.
244 * Otherwise, a ClassCastException is thrown. An
245 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
246 * not in bounds, or if obj is non-null and is not large enough to hold
247 * the pixel data.
248 * @param x The X coordinate of the pixel location
249 * @param y The Y coordinate of the pixel location
250 * @param obj If non-null, a primitive array in which to return
251 * the pixel data.
252 * @param data The DataBuffer containing the image data.
253 * @return the data for the specified pixel.
254 * @see #setDataElements(int, int, Object, DataBuffer)
255 */
256 public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
257 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
258 throw new ArrayIndexOutOfBoundsException
259 ("Coordinate out of bounds!");
260 }
261 int type = getTransferType();
262 int numDataElems = getNumDataElements();
263 int pixelOffset = y*scanlineStride + x;
264
265 switch(type) {
266
267 case DataBuffer.TYPE_BYTE:
268
269 byte[] bdata;
270
271 if (obj == null) {
272 bdata = new byte[numDataElems];
273 } else {
274 bdata = (byte[])obj;
275 }
276
277 for (int i=0; i<numDataElems; i++) {
278 bdata[i] = (byte)data.getElem(bankIndices[i],
279 pixelOffset + bandOffsets[i]);
280 }
281
282 obj = (Object)bdata;
283 break;
284
285 case DataBuffer.TYPE_USHORT:
286 case DataBuffer.TYPE_SHORT:
287
288 short[] sdata;
289
290 if (obj == null) {
291 sdata = new short[numDataElems];
292 } else {
293 sdata = (short[])obj;
294 }
295
296 for (int i=0; i<numDataElems; i++) {
297 sdata[i] = (short)data.getElem(bankIndices[i],
298 pixelOffset + bandOffsets[i]);
299 }
300
301 obj = (Object)sdata;
302 break;
303
304 case DataBuffer.TYPE_INT:
305
306 int[] idata;
307
308 if (obj == null) {
309 idata = new int[numDataElems];
310 } else {
311 idata = (int[])obj;
312 }
313
314 for (int i=0; i<numDataElems; i++) {
315 idata[i] = data.getElem(bankIndices[i],
316 pixelOffset + bandOffsets[i]);
317 }
318
319 obj = (Object)idata;
320 break;
321
322 case DataBuffer.TYPE_FLOAT:
323
324 float[] fdata;
325
326 if (obj == null) {
327 fdata = new float[numDataElems];
328 } else {
329 fdata = (float[])obj;
330 }
331
332 for (int i=0; i<numDataElems; i++) {
333 fdata[i] = data.getElemFloat(bankIndices[i],
334 pixelOffset + bandOffsets[i]);
335 }
336
337 obj = (Object)fdata;
338 break;
339
340 case DataBuffer.TYPE_DOUBLE:
341
342 double[] ddata;
343
344 if (obj == null) {
345 ddata = new double[numDataElems];
346 } else {
347 ddata = (double[])obj;
348 }
349
350 for (int i=0; i<numDataElems; i++) {
351 ddata[i] = data.getElemDouble(bankIndices[i],
352 pixelOffset + bandOffsets[i]);
353 }
354
355 obj = (Object)ddata;
356 break;
357 }
358
359 return obj;
360 }
361
362 /**
363 * Returns all samples for the specified pixel in an int array.
364 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
365 * not in bounds.
366 * @param x The X coordinate of the pixel location
367 * @param y The Y coordinate of the pixel location
368 * @param iArray If non-null, returns the samples in this array
369 * @param data The DataBuffer containing the image data
370 * @return the samples for the specified pixel.
371 * @see #setPixel(int, int, int[], DataBuffer)
372 */
373 public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
374 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
375 throw new ArrayIndexOutOfBoundsException
376 ("Coordinate out of bounds!");
377 }
378
379 int[] pixels;
380
381 if (iArray != null) {
382 pixels = iArray;
383 } else {
384 pixels = new int [numBands];
385 }
386
387 int pixelOffset = y*scanlineStride + x;
388 for (int i=0; i<numBands; i++) {
389 pixels[i] = data.getElem(bankIndices[i],
390 pixelOffset + bandOffsets[i]);
391 }
392 return pixels;
393 }
394
395 /**
396 * Returns all samples for the specified rectangle of pixels in
397 * an int array, one sample per data array element.
398 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
399 * not in bounds.
400 * @param x The X coordinate of the upper left pixel location
401 * @param y The Y coordinate of the upper left pixel location
402 * @param w The width of the pixel rectangle
403 * @param h The height of the pixel rectangle
404 * @param iArray If non-null, returns the samples in this array
405 * @param data The DataBuffer containing the image data
406 * @return the samples for the pixels within the specified region.
407 * @see #setPixels(int, int, int, int, int[], DataBuffer)
408 */
409 public int[] getPixels(int x, int y, int w, int h,
410 int iArray[], DataBuffer data) {
411 int x1 = x + w;
412 int y1 = y + h;
413
414 if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
415 y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
416 {
417 throw new ArrayIndexOutOfBoundsException
418 ("Coordinate out of bounds!");
419 }
420 int[] pixels;
421
422 if (iArray != null) {
423 pixels = iArray;
424 } else {
425 pixels = new int[w*h*numBands];
426 }
427
428 for (int k = 0; k < numBands; k++) {
429 int lineOffset = y*scanlineStride + x + bandOffsets[k];
430 int srcOffset = k;
431 int bank = bankIndices[k];
432
433 for (int i = 0; i < h; i++) {
434 int pixelOffset = lineOffset;
435 for (int j = 0; j < w; j++) {
436 pixels[srcOffset] = data.getElem(bank, pixelOffset++);
437 srcOffset += numBands;
438 }
439 lineOffset += scanlineStride;
440 }
441 }
442 return pixels;
443 }
444
445 /**
446 * Returns as int the sample in a specified band for the pixel
447 * located at (x,y).
448 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
449 * not in bounds.
450 * @param x The X coordinate of the pixel location
451 * @param y The Y coordinate of the pixel location
452 * @param b The band to return
453 * @param data The DataBuffer containing the image data
454 * @return the sample in the specified band for the specified pixel.
455 * @see #setSample(int, int, int, int, DataBuffer)
456 */
457 public int getSample(int x, int y, int b, DataBuffer data) {
458 // Bounds check for 'b' will be performed automatically
459 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
460 throw new ArrayIndexOutOfBoundsException
461 ("Coordinate out of bounds!");
462 }
463 int sample =
464 data.getElem(bankIndices[b],
465 y*scanlineStride + x + bandOffsets[b]);
466 return sample;
467 }
468
469 /**
470 * Returns the sample in a specified band
471 * for the pixel located at (x,y) as a float.
472 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
473 * not in bounds.
474 * @param x The X coordinate of the pixel location
475 * @param y The Y coordinate of the pixel location
476 * @param b The band to return
477 * @param data The DataBuffer containing the image data
478 * @return a float value that represents the sample in the specified
479 * band for the specified pixel.
480 */
481 public float getSampleFloat(int x, int y, int b, DataBuffer data) {
482 // Bounds check for 'b' will be performed automatically
483 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
484 throw new ArrayIndexOutOfBoundsException
485 ("Coordinate out of bounds!");
486 }
487
488 float sample = data.getElemFloat(bankIndices[b],
489 y*scanlineStride + x + bandOffsets[b]);
490 return sample;
491 }
492
493 /**
494 * Returns the sample in a specified band
495 * for a pixel located at (x,y) as a double.
496 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
497 * not in bounds.
498 * @param x The X coordinate of the pixel location
499 * @param y The Y coordinate of the pixel location
500 * @param b The band to return
501 * @param data The DataBuffer containing the image data
502 * @return a double value that represents the sample in the specified
503 * band for the specified pixel.
504 */
505 public double getSampleDouble(int x, int y, int b, DataBuffer data) {
506 // Bounds check for 'b' will be performed automatically
507 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
508 throw new ArrayIndexOutOfBoundsException
509 ("Coordinate out of bounds!");
510 }
511
512 double sample = data.getElemDouble(bankIndices[b],
513 y*scanlineStride + x + bandOffsets[b]);
514 return sample;
515 }
516
517 /**
518 * Returns the samples in a specified band for the specified rectangle
519 * of pixels in an int array, one sample per data array element.
520 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
521 * not in bounds.
522 * @param x The X coordinate of the upper left pixel location
523 * @param y The Y coordinate of the upper left pixel location
524 * @param w The width of the pixel rectangle
525 * @param h The height of the pixel rectangle
526 * @param b The band to return
527 * @param iArray If non-null, returns the samples in this array
528 * @param data The DataBuffer containing the image data
529 * @return the samples in the specified band for the pixels within
530 * the specified region.
531 * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
532 */
533 public int[] getSamples(int x, int y, int w, int h, int b,
534 int iArray[], DataBuffer data) {
535 // Bounds check for 'b' will be performed automatically
536 if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
537 throw new ArrayIndexOutOfBoundsException
538 ("Coordinate out of bounds!");
539 }
540 int samples[];
541 if (iArray != null) {
542 samples = iArray;
543 } else {
544 samples = new int [w*h];
545 }
546
547 int lineOffset = y*scanlineStride + x + bandOffsets[b];
548 int srcOffset = 0;
549 int bank = bankIndices[b];
550
551 for (int i = 0; i < h; i++) {
552 int sampleOffset = lineOffset;
553 for (int j = 0; j < w; j++) {
554 samples[srcOffset++] = data.getElem(bank, sampleOffset++);
555 }
556 lineOffset += scanlineStride;
557 }
558 return samples;
559 }
560
561 /**
562 * Sets the data for a single pixel in the specified DataBuffer from a
563 * primitive array of type TransferType. For a BandedSampleModel,
564 * this will be the same as the data type, and samples are transferred
565 * one per array element.
566 * <p>
567 * The following code illustrates transferring data for one pixel from
568 * DataBuffer <code>db1</code>, whose storage layout is described by
569 * BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
570 * whose storage layout is described by
571 * BandedSampleModel <code>bsm2</code>.
572 * The transfer will generally be more efficient than using
573 * getPixel/setPixel.
574 * <pre>
575 * BandedSampleModel bsm1, bsm2;
576 * DataBufferInt db1, db2;
577 * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
578 * db2);
579 * </pre>
580 * Using getDataElements/setDataElements to transfer between two
581 * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
582 * the same number of bands, corresponding bands have the same number of
583 * bits per sample, and the TransferTypes are the same.
584 * <p>
585 * obj must be a primitive array of type TransferType. Otherwise,
586 * a ClassCastException is thrown. An
587 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
588 * not in bounds, or if obj is not large enough to hold the pixel data.
589 * @param x The X coordinate of the pixel location
590 * @param y The Y coordinate of the pixel location
591 * @param obj If non-null, returns the primitive array in this
592 * object
593 * @param data The DataBuffer containing the image data
594 * @see #getDataElements(int, int, Object, DataBuffer)
595 */
596 public void setDataElements(int x, int y, Object obj, DataBuffer data) {
597 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
598 throw new ArrayIndexOutOfBoundsException
599 ("Coordinate out of bounds!");
600 }
601 int type = getTransferType();
602 int numDataElems = getNumDataElements();
603 int pixelOffset = y*scanlineStride + x;
604
605 switch(type) {
606
607 case DataBuffer.TYPE_BYTE:
608
609 byte[] barray = (byte[])obj;
610
611 for (int i=0; i<numDataElems; i++) {
612 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
613 barray[i] & 0xff);
614 }
615 break;
616
617 case DataBuffer.TYPE_USHORT:
618 case DataBuffer.TYPE_SHORT:
619
620 short[] sarray = (short[])obj;
621
622 for (int i=0; i<numDataElems; i++) {
623 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
624 sarray[i] & 0xffff);
625 }
626 break;
627
628 case DataBuffer.TYPE_INT:
629
630 int[] iarray = (int[])obj;
631
632 for (int i=0; i<numDataElems; i++) {
633 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
634 iarray[i]);
635 }
636 break;
637
638 case DataBuffer.TYPE_FLOAT:
639
640 float[] farray = (float[])obj;
641
642 for (int i=0; i<numDataElems; i++) {
643 data.setElemFloat(bankIndices[i], pixelOffset + bandOffsets[i],
644 farray[i]);
645 }
646 break;
647
648 case DataBuffer.TYPE_DOUBLE:
649
650 double[] darray = (double[])obj;
651
652 for (int i=0; i<numDataElems; i++) {
653 data.setElemDouble(bankIndices[i], pixelOffset + bandOffsets[i],
654 darray[i]);
655 }
656 break;
657
658 }
659 }
660
661 /**
662 * Sets a pixel in the DataBuffer using an int array of samples for input.
663 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
664 * not in bounds.
665 * @param x The X coordinate of the pixel location
666 * @param y The Y coordinate of the pixel location
667 * @param iArray The input samples in an int array
668 * @param data The DataBuffer containing the image data
669 * @see #getPixel(int, int, int[], DataBuffer)
670 */
671 public void setPixel(int x, int y, int iArray[], DataBuffer data) {
672 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
673 throw new ArrayIndexOutOfBoundsException
674 ("Coordinate out of bounds!");
675 }
676 int pixelOffset = y*scanlineStride + x;
677 for (int i=0; i<numBands; i++) {
678 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
679 iArray[i]);
680 }
681 }
682
683 /**
684 * Sets all samples for a rectangle of pixels from an int array containing
685 * one sample per array element.
686 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
687 * not in bounds.
688 * @param x The X coordinate of the upper left pixel location
689 * @param y The Y coordinate of the upper left pixel location
690 * @param w The width of the pixel rectangle
691 * @param h The height of the pixel rectangle
692 * @param iArray The input samples in an int array
693 * @param data The DataBuffer containing the image data
694 * @see #getPixels(int, int, int, int, int[], DataBuffer)
695 */
696 public void setPixels(int x, int y, int w, int h,
697 int iArray[], DataBuffer data) {
698 int x1 = x + w;
699 int y1 = y + h;
700
701 if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
702 y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
703 {
704 throw new ArrayIndexOutOfBoundsException
705 ("Coordinate out of bounds!");
706 }
707
708 for (int k = 0; k < numBands; k++) {
709 int lineOffset = y*scanlineStride + x + bandOffsets[k];
710 int srcOffset = k;
711 int bank = bankIndices[k];
712
713 for (int i = 0; i < h; i++) {
714 int pixelOffset = lineOffset;
715 for (int j = 0; j < w; j++) {
716 data.setElem(bank, pixelOffset++, iArray[srcOffset]);
717 srcOffset += numBands;
718 }
719 lineOffset += scanlineStride;
720 }
721 }
722 }
723
724 /**
725 * Sets a sample in the specified band for the pixel located at (x,y)
726 * in the DataBuffer using an int for input.
727 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
728 * not in bounds.
729 * @param x The X coordinate of the pixel location
730 * @param y The Y coordinate of the pixel location
731 * @param b The band to set
732 * @param s The input sample as an int
733 * @param data The DataBuffer containing the image data
734 * @see #getSample(int, int, int, DataBuffer)
735 */
736 public void setSample(int x, int y, int b, int s,
737 DataBuffer data) {
738 // Bounds check for 'b' will be performed automatically
739 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
740 throw new ArrayIndexOutOfBoundsException
741 ("Coordinate out of bounds!");
742 }
743 data.setElem(bankIndices[b],
744 y*scanlineStride + x + bandOffsets[b], s);
745 }
746
747 /**
748 * Sets a sample in the specified band for the pixel located at (x,y)
749 * in the DataBuffer using a float for input.
750 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
751 * not in bounds.
752 * @param x The X coordinate of the pixel location
753 * @param y The Y coordinate of the pixel location
754 * @param b The band to set
755 * @param s The input sample as a float
756 * @param data The DataBuffer containing the image data
757 * @see #getSample(int, int, int, DataBuffer)
758 */
759 public void setSample(int x, int y, int b,
760 float s ,
761 DataBuffer data) {
762 // Bounds check for 'b' will be performed automatically
763 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
764 throw new ArrayIndexOutOfBoundsException
765 ("Coordinate out of bounds!");
766 }
767 data.setElemFloat(bankIndices[b],
768 y*scanlineStride + x + bandOffsets[b], s);
769 }
770
771 /**
772 * Sets a sample in the specified band for the pixel located at (x,y)
773 * in the DataBuffer using a double for input.
774 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
775 * not in bounds.
776 * @param x The X coordinate of the pixel location
777 * @param y The Y coordinate of the pixel location
778 * @param b The band to set
779 * @param s The input sample as a double
780 * @param data The DataBuffer containing the image data
781 * @see #getSample(int, int, int, DataBuffer)
782 */
783 public void setSample(int x, int y, int b,
784 double s,
785 DataBuffer data) {
786 // Bounds check for 'b' will be performed automatically
787 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
788 throw new ArrayIndexOutOfBoundsException
789 ("Coordinate out of bounds!");
790 }
791 data.setElemDouble(bankIndices[b],
792 y*scanlineStride + x + bandOffsets[b], s);
793 }
794
795 /**
796 * Sets the samples in the specified band for the specified rectangle
797 * of pixels from an int array containing one sample per data array element.
798 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
799 * not in bounds.
800 * @param x The X coordinate of the upper left pixel location
801 * @param y The Y coordinate of the upper left pixel location
802 * @param w The width of the pixel rectangle
803 * @param h The height of the pixel rectangle
804 * @param b The band to set
805 * @param iArray The input sample array
806 * @param data The DataBuffer containing the image data
807 * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
808 */
809 public void setSamples(int x, int y, int w, int h, int b,
810 int iArray[], DataBuffer data) {
811 // Bounds check for 'b' will be performed automatically
812 if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
813 throw new ArrayIndexOutOfBoundsException
814 ("Coordinate out of bounds!");
815 }
816 int lineOffset = y*scanlineStride + x + bandOffsets[b];
817 int srcOffset = 0;
818 int bank = bankIndices[b];
819
820 for (int i = 0; i < h; i++) {
821 int sampleOffset = lineOffset;
822 for (int j = 0; j < w; j++) {
823 data.setElem(bank, sampleOffset++, iArray[srcOffset++]);
824 }
825 lineOffset += scanlineStride;
826 }
827 }
828
829 private static int[] createOffsetArray(int numBands) {
830 int[] bandOffsets = new int[numBands];
831 for (int i=0; i < numBands; i++) {
832 bandOffsets[i] = 0;
833 }
834 return bandOffsets;
835 }
836
837 private static int[] createIndicesArray(int numBands) {
838 int[] bankIndices = new int[numBands];
839 for (int i=0; i < numBands; i++) {
840 bankIndices[i] = i;
841 }
842 return bankIndices;
843 }
844
845 // Differentiate hash code from other ComponentSampleModel subclasses
846 public int hashCode() {
847 return super.hashCode() ^ 0x2;
848 }
849}
java/pkg/java/awt/image/BufferStrategy.class+0−0

Binary file not shown.

java/pkg/java/awt/image/BufferStrategy.java+205−0
@@ -0,0 +1,205 @@
1/*
2 * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.BufferCapabilities;
29import java.awt.Graphics;
30import java.awt.Image;
31
32/**
33 * The <code>BufferStrategy</code> class represents the mechanism with which
34 * to organize complex memory on a particular <code>Canvas</code> or
35 * <code>Window</code>. Hardware and software limitations determine whether and
36 * how a particular buffer strategy can be implemented. These limitations
37 * are detectible through the capabilities of the
38 * <code>GraphicsConfiguration</code> used when creating the
39 * <code>Canvas</code> or <code>Window</code>.
40 * <p>
41 * It is worth noting that the terms <i>buffer</i> and <i>surface</i> are meant
42 * to be synonymous: an area of contiguous memory, either in video device
43 * memory or in system memory.
44 * <p>
45 * There are several types of complex buffer strategies, including
46 * sequential ring buffering and blit buffering.
47 * Sequential ring buffering (i.e., double or triple
48 * buffering) is the most common; an application draws to a single <i>back
49 * buffer</i> and then moves the contents to the front (display) in a single
50 * step, either by copying the data or moving the video pointer.
51 * Moving the video pointer exchanges the buffers so that the first buffer
52 * drawn becomes the <i>front buffer</i>, or what is currently displayed on the
53 * device; this is called <i>page flipping</i>.
54 * <p>
55 * Alternatively, the contents of the back buffer can be copied, or
56 * <i>blitted</i> forward in a chain instead of moving the video pointer.
57 * <p>
58 * <pre>
59 * Double buffering:
60 *
61 * *********** ***********
62 * * * ------> * *
63 * [To display] <---- * Front B * Show * Back B. * <---- Rendering
64 * * * <------ * *
65 * *********** ***********
66 *
67 * Triple buffering:
68 *
69 * [To *********** *********** ***********
70 * display] * * --------+---------+------> * *
71 * <---- * Front B * Show * Mid. B. * * Back B. * <---- Rendering
72 * * * <------ * * <----- * *
73 * *********** *********** ***********
74 *
75 * </pre>
76 * <p>
77 * Here is an example of how buffer strategies can be created and used:
78 * <pre><code>
79 *
80 * // Check the capabilities of the GraphicsConfiguration
81 * ...
82 *
83 * // Create our component
84 * Window w = new Window(gc);
85 *
86 * // Show our window
87 * w.setVisible(true);
88 *
89 * // Create a general double-buffering strategy
90 * w.createBufferStrategy(2);
91 * BufferStrategy strategy = w.getBufferStrategy();
92 *
93 * // Main loop
94 * while (!done) {
95 * // Prepare for rendering the next frame
96 * // ...
97 *
98 * // Render single frame
99 * do {
100 * // The following loop ensures that the contents of the drawing buffer
101 * // are consistent in case the underlying surface was recreated
102 * do {
103 * // Get a new graphics context every time through the loop
104 * // to make sure the strategy is validated
105 * Graphics graphics = strategy.getDrawGraphics();
106 *
107 * // Render to graphics
108 * // ...
109 *
110 * // Dispose the graphics
111 * graphics.dispose();
112 *
113 * // Repeat the rendering if the drawing buffer contents
114 * // were restored
115 * } while (strategy.contentsRestored());
116 *
117 * // Display the buffer
118 * strategy.show();
119 *
120 * // Repeat the rendering if the drawing buffer was lost
121 * } while (strategy.contentsLost());
122 * }
123 *
124 * // Dispose the window
125 * w.setVisible(false);
126 * w.dispose();
127 * </code></pre>
128 *
129 * @see java.awt.Window
130 * @see java.awt.Canvas
131 * @see java.awt.GraphicsConfiguration
132 * @see VolatileImage
133 * @author Michael Martak
134 * @since 1.4
135 */
136public abstract class BufferStrategy {
137
138 /**
139 * Returns the <code>BufferCapabilities</code> for this
140 * <code>BufferStrategy</code>.
141 *
142 * @return the buffering capabilities of this strategy
143 */
144 public abstract BufferCapabilities getCapabilities();
145
146 /**
147 * Creates a graphics context for the drawing buffer. This method may not
148 * be synchronized for performance reasons; use of this method by multiple
149 * threads should be handled at the application level. Disposal of the
150 * graphics object obtained must be handled by the application.
151 *
152 * @return a graphics context for the drawing buffer
153 */
154 public abstract Graphics getDrawGraphics();
155
156 /**
157 * Returns whether the drawing buffer was lost since the last call to
158 * <code>getDrawGraphics</code>. Since the buffers in a buffer strategy
159 * are usually type <code>VolatileImage</code>, they may become lost.
160 * For a discussion on lost buffers, see <code>VolatileImage</code>.
161 *
162 * @return Whether or not the drawing buffer was lost since the last call
163 * to <code>getDrawGraphics</code>.
164 * @see java.awt.image.VolatileImage
165 */
166 public abstract boolean contentsLost();
167
168 /**
169 * Returns whether the drawing buffer was recently restored from a lost
170 * state and reinitialized to the default background color (white).
171 * Since the buffers in a buffer strategy are usually type
172 * <code>VolatileImage</code>, they may become lost. If a surface has
173 * been recently restored from a lost state since the last call to
174 * <code>getDrawGraphics</code>, it may require repainting.
175 * For a discussion on lost buffers, see <code>VolatileImage</code>.
176 *
177 * @return Whether or not the drawing buffer was restored since the last
178 * call to <code>getDrawGraphics</code>.
179 * @see java.awt.image.VolatileImage
180 */
181 public abstract boolean contentsRestored();
182
183 /**
184 * Makes the next available buffer visible by either copying the memory
185 * (blitting) or changing the display pointer (flipping).
186 */
187 public abstract void show();
188
189 /**
190 * Releases system resources currently consumed by this
191 * <code>BufferStrategy</code> and
192 * removes it from the associated Component. After invoking this
193 * method, <code>getBufferStrategy</code> will return null. Trying
194 * to use a <code>BufferStrategy</code> after it has been disposed will
195 * result in undefined behavior.
196 *
197 * @see java.awt.Window#createBufferStrategy
198 * @see java.awt.Canvas#createBufferStrategy
199 * @see java.awt.Window#getBufferStrategy
200 * @see java.awt.Canvas#getBufferStrategy
201 * @since 1.6
202 */
203 public void dispose() {
204 }
205}
java/pkg/java/awt/image/BufferedImage.class+0−0

Binary file not shown.

java/pkg/java/awt/image/BufferedImage.java+1609−0
@@ -0,0 +1,1609 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.Transparency;
29import java.awt.color.ColorSpace;
30import java.awt.Graphics2D;
31import java.awt.GraphicsConfiguration;
32import java.awt.GraphicsEnvironment;
33import java.awt.ImageCapabilities;
34import java.awt.geom.Rectangle2D;
35import java.awt.geom.Point2D;
36import java.awt.Point;
37import java.awt.Rectangle;
38import java.util.Hashtable;
39import java.util.Vector;
40
41import sun.awt.image.BytePackedRaster;
42import sun.awt.image.ShortComponentRaster;
43import sun.awt.image.ByteComponentRaster;
44import sun.awt.image.IntegerComponentRaster;
45import sun.awt.image.OffScreenImageSource;
46
47/**
48 *
49 * The <code>BufferedImage</code> subclass describes an {@link
50 * java.awt.Image Image} with an accessible buffer of image data.
51 * A <code>BufferedImage</code> is comprised of a {@link ColorModel} and a
52 * {@link Raster} of image data.
53 * The number and types of bands in the {@link SampleModel} of the
54 * <code>Raster</code> must match the number and types required by the
55 * <code>ColorModel</code> to represent its color and alpha components.
56 * All <code>BufferedImage</code> objects have an upper left corner
57 * coordinate of (0,&nbsp;0). Any <code>Raster</code> used to construct a
58 * <code>BufferedImage</code> must therefore have minX=0 and minY=0.
59 *
60 * <p>
61 * This class relies on the data fetching and setting methods
62 * of <code>Raster</code>,
63 * and on the color characterization methods of <code>ColorModel</code>.
64 *
65 * @see ColorModel
66 * @see Raster
67 * @see WritableRaster
68 */
69
70public class BufferedImage extends java.awt.Image
71 implements WritableRenderedImage, Transparency
72{
73 int imageType = TYPE_CUSTOM;
74 ColorModel colorModel;
75 WritableRaster raster;
76 OffScreenImageSource osis;
77 Hashtable properties;
78
79 boolean isAlphaPremultiplied;// If true, alpha has been premultiplied in
80 // color channels
81
82 /**
83 * Image Type Constants
84 */
85
86 /**
87 * Image type is not recognized so it must be a customized
88 * image. This type is only used as a return value for the getType()
89 * method.
90 */
91 public static final int TYPE_CUSTOM = 0;
92
93 /**
94 * Represents an image with 8-bit RGB color components packed into
95 * integer pixels. The image has a {@link DirectColorModel} without
96 * alpha.
97 * When data with non-opaque alpha is stored
98 * in an image of this type,
99 * the color data must be adjusted to a non-premultiplied form
100 * and the alpha discarded,
101 * as described in the
102 * {@link java.awt.AlphaComposite} documentation.
103 */
104 public static final int TYPE_INT_RGB = 1;
105
106 /**
107 * Represents an image with 8-bit RGBA color components packed into
108 * integer pixels. The image has a <code>DirectColorModel</code>
109 * with alpha. The color data in this image is considered not to be
110 * premultiplied with alpha. When this type is used as the
111 * <code>imageType</code> argument to a <code>BufferedImage</code>
112 * constructor, the created image is consistent with images
113 * created in the JDK1.1 and earlier releases.
114 */
115 public static final int TYPE_INT_ARGB = 2;
116
117 /**
118 * Represents an image with 8-bit RGBA color components packed into
119 * integer pixels. The image has a <code>DirectColorModel</code>
120 * with alpha. The color data in this image is considered to be
121 * premultiplied with alpha.
122 */
123 public static final int TYPE_INT_ARGB_PRE = 3;
124
125 /**
126 * Represents an image with 8-bit RGB color components, corresponding
127 * to a Windows- or Solaris- style BGR color model, with the colors
128 * Blue, Green, and Red packed into integer pixels. There is no alpha.
129 * The image has a {@link DirectColorModel}.
130 * When data with non-opaque alpha is stored
131 * in an image of this type,
132 * the color data must be adjusted to a non-premultiplied form
133 * and the alpha discarded,
134 * as described in the
135 * {@link java.awt.AlphaComposite} documentation.
136 */
137 public static final int TYPE_INT_BGR = 4;
138
139 /**
140 * Represents an image with 8-bit RGB color components, corresponding
141 * to a Windows-style BGR color model) with the colors Blue, Green,
142 * and Red stored in 3 bytes. There is no alpha. The image has a
143 * <code>ComponentColorModel</code>.
144 * When data with non-opaque alpha is stored
145 * in an image of this type,
146 * the color data must be adjusted to a non-premultiplied form
147 * and the alpha discarded,
148 * as described in the
149 * {@link java.awt.AlphaComposite} documentation.
150 */
151 public static final int TYPE_3BYTE_BGR = 5;
152
153 /**
154 * Represents an image with 8-bit RGBA color components with the colors
155 * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The
156 * image has a <code>ComponentColorModel</code> with alpha. The
157 * color data in this image is considered not to be premultiplied with
158 * alpha. The byte data is interleaved in a single
159 * byte array in the order A, B, G, R
160 * from lower to higher byte addresses within each pixel.
161 */
162 public static final int TYPE_4BYTE_ABGR = 6;
163
164 /**
165 * Represents an image with 8-bit RGBA color components with the colors
166 * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The
167 * image has a <code>ComponentColorModel</code> with alpha. The color
168 * data in this image is considered to be premultiplied with alpha.
169 * The byte data is interleaved in a single byte array in the order
170 * A, B, G, R from lower to higher byte addresses within each pixel.
171 */
172 public static final int TYPE_4BYTE_ABGR_PRE = 7;
173
174 /**
175 * Represents an image with 5-6-5 RGB color components (5-bits red,
176 * 6-bits green, 5-bits blue) with no alpha. This image has
177 * a <code>DirectColorModel</code>.
178 * When data with non-opaque alpha is stored
179 * in an image of this type,
180 * the color data must be adjusted to a non-premultiplied form
181 * and the alpha discarded,
182 * as described in the
183 * {@link java.awt.AlphaComposite} documentation.
184 */
185 public static final int TYPE_USHORT_565_RGB = 8;
186
187 /**
188 * Represents an image with 5-5-5 RGB color components (5-bits red,
189 * 5-bits green, 5-bits blue) with no alpha. This image has
190 * a <code>DirectColorModel</code>.
191 * When data with non-opaque alpha is stored
192 * in an image of this type,
193 * the color data must be adjusted to a non-premultiplied form
194 * and the alpha discarded,
195 * as described in the
196 * {@link java.awt.AlphaComposite} documentation.
197 */
198 public static final int TYPE_USHORT_555_RGB = 9;
199
200 /**
201 * Represents a unsigned byte grayscale image, non-indexed. This
202 * image has a <code>ComponentColorModel</code> with a CS_GRAY
203 * {@link ColorSpace}.
204 * When data with non-opaque alpha is stored
205 * in an image of this type,
206 * the color data must be adjusted to a non-premultiplied form
207 * and the alpha discarded,
208 * as described in the
209 * {@link java.awt.AlphaComposite} documentation.
210 */
211 public static final int TYPE_BYTE_GRAY = 10;
212
213 /**
214 * Represents an unsigned short grayscale image, non-indexed). This
215 * image has a <code>ComponentColorModel</code> with a CS_GRAY
216 * <code>ColorSpace</code>.
217 * When data with non-opaque alpha is stored
218 * in an image of this type,
219 * the color data must be adjusted to a non-premultiplied form
220 * and the alpha discarded,
221 * as described in the
222 * {@link java.awt.AlphaComposite} documentation.
223 */
224 public static final int TYPE_USHORT_GRAY = 11;
225
226 /**
227 * Represents an opaque byte-packed 1, 2, or 4 bit image. The
228 * image has an {@link IndexColorModel} without alpha. When this
229 * type is used as the <code>imageType</code> argument to the
230 * <code>BufferedImage</code> constructor that takes an
231 * <code>imageType</code> argument but no <code>ColorModel</code>
232 * argument, a 1-bit image is created with an
233 * <code>IndexColorModel</code> with two colors in the default
234 * sRGB <code>ColorSpace</code>: {0,&nbsp;0,&nbsp;0} and
235 * {255,&nbsp;255,&nbsp;255}.
236 *
237 * <p> Images with 2 or 4 bits per pixel may be constructed via
238 * the <code>BufferedImage</code> constructor that takes a
239 * <code>ColorModel</code> argument by supplying a
240 * <code>ColorModel</code> with an appropriate map size.
241 *
242 * <p> Images with 8 bits per pixel should use the image types
243 * <code>TYPE_BYTE_INDEXED</code> or <code>TYPE_BYTE_GRAY</code>
244 * depending on their <code>ColorModel</code>.
245
246 * <p> When color data is stored in an image of this type,
247 * the closest color in the colormap is determined
248 * by the <code>IndexColorModel</code> and the resulting index is stored.
249 * Approximation and loss of alpha or color components
250 * can result, depending on the colors in the
251 * <code>IndexColorModel</code> colormap.
252 */
253 public static final int TYPE_BYTE_BINARY = 12;
254
255 /**
256 * Represents an indexed byte image. When this type is used as the
257 * <code>imageType</code> argument to the <code>BufferedImage</code>
258 * constructor that takes an <code>imageType</code> argument
259 * but no <code>ColorModel</code> argument, an
260 * <code>IndexColorModel</code> is created with
261 * a 256-color 6/6/6 color cube palette with the rest of the colors
262 * from 216-255 populated by grayscale values in the
263 * default sRGB ColorSpace.
264 *
265 * <p> When color data is stored in an image of this type,
266 * the closest color in the colormap is determined
267 * by the <code>IndexColorModel</code> and the resulting index is stored.
268 * Approximation and loss of alpha or color components
269 * can result, depending on the colors in the
270 * <code>IndexColorModel</code> colormap.
271 */
272 public static final int TYPE_BYTE_INDEXED = 13;
273
274 private static final int DCM_RED_MASK = 0x00ff0000;
275 private static final int DCM_GREEN_MASK = 0x0000ff00;
276 private static final int DCM_BLUE_MASK = 0x000000ff;
277 private static final int DCM_ALPHA_MASK = 0xff000000;
278 private static final int DCM_565_RED_MASK = 0xf800;
279 private static final int DCM_565_GRN_MASK = 0x07E0;
280 private static final int DCM_565_BLU_MASK = 0x001F;
281 private static final int DCM_555_RED_MASK = 0x7C00;
282 private static final int DCM_555_GRN_MASK = 0x03E0;
283 private static final int DCM_555_BLU_MASK = 0x001F;
284 private static final int DCM_BGR_RED_MASK = 0x0000ff;
285 private static final int DCM_BGR_GRN_MASK = 0x00ff00;
286 private static final int DCM_BGR_BLU_MASK = 0xff0000;
287
288
289 static private native void initIDs();
290 static {
291 ColorModel.loadLibraries();
292 initIDs();
293 }
294
295 /**
296 * Constructs a <code>BufferedImage</code> of one of the predefined
297 * image types. The <code>ColorSpace</code> for the image is the
298 * default sRGB space.
299 * @param width width of the created image
300 * @param height height of the created image
301 * @param imageType type of the created image
302 * @see ColorSpace
303 * @see #TYPE_INT_RGB
304 * @see #TYPE_INT_ARGB
305 * @see #TYPE_INT_ARGB_PRE
306 * @see #TYPE_INT_BGR
307 * @see #TYPE_3BYTE_BGR
308 * @see #TYPE_4BYTE_ABGR
309 * @see #TYPE_4BYTE_ABGR_PRE
310 * @see #TYPE_BYTE_GRAY
311 * @see #TYPE_USHORT_GRAY
312 * @see #TYPE_BYTE_BINARY
313 * @see #TYPE_BYTE_INDEXED
314 * @see #TYPE_USHORT_565_RGB
315 * @see #TYPE_USHORT_555_RGB
316 */
317 public BufferedImage(int width,
318 int height,
319 int imageType) {
320 switch (imageType) {
321 case TYPE_INT_RGB:
322 {
323 colorModel = new DirectColorModel(24,
324 0x00ff0000, // Red
325 0x0000ff00, // Green
326 0x000000ff, // Blue
327 0x0 // Alpha
328 );
329 raster = colorModel.createCompatibleWritableRaster(width,
330 height);
331 }
332 break;
333
334 case TYPE_INT_ARGB:
335 {
336 colorModel = ColorModel.getRGBdefault();
337
338 raster = colorModel.createCompatibleWritableRaster(width,
339 height);
340 }
341 break;
342
343 case TYPE_INT_ARGB_PRE:
344 {
345 colorModel = new
346 DirectColorModel(
347 ColorSpace.getInstance(ColorSpace.CS_sRGB),
348 32,
349 0x00ff0000,// Red
350 0x0000ff00,// Green
351 0x000000ff,// Blue
352 0xff000000,// Alpha
353 true, // Alpha Premultiplied
354 DataBuffer.TYPE_INT
355 );
356
357 raster = colorModel.createCompatibleWritableRaster(width,
358 height);
359 }
360 break;
361
362 case TYPE_INT_BGR:
363 {
364 colorModel = new DirectColorModel(24,
365 0x000000ff, // Red
366 0x0000ff00, // Green
367 0x00ff0000 // Blue
368 );
369 raster = colorModel.createCompatibleWritableRaster(width,
370 height);
371 }
372 break;
373
374 case TYPE_3BYTE_BGR:
375 {
376 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
377 int[] nBits = {8, 8, 8};
378 int[] bOffs = {2, 1, 0};
379 colorModel = new ComponentColorModel(cs, nBits, false, false,
380 Transparency.OPAQUE,
381 DataBuffer.TYPE_BYTE);
382 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
383 width, height,
384 width*3, 3,
385 bOffs, null);
386 }
387 break;
388
389 case TYPE_4BYTE_ABGR:
390 {
391 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
392 int[] nBits = {8, 8, 8, 8};
393 int[] bOffs = {3, 2, 1, 0};
394 colorModel = new ComponentColorModel(cs, nBits, true, false,
395 Transparency.TRANSLUCENT,
396 DataBuffer.TYPE_BYTE);
397 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
398 width, height,
399 width*4, 4,
400 bOffs, null);
401 }
402 break;
403
404 case TYPE_4BYTE_ABGR_PRE:
405 {
406 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
407 int[] nBits = {8, 8, 8, 8};
408 int[] bOffs = {3, 2, 1, 0};
409 colorModel = new ComponentColorModel(cs, nBits, true, true,
410 Transparency.TRANSLUCENT,
411 DataBuffer.TYPE_BYTE);
412 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
413 width, height,
414 width*4, 4,
415 bOffs, null);
416 }
417 break;
418
419 case TYPE_BYTE_GRAY:
420 {
421 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
422 int[] nBits = {8};
423 colorModel = new ComponentColorModel(cs, nBits, false, true,
424 Transparency.OPAQUE,
425 DataBuffer.TYPE_BYTE);
426 raster = colorModel.createCompatibleWritableRaster(width,
427 height);
428 }
429 break;
430
431 case TYPE_USHORT_GRAY:
432 {
433 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
434 int[] nBits = {16};
435 colorModel = new ComponentColorModel(cs, nBits, false, true,
436 Transparency.OPAQUE,
437 DataBuffer.TYPE_USHORT);
438 raster = colorModel.createCompatibleWritableRaster(width,
439 height);
440 }
441 break;
442
443 case TYPE_BYTE_BINARY:
444 {
445 byte[] arr = {(byte)0, (byte)0xff};
446
447 colorModel = new IndexColorModel(1, 2, arr, arr, arr);
448 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
449 width, height, 1, 1, null);
450 }
451 break;
452
453 case TYPE_BYTE_INDEXED:
454 {
455 // Create a 6x6x6 color cube
456 int[] cmap = new int[256];
457 int i=0;
458 for (int r=0; r < 256; r += 51) {
459 for (int g=0; g < 256; g += 51) {
460 for (int b=0; b < 256; b += 51) {
461 cmap[i++] = (r<<16)|(g<<8)|b;
462 }
463 }
464 }
465 // And populate the rest of the cmap with gray values
466 int grayIncr = 256/(256-i);
467
468 // The gray ramp will be between 18 and 252
469 int gray = grayIncr*3;
470 for (; i < 256; i++) {
471 cmap[i] = (gray<<16)|(gray<<8)|gray;
472 gray += grayIncr;
473 }
474
475 colorModel = new IndexColorModel(8, 256, cmap, 0, false, -1,
476 DataBuffer.TYPE_BYTE);
477 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
478 width, height, 1, null);
479 }
480 break;
481
482 case TYPE_USHORT_565_RGB:
483 {
484 colorModel = new DirectColorModel(16,
485 DCM_565_RED_MASK,
486 DCM_565_GRN_MASK,
487 DCM_565_BLU_MASK
488 );
489 raster = colorModel.createCompatibleWritableRaster(width,
490 height);
491 }
492 break;
493
494 case TYPE_USHORT_555_RGB:
495 {
496 colorModel = new DirectColorModel(15,
497 DCM_555_RED_MASK,
498 DCM_555_GRN_MASK,
499 DCM_555_BLU_MASK
500 );
501 raster = colorModel.createCompatibleWritableRaster(width,
502 height);
503 }
504 break;
505
506 default:
507 throw new IllegalArgumentException ("Unknown image type " +
508 imageType);
509 }
510
511 this.imageType = imageType;
512 }
513
514 /**
515 * Constructs a <code>BufferedImage</code> of one of the predefined
516 * image types:
517 * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED.
518 *
519 * <p> If the image type is TYPE_BYTE_BINARY, the number of
520 * entries in the color model is used to determine whether the
521 * image should have 1, 2, or 4 bits per pixel. If the color model
522 * has 1 or 2 entries, the image will have 1 bit per pixel. If it
523 * has 3 or 4 entries, the image with have 2 bits per pixel. If
524 * it has between 5 and 16 entries, the image will have 4 bits per
525 * pixel. Otherwise, an IllegalArgumentException will be thrown.
526 *
527 * @param width width of the created image
528 * @param height height of the created image
529 * @param imageType type of the created image
530 * @param cm <code>IndexColorModel</code> of the created image
531 * @throws IllegalArgumentException if the imageType is not
532 * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED or if the imageType is
533 * TYPE_BYTE_BINARY and the color map has more than 16 entries.
534 * @see #TYPE_BYTE_BINARY
535 * @see #TYPE_BYTE_INDEXED
536 */
537 public BufferedImage (int width,
538 int height,
539 int imageType,
540 IndexColorModel cm) {
541 if (cm.hasAlpha() && cm.isAlphaPremultiplied()) {
542 throw new IllegalArgumentException("This image types do not have "+
543 "premultiplied alpha.");
544 }
545
546 switch(imageType) {
547 case TYPE_BYTE_BINARY:
548 int bits; // Will be set below
549 int mapSize = cm.getMapSize();
550 if (mapSize <= 2) {
551 bits = 1;
552 } else if (mapSize <= 4) {
553 bits = 2;
554 } else if (mapSize <= 16) {
555 bits = 4;
556 } else {
557 throw new IllegalArgumentException
558 ("Color map for TYPE_BYTE_BINARY " +
559 "must have no more than 16 entries");
560 }
561 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
562 width, height, 1, bits, null);
563 break;
564
565 case TYPE_BYTE_INDEXED:
566 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
567 width, height, 1, null);
568 break;
569 default:
570 throw new IllegalArgumentException("Invalid image type (" +
571 imageType+"). Image type must"+
572 " be either TYPE_BYTE_BINARY or "+
573 " TYPE_BYTE_INDEXED");
574 }
575
576 if (!cm.isCompatibleRaster(raster)) {
577 throw new IllegalArgumentException("Incompatible image type and IndexColorModel");
578 }
579
580 colorModel = cm;
581 this.imageType = imageType;
582 }
583
584 /**
585 * Constructs a new <code>BufferedImage</code> with a specified
586 * <code>ColorModel</code> and <code>Raster</code>. If the number and
587 * types of bands in the <code>SampleModel</code> of the
588 * <code>Raster</code> do not match the number and types required by
589 * the <code>ColorModel</code> to represent its color and alpha
590 * components, a {@link RasterFormatException} is thrown. This
591 * method can multiply or divide the color <code>Raster</code> data by
592 * alpha to match the <code>alphaPremultiplied</code> state
593 * in the <code>ColorModel</code>. Properties for this
594 * <code>BufferedImage</code> can be established by passing
595 * in a {@link Hashtable} of <code>String</code>/<code>Object</code>
596 * pairs.
597 * @param cm <code>ColorModel</code> for the new image
598 * @param raster <code>Raster</code> for the image data
599 * @param isRasterPremultiplied if <code>true</code>, the data in
600 * the raster has been premultiplied with alpha.
601 * @param properties <code>Hashtable</code> of
602 * <code>String</code>/<code>Object</code> pairs.
603 * @exception <code>RasterFormatException</code> if the number and
604 * types of bands in the <code>SampleModel</code> of the
605 * <code>Raster</code> do not match the number and types required by
606 * the <code>ColorModel</code> to represent its color and alpha
607 * components.
608 * @exception <code>IllegalArgumentException</code> if
609 * <code>raster</code> is incompatible with <code>cm</code>
610 * @see ColorModel
611 * @see Raster
612 * @see WritableRaster
613 */
614
615
616/*
617 *
618 * FOR NOW THE CODE WHICH DEFINES THE RASTER TYPE IS DUPLICATED BY DVF
619 * SEE THE METHOD DEFINERASTERTYPE @ RASTEROUTPUTMANAGER
620 *
621 */
622 public BufferedImage (ColorModel cm,
623 WritableRaster raster,
624 boolean isRasterPremultiplied,
625 Hashtable<?,?> properties) {
626
627 if (!cm.isCompatibleRaster(raster)) {
628 throw new
629 IllegalArgumentException("Raster "+raster+
630 " is incompatible with ColorModel "+
631 cm);
632 }
633
634 if ((raster.minX != 0) || (raster.minY != 0)) {
635 throw new
636 IllegalArgumentException("Raster "+raster+
637 " has minX or minY not equal to zero: "
638 + raster.minX + " " + raster.minY);
639 }
640
641 colorModel = cm;
642 this.raster = raster;
643 this.properties = properties;
644 int numBands = raster.getNumBands();
645 boolean isAlphaPre = cm.isAlphaPremultiplied();
646 ColorSpace cs;
647
648 // Force the raster data alpha state to match the premultiplied
649 // state in the color model
650 coerceData(isRasterPremultiplied);
651
652 SampleModel sm = raster.getSampleModel();
653 cs = cm.getColorSpace();
654 int csType = cs.getType();
655 if (csType != ColorSpace.TYPE_RGB) {
656 if (csType == ColorSpace.TYPE_GRAY
657 && cm instanceof ComponentColorModel) {
658 // Check if this might be a child raster (fix for bug 4240596)
659 if (sm instanceof ComponentSampleModel &&
660 ((ComponentSampleModel)sm).getPixelStride() != numBands) {
661 imageType = TYPE_CUSTOM;
662 } else if (raster instanceof ByteComponentRaster &&
663 raster.getNumBands() == 1 &&
664 cm.getComponentSize(0) == 8 &&
665 ((ByteComponentRaster)raster).getPixelStride() == 1) {
666 imageType = TYPE_BYTE_GRAY;
667 } else if (raster instanceof ShortComponentRaster &&
668 raster.getNumBands() == 1 &&
669 cm.getComponentSize(0) == 16 &&
670 ((ShortComponentRaster)raster).getPixelStride() == 1) {
671 imageType = TYPE_USHORT_GRAY;
672 }
673 } else {
674 imageType = TYPE_CUSTOM;
675 }
676 return;
677 }
678
679 if ((raster instanceof IntegerComponentRaster) &&
680 (numBands == 3 || numBands == 4)) {
681 IntegerComponentRaster iraster =
682 (IntegerComponentRaster) raster;
683 // Check if the raster params and the color model
684 // are correct
685 int pixSize = cm.getPixelSize();
686 if (iraster.getPixelStride() == 1 &&
687 cm instanceof DirectColorModel &&
688 (pixSize == 32 || pixSize == 24))
689 {
690 // Now check on the DirectColorModel params
691 DirectColorModel dcm = (DirectColorModel) cm;
692 int rmask = dcm.getRedMask();
693 int gmask = dcm.getGreenMask();
694 int bmask = dcm.getBlueMask();
695 if (rmask == DCM_RED_MASK && gmask == DCM_GREEN_MASK &&
696 bmask == DCM_BLUE_MASK)
697 {
698 if (dcm.getAlphaMask() == DCM_ALPHA_MASK) {
699 imageType = (isAlphaPre
700 ? TYPE_INT_ARGB_PRE
701 : TYPE_INT_ARGB);
702 }
703 else {
704 // No Alpha
705 if (!dcm.hasAlpha()) {
706 imageType = TYPE_INT_RGB;
707 }
708 }
709 } // if (dcm.getRedMask() == DCM_RED_MASK &&
710 else if (rmask == DCM_BGR_RED_MASK && gmask == DCM_BGR_GRN_MASK
711 && bmask == DCM_BGR_BLU_MASK) {
712 if (!dcm.hasAlpha()) {
713 imageType = TYPE_INT_BGR;
714 }
715 } // if (rmask == DCM_BGR_RED_MASK &&
716 } // if (iraster.getPixelStride() == 1
717 } // ((raster instanceof IntegerComponentRaster) &&
718 else if ((cm instanceof IndexColorModel) && (numBands == 1) &&
719 (!cm.hasAlpha() || !isAlphaPre))
720 {
721 IndexColorModel icm = (IndexColorModel) cm;
722 int pixSize = icm.getPixelSize();
723
724 if (raster instanceof BytePackedRaster) {
725 imageType = TYPE_BYTE_BINARY;
726 } // if (raster instanceof BytePackedRaster)
727 else if (raster instanceof ByteComponentRaster) {
728 ByteComponentRaster braster = (ByteComponentRaster) raster;
729 if (braster.getPixelStride() == 1 && pixSize <= 8) {
730 imageType = TYPE_BYTE_INDEXED;
731 }
732 }
733 } // else if (cm instanceof IndexColorModel) && (numBands == 1))
734 else if ((raster instanceof ShortComponentRaster)
735 && (cm instanceof DirectColorModel)
736 && (numBands == 3)
737 && !cm.hasAlpha())
738 {
739 DirectColorModel dcm = (DirectColorModel) cm;
740 if (dcm.getRedMask() == DCM_565_RED_MASK) {
741 if (dcm.getGreenMask() == DCM_565_GRN_MASK &&
742 dcm.getBlueMask() == DCM_565_BLU_MASK) {
743 imageType = TYPE_USHORT_565_RGB;
744 }
745 }
746 else if (dcm.getRedMask() == DCM_555_RED_MASK) {
747 if (dcm.getGreenMask() == DCM_555_GRN_MASK &&
748 dcm.getBlueMask() == DCM_555_BLU_MASK) {
749 imageType = TYPE_USHORT_555_RGB;
750 }
751 }
752 } // else if ((cm instanceof IndexColorModel) && (numBands == 1))
753 else if ((raster instanceof ByteComponentRaster)
754 && (cm instanceof ComponentColorModel)
755 && (raster.getSampleModel() instanceof PixelInterleavedSampleModel)
756 && (numBands == 3 || numBands == 4))
757 {
758 ComponentColorModel ccm = (ComponentColorModel) cm;
759 PixelInterleavedSampleModel csm =
760 (PixelInterleavedSampleModel)raster.getSampleModel();
761 ByteComponentRaster braster = (ByteComponentRaster) raster;
762 int[] offs = csm.getBandOffsets();
763 if (ccm.getNumComponents() != numBands) {
764 throw new RasterFormatException("Number of components in "+
765 "ColorModel ("+
766 ccm.getNumComponents()+
767 ") does not match # in "+
768 " Raster ("+numBands+")");
769 }
770 int[] nBits = ccm.getComponentSize();
771 boolean is8bit = true;
772 for (int i=0; i < numBands; i++) {
773 if (nBits[i] != 8) {
774 is8bit = false;
775 break;
776 }
777 }
778 if (is8bit &&
779 offs[0] == numBands-1 &&
780 offs[1] == numBands-2 &&
781 offs[2] == numBands-3)
782 {
783 if (numBands == 3) {
784 imageType = TYPE_3BYTE_BGR;
785 }
786 else if (offs[3] == 0) {
787 imageType = (isAlphaPre
788 ? TYPE_4BYTE_ABGR_PRE
789 : TYPE_4BYTE_ABGR);
790 }
791 }
792 } // else if ((raster instanceof ByteComponentRaster) &&
793 }
794
795 /**
796 * Returns the image type. If it is not one of the known types,
797 * TYPE_CUSTOM is returned.
798 * @return the image type of this <code>BufferedImage</code>.
799 * @see #TYPE_INT_RGB
800 * @see #TYPE_INT_ARGB
801 * @see #TYPE_INT_ARGB_PRE
802 * @see #TYPE_INT_BGR
803 * @see #TYPE_3BYTE_BGR
804 * @see #TYPE_4BYTE_ABGR
805 * @see #TYPE_4BYTE_ABGR_PRE
806 * @see #TYPE_BYTE_GRAY
807 * @see #TYPE_BYTE_BINARY
808 * @see #TYPE_BYTE_INDEXED
809 * @see #TYPE_USHORT_GRAY
810 * @see #TYPE_USHORT_565_RGB
811 * @see #TYPE_USHORT_555_RGB
812 * @see #TYPE_CUSTOM
813 */
814 public int getType() {
815 return imageType;
816 }
817
818 /**
819 * Returns the <code>ColorModel</code>.
820 * @return the <code>ColorModel</code> of this
821 * <code>BufferedImage</code>.
822 */
823 public ColorModel getColorModel() {
824 return colorModel;
825 }
826
827 /**
828 * Returns the {@link WritableRaster}.
829 * @return the <code>WriteableRaster</code> of this
830 * <code>BufferedImage</code>.
831 */
832 public WritableRaster getRaster() {
833 return raster;
834 }
835
836
837 /**
838 * Returns a <code>WritableRaster</code> representing the alpha
839 * channel for <code>BufferedImage</code> objects
840 * with <code>ColorModel</code> objects that support a separate
841 * spatial alpha channel, such as <code>ComponentColorModel</code> and
842 * <code>DirectColorModel</code>. Returns <code>null</code> if there
843 * is no alpha channel associated with the <code>ColorModel</code> in
844 * this image. This method assumes that for all
845 * <code>ColorModel</code> objects other than
846 * <code>IndexColorModel</code>, if the <code>ColorModel</code>
847 * supports alpha, there is a separate alpha channel
848 * which is stored as the last band of image data.
849 * If the image uses an <code>IndexColorModel</code> that
850 * has alpha in the lookup table, this method returns
851 * <code>null</code> since there is no spatially discrete alpha
852 * channel. This method creates a new
853 * <code>WritableRaster</code>, but shares the data array.
854 * @return a <code>WritableRaster</code> or <code>null</code> if this
855 * <code>BufferedImage</code> has no alpha channel associated
856 * with its <code>ColorModel</code>.
857 */
858 public WritableRaster getAlphaRaster() {
859 return colorModel.getAlphaRaster(raster);
860 }
861
862 /**
863 * Returns an integer pixel in the default RGB color model
864 * (TYPE_INT_ARGB) and default sRGB colorspace. Color
865 * conversion takes place if this default model does not match
866 * the image <code>ColorModel</code>. There are only 8-bits of
867 * precision for each color component in the returned data when using
868 * this method.
869 *
870 * <p>
871 *
872 * An <code>ArrayOutOfBoundsException</code> may be thrown
873 * if the coordinates are not in bounds.
874 * However, explicit bounds checking is not guaranteed.
875 *
876 * @param x the X coordinate of the pixel from which to get
877 * the pixel in the default RGB color model and sRGB
878 * color space
879 * @param y the Y coordinate of the pixel from which to get
880 * the pixel in the default RGB color model and sRGB
881 * color space
882 * @return an integer pixel in the default RGB color model and
883 * default sRGB colorspace.
884 * @see #setRGB(int, int, int)
885 * @see #setRGB(int, int, int, int, int[], int, int)
886 */
887 public int getRGB(int x, int y) {
888 return colorModel.getRGB(raster.getDataElements(x, y, null));
889 }
890
891 /**
892 * Returns an array of integer pixels in the default RGB color model
893 * (TYPE_INT_ARGB) and default sRGB color space,
894 * from a portion of the image data. Color conversion takes
895 * place if the default model does not match the image
896 * <code>ColorModel</code>. There are only 8-bits of precision for
897 * each color component in the returned data when
898 * using this method. With a specified coordinate (x,&nbsp;y) in the
899 * image, the ARGB pixel can be accessed in this way:
900 * </p>
901 *
902 * <pre>
903 * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)]; </pre>
904 *
905 * <p>
906 *
907 * An <code>ArrayOutOfBoundsException</code> may be thrown
908 * if the region is not in bounds.
909 * However, explicit bounds checking is not guaranteed.
910 *
911 * @param startX the starting X coordinate
912 * @param startY the starting Y coordinate
913 * @param w width of region
914 * @param h height of region
915 * @param rgbArray if not <code>null</code>, the rgb pixels are
916 * written here
917 * @param offset offset into the <code>rgbArray</code>
918 * @param scansize scanline stride for the <code>rgbArray</code>
919 * @return array of RGB pixels.
920 * @see #setRGB(int, int, int)
921 * @see #setRGB(int, int, int, int, int[], int, int)
922 */
923 public int[] getRGB(int startX, int startY, int w, int h,
924 int[] rgbArray, int offset, int scansize) {
925 int yoff = offset;
926 int off;
927 Object data;
928 int nbands = raster.getNumBands();
929 int dataType = raster.getDataBuffer().getDataType();
930 switch (dataType) {
931 case DataBuffer.TYPE_BYTE:
932 data = new byte[nbands];
933 break;
934 case DataBuffer.TYPE_USHORT:
935 data = new short[nbands];
936 break;
937 case DataBuffer.TYPE_INT:
938 data = new int[nbands];
939 break;
940 case DataBuffer.TYPE_FLOAT:
941 data = new float[nbands];
942 break;
943 case DataBuffer.TYPE_DOUBLE:
944 data = new double[nbands];
945 break;
946 default:
947 throw new IllegalArgumentException("Unknown data buffer type: "+
948 dataType);
949 }
950
951 if (rgbArray == null) {
952 rgbArray = new int[offset+h*scansize];
953 }
954
955 for (int y = startY; y < startY+h; y++, yoff+=scansize) {
956 off = yoff;
957 for (int x = startX; x < startX+w; x++) {
958 rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x,
959 y,
960 data));
961 }
962 }
963
964 return rgbArray;
965 }
966
967
968 /**
969 * Sets a pixel in this <code>BufferedImage</code> to the specified
970 * RGB value. The pixel is assumed to be in the default RGB color
971 * model, TYPE_INT_ARGB, and default sRGB color space. For images
972 * with an <code>IndexColorModel</code>, the index with the nearest
973 * color is chosen.
974 *
975 * <p>
976 *
977 * An <code>ArrayOutOfBoundsException</code> may be thrown
978 * if the coordinates are not in bounds.
979 * However, explicit bounds checking is not guaranteed.
980 *
981 * @param x the X coordinate of the pixel to set
982 * @param y the Y coordinate of the pixel to set
983 * @param rgb the RGB value
984 * @see #getRGB(int, int)
985 * @see #getRGB(int, int, int, int, int[], int, int)
986 */
987 public synchronized void setRGB(int x, int y, int rgb) {
988 raster.setDataElements(x, y, colorModel.getDataElements(rgb, null));
989 }
990
991 /**
992 * Sets an array of integer pixels in the default RGB color model
993 * (TYPE_INT_ARGB) and default sRGB color space,
994 * into a portion of the image data. Color conversion takes place
995 * if the default model does not match the image
996 * <code>ColorModel</code>. There are only 8-bits of precision for
997 * each color component in the returned data when
998 * using this method. With a specified coordinate (x,&nbsp;y) in the
999 * this image, the ARGB pixel can be accessed in this way:
1000 * <pre>
1001 * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)];
1002 * </pre>
1003 * WARNING: No dithering takes place.
1004 *
1005 * <p>
1006 *
1007 * An <code>ArrayOutOfBoundsException</code> may be thrown
1008 * if the region is not in bounds.
1009 * However, explicit bounds checking is not guaranteed.
1010 *
1011 * @param startX the starting X coordinate
1012 * @param startY the starting Y coordinate
1013 * @param w width of the region
1014 * @param h height of the region
1015 * @param rgbArray the rgb pixels
1016 * @param offset offset into the <code>rgbArray</code>
1017 * @param scansize scanline stride for the <code>rgbArray</code>
1018 * @see #getRGB(int, int)
1019 * @see #getRGB(int, int, int, int, int[], int, int)
1020 */
1021 public void setRGB(int startX, int startY, int w, int h,
1022 int[] rgbArray, int offset, int scansize) {
1023 int yoff = offset;
1024 int off;
1025 Object pixel = null;
1026
1027 for (int y = startY; y < startY+h; y++, yoff+=scansize) {
1028 off = yoff;
1029 for (int x = startX; x < startX+w; x++) {
1030 pixel = colorModel.getDataElements(rgbArray[off++], pixel);
1031 raster.setDataElements(x, y, pixel);
1032 }
1033 }
1034 }
1035
1036
1037 /**
1038 * Returns the width of the <code>BufferedImage</code>.
1039 * @return the width of this <code>BufferedImage</code>
1040 */
1041 public int getWidth() {
1042 return raster.getWidth();
1043 }
1044
1045 /**
1046 * Returns the height of the <code>BufferedImage</code>.
1047 * @return the height of this <code>BufferedImage</code>
1048 */
1049 public int getHeight() {
1050 return raster.getHeight();
1051 }
1052
1053 /**
1054 * Returns the width of the <code>BufferedImage</code>.
1055 * @param observer ignored
1056 * @return the width of this <code>BufferedImage</code>
1057 */
1058 public int getWidth(ImageObserver observer) {
1059 return raster.getWidth();
1060 }
1061
1062 /**
1063 * Returns the height of the <code>BufferedImage</code>.
1064 * @param observer ignored
1065 * @return the height of this <code>BufferedImage</code>
1066 */
1067 public int getHeight(ImageObserver observer) {
1068 return raster.getHeight();
1069 }
1070
1071 /**
1072 * Returns the object that produces the pixels for the image.
1073 * @return the {@link ImageProducer} that is used to produce the
1074 * pixels for this image.
1075 * @see ImageProducer
1076 */
1077 public ImageProducer getSource() {
1078 if (osis == null) {
1079 if (properties == null) {
1080 properties = new Hashtable();
1081 }
1082 osis = new OffScreenImageSource(this, properties);
1083 }
1084 return osis;
1085 }
1086
1087
1088 /**
1089 * Returns a property of the image by name. Individual property names
1090 * are defined by the various image formats. If a property is not
1091 * defined for a particular image, this method returns the
1092 * <code>UndefinedProperty</code> field. If the properties
1093 * for this image are not yet known, then this method returns
1094 * <code>null</code> and the <code>ImageObserver</code> object is
1095 * notified later. The property name "comment" should be used to
1096 * store an optional comment that can be presented to the user as a
1097 * description of the image, its source, or its author.
1098 * @param name the property name
1099 * @param observer the <code>ImageObserver</code> that receives
1100 * notification regarding image information
1101 * @return an {@link Object} that is the property referred to by the
1102 * specified <code>name</code> or <code>null</code> if the
1103 * properties of this image are not yet known.
1104 * @throws <code>NullPointerException</code> if the property name is null.
1105 * @see ImageObserver
1106 * @see java.awt.Image#UndefinedProperty
1107 */
1108 public Object getProperty(String name, ImageObserver observer) {
1109 return getProperty(name);
1110 }
1111
1112 /**
1113 * Returns a property of the image by name.
1114 * @param name the property name
1115 * @return an <code>Object</code> that is the property referred to by
1116 * the specified <code>name</code>.
1117 * @throws <code>NullPointerException</code> if the property name is null.
1118 */
1119 public Object getProperty(String name) {
1120 if (name == null) {
1121 throw new NullPointerException("null property name is not allowed");
1122 }
1123 if (properties == null) {
1124 return java.awt.Image.UndefinedProperty;
1125 }
1126 Object o = properties.get(name);
1127 if (o == null) {
1128 o = java.awt.Image.UndefinedProperty;
1129 }
1130 return o;
1131 }
1132
1133 /**
1134 * This method returns a {@link Graphics2D}, but is here
1135 * for backwards compatibility. {@link #createGraphics() createGraphics} is more
1136 * convenient, since it is declared to return a
1137 * <code>Graphics2D</code>.
1138 * @return a <code>Graphics2D</code>, which can be used to draw into
1139 * this image.
1140 */
1141 public java.awt.Graphics getGraphics() {
1142 return createGraphics();
1143 }
1144
1145 /**
1146 * Creates a <code>Graphics2D</code>, which can be used to draw into
1147 * this <code>BufferedImage</code>.
1148 * @return a <code>Graphics2D</code>, used for drawing into this
1149 * image.
1150 */
1151 public Graphics2D createGraphics() {
1152 GraphicsEnvironment env =
1153 GraphicsEnvironment.getLocalGraphicsEnvironment();
1154 return env.createGraphics(this);
1155 }
1156
1157 /**
1158 * Returns a subimage defined by a specified rectangular region.
1159 * The returned <code>BufferedImage</code> shares the same
1160 * data array as the original image.
1161 * @param x the X coordinate of the upper-left corner of the
1162 * specified rectangular region
1163 * @param y the Y coordinate of the upper-left corner of the
1164 * specified rectangular region
1165 * @param w the width of the specified rectangular region
1166 * @param h the height of the specified rectangular region
1167 * @return a <code>BufferedImage</code> that is the subimage of this
1168 * <code>BufferedImage</code>.
1169 * @exception <code>RasterFormatException</code> if the specified
1170 * area is not contained within this <code>BufferedImage</code>.
1171 */
1172 public BufferedImage getSubimage (int x, int y, int w, int h) {
1173 return new BufferedImage (colorModel,
1174 raster.createWritableChild(x, y, w, h,
1175 0, 0, null),
1176 colorModel.isAlphaPremultiplied(),
1177 properties);
1178 }
1179
1180 /**
1181 * Returns whether or not the alpha has been premultiplied. It
1182 * returns <code>false</code> if there is no alpha.
1183 * @return <code>true</code> if the alpha has been premultiplied;
1184 * <code>false</code> otherwise.
1185 */
1186 public boolean isAlphaPremultiplied() {
1187 return colorModel.isAlphaPremultiplied();
1188 }
1189
1190 /**
1191 * Forces the data to match the state specified in the
1192 * <code>isAlphaPremultiplied</code> variable. It may multiply or
1193 * divide the color raster data by alpha, or do nothing if the data is
1194 * in the correct state.
1195 * @param isAlphaPremultiplied <code>true</code> if the alpha has been
1196 * premultiplied; <code>false</code> otherwise.
1197 */
1198 public void coerceData (boolean isAlphaPremultiplied) {
1199 if (colorModel.hasAlpha() &&
1200 colorModel.isAlphaPremultiplied() != isAlphaPremultiplied) {
1201 // Make the color model do the conversion
1202 colorModel = colorModel.coerceData (raster, isAlphaPremultiplied);
1203 }
1204 }
1205
1206 /**
1207 * Returns a <code>String</code> representation of this
1208 * <code>BufferedImage</code> object and its values.
1209 * @return a <code>String</code> representing this
1210 * <code>BufferedImage</code>.
1211 */
1212 public String toString() {
1213 return "BufferedImage@"+Integer.toHexString(hashCode())
1214 +": type = "+imageType
1215 +" "+colorModel+" "+raster;
1216 }
1217
1218 /**
1219 * Returns a {@link Vector} of {@link RenderedImage} objects that are
1220 * the immediate sources, not the sources of these immediate sources,
1221 * of image data for this <code>BufferedImage</code>. This
1222 * method returns <code>null</code> if the <code>BufferedImage</code>
1223 * has no information about its immediate sources. It returns an
1224 * empty <code>Vector</code> if the <code>BufferedImage</code> has no
1225 * immediate sources.
1226 * @return a <code>Vector</code> containing immediate sources of
1227 * this <code>BufferedImage</code> object's image date, or
1228 * <code>null</code> if this <code>BufferedImage</code> has
1229 * no information about its immediate sources, or an empty
1230 * <code>Vector</code> if this <code>BufferedImage</code>
1231 * has no immediate sources.
1232 */
1233 public Vector<RenderedImage> getSources() {
1234 return null;
1235 }
1236
1237 /**
1238 * Returns an array of names recognized by
1239 * {@link #getProperty(String) getProperty(String)}
1240 * or <code>null</code>, if no property names are recognized.
1241 * @return a <code>String</code> array containing all of the property
1242 * names that <code>getProperty(String)</code> recognizes;
1243 * or <code>null</code> if no property names are recognized.
1244 */
1245 public String[] getPropertyNames() {
1246 return null;
1247 }
1248
1249 /**
1250 * Returns the minimum x coordinate of this
1251 * <code>BufferedImage</code>. This is always zero.
1252 * @return the minimum x coordinate of this
1253 * <code>BufferedImage</code>.
1254 */
1255 public int getMinX() {
1256 return raster.getMinX();
1257 }
1258
1259 /**
1260 * Returns the minimum y coordinate of this
1261 * <code>BufferedImage</code>. This is always zero.
1262 * @return the minimum y coordinate of this
1263 * <code>BufferedImage</code>.
1264 */
1265 public int getMinY() {
1266 return raster.getMinY();
1267 }
1268
1269 /**
1270 * Returns the <code>SampleModel</code> associated with this
1271 * <code>BufferedImage</code>.
1272 * @return the <code>SampleModel</code> of this
1273 * <code>BufferedImage</code>.
1274 */
1275 public SampleModel getSampleModel() {
1276 return raster.getSampleModel();
1277 }
1278
1279 /**
1280 * Returns the number of tiles in the x direction.
1281 * This is always one.
1282 * @return the number of tiles in the x direction.
1283 */
1284 public int getNumXTiles() {
1285 return 1;
1286 }
1287
1288 /**
1289 * Returns the number of tiles in the y direction.
1290 * This is always one.
1291 * @return the number of tiles in the y direction.
1292 */
1293 public int getNumYTiles() {
1294 return 1;
1295 }
1296
1297 /**
1298 * Returns the minimum tile index in the x direction.
1299 * This is always zero.
1300 * @return the minimum tile index in the x direction.
1301 */
1302 public int getMinTileX() {
1303 return 0;
1304 }
1305
1306 /**
1307 * Returns the minimum tile index in the y direction.
1308 * This is always zero.
1309 * @return the mininum tile index in the y direction.
1310 */
1311 public int getMinTileY() {
1312 return 0;
1313 }
1314
1315 /**
1316 * Returns the tile width in pixels.
1317 * @return the tile width in pixels.
1318 */
1319 public int getTileWidth() {
1320 return raster.getWidth();
1321 }
1322
1323 /**
1324 * Returns the tile height in pixels.
1325 * @return the tile height in pixels.
1326 */
1327 public int getTileHeight() {
1328 return raster.getHeight();
1329 }
1330
1331 /**
1332 * Returns the x offset of the tile grid relative to the origin,
1333 * For example, the x coordinate of the location of tile
1334 * (0,&nbsp;0). This is always zero.
1335 * @return the x offset of the tile grid.
1336 */
1337 public int getTileGridXOffset() {
1338 return raster.getSampleModelTranslateX();
1339 }
1340
1341 /**
1342 * Returns the y offset of the tile grid relative to the origin,
1343 * For example, the y coordinate of the location of tile
1344 * (0,&nbsp;0). This is always zero.
1345 * @return the y offset of the tile grid.
1346 */
1347 public int getTileGridYOffset() {
1348 return raster.getSampleModelTranslateY();
1349 }
1350
1351 /**
1352 * Returns tile (<code>tileX</code>,&nbsp;<code>tileY</code>). Note
1353 * that <code>tileX</code> and <code>tileY</code> are indices
1354 * into the tile array, not pixel locations. The <code>Raster</code>
1355 * that is returned is live, which means that it is updated if the
1356 * image is changed.
1357 * @param tileX the x index of the requested tile in the tile array
1358 * @param tileY the y index of the requested tile in the tile array
1359 * @return a <code>Raster</code> that is the tile defined by the
1360 * arguments <code>tileX</code> and <code>tileY</code>.
1361 * @exception <code>ArrayIndexOutOfBoundsException</code> if both
1362 * <code>tileX</code> and <code>tileY</code> are not
1363 * equal to 0
1364 */
1365 public Raster getTile(int tileX, int tileY) {
1366 if (tileX == 0 && tileY == 0) {
1367 return raster;
1368 }
1369 throw new ArrayIndexOutOfBoundsException("BufferedImages only have"+
1370 " one tile with index 0,0");
1371 }
1372
1373 /**
1374 * Returns the image as one large tile. The <code>Raster</code>
1375 * returned is a copy of the image data is not updated if the
1376 * image is changed.
1377 * @return a <code>Raster</code> that is a copy of the image data.
1378 * @see #setData(Raster)
1379 */
1380 public Raster getData() {
1381
1382 // REMIND : this allocates a whole new tile if raster is a
1383 // subtile. (It only copies in the requested area)
1384 // We should do something smarter.
1385 int width = raster.getWidth();
1386 int height = raster.getHeight();
1387 int startX = raster.getMinX();
1388 int startY = raster.getMinY();
1389 WritableRaster wr =
1390 Raster.createWritableRaster(raster.getSampleModel(),
1391 new Point(raster.getSampleModelTranslateX(),
1392 raster.getSampleModelTranslateY()));
1393
1394 Object tdata = null;
1395
1396 for (int i = startY; i < startY+height; i++) {
1397 tdata = raster.getDataElements(startX,i,width,1,tdata);
1398 wr.setDataElements(startX,i,width,1, tdata);
1399 }
1400 return wr;
1401 }
1402
1403 /**
1404 * Computes and returns an arbitrary region of the
1405 * <code>BufferedImage</code>. The <code>Raster</code> returned is a
1406 * copy of the image data and is not updated if the image is
1407 * changed.
1408 * @param rect the region of the <code>BufferedImage</code> to be
1409 * returned.
1410 * @return a <code>Raster</code> that is a copy of the image data of
1411 * the specified region of the <code>BufferedImage</code>
1412 * @see #setData(Raster)
1413 */
1414 public Raster getData(Rectangle rect) {
1415 SampleModel sm = raster.getSampleModel();
1416 SampleModel nsm = sm.createCompatibleSampleModel(rect.width,
1417 rect.height);
1418 WritableRaster wr = Raster.createWritableRaster(nsm,
1419 rect.getLocation());
1420 int width = rect.width;
1421 int height = rect.height;
1422 int startX = rect.x;
1423 int startY = rect.y;
1424
1425 Object tdata = null;
1426
1427 for (int i = startY; i < startY+height; i++) {
1428 tdata = raster.getDataElements(startX,i,width,1,tdata);
1429 wr.setDataElements(startX,i,width,1, tdata);
1430 }
1431 return wr;
1432 }
1433
1434 /**
1435 * Computes an arbitrary rectangular region of the
1436 * <code>BufferedImage</code> and copies it into a specified
1437 * <code>WritableRaster</code>. The region to be computed is
1438 * determined from the bounds of the specified
1439 * <code>WritableRaster</code>. The specified
1440 * <code>WritableRaster</code> must have a
1441 * <code>SampleModel</code> that is compatible with this image. If
1442 * <code>outRaster</code> is <code>null</code>,
1443 * an appropriate <code>WritableRaster</code> is created.
1444 * @param outRaster a <code>WritableRaster</code> to hold the returned
1445 * part of the image, or <code>null</code>
1446 * @return a reference to the supplied or created
1447 * <code>WritableRaster</code>.
1448 */
1449 public WritableRaster copyData(WritableRaster outRaster) {
1450 if (outRaster == null) {
1451 return (WritableRaster) getData();
1452 }
1453 int width = outRaster.getWidth();
1454 int height = outRaster.getHeight();
1455 int startX = outRaster.getMinX();
1456 int startY = outRaster.getMinY();
1457
1458 Object tdata = null;
1459
1460 for (int i = startY; i < startY+height; i++) {
1461 tdata = raster.getDataElements(startX,i,width,1,tdata);
1462 outRaster.setDataElements(startX,i,width,1, tdata);
1463 }
1464
1465 return outRaster;
1466 }
1467
1468 /**
1469 * Sets a rectangular region of the image to the contents of the
1470 * specified <code>Raster</code> <code>r</code>, which is
1471 * assumed to be in the same coordinate space as the
1472 * <code>BufferedImage</code>. The operation is clipped to the bounds
1473 * of the <code>BufferedImage</code>.
1474 * @param r the specified <code>Raster</code>
1475 * @see #getData
1476 * @see #getData(Rectangle)
1477 */
1478 public void setData(Raster r) {
1479 int width = r.getWidth();
1480 int height = r.getHeight();
1481 int startX = r.getMinX();
1482 int startY = r.getMinY();
1483
1484 int[] tdata = null;
1485
1486 // Clip to the current Raster
1487 Rectangle rclip = new Rectangle(startX, startY, width, height);
1488 Rectangle bclip = new Rectangle(0, 0, raster.width, raster.height);
1489 Rectangle intersect = rclip.intersection(bclip);
1490 if (intersect.isEmpty()) {
1491 return;
1492 }
1493 width = intersect.width;
1494 height = intersect.height;
1495 startX = intersect.x;
1496 startY = intersect.y;
1497
1498 // remind use get/setDataElements for speed if Rasters are
1499 // compatible
1500 for (int i = startY; i < startY+height; i++) {
1501 tdata = r.getPixels(startX,i,width,1,tdata);
1502 raster.setPixels(startX,i,width,1, tdata);
1503 }
1504 }
1505
1506
1507 /**
1508 * Adds a tile observer. If the observer is already present,
1509 * it receives multiple notifications.
1510 * @param to the specified {@link TileObserver}
1511 */
1512 public void addTileObserver (TileObserver to) {
1513 }
1514
1515 /**
1516 * Removes a tile observer. If the observer was not registered,
1517 * nothing happens. If the observer was registered for multiple
1518 * notifications, it is now registered for one fewer notification.
1519 * @param to the specified <code>TileObserver</code>.
1520 */
1521 public void removeTileObserver (TileObserver to) {
1522 }
1523
1524 /**
1525 * Returns whether or not a tile is currently checked out for writing.
1526 * @param tileX the x index of the tile.
1527 * @param tileY the y index of the tile.
1528 * @return <code>true</code> if the tile specified by the specified
1529 * indices is checked out for writing; <code>false</code>
1530 * otherwise.
1531 * @exception <code>ArrayIndexOutOfBoundsException</code> if both
1532 * <code>tileX</code> and <code>tileY</code> are not equal
1533 * to 0
1534 */
1535 public boolean isTileWritable (int tileX, int tileY) {
1536 if (tileX == 0 && tileY == 0) {
1537 return true;
1538 }
1539 throw new IllegalArgumentException("Only 1 tile in image");
1540 }
1541
1542 /**
1543 * Returns an array of {@link Point} objects indicating which tiles
1544 * are checked out for writing. Returns <code>null</code> if none are
1545 * checked out.
1546 * @return a <code>Point</code> array that indicates the tiles that
1547 * are checked out for writing, or <code>null</code> if no
1548 * tiles are checked out for writing.
1549 */
1550 public Point[] getWritableTileIndices() {
1551 Point[] p = new Point[1];
1552 p[0] = new Point(0, 0);
1553
1554 return p;
1555 }
1556
1557 /**
1558 * Returns whether or not any tile is checked out for writing.
1559 * Semantically equivalent to
1560 * <pre>
1561 * (getWritableTileIndices() != null).
1562 * </pre>
1563 * @return <code>true</code> if any tile is checked out for writing;
1564 * <code>false</code> otherwise.
1565 */
1566 public boolean hasTileWriters () {
1567 return true;
1568 }
1569
1570 /**
1571 * Checks out a tile for writing. All registered
1572 * <code>TileObservers</code> are notified when a tile goes from having
1573 * no writers to having one writer.
1574 * @param tileX the x index of the tile
1575 * @param tileY the y index of the tile
1576 * @return a <code>WritableRaster</code> that is the tile, indicated by
1577 * the specified indices, to be checked out for writing.
1578 */
1579 public WritableRaster getWritableTile (int tileX, int tileY) {
1580 return raster;
1581 }
1582
1583 /**
1584 * Relinquishes permission to write to a tile. If the caller
1585 * continues to write to the tile, the results are undefined.
1586 * Calls to this method should only appear in matching pairs
1587 * with calls to {@link #getWritableTile(int, int) getWritableTile(int, int)}. Any other leads
1588 * to undefined results. All registered <code>TileObservers</code>
1589 * are notified when a tile goes from having one writer to having no
1590 * writers.
1591 * @param tileX the x index of the tile
1592 * @param tileY the y index of the tile
1593 */
1594 public void releaseWritableTile (int tileX, int tileY) {
1595 }
1596
1597 /**
1598 * Returns the transparency. Returns either OPAQUE, BITMASK,
1599 * or TRANSLUCENT.
1600 * @return the transparency of this <code>BufferedImage</code>.
1601 * @see Transparency#OPAQUE
1602 * @see Transparency#BITMASK
1603 * @see Transparency#TRANSLUCENT
1604 * @since 1.5
1605 */
1606 public int getTransparency() {
1607 return colorModel.getTransparency();
1608 }
1609}
java/pkg/java/awt/image/BufferedImageFilter.class+0−0

Binary file not shown.

java/pkg/java/awt/image/BufferedImageFilter.java+417−0
@@ -0,0 +1,417 @@
1/*
2 * Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.util.Hashtable;
29import java.awt.image.ImageConsumer;
30import java.awt.image.ImageFilter;
31
32/**
33 * The <code>BufferedImageFilter</code> class subclasses an
34 * <code>ImageFilter</code> to provide a simple means of
35 * using a single-source/single-destination image operator
36 * ({@link BufferedImageOp}) to filter a <code>BufferedImage</code>
37 * in the Image Producer/Consumer/Observer
38 * paradigm. Examples of these image operators are: {@link ConvolveOp},
39 * {@link AffineTransformOp} and {@link LookupOp}.
40 *
41 * @see ImageFilter
42 * @see BufferedImage
43 * @see BufferedImageOp
44 */
45
46public class BufferedImageFilter extends ImageFilter implements Cloneable {
47 BufferedImageOp bufferedImageOp;
48 ColorModel model;
49 int width;
50 int height;
51 byte[] bytePixels;
52 int[] intPixels;
53
54 /**
55 * Constructs a <code>BufferedImageFilter</code> with the
56 * specified single-source/single-destination operator.
57 * @param op the specified <code>BufferedImageOp</code> to
58 * use to filter a <code>BufferedImage</code>
59 * @throws NullPointerException if op is null
60 */
61 public BufferedImageFilter (BufferedImageOp op) {
62 super();
63 if (op == null) {
64 throw new NullPointerException("Operation cannot be null");
65 }
66 bufferedImageOp = op;
67 }
68
69 /**
70 * Returns the <code>BufferedImageOp</code>.
71 * @return the operator of this <code>BufferedImageFilter</code>.
72 */
73 public BufferedImageOp getBufferedImageOp() {
74 return bufferedImageOp;
75 }
76
77 /**
78 * Filters the information provided in the
79 * {@link ImageConsumer#setDimensions(int, int) setDimensions } method
80 * of the {@link ImageConsumer} interface.
81 * <p>
82 * Note: This method is intended to be called by the
83 * {@link ImageProducer} of the <code>Image</code> whose pixels are
84 * being filtered. Developers using this class to retrieve pixels from
85 * an image should avoid calling this method directly since that
86 * operation could result in problems with retrieving the requested
87 * pixels.
88 * <p>
89 * @param width the width to which to set the width of this
90 * <code>BufferedImageFilter</code>
91 * @param height the height to which to set the height of this
92 * <code>BufferedImageFilter</code>
93 * @see ImageConsumer#setDimensions
94 */
95 public void setDimensions(int width, int height) {
96 if (width <= 0 || height <= 0) {
97 imageComplete(STATICIMAGEDONE);
98 return;
99 }
100 this.width = width;
101 this.height = height;
102 }
103
104 /**
105 * Filters the information provided in the
106 * {@link ImageConsumer#setColorModel(ColorModel) setColorModel} method
107 * of the <code>ImageConsumer</code> interface.
108 * <p>
109 * If <code>model</code> is <code>null</code>, this
110 * method clears the current <code>ColorModel</code> of this
111 * <code>BufferedImageFilter</code>.
112 * <p>
113 * Note: This method is intended to be called by the
114 * <code>ImageProducer</code> of the <code>Image</code>
115 * whose pixels are being filtered. Developers using this
116 * class to retrieve pixels from an image
117 * should avoid calling this method directly since that
118 * operation could result in problems with retrieving the
119 * requested pixels.
120 * @param model the {@link ColorModel} to which to set the
121 * <code>ColorModel</code> of this <code>BufferedImageFilter</code>
122 * @see ImageConsumer#setColorModel
123 */
124 public void setColorModel(ColorModel model) {
125 this.model = model;
126 }
127
128 private void convertToRGB() {
129 int size = width * height;
130 int newpixels[] = new int[size];
131 if (bytePixels != null) {
132 for (int i = 0; i < size; i++) {
133 newpixels[i] = this.model.getRGB(bytePixels[i] & 0xff);
134 }
135 } else if (intPixels != null) {
136 for (int i = 0; i < size; i++) {
137 newpixels[i] = this.model.getRGB(intPixels[i]);
138 }
139 }
140 bytePixels = null;
141 intPixels = newpixels;
142 this.model = ColorModel.getRGBdefault();
143 }
144
145 /**
146 * Filters the information provided in the <code>setPixels</code>
147 * method of the <code>ImageConsumer</code> interface which takes
148 * an array of bytes.
149 * <p>
150 * Note: This method is intended to be called by the
151 * <code>ImageProducer</code> of the <code>Image</code> whose pixels
152 * are being filtered. Developers using
153 * this class to retrieve pixels from an image should avoid calling
154 * this method directly since that operation could result in problems
155 * with retrieving the requested pixels.
156 * @throws IllegalArgumentException if width or height are less than
157 * zero.
158 * @see ImageConsumer#setPixels(int, int, int, int, ColorModel, byte[],
159 int, int)
160 */
161 public void setPixels(int x, int y, int w, int h,
162 ColorModel model, byte pixels[], int off,
163 int scansize) {
164 // Fix 4184230
165 if (w < 0 || h < 0) {
166 throw new IllegalArgumentException("Width ("+w+
167 ") and height ("+h+
168 ") must be > 0");
169 }
170 // Nothing to do
171 if (w == 0 || h == 0) {
172 return;
173 }
174 if (y < 0) {
175 int diff = -y;
176 if (diff >= h) {
177 return;
178 }
179 off += scansize * diff;
180 y += diff;
181 h -= diff;
182 }
183 if (y + h > height) {
184 h = height - y;
185 if (h <= 0) {
186 return;
187 }
188 }
189 if (x < 0) {
190 int diff = -x;
191 if (diff >= w) {
192 return;
193 }
194 off += diff;
195 x += diff;
196 w -= diff;
197 }
198 if (x + w > width) {
199 w = width - x;
200 if (w <= 0) {
201 return;
202 }
203 }
204 int dstPtr = y*width + x;
205 if (intPixels == null) {
206 if (bytePixels == null) {
207 bytePixels = new byte[width*height];
208 this.model = model;
209 } else if (this.model != model) {
210 convertToRGB();
211 }
212 if (bytePixels != null) {
213 for (int sh = h; sh > 0; sh--) {
214 System.arraycopy(pixels, off, bytePixels, dstPtr, w);
215 off += scansize;
216 dstPtr += width;
217 }
218 }
219 }
220 if (intPixels != null) {
221 int dstRem = width - w;
222 int srcRem = scansize - w;
223 for (int sh = h; sh > 0; sh--) {
224 for (int sw = w; sw > 0; sw--) {
225 intPixels[dstPtr++] = model.getRGB(pixels[off++]&0xff);
226 }
227 off += srcRem;
228 dstPtr += dstRem;
229 }
230 }
231 }
232 /**
233 * Filters the information provided in the <code>setPixels</code>
234 * method of the <code>ImageConsumer</code> interface which takes
235 * an array of integers.
236 * <p>
237 * Note: This method is intended to be called by the
238 * <code>ImageProducer</code> of the <code>Image</code> whose
239 * pixels are being filtered. Developers using this class to
240 * retrieve pixels from an image should avoid calling this method
241 * directly since that operation could result in problems
242 * with retrieving the requested pixels.
243 * @throws IllegalArgumentException if width or height are less than
244 * zero.
245 * @see ImageConsumer#setPixels(int, int, int, int, ColorModel, int[],
246 int, int)
247 */
248 public void setPixels(int x, int y, int w, int h,
249 ColorModel model, int pixels[], int off,
250 int scansize) {
251 // Fix 4184230
252 if (w < 0 || h < 0) {
253 throw new IllegalArgumentException("Width ("+w+
254 ") and height ("+h+
255 ") must be > 0");
256 }
257 // Nothing to do
258 if (w == 0 || h == 0) {
259 return;
260 }
261 if (y < 0) {
262 int diff = -y;
263 if (diff >= h) {
264 return;
265 }
266 off += scansize * diff;
267 y += diff;
268 h -= diff;
269 }
270 if (y + h > height) {
271 h = height - y;
272 if (h <= 0) {
273 return;
274 }
275 }
276 if (x < 0) {
277 int diff = -x;
278 if (diff >= w) {
279 return;
280 }
281 off += diff;
282 x += diff;
283 w -= diff;
284 }
285 if (x + w > width) {
286 w = width - x;
287 if (w <= 0) {
288 return;
289 }
290 }
291
292 if (intPixels == null) {
293 if (bytePixels == null) {
294 intPixels = new int[width * height];
295 this.model = model;
296 } else {
297 convertToRGB();
298 }
299 }
300 int dstPtr = y*width + x;
301 if (this.model == model) {
302 for (int sh = h; sh > 0; sh--) {
303 System.arraycopy(pixels, off, intPixels, dstPtr, w);
304 off += scansize;
305 dstPtr += width;
306 }
307 } else {
308 if (this.model != ColorModel.getRGBdefault()) {
309 convertToRGB();
310 }
311 int dstRem = width - w;
312 int srcRem = scansize - w;
313 for (int sh = h; sh > 0; sh--) {
314 for (int sw = w; sw > 0; sw--) {
315 intPixels[dstPtr++] = model.getRGB(pixels[off++]);
316 }
317 off += srcRem;
318 dstPtr += dstRem;
319 }
320 }
321 }
322
323 /**
324 * Filters the information provided in the <code>imageComplete</code>
325 * method of the <code>ImageConsumer</code> interface.
326 * <p>
327 * Note: This method is intended to be called by the
328 * <code>ImageProducer</code> of the <code>Image</code> whose pixels
329 * are being filtered. Developers using
330 * this class to retrieve pixels from an image should avoid calling
331 * this method directly since that operation could result in problems
332 * with retrieving the requested pixels.
333 * @param status the status of image loading
334 * @throws ImagingOpException if there was a problem calling the filter
335 * method of the <code>BufferedImageOp</code> associated with this
336 * instance.
337 * @see ImageConsumer#imageComplete
338 */
339 public void imageComplete(int status) {
340 WritableRaster wr;
341 switch(status) {
342 case IMAGEERROR:
343 case IMAGEABORTED:
344 // reinitialize the params
345 model = null;
346 width = -1;
347 height = -1;
348 intPixels = null;
349 bytePixels = null;
350 break;
351
352 case SINGLEFRAMEDONE:
353 case STATICIMAGEDONE:
354 if (width <= 0 || height <= 0) break;
355 if (model instanceof DirectColorModel) {
356 if (intPixels == null) break;
357 wr = createDCMraster();
358 }
359 else if (model instanceof IndexColorModel) {
360 int[] bandOffsets = {0};
361 if (bytePixels == null) break;
362 DataBufferByte db = new DataBufferByte(bytePixels,
363 width*height);
364 wr = Raster.createInterleavedRaster(db, width, height, width,
365 1, bandOffsets, null);
366 }
367 else {
368 convertToRGB();
369 if (intPixels == null) break;
370 wr = createDCMraster();
371 }
372 BufferedImage bi = new BufferedImage(model, wr,
373 model.isAlphaPremultiplied(),
374 null);
375 bi = bufferedImageOp.filter(bi, null);
376 WritableRaster r = bi.getRaster();
377 ColorModel cm = bi.getColorModel();
378 int w = r.getWidth();
379 int h = r.getHeight();
380 consumer.setDimensions(w, h);
381 consumer.setColorModel(cm);
382 if (cm instanceof DirectColorModel) {
383 DataBufferInt db = (DataBufferInt) r.getDataBuffer();
384 consumer.setPixels(0, 0, w, h,
385 cm, db.getData(), 0, w);
386 }
387 else if (cm instanceof IndexColorModel) {
388 DataBufferByte db = (DataBufferByte) r.getDataBuffer();
389 consumer.setPixels(0, 0, w, h,
390 cm, db.getData(), 0, w);
391 }
392 else {
393 throw new InternalError("Unknown color model "+cm);
394 }
395 break;
396 }
397 consumer.imageComplete(status);
398 }
399
400 private final WritableRaster createDCMraster() {
401 WritableRaster wr;
402 DirectColorModel dcm = (DirectColorModel) model;
403 boolean hasAlpha = model.hasAlpha();
404 int[] bandMasks = new int[3+(hasAlpha ? 1 : 0)];
405 bandMasks[0] = dcm.getRedMask();
406 bandMasks[1] = dcm.getGreenMask();
407 bandMasks[2] = dcm.getBlueMask();
408 if (hasAlpha) {
409 bandMasks[3] = dcm.getAlphaMask();
410 }
411 DataBufferInt db = new DataBufferInt(intPixels, width*height);
412 wr = Raster.createPackedRaster(db, width, height, width,
413 bandMasks, null);
414 return wr;
415 }
416
417}
java/pkg/java/awt/image/BufferedImageOp.class+0−0

Binary file not shown.

java/pkg/java/awt/image/BufferedImageOp.java+136−0
@@ -0,0 +1,136 @@
1/*
2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.geom.Rectangle2D;
29import java.awt.geom.Point2D;
30import java.awt.RenderingHints;
31
32/**
33 * This interface describes single-input/single-output
34 * operations performed on <CODE>BufferedImage</CODE> objects.
35 * It is implemented by <CODE>AffineTransformOp</CODE>,
36 * <CODE>ConvolveOp</CODE>, <CODE>ColorConvertOp</CODE>, <CODE>RescaleOp</CODE>,
37 * and <CODE>LookupOp</CODE>. These objects can be passed into
38 * a <CODE>BufferedImageFilter</CODE> to operate on a
39 * <CODE>BufferedImage</CODE> in the
40 * ImageProducer-ImageFilter-ImageConsumer paradigm.
41 * <p>
42 * Classes that implement this
43 * interface must specify whether or not they allow in-place filtering--
44 * filter operations where the source object is equal to the destination
45 * object.
46 * <p>
47 * This interface cannot be used to describe more sophisticated operations
48 * such as those that take multiple sources. Note that this restriction also
49 * means that the values of the destination pixels prior to the operation are
50 * not used as input to the filter operation.
51
52 * @see BufferedImage
53 * @see BufferedImageFilter
54 * @see AffineTransformOp
55 * @see BandCombineOp
56 * @see ColorConvertOp
57 * @see ConvolveOp
58 * @see LookupOp
59 * @see RescaleOp
60 */
61public interface BufferedImageOp {
62 /**
63 * Performs a single-input/single-output operation on a
64 * <CODE>BufferedImage</CODE>.
65 * If the color models for the two images do not match, a color
66 * conversion into the destination color model is performed.
67 * If the destination image is null,
68 * a <CODE>BufferedImage</CODE> with an appropriate <CODE>ColorModel</CODE>
69 * is created.
70 * <p>
71 * An <CODE>IllegalArgumentException</CODE> may be thrown if the source
72 * and/or destination image is incompatible with the types of images $
73 * allowed by the class implementing this filter.
74 *
75 * @param src The <CODE>BufferedImage</CODE> to be filtered
76 * @param dest The <CODE>BufferedImage</CODE> in which to store the results$
77 *
78 * @return The filtered <CODE>BufferedImage</CODE>.
79 *
80 * @throws IllegalArgumentException If the source and/or destination
81 * image is not compatible with the types of images allowed by the class
82 * implementing this filter.
83 */
84 public BufferedImage filter(BufferedImage src, BufferedImage dest);
85
86 /**
87 * Returns the bounding box of the filtered destination image.
88 * An <CODE>IllegalArgumentException</CODE> may be thrown if the source
89 * image is incompatible with the types of images allowed
90 * by the class implementing this filter.
91 *
92 * @param src The <CODE>BufferedImage</CODE> to be filtered
93 *
94 * @return The <CODE>Rectangle2D</CODE> representing the destination
95 * image's bounding box.
96 */
97 public Rectangle2D getBounds2D (BufferedImage src);
98
99 /**
100 * Creates a zeroed destination image with the correct size and number of
101 * bands.
102 * An <CODE>IllegalArgumentException</CODE> may be thrown if the source
103 * image is incompatible with the types of images allowed
104 * by the class implementing this filter.
105 *
106 * @param src The <CODE>BufferedImage</CODE> to be filtered
107 * @param destCM <CODE>ColorModel</CODE> of the destination. If null,
108 * the <CODE>ColorModel</CODE> of the source is used.
109 *
110 * @return The zeroed destination image.
111 */
112 public BufferedImage createCompatibleDestImage (BufferedImage src,
113 ColorModel destCM);
114
115 /**
116 * Returns the location of the corresponding destination point given a
117 * point in the source image. If <CODE>dstPt</CODE> is specified, it
118 * is used to hold the return value.
119 * @param srcPt the <code>Point2D</code> that represents the point in
120 * the source image
121 * @param dstPt The <CODE>Point2D</CODE> in which to store the result
122 *
123 * @return The <CODE>Point2D</CODE> in the destination image that
124 * corresponds to the specified point in the source image.
125 */
126 public Point2D getPoint2D (Point2D srcPt, Point2D dstPt);
127
128 /**
129 * Returns the rendering hints for this operation.
130 *
131 * @return The <CODE>RenderingHints</CODE> object for this
132 * <CODE>BufferedImageOp</CODE>. Returns
133 * null if no hints have been set.
134 */
135 public RenderingHints getRenderingHints();
136}
java/pkg/java/awt/image/ByteLookupTable.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ByteLookupTable.java+210−0
@@ -0,0 +1,210 @@
1/*
2 * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28
29/**
30 * This class defines a lookup table object. The output of a
31 * lookup operation using an object of this class is interpreted
32 * as an unsigned byte quantity. The lookup table contains byte
33 * data arrays for one or more bands (or components) of an image,
34 * and it contains an offset which will be subtracted from the
35 * input values before indexing the arrays. This allows an array
36 * smaller than the native data size to be provided for a
37 * constrained input. If there is only one array in the lookup
38 * table, it will be applied to all bands.
39 *
40 * @see ShortLookupTable
41 * @see LookupOp
42 */
43public class ByteLookupTable extends LookupTable {
44
45 /**
46 * Constants
47 */
48
49 byte data[][];
50
51 /**
52 * Constructs a ByteLookupTable object from an array of byte
53 * arrays representing a lookup table for each
54 * band. The offset will be subtracted from input
55 * values before indexing into the arrays. The number of
56 * bands is the length of the data argument. The
57 * data array for each band is stored as a reference.
58 * @param offset the value subtracted from the input values
59 * before indexing into the arrays
60 * @param data an array of byte arrays representing a lookup
61 * table for each band
62 * @throws IllegalArgumentException if <code>offset</code> is
63 * is less than 0 or if the length of <code>data</code>
64 * is less than 1
65 */
66 public ByteLookupTable(int offset, byte data[][]) {
67 super(offset,data.length);
68 numComponents = data.length;
69 numEntries = data[0].length;
70 this.data = new byte[numComponents][];
71 // Allocate the array and copy the data reference
72 for (int i=0; i < numComponents; i++) {
73 this.data[i] = data[i];
74 }
75 }
76
77 /**
78 * Constructs a ByteLookupTable object from an array
79 * of bytes representing a lookup table to be applied to all
80 * bands. The offset will be subtracted from input
81 * values before indexing into the array.
82 * The data array is stored as a reference.
83 * @param offset the value subtracted from the input values
84 * before indexing into the array
85 * @param data an array of bytes
86 * @throws IllegalArgumentException if <code>offset</code> is
87 * is less than 0 or if the length of <code>data</code>
88 * is less than 1
89 */
90 public ByteLookupTable(int offset, byte data[]) {
91 super(offset,data.length);
92 numComponents = 1;
93 numEntries = data.length;
94 this.data = new byte[1][];
95 this.data[0] = data;
96 }
97
98 /**
99 * Returns the lookup table data by reference. If this ByteLookupTable
100 * was constructed using a single byte array, the length of the returned
101 * array is one.
102 * @return the data array of this <code>ByteLookupTable</code>.
103 */
104 public final byte[][] getTable(){
105 return data;
106 }
107
108 /**
109 * Returns an array of samples of a pixel, translated with the lookup
110 * table. The source and destination array can be the same array.
111 * Array <code>dst</code> is returned.
112 *
113 * @param src the source array.
114 * @param dst the destination array. This array must be at least as
115 * long as <code>src</code>. If <code>dst</code> is
116 * <code>null</code>, a new array will be allocated having the
117 * same length as <code>src</code>.
118 * @return the array <code>dst</code>, an <code>int</code> array of
119 * samples.
120 * @exception ArrayIndexOutOfBoundsException if <code>src</code> is
121 * longer than <code>dst</code> or if for any element
122 * <code>i</code> of <code>src</code>,
123 * <code>src[i]-offset</code> is either less than zero or
124 * greater than or equal to the length of the lookup table
125 * for any band.
126 */
127 public int[] lookupPixel(int[] src, int[] dst){
128 if (dst == null) {
129 // Need to alloc a new destination array
130 dst = new int[src.length];
131 }
132
133 if (numComponents == 1) {
134 // Apply one LUT to all bands
135 for (int i=0; i < src.length; i++) {
136 int s = src[i] - offset;
137 if (s < 0) {
138 throw new ArrayIndexOutOfBoundsException("src["+i+
139 "]-offset is "+
140 "less than zero");
141 }
142 dst[i] = (int) data[0][s];
143 }
144 }
145 else {
146 for (int i=0; i < src.length; i++) {
147 int s = src[i] - offset;
148 if (s < 0) {
149 throw new ArrayIndexOutOfBoundsException("src["+i+
150 "]-offset is "+
151 "less than zero");
152 }
153 dst[i] = (int) data[i][s];
154 }
155 }
156 return dst;
157 }
158
159 /**
160 * Returns an array of samples of a pixel, translated with the lookup
161 * table. The source and destination array can be the same array.
162 * Array <code>dst</code> is returned.
163 *
164 * @param src the source array.
165 * @param dst the destination array. This array must be at least as
166 * long as <code>src</code>. If <code>dst</code> is
167 * <code>null</code>, a new array will be allocated having the
168 * same length as <code>src</code>.
169 * @return the array <code>dst</code>, an <code>int</code> array of
170 * samples.
171 * @exception ArrayIndexOutOfBoundsException if <code>src</code> is
172 * longer than <code>dst</code> or if for any element
173 * <code>i</code> of <code>src</code>,
174 * <code>(src[i]&0xff)-offset</code> is either less than
175 * zero or greater than or equal to the length of the
176 * lookup table for any band.
177 */
178 public byte[] lookupPixel(byte[] src, byte[] dst){
179 if (dst == null) {
180 // Need to alloc a new destination array
181 dst = new byte[src.length];
182 }
183
184 if (numComponents == 1) {
185 // Apply one LUT to all bands
186 for (int i=0; i < src.length; i++) {
187 int s = (src[i]&0xff) - offset;
188 if (s < 0) {
189 throw new ArrayIndexOutOfBoundsException("src["+i+
190 "]-offset is "+
191 "less than zero");
192 }
193 dst[i] = data[0][s];
194 }
195 }
196 else {
197 for (int i=0; i < src.length; i++) {
198 int s = (src[i]&0xff) - offset;
199 if (s < 0) {
200 throw new ArrayIndexOutOfBoundsException("src["+i+
201 "]-offset is "+
202 "less than zero");
203 }
204 dst[i] = data[i][s];
205 }
206 }
207 return dst;
208 }
209
210}
java/pkg/java/awt/image/ColorConvertOp.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ColorConvertOp.java+1109−0
@@ -0,0 +1,1109 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26/**********************************************************************
27 **********************************************************************
28 **********************************************************************
29 *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
30 *** As an unpublished work pursuant to Title 17 of the United ***
31 *** States Code. All rights reserved. ***
32 **********************************************************************
33 **********************************************************************
34 **********************************************************************/
35
36package java.awt.image;
37
38import java.awt.Point;
39import java.awt.Graphics2D;
40import java.awt.color.*;
41import sun.java2d.cmm.ColorTransform;
42import sun.java2d.cmm.CMSManager;
43import sun.java2d.cmm.ProfileDeferralMgr;
44import sun.java2d.cmm.PCMM;
45import java.awt.geom.Rectangle2D;
46import java.awt.geom.Point2D;
47import java.awt.RenderingHints;
48
49/**
50 * This class performs a pixel-by-pixel color conversion of the data in
51 * the source image. The resulting color values are scaled to the precision
52 * of the destination image. Color conversion can be specified
53 * via an array of ColorSpace objects or an array of ICC_Profile objects.
54 * <p>
55 * If the source is a BufferedImage with premultiplied alpha, the
56 * color components are divided by the alpha component before color conversion.
57 * If the destination is a BufferedImage with premultiplied alpha, the
58 * color components are multiplied by the alpha component after conversion.
59 * Rasters are treated as having no alpha channel, i.e. all bands are
60 * color bands.
61 * <p>
62 * If a RenderingHints object is specified in the constructor, the
63 * color rendering hint and the dithering hint may be used to control
64 * color conversion.
65 * <p>
66 * Note that Source and Destination may be the same object.
67 * <p>
68 * @see java.awt.RenderingHints#KEY_COLOR_RENDERING
69 * @see java.awt.RenderingHints#KEY_DITHERING
70 */
71public class ColorConvertOp implements BufferedImageOp, RasterOp {
72 ICC_Profile[] profileList;
73 ColorSpace[] CSList;
74 ColorTransform thisTransform, thisRasterTransform;
75 ICC_Profile thisSrcProfile, thisDestProfile;
76 RenderingHints hints;
77 boolean gotProfiles;
78 float[] srcMinVals, srcMaxVals, dstMinVals, dstMaxVals;
79
80 /* the class initializer */
81 static {
82 if (ProfileDeferralMgr.deferring) {
83 ProfileDeferralMgr.activateProfiles();
84 }
85 }
86
87 /**
88 * Constructs a new ColorConvertOp which will convert
89 * from a source color space to a destination color space.
90 * The RenderingHints argument may be null.
91 * This Op can be used only with BufferedImages, and will convert
92 * directly from the ColorSpace of the source image to that of the
93 * destination. The destination argument of the filter method
94 * cannot be specified as null.
95 * @param hints the <code>RenderingHints</code> object used to control
96 * the color conversion, or <code>null</code>
97 */
98 public ColorConvertOp (RenderingHints hints)
99 {
100 profileList = new ICC_Profile [0]; /* 0 length list */
101 this.hints = hints;
102 }
103
104 /**
105 * Constructs a new ColorConvertOp from a ColorSpace object.
106 * The RenderingHints argument may be null. This
107 * Op can be used only with BufferedImages, and is primarily useful
108 * when the {@link #filter(BufferedImage, BufferedImage) filter}
109 * method is invoked with a destination argument of null.
110 * In that case, the ColorSpace defines the destination color space
111 * for the destination created by the filter method. Otherwise, the
112 * ColorSpace defines an intermediate space to which the source is
113 * converted before being converted to the destination space.
114 * @param cspace defines the destination <code>ColorSpace</code> or an
115 * intermediate <code>ColorSpace</code>
116 * @param hints the <code>RenderingHints</code> object used to control
117 * the color conversion, or <code>null</code>
118 * @throws NullPointerException if cspace is null
119 */
120 public ColorConvertOp (ColorSpace cspace, RenderingHints hints)
121 {
122 if (cspace == null) {
123 throw new NullPointerException("ColorSpace cannot be null");
124 }
125 if (cspace instanceof ICC_ColorSpace) {
126 profileList = new ICC_Profile [1]; /* 1 profile in the list */
127
128 profileList [0] = ((ICC_ColorSpace) cspace).getProfile();
129 }
130 else {
131 CSList = new ColorSpace[1]; /* non-ICC case: 1 ColorSpace in list */
132 CSList[0] = cspace;
133 }
134 this.hints = hints;
135 }
136
137
138 /**
139 * Constructs a new ColorConvertOp from two ColorSpace objects.
140 * The RenderingHints argument may be null.
141 * This Op is primarily useful for calling the filter method on
142 * Rasters, in which case the two ColorSpaces define the operation
143 * to be performed on the Rasters. In that case, the number of bands
144 * in the source Raster must match the number of components in
145 * srcCspace, and the number of bands in the destination Raster
146 * must match the number of components in dstCspace. For BufferedImages,
147 * the two ColorSpaces define intermediate spaces through which the
148 * source is converted before being converted to the destination space.
149 * @param srcCspace the source <code>ColorSpace</code>
150 * @param dstCspace the destination <code>ColorSpace</code>
151 * @param hints the <code>RenderingHints</code> object used to control
152 * the color conversion, or <code>null</code>
153 * @throws NullPointerException if either srcCspace or dstCspace is null
154 */
155 public ColorConvertOp(ColorSpace srcCspace, ColorSpace dstCspace,
156 RenderingHints hints)
157 {
158 if ((srcCspace == null) || (dstCspace == null)) {
159 throw new NullPointerException("ColorSpaces cannot be null");
160 }
161 if ((srcCspace instanceof ICC_ColorSpace) &&
162 (dstCspace instanceof ICC_ColorSpace)) {
163 profileList = new ICC_Profile [2]; /* 2 profiles in the list */
164
165 profileList [0] = ((ICC_ColorSpace) srcCspace).getProfile();
166 profileList [1] = ((ICC_ColorSpace) dstCspace).getProfile();
167
168 getMinMaxValsFromColorSpaces(srcCspace, dstCspace);
169 } else {
170 /* non-ICC case: 2 ColorSpaces in list */
171 CSList = new ColorSpace[2];
172 CSList[0] = srcCspace;
173 CSList[1] = dstCspace;
174 }
175 this.hints = hints;
176 }
177
178
179 /**
180 * Constructs a new ColorConvertOp from an array of ICC_Profiles.
181 * The RenderingHints argument may be null.
182 * The sequence of profiles may include profiles that represent color
183 * spaces, profiles that represent effects, etc. If the whole sequence
184 * does not represent a well-defined color conversion, an exception is
185 * thrown.
186 * <p>For BufferedImages, if the ColorSpace
187 * of the source BufferedImage does not match the requirements of the
188 * first profile in the array,
189 * the first conversion is to an appropriate ColorSpace.
190 * If the requirements of the last profile in the array are not met
191 * by the ColorSpace of the destination BufferedImage,
192 * the last conversion is to the destination's ColorSpace.
193 * <p>For Rasters, the number of bands in the source Raster must match
194 * the requirements of the first profile in the array, and the
195 * number of bands in the destination Raster must match the requirements
196 * of the last profile in the array. The array must have at least two
197 * elements or calling the filter method for Rasters will throw an
198 * IllegalArgumentException.
199 * @param profiles the array of <code>ICC_Profile</code> objects
200 * @param hints the <code>RenderingHints</code> object used to control
201 * the color conversion, or <code>null</code>
202 * @exception IllegalArgumentException when the profile sequence does not
203 * specify a well-defined color conversion
204 * @exception NullPointerException if profiles is null
205 */
206 public ColorConvertOp (ICC_Profile[] profiles, RenderingHints hints)
207 {
208 if (profiles == null) {
209 throw new NullPointerException("Profiles cannot be null");
210 }
211 gotProfiles = true;
212 profileList = new ICC_Profile[profiles.length];
213 for (int i1 = 0; i1 < profiles.length; i1++) {
214 profileList[i1] = profiles[i1];
215 }
216 this.hints = hints;
217 }
218
219
220 /**
221 * Returns the array of ICC_Profiles used to construct this ColorConvertOp.
222 * Returns null if the ColorConvertOp was not constructed from such an
223 * array.
224 * @return the array of <code>ICC_Profile</code> objects of this
225 * <code>ColorConvertOp</code>, or <code>null</code> if this
226 * <code>ColorConvertOp</code> was not constructed with an
227 * array of <code>ICC_Profile</code> objects.
228 */
229 public final ICC_Profile[] getICC_Profiles() {
230 if (gotProfiles) {
231 ICC_Profile[] profiles = new ICC_Profile[profileList.length];
232 for (int i1 = 0; i1 < profileList.length; i1++) {
233 profiles[i1] = profileList[i1];
234 }
235 return profiles;
236 }
237 return null;
238 }
239
240 /**
241 * ColorConverts the source BufferedImage.
242 * If the destination image is null,
243 * a BufferedImage will be created with an appropriate ColorModel.
244 * @param src the source <code>BufferedImage</code> to be converted
245 * @param dest the destination <code>BufferedImage</code>,
246 * or <code>null</code>
247 * @return <code>dest</code> color converted from <code>src</code>
248 * or a new, converted <code>BufferedImage</code>
249 * if <code>dest</code> is <code>null</code>
250 * @exception IllegalArgumentException if dest is null and this op was
251 * constructed using the constructor which takes only a
252 * RenderingHints argument, since the operation is ill defined.
253 */
254 public final BufferedImage filter(BufferedImage src, BufferedImage dest) {
255 ColorSpace srcColorSpace, destColorSpace;
256 BufferedImage savdest = null;
257
258 if (src.getColorModel() instanceof IndexColorModel) {
259 IndexColorModel icm = (IndexColorModel) src.getColorModel();
260 src = icm.convertToIntDiscrete(src.getRaster(), true);
261 }
262 srcColorSpace = src.getColorModel().getColorSpace();
263 if (dest != null) {
264 if (dest.getColorModel() instanceof IndexColorModel) {
265 savdest = dest;
266 dest = null;
267 destColorSpace = null;
268 } else {
269 destColorSpace = dest.getColorModel().getColorSpace();
270 }
271 } else {
272 destColorSpace = null;
273 }
274
275 if ((CSList != null) ||
276 (!(srcColorSpace instanceof ICC_ColorSpace)) ||
277 ((dest != null) &&
278 (!(destColorSpace instanceof ICC_ColorSpace)))) {
279 /* non-ICC case */
280 dest = nonICCBIFilter(src, srcColorSpace, dest, destColorSpace);
281 } else {
282 dest = ICCBIFilter(src, srcColorSpace, dest, destColorSpace);
283 }
284
285 if (savdest != null) {
286 Graphics2D big = savdest.createGraphics();
287 try {
288 big.drawImage(dest, 0, 0, null);
289 } finally {
290 big.dispose();
291 }
292 return savdest;
293 } else {
294 return dest;
295 }
296 }
297
298 private final BufferedImage ICCBIFilter(BufferedImage src,
299 ColorSpace srcColorSpace,
300 BufferedImage dest,
301 ColorSpace destColorSpace) {
302 int nProfiles = profileList.length;
303 ICC_Profile srcProfile = null, destProfile = null;
304
305 srcProfile = ((ICC_ColorSpace) srcColorSpace).getProfile();
306
307 if (dest == null) { /* last profile in the list defines
308 the output color space */
309 if (nProfiles == 0) {
310 throw new IllegalArgumentException(
311 "Destination ColorSpace is undefined");
312 }
313 destProfile = profileList [nProfiles - 1];
314 dest = createCompatibleDestImage(src, null);
315 }
316 else {
317 if (src.getHeight() != dest.getHeight() ||
318 src.getWidth() != dest.getWidth()) {
319 throw new IllegalArgumentException(
320 "Width or height of BufferedImages do not match");
321 }
322 destProfile = ((ICC_ColorSpace) destColorSpace).getProfile();
323 }
324
325 /* Checking if all profiles in the transform sequence are the same.
326 * If so, performing just copying the data.
327 */
328 if (srcProfile == destProfile) {
329 boolean noTrans = true;
330 for (int i = 0; i < nProfiles; i++) {
331 if (srcProfile != profileList[i]) {
332 noTrans = false;
333 break;
334 }
335 }
336 if (noTrans) {
337 Graphics2D g = dest.createGraphics();
338 try {
339 g.drawImage(src, 0, 0, null);
340 } finally {
341 g.dispose();
342 }
343
344 return dest;
345 }
346 }
347
348 /* make a new transform if needed */
349 if ((thisTransform == null) || (thisSrcProfile != srcProfile) ||
350 (thisDestProfile != destProfile) ) {
351 updateBITransform(srcProfile, destProfile);
352 }
353
354 /* color convert the image */
355 thisTransform.colorConvert(src, dest);
356
357 return dest;
358 }
359
360 private void updateBITransform(ICC_Profile srcProfile,
361 ICC_Profile destProfile) {
362 ICC_Profile[] theProfiles;
363 int i1, nProfiles, nTransforms, whichTrans, renderState;
364 ColorTransform[] theTransforms;
365 boolean useSrc = false, useDest = false;
366
367 nProfiles = profileList.length;
368 nTransforms = nProfiles;
369 if ((nProfiles == 0) || (srcProfile != profileList[0])) {
370 nTransforms += 1;
371 useSrc = true;
372 }
373 if ((nProfiles == 0) || (destProfile != profileList[nProfiles - 1]) ||
374 (nTransforms < 2)) {
375 nTransforms += 1;
376 useDest = true;
377 }
378
379 /* make the profile list */
380 theProfiles = new ICC_Profile[nTransforms]; /* the list of profiles
381 for this Op */
382
383 int idx = 0;
384 if (useSrc) {
385 /* insert source as first profile */
386 theProfiles[idx++] = srcProfile;
387 }
388
389 for (i1 = 0; i1 < nProfiles; i1++) {
390 /* insert profiles defined in this Op */
391 theProfiles[idx++] = profileList [i1];
392 }
393
394 if (useDest) {
395 /* insert dest as last profile */
396 theProfiles[idx] = destProfile;
397 }
398
399 /* make the transform list */
400 theTransforms = new ColorTransform [nTransforms];
401
402 /* initialize transform get loop */
403 if (theProfiles[0].getProfileClass() == ICC_Profile.CLASS_OUTPUT) {
404 /* if first profile is a printer
405 render as colorimetric */
406 renderState = ICC_Profile.icRelativeColorimetric;
407 }
408 else {
409 renderState = ICC_Profile.icPerceptual; /* render any other
410 class perceptually */
411 }
412
413 whichTrans = ColorTransform.In;
414
415 PCMM mdl = CMSManager.getModule();
416
417 /* get the transforms from each profile */
418 for (i1 = 0; i1 < nTransforms; i1++) {
419 if (i1 == nTransforms -1) { /* last profile? */
420 whichTrans = ColorTransform.Out; /* get output transform */
421 }
422 else { /* check for abstract profile */
423 if ((whichTrans == ColorTransform.Simulation) &&
424 (theProfiles[i1].getProfileClass () ==
425 ICC_Profile.CLASS_ABSTRACT)) {
426 renderState = ICC_Profile.icPerceptual;
427 whichTrans = ColorTransform.In;
428 }
429 }
430
431 theTransforms[i1] = mdl.createTransform (
432 theProfiles[i1], renderState, whichTrans);
433
434 /* get this profile's rendering intent to select transform
435 from next profile */
436 renderState = getRenderingIntent(theProfiles[i1]);
437
438 /* "middle" profiles use simulation transform */
439 whichTrans = ColorTransform.Simulation;
440 }
441
442 /* make the net transform */
443 thisTransform = mdl.createTransform(theTransforms);
444
445 /* update corresponding source and dest profiles */
446 thisSrcProfile = srcProfile;
447 thisDestProfile = destProfile;
448 }
449
450 /**
451 * ColorConverts the image data in the source Raster.
452 * If the destination Raster is null, a new Raster will be created.
453 * The number of bands in the source and destination Rasters must
454 * meet the requirements explained above. The constructor used to
455 * create this ColorConvertOp must have provided enough information
456 * to define both source and destination color spaces. See above.
457 * Otherwise, an exception is thrown.
458 * @param src the source <code>Raster</code> to be converted
459 * @param dest the destination <code>WritableRaster</code>,
460 * or <code>null</code>
461 * @return <code>dest</code> color converted from <code>src</code>
462 * or a new, converted <code>WritableRaster</code>
463 * if <code>dest</code> is <code>null</code>
464 * @exception IllegalArgumentException if the number of source or
465 * destination bands is incorrect, the source or destination
466 * color spaces are undefined, or this op was constructed
467 * with one of the constructors that applies only to
468 * operations on BufferedImages.
469 */
470 public final WritableRaster filter (Raster src, WritableRaster dest) {
471
472 if (CSList != null) {
473 /* non-ICC case */
474 return nonICCRasterFilter(src, dest);
475 }
476 int nProfiles = profileList.length;
477 if (nProfiles < 2) {
478 throw new IllegalArgumentException(
479 "Source or Destination ColorSpace is undefined");
480 }
481 if (src.getNumBands() != profileList[0].getNumComponents()) {
482 throw new IllegalArgumentException(
483 "Numbers of source Raster bands and source color space " +
484 "components do not match");
485 }
486 if (dest == null) {
487 dest = createCompatibleDestRaster(src);
488 }
489 else {
490 if (src.getHeight() != dest.getHeight() ||
491 src.getWidth() != dest.getWidth()) {
492 throw new IllegalArgumentException(
493 "Width or height of Rasters do not match");
494 }
495 if (dest.getNumBands() !=
496 profileList[nProfiles-1].getNumComponents()) {
497 throw new IllegalArgumentException(
498 "Numbers of destination Raster bands and destination " +
499 "color space components do not match");
500 }
501 }
502
503 /* make a new transform if needed */
504 if (thisRasterTransform == null) {
505 int i1, whichTrans, renderState;
506 ColorTransform[] theTransforms;
507
508 /* make the transform list */
509 theTransforms = new ColorTransform [nProfiles];
510
511 /* initialize transform get loop */
512 if (profileList[0].getProfileClass() == ICC_Profile.CLASS_OUTPUT) {
513 /* if first profile is a printer
514 render as colorimetric */
515 renderState = ICC_Profile.icRelativeColorimetric;
516 }
517 else {
518 renderState = ICC_Profile.icPerceptual; /* render any other
519 class perceptually */
520 }
521
522 whichTrans = ColorTransform.In;
523
524 PCMM mdl = CMSManager.getModule();
525
526 /* get the transforms from each profile */
527 for (i1 = 0; i1 < nProfiles; i1++) {
528 if (i1 == nProfiles -1) { /* last profile? */
529 whichTrans = ColorTransform.Out; /* get output transform */
530 }
531 else { /* check for abstract profile */
532 if ((whichTrans == ColorTransform.Simulation) &&
533 (profileList[i1].getProfileClass () ==
534 ICC_Profile.CLASS_ABSTRACT)) {
535 renderState = ICC_Profile.icPerceptual;
536 whichTrans = ColorTransform.In;
537 }
538 }
539
540 theTransforms[i1] = mdl.createTransform (
541 profileList[i1], renderState, whichTrans);
542
543 /* get this profile's rendering intent to select transform
544 from next profile */
545 renderState = getRenderingIntent(profileList[i1]);
546
547 /* "middle" profiles use simulation transform */
548 whichTrans = ColorTransform.Simulation;
549 }
550
551 /* make the net transform */
552 thisRasterTransform = mdl.createTransform(theTransforms);
553 }
554
555 int srcTransferType = src.getTransferType();
556 int dstTransferType = dest.getTransferType();
557 if ((srcTransferType == DataBuffer.TYPE_FLOAT) ||
558 (srcTransferType == DataBuffer.TYPE_DOUBLE) ||
559 (dstTransferType == DataBuffer.TYPE_FLOAT) ||
560 (dstTransferType == DataBuffer.TYPE_DOUBLE)) {
561 if (srcMinVals == null) {
562 getMinMaxValsFromProfiles(profileList[0],
563 profileList[nProfiles-1]);
564 }
565 /* color convert the raster */
566 thisRasterTransform.colorConvert(src, dest,
567 srcMinVals, srcMaxVals,
568 dstMinVals, dstMaxVals);
569 } else {
570 /* color convert the raster */
571 thisRasterTransform.colorConvert(src, dest);
572 }
573
574
575 return dest;
576 }
577
578 /**
579 * Returns the bounding box of the destination, given this source.
580 * Note that this will be the same as the the bounding box of the
581 * source.
582 * @param src the source <code>BufferedImage</code>
583 * @return a <code>Rectangle2D</code> that is the bounding box
584 * of the destination, given the specified <code>src</code>
585 */
586 public final Rectangle2D getBounds2D (BufferedImage src) {
587 return getBounds2D(src.getRaster());
588 }
589
590 /**
591 * Returns the bounding box of the destination, given this source.
592 * Note that this will be the same as the the bounding box of the
593 * source.
594 * @param src the source <code>Raster</code>
595 * @return a <code>Rectangle2D</code> that is the bounding box
596 * of the destination, given the specified <code>src</code>
597 */
598 public final Rectangle2D getBounds2D (Raster src) {
599 /* return new Rectangle (src.getXOffset(),
600 src.getYOffset(),
601 src.getWidth(), src.getHeight()); */
602 return src.getBounds();
603 }
604
605 /**
606 * Creates a zeroed destination image with the correct size and number of
607 * bands, given this source.
608 * @param src Source image for the filter operation.
609 * @param destCM ColorModel of the destination. If null, an
610 * appropriate ColorModel will be used.
611 * @return a <code>BufferedImage</code> with the correct size and
612 * number of bands from the specified <code>src</code>.
613 * @throws IllegalArgumentException if <code>destCM</code> is
614 * <code>null</code> and this <code>ColorConvertOp</code> was
615 * created without any <code>ICC_Profile</code> or
616 * <code>ColorSpace</code> defined for the destination
617 */
618 public BufferedImage createCompatibleDestImage (BufferedImage src,
619 ColorModel destCM) {
620 ColorSpace cs = null;;
621 if (destCM == null) {
622 if (CSList == null) {
623 /* ICC case */
624 int nProfiles = profileList.length;
625 if (nProfiles == 0) {
626 throw new IllegalArgumentException(
627 "Destination ColorSpace is undefined");
628 }
629 ICC_Profile destProfile = profileList[nProfiles - 1];
630 cs = new ICC_ColorSpace(destProfile);
631 } else {
632 /* non-ICC case */
633 int nSpaces = CSList.length;
634 cs = CSList[nSpaces - 1];
635 }
636 }
637 return createCompatibleDestImage(src, destCM, cs);
638 }
639
640 private BufferedImage createCompatibleDestImage(BufferedImage src,
641 ColorModel destCM,
642 ColorSpace destCS) {
643 BufferedImage image;
644 if (destCM == null) {
645 ColorModel srcCM = src.getColorModel();
646 int nbands = destCS.getNumComponents();
647 boolean hasAlpha = srcCM.hasAlpha();
648 if (hasAlpha) {
649 nbands += 1;
650 }
651 int[] nbits = new int[nbands];
652 for (int i = 0; i < nbands; i++) {
653 nbits[i] = 8;
654 }
655 destCM = new ComponentColorModel(destCS, nbits, hasAlpha,
656 srcCM.isAlphaPremultiplied(),
657 srcCM.getTransparency(),
658 DataBuffer.TYPE_BYTE);
659 }
660 int w = src.getWidth();
661 int h = src.getHeight();
662 image = new BufferedImage(destCM,
663 destCM.createCompatibleWritableRaster(w, h),
664 destCM.isAlphaPremultiplied(), null);
665 return image;
666 }
667
668
669 /**
670 * Creates a zeroed destination Raster with the correct size and number of
671 * bands, given this source.
672 * @param src the specified <code>Raster</code>
673 * @return a <code>WritableRaster</code> with the correct size and number
674 * of bands from the specified <code>src</code>
675 * @throws IllegalArgumentException if this <code>ColorConvertOp</code>
676 * was created without sufficient information to define the
677 * <code>dst</code> and <code>src</code> color spaces
678 */
679 public WritableRaster createCompatibleDestRaster (Raster src) {
680 int ncomponents;
681
682 if (CSList != null) {
683 /* non-ICC case */
684 if (CSList.length != 2) {
685 throw new IllegalArgumentException(
686 "Destination ColorSpace is undefined");
687 }
688 ncomponents = CSList[1].getNumComponents();
689 } else {
690 /* ICC case */
691 int nProfiles = profileList.length;
692 if (nProfiles < 2) {
693 throw new IllegalArgumentException(
694 "Destination ColorSpace is undefined");
695 }
696 ncomponents = profileList[nProfiles-1].getNumComponents();
697 }
698
699 WritableRaster dest =
700 Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
701 src.getWidth(),
702 src.getHeight(),
703 ncomponents,
704 new Point(src.getMinX(), src.getMinY()));
705 return dest;
706 }
707
708 /**
709 * Returns the location of the destination point given a
710 * point in the source. If <code>dstPt</code> is non-null,
711 * it will be used to hold the return value. Note that
712 * for this class, the destination point will be the same
713 * as the source point.
714 * @param srcPt the specified source <code>Point2D</code>
715 * @param dstPt the destination <code>Point2D</code>
716 * @return <code>dstPt</code> after setting its location to be
717 * the same as <code>srcPt</code>
718 */
719 public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) {
720 if (dstPt == null) {
721 dstPt = new Point2D.Float();
722 }
723 dstPt.setLocation(srcPt.getX(), srcPt.getY());
724
725 return dstPt;
726 }
727
728
729 /**
730 * Returns the RenderingIntent from the specified ICC Profile.
731 */
732 private int getRenderingIntent (ICC_Profile profile) {
733 byte[] header = profile.getData(ICC_Profile.icSigHead);
734 int index = ICC_Profile.icHdrRenderingIntent;
735 return (((header[index] & 0xff) << 24) |
736 ((header[index+1] & 0xff) << 16) |
737 ((header[index+2] & 0xff) << 8) |
738 (header[index+3] & 0xff));
739 }
740
741 /**
742 * Returns the rendering hints used by this op.
743 * @return the <code>RenderingHints</code> object of this
744 * <code>ColorConvertOp</code>
745 */
746 public final RenderingHints getRenderingHints() {
747 return hints;
748 }
749
750 private final BufferedImage nonICCBIFilter(BufferedImage src,
751 ColorSpace srcColorSpace,
752 BufferedImage dst,
753 ColorSpace dstColorSpace) {
754
755 int w = src.getWidth();
756 int h = src.getHeight();
757 ICC_ColorSpace ciespace =
758 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);
759 if (dst == null) {
760 dst = createCompatibleDestImage(src, null);
761 dstColorSpace = dst.getColorModel().getColorSpace();
762 } else {
763 if ((h != dst.getHeight()) || (w != dst.getWidth())) {
764 throw new IllegalArgumentException(
765 "Width or height of BufferedImages do not match");
766 }
767 }
768 Raster srcRas = src.getRaster();
769 WritableRaster dstRas = dst.getRaster();
770 ColorModel srcCM = src.getColorModel();
771 ColorModel dstCM = dst.getColorModel();
772 int srcNumComp = srcCM.getNumColorComponents();
773 int dstNumComp = dstCM.getNumColorComponents();
774 boolean dstHasAlpha = dstCM.hasAlpha();
775 boolean needSrcAlpha = srcCM.hasAlpha() && dstHasAlpha;
776 ColorSpace[] list;
777 if ((CSList == null) && (profileList.length != 0)) {
778 /* possible non-ICC src, some profiles, possible non-ICC dst */
779 boolean nonICCSrc, nonICCDst;
780 ICC_Profile srcProfile, dstProfile;
781 if (!(srcColorSpace instanceof ICC_ColorSpace)) {
782 nonICCSrc = true;
783 srcProfile = ciespace.getProfile();
784 } else {
785 nonICCSrc = false;
786 srcProfile = ((ICC_ColorSpace) srcColorSpace).getProfile();
787 }
788 if (!(dstColorSpace instanceof ICC_ColorSpace)) {
789 nonICCDst = true;
790 dstProfile = ciespace.getProfile();
791 } else {
792 nonICCDst = false;
793 dstProfile = ((ICC_ColorSpace) dstColorSpace).getProfile();
794 }
795 /* make a new transform if needed */
796 if ((thisTransform == null) || (thisSrcProfile != srcProfile) ||
797 (thisDestProfile != dstProfile) ) {
798 updateBITransform(srcProfile, dstProfile);
799 }
800 // process per scanline
801 float maxNum = 65535.0f; // use 16-bit precision in CMM
802 ColorSpace cs;
803 int iccSrcNumComp;
804 if (nonICCSrc) {
805 cs = ciespace;
806 iccSrcNumComp = 3;
807 } else {
808 cs = srcColorSpace;
809 iccSrcNumComp = srcNumComp;
810 }
811 float[] srcMinVal = new float[iccSrcNumComp];
812 float[] srcInvDiffMinMax = new float[iccSrcNumComp];
813 for (int i = 0; i < srcNumComp; i++) {
814 srcMinVal[i] = cs.getMinValue(i);
815 srcInvDiffMinMax[i] = maxNum / (cs.getMaxValue(i) - srcMinVal[i]);
816 }
817 int iccDstNumComp;
818 if (nonICCDst) {
819 cs = ciespace;
820 iccDstNumComp = 3;
821 } else {
822 cs = dstColorSpace;
823 iccDstNumComp = dstNumComp;
824 }
825 float[] dstMinVal = new float[iccDstNumComp];
826 float[] dstDiffMinMax = new float[iccDstNumComp];
827 for (int i = 0; i < dstNumComp; i++) {
828 dstMinVal[i] = cs.getMinValue(i);
829 dstDiffMinMax[i] = (cs.getMaxValue(i) - dstMinVal[i]) / maxNum;
830 }
831 float[] dstColor;
832 if (dstHasAlpha) {
833 int size = ((dstNumComp + 1) > 3) ? (dstNumComp + 1) : 3;
834 dstColor = new float[size];
835 } else {
836 int size = (dstNumComp > 3) ? dstNumComp : 3;
837 dstColor = new float[size];
838 }
839 short[] srcLine = new short[w * iccSrcNumComp];
840 short[] dstLine = new short[w * iccDstNumComp];
841 Object pixel;
842 float[] color;
843 float[] alpha = null;
844 if (needSrcAlpha) {
845 alpha = new float[w];
846 }
847 int idx;
848 // process each scanline
849 for (int y = 0; y < h; y++) {
850 // convert src scanline
851 pixel = null;
852 color = null;
853 idx = 0;
854 for (int x = 0; x < w; x++) {
855 pixel = srcRas.getDataElements(x, y, pixel);
856 color = srcCM.getNormalizedComponents(pixel, color, 0);
857 if (needSrcAlpha) {
858 alpha[x] = color[srcNumComp];
859 }
860 if (nonICCSrc) {
861 color = srcColorSpace.toCIEXYZ(color);
862 }
863 for (int i = 0; i < iccSrcNumComp; i++) {
864 srcLine[idx++] = (short)
865 ((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] +
866 0.5f);
867 }
868 }
869 // color convert srcLine to dstLine
870 thisTransform.colorConvert(srcLine, dstLine);
871 // convert dst scanline
872 pixel = null;
873 idx = 0;
874 for (int x = 0; x < w; x++) {
875 for (int i = 0; i < iccDstNumComp; i++) {
876 dstColor[i] = ((float) (dstLine[idx++] & 0xffff)) *
877 dstDiffMinMax[i] + dstMinVal[i];
878 }
879 if (nonICCDst) {
880 color = srcColorSpace.fromCIEXYZ(dstColor);
881 for (int i = 0; i < dstNumComp; i++) {
882 dstColor[i] = color[i];
883 }
884 }
885 if (needSrcAlpha) {
886 dstColor[dstNumComp] = alpha[x];
887 } else if (dstHasAlpha) {
888 dstColor[dstNumComp] = 1.0f;
889 }
890 pixel = dstCM.getDataElements(dstColor, 0, pixel);
891 dstRas.setDataElements(x, y, pixel);
892 }
893 }
894 } else {
895 /* possible non-ICC src, possible CSList, possible non-ICC dst */
896 // process per pixel
897 int numCS;
898 if (CSList == null) {
899 numCS = 0;
900 } else {
901 numCS = CSList.length;
902 }
903 float[] dstColor;
904 if (dstHasAlpha) {
905 dstColor = new float[dstNumComp + 1];
906 } else {
907 dstColor = new float[dstNumComp];
908 }
909 Object spixel = null;
910 Object dpixel = null;
911 float[] color = null;
912 float[] tmpColor;
913 // process each pixel
914 for (int y = 0; y < h; y++) {
915 for (int x = 0; x < w; x++) {
916 spixel = srcRas.getDataElements(x, y, spixel);
917 color = srcCM.getNormalizedComponents(spixel, color, 0);
918 tmpColor = srcColorSpace.toCIEXYZ(color);
919 for (int i = 0; i < numCS; i++) {
920 tmpColor = CSList[i].fromCIEXYZ(tmpColor);
921 tmpColor = CSList[i].toCIEXYZ(tmpColor);
922 }
923 tmpColor = dstColorSpace.fromCIEXYZ(tmpColor);
924 for (int i = 0; i < dstNumComp; i++) {
925 dstColor[i] = tmpColor[i];
926 }
927 if (needSrcAlpha) {
928 dstColor[dstNumComp] = color[srcNumComp];
929 } else if (dstHasAlpha) {
930 dstColor[dstNumComp] = 1.0f;
931 }
932 dpixel = dstCM.getDataElements(dstColor, 0, dpixel);
933 dstRas.setDataElements(x, y, dpixel);
934
935 }
936 }
937 }
938
939 return dst;
940 }
941
942 /* color convert a Raster - handles byte, ushort, int, short, float,
943 or double transferTypes */
944 private final WritableRaster nonICCRasterFilter(Raster src,
945 WritableRaster dst) {
946
947 if (CSList.length != 2) {
948 throw new IllegalArgumentException(
949 "Destination ColorSpace is undefined");
950 }
951 if (src.getNumBands() != CSList[0].getNumComponents()) {
952 throw new IllegalArgumentException(
953 "Numbers of source Raster bands and source color space " +
954 "components do not match");
955 }
956 if (dst == null) {
957 dst = createCompatibleDestRaster(src);
958 } else {
959 if (src.getHeight() != dst.getHeight() ||
960 src.getWidth() != dst.getWidth()) {
961 throw new IllegalArgumentException(
962 "Width or height of Rasters do not match");
963 }
964 if (dst.getNumBands() != CSList[1].getNumComponents()) {
965 throw new IllegalArgumentException(
966 "Numbers of destination Raster bands and destination " +
967 "color space components do not match");
968 }
969 }
970
971 if (srcMinVals == null) {
972 getMinMaxValsFromColorSpaces(CSList[0], CSList[1]);
973 }
974
975 SampleModel srcSM = src.getSampleModel();
976 SampleModel dstSM = dst.getSampleModel();
977 boolean srcIsFloat, dstIsFloat;
978 int srcTransferType = src.getTransferType();
979 int dstTransferType = dst.getTransferType();
980 if ((srcTransferType == DataBuffer.TYPE_FLOAT) ||
981 (srcTransferType == DataBuffer.TYPE_DOUBLE)) {
982 srcIsFloat = true;
983 } else {
984 srcIsFloat = false;
985 }
986 if ((dstTransferType == DataBuffer.TYPE_FLOAT) ||
987 (dstTransferType == DataBuffer.TYPE_DOUBLE)) {
988 dstIsFloat = true;
989 } else {
990 dstIsFloat = false;
991 }
992 int w = src.getWidth();
993 int h = src.getHeight();
994 int srcNumBands = src.getNumBands();
995 int dstNumBands = dst.getNumBands();
996 float[] srcScaleFactor = null;
997 float[] dstScaleFactor = null;
998 if (!srcIsFloat) {
999 srcScaleFactor = new float[srcNumBands];
1000 for (int i = 0; i < srcNumBands; i++) {
1001 if (srcTransferType == DataBuffer.TYPE_SHORT) {
1002 srcScaleFactor[i] = (srcMaxVals[i] - srcMinVals[i]) /
1003 32767.0f;
1004 } else {
1005 srcScaleFactor[i] = (srcMaxVals[i] - srcMinVals[i]) /
1006 ((float) ((1 << srcSM.getSampleSize(i)) - 1));
1007 }
1008 }
1009 }
1010 if (!dstIsFloat) {
1011 dstScaleFactor = new float[dstNumBands];
1012 for (int i = 0; i < dstNumBands; i++) {
1013 if (dstTransferType == DataBuffer.TYPE_SHORT) {
1014 dstScaleFactor[i] = 32767.0f /
1015 (dstMaxVals[i] - dstMinVals[i]);
1016 } else {
1017 dstScaleFactor[i] =
1018 ((float) ((1 << dstSM.getSampleSize(i)) - 1)) /
1019 (dstMaxVals[i] - dstMinVals[i]);
1020 }
1021 }
1022 }
1023 int ys = src.getMinY();
1024 int yd = dst.getMinY();
1025 int xs, xd;
1026 float sample;
1027 float[] color = new float[srcNumBands];
1028 float[] tmpColor;
1029 ColorSpace srcColorSpace = CSList[0];
1030 ColorSpace dstColorSpace = CSList[1];
1031 // process each pixel
1032 for (int y = 0; y < h; y++, ys++, yd++) {
1033 // get src scanline
1034 xs = src.getMinX();
1035 xd = dst.getMinX();
1036 for (int x = 0; x < w; x++, xs++, xd++) {
1037 for (int i = 0; i < srcNumBands; i++) {
1038 sample = src.getSampleFloat(xs, ys, i);
1039 if (!srcIsFloat) {
1040 sample = sample * srcScaleFactor[i] + srcMinVals[i];
1041 }
1042 color[i] = sample;
1043 }
1044 tmpColor = srcColorSpace.toCIEXYZ(color);
1045 tmpColor = dstColorSpace.fromCIEXYZ(tmpColor);
1046 for (int i = 0; i < dstNumBands; i++) {
1047 sample = tmpColor[i];
1048 if (!dstIsFloat) {
1049 sample = (sample - dstMinVals[i]) * dstScaleFactor[i];
1050 }
1051 dst.setSample(xd, yd, i, sample);
1052 }
1053 }
1054 }
1055 return dst;
1056 }
1057
1058 private void getMinMaxValsFromProfiles(ICC_Profile srcProfile,
1059 ICC_Profile dstProfile) {
1060 int type = srcProfile.getColorSpaceType();
1061 int nc = srcProfile.getNumComponents();
1062 srcMinVals = new float[nc];
1063 srcMaxVals = new float[nc];
1064 setMinMax(type, nc, srcMinVals, srcMaxVals);
1065 type = dstProfile.getColorSpaceType();
1066 nc = dstProfile.getNumComponents();
1067 dstMinVals = new float[nc];
1068 dstMaxVals = new float[nc];
1069 setMinMax(type, nc, dstMinVals, dstMaxVals);
1070 }
1071
1072 private void setMinMax(int type, int nc, float[] minVals, float[] maxVals) {
1073 if (type == ColorSpace.TYPE_Lab) {
1074 minVals[0] = 0.0f; // L
1075 maxVals[0] = 100.0f;
1076 minVals[1] = -128.0f; // a
1077 maxVals[1] = 127.0f;
1078 minVals[2] = -128.0f; // b
1079 maxVals[2] = 127.0f;
1080 } else if (type == ColorSpace.TYPE_XYZ) {
1081 minVals[0] = minVals[1] = minVals[2] = 0.0f; // X, Y, Z
1082 maxVals[0] = maxVals[1] = maxVals[2] = 1.0f + (32767.0f/ 32768.0f);
1083 } else {
1084 for (int i = 0; i < nc; i++) {
1085 minVals[i] = 0.0f;
1086 maxVals[i] = 1.0f;
1087 }
1088 }
1089 }
1090
1091 private void getMinMaxValsFromColorSpaces(ColorSpace srcCspace,
1092 ColorSpace dstCspace) {
1093 int nc = srcCspace.getNumComponents();
1094 srcMinVals = new float[nc];
1095 srcMaxVals = new float[nc];
1096 for (int i = 0; i < nc; i++) {
1097 srcMinVals[i] = srcCspace.getMinValue(i);
1098 srcMaxVals[i] = srcCspace.getMaxValue(i);
1099 }
1100 nc = dstCspace.getNumComponents();
1101 dstMinVals = new float[nc];
1102 dstMaxVals = new float[nc];
1103 for (int i = 0; i < nc; i++) {
1104 dstMinVals[i] = dstCspace.getMinValue(i);
1105 dstMaxVals[i] = dstCspace.getMaxValue(i);
1106 }
1107 }
1108
1109}
java/pkg/java/awt/image/ColorModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ColorModel.java+1959−0
@@ -0,0 +1,1959 @@
1/*
2 * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.Transparency;
29import java.awt.color.ColorSpace;
30import java.awt.color.ICC_ColorSpace;
31import sun.java2d.cmm.CMSManager;
32import sun.java2d.cmm.ColorTransform;
33import sun.java2d.cmm.PCMM;
34import java.awt.Toolkit;
35import java.util.Collections;
36import java.util.Map;
37import java.util.WeakHashMap;
38
39/**
40 * The <code>ColorModel</code> abstract class encapsulates the
41 * methods for translating a pixel value to color components
42 * (for example, red, green, and blue) and an alpha component.
43 * In order to render an image to the screen, a printer, or another
44 * image, pixel values must be converted to color and alpha components.
45 * As arguments to or return values from methods of this class,
46 * pixels are represented as 32-bit ints or as arrays of primitive types.
47 * The number, order, and interpretation of color components for a
48 * <code>ColorModel</code> is specified by its <code>ColorSpace</code>.
49 * A <code>ColorModel</code> used with pixel data that does not include
50 * alpha information treats all pixels as opaque, which is an alpha
51 * value of 1.0.
52 * <p>
53 * This <code>ColorModel</code> class supports two representations of
54 * pixel values. A pixel value can be a single 32-bit int or an
55 * array of primitive types. The Java(tm) Platform 1.0 and 1.1 APIs
56 * represented pixels as single <code>byte</code> or single
57 * <code>int</code> values. For purposes of the <code>ColorModel</code>
58 * class, pixel value arguments were passed as ints. The Java(tm) 2
59 * Platform API introduced additional classes for representing images.
60 * With {@link BufferedImage} or {@link RenderedImage}
61 * objects, based on {@link Raster} and {@link SampleModel} classes, pixel
62 * values might not be conveniently representable as a single int.
63 * Consequently, <code>ColorModel</code> now has methods that accept
64 * pixel values represented as arrays of primitive types. The primitive
65 * type used by a particular <code>ColorModel</code> object is called its
66 * transfer type.
67 * <p>
68 * <code>ColorModel</code> objects used with images for which pixel values
69 * are not conveniently representable as a single int throw an
70 * {@link IllegalArgumentException} when methods taking a single int pixel
71 * argument are called. Subclasses of <code>ColorModel</code> must
72 * specify the conditions under which this occurs. This does not
73 * occur with {@link DirectColorModel} or {@link IndexColorModel} objects.
74 * <p>
75 * Currently, the transfer types supported by the Java 2D(tm) API are
76 * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT,
77 * DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, and DataBuffer.TYPE_DOUBLE.
78 * Most rendering operations will perform much faster when using ColorModels
79 * and images based on the first three of these types. In addition, some
80 * image filtering operations are not supported for ColorModels and
81 * images based on the latter three types.
82 * The transfer type for a particular <code>ColorModel</code> object is
83 * specified when the object is created, either explicitly or by default.
84 * All subclasses of <code>ColorModel</code> must specify what the
85 * possible transfer types are and how the number of elements in the
86 * primitive arrays representing pixels is determined.
87 * <p>
88 * For <code>BufferedImages</code>, the transfer type of its
89 * <code>Raster</code> and of the <code>Raster</code> object's
90 * <code>SampleModel</code> (available from the
91 * <code>getTransferType</code> methods of these classes) must match that
92 * of the <code>ColorModel</code>. The number of elements in an array
93 * representing a pixel for the <code>Raster</code> and
94 * <code>SampleModel</code> (available from the
95 * <code>getNumDataElements</code> methods of these classes) must match
96 * that of the <code>ColorModel</code>.
97 * <p>
98 * The algorithm used to convert from pixel values to color and alpha
99 * components varies by subclass. For example, there is not necessarily
100 * a one-to-one correspondence between samples obtained from the
101 * <code>SampleModel</code> of a <code>BufferedImage</code> object's
102 * <code>Raster</code> and color/alpha components. Even when
103 * there is such a correspondence, the number of bits in a sample is not
104 * necessarily the same as the number of bits in the corresponding color/alpha
105 * component. Each subclass must specify how the translation from
106 * pixel values to color/alpha components is done.
107 * <p>
108 * Methods in the <code>ColorModel</code> class use two different
109 * representations of color and alpha components - a normalized form
110 * and an unnormalized form. In the normalized form, each component is a
111 * <code>float</code> value between some minimum and maximum values. For
112 * the alpha component, the minimum is 0.0 and the maximum is 1.0. For
113 * color components the minimum and maximum values for each component can
114 * be obtained from the <code>ColorSpace</code> object. These values
115 * will often be 0.0 and 1.0 (e.g. normalized component values for the
116 * default sRGB color space range from 0.0 to 1.0), but some color spaces
117 * have component values with different upper and lower limits. These
118 * limits can be obtained using the <code>getMinValue</code> and
119 * <code>getMaxValue</code> methods of the <code>ColorSpace</code>
120 * class. Normalized color component values are not premultiplied.
121 * All <code>ColorModels</code> must support the normalized form.
122 * <p>
123 * In the unnormalized
124 * form, each component is an unsigned integral value between 0 and
125 * 2<sup>n</sup> - 1, where n is the number of significant bits for a
126 * particular component. If pixel values for a particular
127 * <code>ColorModel</code> represent color samples premultiplied by
128 * the alpha sample, unnormalized color component values are
129 * also premultiplied. The unnormalized form is used only with instances
130 * of <code>ColorModel</code> whose <code>ColorSpace</code> has minimum
131 * component values of 0.0 for all components and maximum values of
132 * 1.0 for all components.
133 * The unnormalized form for color and alpha components can be a convenient
134 * representation for <code>ColorModels</code> whose normalized component
135 * values all lie
136 * between 0.0 and 1.0. In such cases the integral value 0 maps to 0.0 and
137 * the value 2<sup>n</sup> - 1 maps to 1.0. In other cases, such as
138 * when the normalized component values can be either negative or positive,
139 * the unnormalized form is not convenient. Such <code>ColorModel</code>
140 * objects throw an {@link IllegalArgumentException} when methods involving
141 * an unnormalized argument are called. Subclasses of <code>ColorModel</code>
142 * must specify the conditions under which this occurs.
143 *
144 * @see IndexColorModel
145 * @see ComponentColorModel
146 * @see PackedColorModel
147 * @see DirectColorModel
148 * @see java.awt.Image
149 * @see BufferedImage
150 * @see RenderedImage
151 * @see java.awt.color.ColorSpace
152 * @see SampleModel
153 * @see Raster
154 * @see DataBuffer
155 */
156public abstract class ColorModel implements Transparency{
157 private long pData; // Placeholder for data for native functions
158
159 /**
160 * The total number of bits in the pixel.
161 */
162 protected int pixel_bits;
163 int nBits[];
164 int transparency = Transparency.TRANSLUCENT;
165 boolean supportsAlpha = true;
166 boolean isAlphaPremultiplied = false;
167 int numComponents = -1;
168 int numColorComponents = -1;
169 ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
170 int colorSpaceType = ColorSpace.TYPE_RGB;
171 int maxBits;
172 boolean is_sRGB = true;
173
174 /**
175 * Data type of the array used to represent pixel values.
176 */
177 protected int transferType;
178
179 /**
180 * This is copied from java.awt.Toolkit since we need the library
181 * loaded in java.awt.image also:
182 *
183 * WARNING: This is a temporary workaround for a problem in the
184 * way the AWT loads native libraries. A number of classes in the
185 * AWT package have a native method, initIDs(), which initializes
186 * the JNI field and method ids used in the native portion of
187 * their implementation.
188 *
189 * Since the use and storage of these ids is done by the
190 * implementation libraries, the implementation of these method is
191 * provided by the particular AWT implementations (for example,
192 * "Toolkit"s/Peer), such as Motif, Microsoft Windows, or Tiny. The
193 * problem is that this means that the native libraries must be
194 * loaded by the java.* classes, which do not necessarily know the
195 * names of the libraries to load. A better way of doing this
196 * would be to provide a separate library which defines java.awt.*
197 * initIDs, and exports the relevant symbols out to the
198 * implementation libraries.
199 *
200 * For now, we know it's done by the implementation, and we assume
201 * that the name of the library is "awt". -br.
202 */
203 private static boolean loaded = false;
204 static void loadLibraries() {
205 if (!loaded) {
206 java.security.AccessController.doPrivileged(
207 new sun.security.action.LoadLibraryAction("awt"));
208 loaded = true;
209 }
210 }
211 private static native void initIDs();
212 static {
213 /* ensure that the proper libraries are loaded */
214 loadLibraries();
215 initIDs();
216 }
217 private static ColorModel RGBdefault;
218
219 /**
220 * Returns a <code>DirectColorModel</code> that describes the default
221 * format for integer RGB values used in many of the methods in the
222 * AWT image interfaces for the convenience of the programmer.
223 * The color space is the default {@link ColorSpace}, sRGB.
224 * The format for the RGB values is an integer with 8 bits
225 * each of alpha, red, green, and blue color components ordered
226 * correspondingly from the most significant byte to the least
227 * significant byte, as in: 0xAARRGGBB. Color components are
228 * not premultiplied by the alpha component. This format does not
229 * necessarily represent the native or the most efficient
230 * <code>ColorModel</code> for a particular device or for all images.
231 * It is merely used as a common color model format.
232 * @return a <code>DirectColorModel</code>object describing default
233 * RGB values.
234 */
235 public static ColorModel getRGBdefault() {
236 if (RGBdefault == null) {
237 RGBdefault = new DirectColorModel(32,
238 0x00ff0000, // Red
239 0x0000ff00, // Green
240 0x000000ff, // Blue
241 0xff000000 // Alpha
242 );
243 }
244 return RGBdefault;
245 }
246
247 /**
248 * Constructs a <code>ColorModel</code> that translates pixels of the
249 * specified number of bits to color/alpha components. The color
250 * space is the default RGB <code>ColorSpace</code>, which is sRGB.
251 * Pixel values are assumed to include alpha information. If color
252 * and alpha information are represented in the pixel value as
253 * separate spatial bands, the color bands are assumed not to be
254 * premultiplied with the alpha value. The transparency type is
255 * java.awt.Transparency.TRANSLUCENT. The transfer type will be the
256 * smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
257 * or DataBuffer.TYPE_INT that can hold a single pixel
258 * (or DataBuffer.TYPE_UNDEFINED if bits is greater
259 * than 32). Since this constructor has no information about the
260 * number of bits per color and alpha component, any subclass calling
261 * this constructor should override any method that requires this
262 * information.
263 * @param bits the number of bits of a pixel
264 * @throws IllegalArgumentException if the number
265 * of bits in <code>bits</code> is less than 1
266 */
267 public ColorModel(int bits) {
268 pixel_bits = bits;
269 if (bits < 1) {
270 throw new IllegalArgumentException("Number of bits must be > 0");
271 }
272 numComponents = 4;
273 numColorComponents = 3;
274 maxBits = bits;
275 // REMIND: make sure transferType is set correctly
276 transferType = ColorModel.getDefaultTransferType(bits);
277 }
278
279 /**
280 * Constructs a <code>ColorModel</code> that translates pixel values
281 * to color/alpha components. Color components will be in the
282 * specified <code>ColorSpace</code>. <code>pixel_bits</code> is the
283 * number of bits in the pixel values. The bits array
284 * specifies the number of significant bits per color and alpha component.
285 * Its length should be the number of components in the
286 * <code>ColorSpace</code> if there is no alpha information in the
287 * pixel values, or one more than this number if there is alpha
288 * information. <code>hasAlpha</code> indicates whether or not alpha
289 * information is present. The <code>boolean</code>
290 * <code>isAlphaPremultiplied</code> specifies how to interpret pixel
291 * values in which color and alpha information are represented as
292 * separate spatial bands. If the <code>boolean</code>
293 * is <code>true</code>, color samples are assumed to have been
294 * multiplied by the alpha sample. The <code>transparency</code>
295 * specifies what alpha values can be represented by this color model.
296 * The transfer type is the type of primitive array used to represent
297 * pixel values. Note that the bits array contains the number of
298 * significant bits per color/alpha component after the translation
299 * from pixel values. For example, for an
300 * <code>IndexColorModel</code> with <code>pixel_bits</code> equal to
301 * 16, the bits array might have four elements with each element set
302 * to 8.
303 * @param pixel_bits the number of bits in the pixel values
304 * @param bits array that specifies the number of significant bits
305 * per color and alpha component
306 * @param cspace the specified <code>ColorSpace</code>
307 * @param hasAlpha <code>true</code> if alpha information is present;
308 * <code>false</code> otherwise
309 * @param isAlphaPremultiplied <code>true</code> if color samples are
310 * assumed to be premultiplied by the alpha samples;
311 * <code>false</code> otherwise
312 * @param transparency what alpha values can be represented by this
313 * color model
314 * @param transferType the type of the array used to represent pixel
315 * values
316 * @throws IllegalArgumentException if the length of
317 * the bit array is less than the number of color or alpha
318 * components in this <code>ColorModel</code>, or if the
319 * transparency is not a valid value.
320 * @throws IllegalArgumentException if the sum of the number
321 * of bits in <code>bits</code> is less than 1 or if
322 * any of the elements in <code>bits</code> is less than 0.
323 * @see java.awt.Transparency
324 */
325 protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
326 boolean hasAlpha,
327 boolean isAlphaPremultiplied,
328 int transparency,
329 int transferType) {
330 colorSpace = cspace;
331 colorSpaceType = cspace.getType();
332 numColorComponents = cspace.getNumComponents();
333 numComponents = numColorComponents + (hasAlpha ? 1 : 0);
334 supportsAlpha = hasAlpha;
335 if (bits.length < numComponents) {
336 throw new IllegalArgumentException("Number of color/alpha "+
337 "components should be "+
338 numComponents+
339 " but length of bits array is "+
340 bits.length);
341 }
342
343 // 4186669
344 if (transparency < Transparency.OPAQUE ||
345 transparency > Transparency.TRANSLUCENT)
346 {
347 throw new IllegalArgumentException("Unknown transparency: "+
348 transparency);
349 }
350
351 if (supportsAlpha == false) {
352 this.isAlphaPremultiplied = false;
353 this.transparency = Transparency.OPAQUE;
354 }
355 else {
356 this.isAlphaPremultiplied = isAlphaPremultiplied;
357 this.transparency = transparency;
358 }
359
360 nBits = (int[]) bits.clone();
361 this.pixel_bits = pixel_bits;
362 if (pixel_bits <= 0) {
363 throw new IllegalArgumentException("Number of pixel bits must "+
364 "be > 0");
365 }
366 // Check for bits < 0
367 maxBits = 0;
368 for (int i=0; i < bits.length; i++) {
369 // bug 4304697
370 if (bits[i] < 0) {
371 throw new
372 IllegalArgumentException("Number of bits must be >= 0");
373 }
374 if (maxBits < bits[i]) {
375 maxBits = bits[i];
376 }
377 }
378
379 // Make sure that we don't have all 0-bit components
380 if (maxBits == 0) {
381 throw new IllegalArgumentException("There must be at least "+
382 "one component with > 0 "+
383 "pixel bits.");
384 }
385
386 // Save this since we always need to check if it is the default CS
387 if (cspace != ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
388 is_sRGB = false;
389 }
390
391 // Save the transfer type
392 this.transferType = transferType;
393 }
394
395 /**
396 * Returns whether or not alpha is supported in this
397 * <code>ColorModel</code>.
398 * @return <code>true</code> if alpha is supported in this
399 * <code>ColorModel</code>; <code>false</code> otherwise.
400 */
401 final public boolean hasAlpha() {
402 return supportsAlpha;
403 }
404
405 /**
406 * Returns whether or not the alpha has been premultiplied in the
407 * pixel values to be translated by this <code>ColorModel</code>.
408 * If the boolean is <code>true</code>, this <code>ColorModel</code>
409 * is to be used to interpret pixel values in which color and alpha
410 * information are represented as separate spatial bands, and color
411 * samples are assumed to have been multiplied by the
412 * alpha sample.
413 * @return <code>true</code> if the alpha values are premultiplied
414 * in the pixel values to be translated by this
415 * <code>ColorModel</code>; <code>false</code> otherwise.
416 */
417 final public boolean isAlphaPremultiplied() {
418 return isAlphaPremultiplied;
419 }
420
421 /**
422 * Returns the transfer type of this <code>ColorModel</code>.
423 * The transfer type is the type of primitive array used to represent
424 * pixel values as arrays.
425 * @return the transfer type.
426 * @since 1.3
427 */
428 final public int getTransferType() {
429 return transferType;
430 }
431
432 /**
433 * Returns the number of bits per pixel described by this
434 * <code>ColorModel</code>.
435 * @return the number of bits per pixel.
436 */
437 public int getPixelSize() {
438 return pixel_bits;
439 }
440
441 /**
442 * Returns the number of bits for the specified color/alpha component.
443 * Color components are indexed in the order specified by the
444 * <code>ColorSpace</code>. Typically, this order reflects the name
445 * of the color space type. For example, for TYPE_RGB, index 0
446 * corresponds to red, index 1 to green, and index 2
447 * to blue. If this <code>ColorModel</code> supports alpha, the alpha
448 * component corresponds to the index following the last color
449 * component.
450 * @param componentIdx the index of the color/alpha component
451 * @return the number of bits for the color/alpha component at the
452 * specified index.
453 * @throws ArrayIndexOutOfBoundsException if <code>componentIdx</code>
454 * is greater than the number of components or
455 * less than zero
456 * @throws NullPointerException if the number of bits array is
457 * <code>null</code>
458 */
459 public int getComponentSize(int componentIdx) {
460 // REMIND:
461 if (nBits == null) {
462 throw new NullPointerException("Number of bits array is null.");
463 }
464
465 return nBits[componentIdx];
466 }
467
468 /**
469 * Returns an array of the number of bits per color/alpha component.
470 * The array contains the color components in the order specified by the
471 * <code>ColorSpace</code>, followed by the alpha component, if
472 * present.
473 * @return an array of the number of bits per color/alpha component
474 */
475 public int[] getComponentSize() {
476 if (nBits != null) {
477 return (int[]) nBits.clone();
478 }
479
480 return null;
481 }
482
483 /**
484 * Returns the transparency. Returns either OPAQUE, BITMASK,
485 * or TRANSLUCENT.
486 * @return the transparency of this <code>ColorModel</code>.
487 * @see Transparency#OPAQUE
488 * @see Transparency#BITMASK
489 * @see Transparency#TRANSLUCENT
490 */
491 public int getTransparency() {
492 return transparency;
493 }
494
495 /**
496 * Returns the number of components, including alpha, in this
497 * <code>ColorModel</code>. This is equal to the number of color
498 * components, optionally plus one, if there is an alpha component.
499 * @return the number of components in this <code>ColorModel</code>
500 */
501 public int getNumComponents() {
502 return numComponents;
503 }
504
505 /**
506 * Returns the number of color components in this
507 * <code>ColorModel</code>.
508 * This is the number of components returned by
509 * {@link ColorSpace#getNumComponents}.
510 * @return the number of color components in this
511 * <code>ColorModel</code>.
512 * @see ColorSpace#getNumComponents
513 */
514 public int getNumColorComponents() {
515 return numColorComponents;
516 }
517
518 /**
519 * Returns the red color component for the specified pixel, scaled
520 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
521 * is done if necessary. The pixel value is specified as an int.
522 * An <code>IllegalArgumentException</code> is thrown if pixel
523 * values for this <code>ColorModel</code> are not conveniently
524 * representable as a single int. The returned value is not a
525 * pre-multiplied value. For example, if the
526 * alpha is premultiplied, this method divides it out before returning
527 * the value. If the alpha value is 0, the red value is 0.
528 * @param pixel a specified pixel
529 * @return the value of the red component of the specified pixel.
530 */
531 public abstract int getRed(int pixel);
532
533 /**
534 * Returns the green color component for the specified pixel, scaled
535 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
536 * is done if necessary. The pixel value is specified as an int.
537 * An <code>IllegalArgumentException</code> is thrown if pixel
538 * values for this <code>ColorModel</code> are not conveniently
539 * representable as a single int. The returned value is a non
540 * pre-multiplied value. For example, if the alpha is premultiplied,
541 * this method divides it out before returning
542 * the value. If the alpha value is 0, the green value is 0.
543 * @param pixel the specified pixel
544 * @return the value of the green component of the specified pixel.
545 */
546 public abstract int getGreen(int pixel);
547
548 /**
549 * Returns the blue color component for the specified pixel, scaled
550 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
551 * is done if necessary. The pixel value is specified as an int.
552 * An <code>IllegalArgumentException</code> is thrown if pixel values
553 * for this <code>ColorModel</code> are not conveniently representable
554 * as a single int. The returned value is a non pre-multiplied
555 * value, for example, if the alpha is premultiplied, this method
556 * divides it out before returning the value. If the alpha value is
557 * 0, the blue value is 0.
558 * @param pixel the specified pixel
559 * @return the value of the blue component of the specified pixel.
560 */
561 public abstract int getBlue(int pixel);
562
563 /**
564 * Returns the alpha component for the specified pixel, scaled
565 * from 0 to 255. The pixel value is specified as an int.
566 * An <code>IllegalArgumentException</code> is thrown if pixel
567 * values for this <code>ColorModel</code> are not conveniently
568 * representable as a single int.
569 * @param pixel the specified pixel
570 * @return the value of alpha component of the specified pixel.
571 */
572 public abstract int getAlpha(int pixel);
573
574 /**
575 * Returns the color/alpha components of the pixel in the default
576 * RGB color model format. A color conversion is done if necessary.
577 * The pixel value is specified as an int.
578 * An <code>IllegalArgumentException</code> thrown if pixel values
579 * for this <code>ColorModel</code> are not conveniently representable
580 * as a single int. The returned value is in a non
581 * pre-multiplied format. For example, if the alpha is premultiplied,
582 * this method divides it out of the color components. If the alpha
583 * value is 0, the color values are 0.
584 * @param pixel the specified pixel
585 * @return the RGB value of the color/alpha components of the
586 * specified pixel.
587 * @see ColorModel#getRGBdefault
588 */
589 public int getRGB(int pixel) {
590 return (getAlpha(pixel) << 24)
591 | (getRed(pixel) << 16)
592 | (getGreen(pixel) << 8)
593 | (getBlue(pixel) << 0);
594 }
595
596 /**
597 * Returns the red color component for the specified pixel, scaled
598 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
599 * color conversion is done if necessary. The pixel value is
600 * specified by an array of data elements of type transferType passed
601 * in as an object reference. The returned value is a non
602 * pre-multiplied value. For example, if alpha is premultiplied,
603 * this method divides it out before returning
604 * the value. If the alpha value is 0, the red value is 0.
605 * If <code>inData</code> is not a primitive array of type
606 * transferType, a <code>ClassCastException</code> is thrown. An
607 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
608 * <code>inData</code> is not large enough to hold a pixel value for
609 * this <code>ColorModel</code>.
610 * If this <code>transferType</code> is not supported, a
611 * <code>UnsupportedOperationException</code> will be
612 * thrown. Since
613 * <code>ColorModel</code> is an abstract class, any instance
614 * must be an instance of a subclass. Subclasses inherit the
615 * implementation of this method and if they don't override it, this
616 * method throws an exception if the subclass uses a
617 * <code>transferType</code> other than
618 * <code>DataBuffer.TYPE_BYTE</code>,
619 * <code>DataBuffer.TYPE_USHORT</code>, or
620 * <code>DataBuffer.TYPE_INT</code>.
621 * @param inData an array of pixel values
622 * @return the value of the red component of the specified pixel.
623 * @throws ClassCastException if <code>inData</code>
624 * is not a primitive array of type <code>transferType</code>
625 * @throws ArrayIndexOutOfBoundsException if
626 * <code>inData</code> is not large enough to hold a pixel value
627 * for this <code>ColorModel</code>
628 * @throws UnsupportedOperationException if this
629 * <code>tranferType</code> is not supported by this
630 * <code>ColorModel</code>
631 */
632 public int getRed(Object inData) {
633 int pixel=0,length=0;
634 switch (transferType) {
635 case DataBuffer.TYPE_BYTE:
636 byte bdata[] = (byte[])inData;
637 pixel = bdata[0] & 0xff;
638 length = bdata.length;
639 break;
640 case DataBuffer.TYPE_USHORT:
641 short sdata[] = (short[])inData;
642 pixel = sdata[0] & 0xffff;
643 length = sdata.length;
644 break;
645 case DataBuffer.TYPE_INT:
646 int idata[] = (int[])inData;
647 pixel = idata[0];
648 length = idata.length;
649 break;
650 default:
651 throw new UnsupportedOperationException("This method has not been "+
652 "implemented for transferType " + transferType);
653 }
654 if (length == 1) {
655 return getRed(pixel);
656 }
657 else {
658 throw new UnsupportedOperationException
659 ("This method is not supported by this color model");
660 }
661 }
662
663 /**
664 * Returns the green color component for the specified pixel, scaled
665 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
666 * color conversion is done if necessary. The pixel value is
667 * specified by an array of data elements of type transferType passed
668 * in as an object reference. The returned value will be a non
669 * pre-multiplied value. For example, if the alpha is premultiplied,
670 * this method divides it out before returning the value. If the
671 * alpha value is 0, the green value is 0. If <code>inData</code> is
672 * not a primitive array of type transferType, a
673 * <code>ClassCastException</code> is thrown. An
674 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
675 * <code>inData</code> is not large enough to hold a pixel value for
676 * this <code>ColorModel</code>.
677 * If this <code>transferType</code> is not supported, a
678 * <code>UnsupportedOperationException</code> will be
679 * thrown. Since
680 * <code>ColorModel</code> is an abstract class, any instance
681 * must be an instance of a subclass. Subclasses inherit the
682 * implementation of this method and if they don't override it, this
683 * method throws an exception if the subclass uses a
684 * <code>transferType</code> other than
685 * <code>DataBuffer.TYPE_BYTE</code>,
686 * <code>DataBuffer.TYPE_USHORT</code>, or
687 * <code>DataBuffer.TYPE_INT</code>.
688 * @param inData an array of pixel values
689 * @return the value of the green component of the specified pixel.
690 * @throws <code>ClassCastException</code> if <code>inData</code>
691 * is not a primitive array of type <code>transferType</code>
692 * @throws <code>ArrayIndexOutOfBoundsException</code> if
693 * <code>inData</code> is not large enough to hold a pixel value
694 * for this <code>ColorModel</code>
695 * @throws <code>UnsupportedOperationException</code> if this
696 * <code>tranferType</code> is not supported by this
697 * <code>ColorModel</code>
698 */
699 public int getGreen(Object inData) {
700 int pixel=0,length=0;
701 switch (transferType) {
702 case DataBuffer.TYPE_BYTE:
703 byte bdata[] = (byte[])inData;
704 pixel = bdata[0] & 0xff;
705 length = bdata.length;
706 break;
707 case DataBuffer.TYPE_USHORT:
708 short sdata[] = (short[])inData;
709 pixel = sdata[0] & 0xffff;
710 length = sdata.length;
711 break;
712 case DataBuffer.TYPE_INT:
713 int idata[] = (int[])inData;
714 pixel = idata[0];
715 length = idata.length;
716 break;
717 default:
718 throw new UnsupportedOperationException("This method has not been "+
719 "implemented for transferType " + transferType);
720 }
721 if (length == 1) {
722 return getGreen(pixel);
723 }
724 else {
725 throw new UnsupportedOperationException
726 ("This method is not supported by this color model");
727 }
728 }
729
730 /**
731 * Returns the blue color component for the specified pixel, scaled
732 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
733 * color conversion is done if necessary. The pixel value is
734 * specified by an array of data elements of type transferType passed
735 * in as an object reference. The returned value is a non
736 * pre-multiplied value. For example, if the alpha is premultiplied,
737 * this method divides it out before returning the value. If the
738 * alpha value is 0, the blue value will be 0. If
739 * <code>inData</code> is not a primitive array of type transferType,
740 * a <code>ClassCastException</code> is thrown. An
741 * <code>ArrayIndexOutOfBoundsException</code> is
742 * thrown if <code>inData</code> is not large enough to hold a pixel
743 * value for this <code>ColorModel</code>.
744 * If this <code>transferType</code> is not supported, a
745 * <code>UnsupportedOperationException</code> will be
746 * thrown. Since
747 * <code>ColorModel</code> is an abstract class, any instance
748 * must be an instance of a subclass. Subclasses inherit the
749 * implementation of this method and if they don't override it, this
750 * method throws an exception if the subclass uses a
751 * <code>transferType</code> other than
752 * <code>DataBuffer.TYPE_BYTE</code>,
753 * <code>DataBuffer.TYPE_USHORT</code>, or
754 * <code>DataBuffer.TYPE_INT</code>.
755 * @param inData an array of pixel values
756 * @return the value of the blue component of the specified pixel.
757 * @throws ClassCastException if <code>inData</code>
758 * is not a primitive array of type <code>transferType</code>
759 * @throws ArrayIndexOutOfBoundsException if
760 * <code>inData</code> is not large enough to hold a pixel value
761 * for this <code>ColorModel</code>
762 * @throws UnsupportedOperationException if this
763 * <code>tranferType</code> is not supported by this
764 * <code>ColorModel</code>
765 */
766 public int getBlue(Object inData) {
767 int pixel=0,length=0;
768 switch (transferType) {
769 case DataBuffer.TYPE_BYTE:
770 byte bdata[] = (byte[])inData;
771 pixel = bdata[0] & 0xff;
772 length = bdata.length;
773 break;
774 case DataBuffer.TYPE_USHORT:
775 short sdata[] = (short[])inData;
776 pixel = sdata[0] & 0xffff;
777 length = sdata.length;
778 break;
779 case DataBuffer.TYPE_INT:
780 int idata[] = (int[])inData;
781 pixel = idata[0];
782 length = idata.length;
783 break;
784 default:
785 throw new UnsupportedOperationException("This method has not been "+
786 "implemented for transferType " + transferType);
787 }
788 if (length == 1) {
789 return getBlue(pixel);
790 }
791 else {
792 throw new UnsupportedOperationException
793 ("This method is not supported by this color model");
794 }
795 }
796
797 /**
798 * Returns the alpha component for the specified pixel, scaled
799 * from 0 to 255. The pixel value is specified by an array of data
800 * elements of type transferType passed in as an object reference.
801 * If inData is not a primitive array of type transferType, a
802 * <code>ClassCastException</code> is thrown. An
803 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
804 * <code>inData</code> is not large enough to hold a pixel value for
805 * this <code>ColorModel</code>.
806 * If this <code>transferType</code> is not supported, a
807 * <code>UnsupportedOperationException</code> will be
808 * thrown. Since
809 * <code>ColorModel</code> is an abstract class, any instance
810 * must be an instance of a subclass. Subclasses inherit the
811 * implementation of this method and if they don't override it, this
812 * method throws an exception if the subclass uses a
813 * <code>transferType</code> other than
814 * <code>DataBuffer.TYPE_BYTE</code>,
815 * <code>DataBuffer.TYPE_USHORT</code>, or
816 * <code>DataBuffer.TYPE_INT</code>.
817 * @param inData the specified pixel
818 * @return the alpha component of the specified pixel, scaled from
819 * 0 to 255.
820 * @throws ClassCastException if <code>inData</code>
821 * is not a primitive array of type <code>transferType</code>
822 * @throws ArrayIndexOutOfBoundsException if
823 * <code>inData</code> is not large enough to hold a pixel value
824 * for this <code>ColorModel</code>
825 * @throws UnsupportedOperationException if this
826 * <code>tranferType</code> is not supported by this
827 * <code>ColorModel</code>
828 */
829 public int getAlpha(Object inData) {
830 int pixel=0,length=0;
831 switch (transferType) {
832 case DataBuffer.TYPE_BYTE:
833 byte bdata[] = (byte[])inData;
834 pixel = bdata[0] & 0xff;
835 length = bdata.length;
836 break;
837 case DataBuffer.TYPE_USHORT:
838 short sdata[] = (short[])inData;
839 pixel = sdata[0] & 0xffff;
840 length = sdata.length;
841 break;
842 case DataBuffer.TYPE_INT:
843 int idata[] = (int[])inData;
844 pixel = idata[0];
845 length = idata.length;
846 break;
847 default:
848 throw new UnsupportedOperationException("This method has not been "+
849 "implemented for transferType " + transferType);
850 }
851 if (length == 1) {
852 return getAlpha(pixel);
853 }
854 else {
855 throw new UnsupportedOperationException
856 ("This method is not supported by this color model");
857 }
858 }
859
860 /**
861 * Returns the color/alpha components for the specified pixel in the
862 * default RGB color model format. A color conversion is done if
863 * necessary. The pixel value is specified by an array of data
864 * elements of type transferType passed in as an object reference.
865 * If inData is not a primitive array of type transferType, a
866 * <code>ClassCastException</code> is thrown. An
867 * <code>ArrayIndexOutOfBoundsException</code> is
868 * thrown if <code>inData</code> is not large enough to hold a pixel
869 * value for this <code>ColorModel</code>.
870 * The returned value will be in a non pre-multiplied format, i.e. if
871 * the alpha is premultiplied, this method will divide it out of the
872 * color components (if the alpha value is 0, the color values will be 0).
873 * @param inData the specified pixel
874 * @return the color and alpha components of the specified pixel.
875 * @see ColorModel#getRGBdefault
876 */
877 public int getRGB(Object inData) {
878 return (getAlpha(inData) << 24)
879 | (getRed(inData) << 16)
880 | (getGreen(inData) << 8)
881 | (getBlue(inData) << 0);
882 }
883
884 /**
885 * Returns a data element array representation of a pixel in this
886 * <code>ColorModel</code>, given an integer pixel representation in
887 * the default RGB color model.
888 * This array can then be passed to the
889 * {@link WritableRaster#setDataElements} method of
890 * a {@link WritableRaster} object. If the pixel variable is
891 * <code>null</code>, a new array will be allocated. If
892 * <code>pixel</code> is not
893 * <code>null</code>, it must be a primitive array of type
894 * <code>transferType</code>; otherwise, a
895 * <code>ClassCastException</code> is thrown. An
896 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
897 * <code>pixel</code> is
898 * not large enough to hold a pixel value for this
899 * <code>ColorModel</code>. The pixel array is returned.
900 * If this <code>transferType</code> is not supported, a
901 * <code>UnsupportedOperationException</code> will be
902 * thrown. Since <code>ColorModel</code> is an abstract class,
903 * any instance is an instance of a subclass. Subclasses must
904 * override this method since the implementation in this abstract
905 * class throws an <code>UnsupportedOperationException</code>.
906 * @param rgb the integer pixel representation in the default RGB
907 * color model
908 * @param pixel the specified pixel
909 * @return an array representation of the specified pixel in this
910 * <code>ColorModel</code>.
911 * @throws ClassCastException if <code>pixel</code>
912 * is not a primitive array of type <code>transferType</code>
913 * @throws ArrayIndexOutOfBoundsException if
914 * <code>pixel</code> is not large enough to hold a pixel value
915 * for this <code>ColorModel</code>
916 * @throws UnsupportedOperationException if this
917 * method is not supported by this <code>ColorModel</code>
918 * @see WritableRaster#setDataElements
919 * @see SampleModel#setDataElements
920 */
921 public Object getDataElements(int rgb, Object pixel) {
922 throw new UnsupportedOperationException
923 ("This method is not supported by this color model.");
924 }
925
926 /**
927 * Returns an array of unnormalized color/alpha components given a pixel
928 * in this <code>ColorModel</code>. The pixel value is specified as
929 * an <code>int</code>. An <code>IllegalArgumentException</code>
930 * will be thrown if pixel values for this <code>ColorModel</code> are
931 * not conveniently representable as a single <code>int</code> or if
932 * color component values for this <code>ColorModel</code> are not
933 * conveniently representable in the unnormalized form.
934 * For example, this method can be used to retrieve the
935 * components for a specific pixel value in a
936 * <code>DirectColorModel</code>. If the components array is
937 * <code>null</code>, a new array will be allocated. The
938 * components array will be returned. Color/alpha components are
939 * stored in the components array starting at <code>offset</code>
940 * (even if the array is allocated by this method). An
941 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
942 * components array is not <code>null</code> and is not large
943 * enough to hold all the color and alpha components (starting at offset).
944 * Since <code>ColorModel</code> is an abstract class,
945 * any instance is an instance of a subclass. Subclasses must
946 * override this method since the implementation in this abstract
947 * class throws an <code>UnsupportedOperationException</code>.
948 * @param pixel the specified pixel
949 * @param components the array to receive the color and alpha
950 * components of the specified pixel
951 * @param offset the offset into the <code>components</code> array at
952 * which to start storing the color and alpha components
953 * @return an array containing the color and alpha components of the
954 * specified pixel starting at the specified offset.
955 * @throws UnsupportedOperationException if this
956 * method is not supported by this <code>ColorModel</code>
957 */
958 public int[] getComponents(int pixel, int[] components, int offset) {
959 throw new UnsupportedOperationException
960 ("This method is not supported by this color model.");
961 }
962
963 /**
964 * Returns an array of unnormalized color/alpha components given a pixel
965 * in this <code>ColorModel</code>. The pixel value is specified by
966 * an array of data elements of type transferType passed in as an
967 * object reference. If <code>pixel</code> is not a primitive array
968 * of type transferType, a <code>ClassCastException</code> is thrown.
969 * An <code>IllegalArgumentException</code> will be thrown if color
970 * component values for this <code>ColorModel</code> are not
971 * conveniently representable in the unnormalized form.
972 * An <code>ArrayIndexOutOfBoundsException</code> is
973 * thrown if <code>pixel</code> is not large enough to hold a pixel
974 * value for this <code>ColorModel</code>.
975 * This method can be used to retrieve the components for a specific
976 * pixel value in any <code>ColorModel</code>. If the components
977 * array is <code>null</code>, a new array will be allocated. The
978 * components array will be returned. Color/alpha components are
979 * stored in the <code>components</code> array starting at
980 * <code>offset</code> (even if the array is allocated by this
981 * method). An <code>ArrayIndexOutOfBoundsException</code>
982 * is thrown if the components array is not <code>null</code> and is
983 * not large enough to hold all the color and alpha components
984 * (starting at <code>offset</code>).
985 * Since <code>ColorModel</code> is an abstract class,
986 * any instance is an instance of a subclass. Subclasses must
987 * override this method since the implementation in this abstract
988 * class throws an <code>UnsupportedOperationException</code>.
989 * @param pixel the specified pixel
990 * @param components an array that receives the color and alpha
991 * components of the specified pixel
992 * @param offset the index into the <code>components</code> array at
993 * which to begin storing the color and alpha components of the
994 * specified pixel
995 * @return an array containing the color and alpha components of the
996 * specified pixel starting at the specified offset.
997 * @throws UnsupportedOperationException if this
998 * method is not supported by this <code>ColorModel</code>
999 */
1000 public int[] getComponents(Object pixel, int[] components, int offset) {
1001 throw new UnsupportedOperationException
1002 ("This method is not supported by this color model.");
1003 }
1004
1005 /**
1006 * Returns an array of all of the color/alpha components in unnormalized
1007 * form, given a normalized component array. Unnormalized components
1008 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1009 * n is the number of bits for a particular component. Normalized
1010 * components are float values between a per component minimum and
1011 * maximum specified by the <code>ColorSpace</code> object for this
1012 * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
1013 * will be thrown if color component values for this
1014 * <code>ColorModel</code> are not conveniently representable in the
1015 * unnormalized form. If the
1016 * <code>components</code> array is <code>null</code>, a new array
1017 * will be allocated. The <code>components</code> array will
1018 * be returned. Color/alpha components are stored in the
1019 * <code>components</code> array starting at <code>offset</code> (even
1020 * if the array is allocated by this method). An
1021 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1022 * <code>components</code> array is not <code>null</code> and is not
1023 * large enough to hold all the color and alpha
1024 * components (starting at <code>offset</code>). An
1025 * <code>IllegalArgumentException</code> is thrown if the
1026 * <code>normComponents</code> array is not large enough to hold
1027 * all the color and alpha components starting at
1028 * <code>normOffset</code>.
1029 * @param normComponents an array containing normalized components
1030 * @param normOffset the offset into the <code>normComponents</code>
1031 * array at which to start retrieving normalized components
1032 * @param components an array that receives the components from
1033 * <code>normComponents</code>
1034 * @param offset the index into <code>components</code> at which to
1035 * begin storing normalized components from
1036 * <code>normComponents</code>
1037 * @return an array containing unnormalized color and alpha
1038 * components.
1039 * @throws IllegalArgumentException If the component values for this
1040 * <CODE>ColorModel</CODE> are not conveniently representable in the
1041 * unnormalized form.
1042 * @throws IllegalArgumentException if the length of
1043 * <code>normComponents</code> minus <code>normOffset</code>
1044 * is less than <code>numComponents</code>
1045 * @throws UnsupportedOperationException if the
1046 * constructor of this <code>ColorModel</code> called the
1047 * <code>super(bits)</code> constructor, but did not
1048 * override this method. See the constructor,
1049 * {@link #ColorModel(int)}.
1050 */
1051 public int[] getUnnormalizedComponents(float[] normComponents,
1052 int normOffset,
1053 int[] components, int offset) {
1054 // Make sure that someone isn't using a custom color model
1055 // that called the super(bits) constructor.
1056 if (colorSpace == null) {
1057 throw new UnsupportedOperationException("This method is not supported "+
1058 "by this color model.");
1059 }
1060
1061 if (nBits == null) {
1062 throw new UnsupportedOperationException ("This method is not supported. "+
1063 "Unable to determine #bits per "+
1064 "component.");
1065 }
1066 if ((normComponents.length - normOffset) < numComponents) {
1067 throw new
1068 IllegalArgumentException(
1069 "Incorrect number of components. Expecting "+
1070 numComponents);
1071 }
1072
1073 if (components == null) {
1074 components = new int[offset+numComponents];
1075 }
1076
1077 if (supportsAlpha && isAlphaPremultiplied) {
1078 float normAlpha = normComponents[normOffset+numColorComponents];
1079 for (int i=0; i < numColorComponents; i++) {
1080 components[offset+i] = (int) (normComponents[normOffset+i]
1081 * ((1<<nBits[i]) - 1)
1082 * normAlpha + 0.5f);
1083 }
1084 components[offset+numColorComponents] = (int)
1085 (normAlpha * ((1<<nBits[numColorComponents]) - 1) + 0.5f);
1086 }
1087 else {
1088 for (int i=0; i < numComponents; i++) {
1089 components[offset+i] = (int) (normComponents[normOffset+i]
1090 * ((1<<nBits[i]) - 1) + 0.5f);
1091 }
1092 }
1093
1094 return components;
1095 }
1096
1097 /**
1098 * Returns an array of all of the color/alpha components in normalized
1099 * form, given an unnormalized component array. Unnormalized components
1100 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1101 * n is the number of bits for a particular component. Normalized
1102 * components are float values between a per component minimum and
1103 * maximum specified by the <code>ColorSpace</code> object for this
1104 * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
1105 * will be thrown if color component values for this
1106 * <code>ColorModel</code> are not conveniently representable in the
1107 * unnormalized form. If the
1108 * <code>normComponents</code> array is <code>null</code>, a new array
1109 * will be allocated. The <code>normComponents</code> array
1110 * will be returned. Color/alpha components are stored in the
1111 * <code>normComponents</code> array starting at
1112 * <code>normOffset</code> (even if the array is allocated by this
1113 * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
1114 * if the <code>normComponents</code> array is not <code>null</code>
1115 * and is not large enough to hold all the color and alpha components
1116 * (starting at <code>normOffset</code>). An
1117 * <code>IllegalArgumentException</code> is thrown if the
1118 * <code>components</code> array is not large enough to hold all the
1119 * color and alpha components starting at <code>offset</code>.
1120 * <p>
1121 * Since <code>ColorModel</code> is an abstract class,
1122 * any instance is an instance of a subclass. The default implementation
1123 * of this method in this abstract class assumes that component values
1124 * for this class are conveniently representable in the unnormalized
1125 * form. Therefore, subclasses which may
1126 * have instances which do not support the unnormalized form must
1127 * override this method.
1128 * @param components an array containing unnormalized components
1129 * @param offset the offset into the <code>components</code> array at
1130 * which to start retrieving unnormalized components
1131 * @param normComponents an array that receives the normalized components
1132 * @param normOffset the index into <code>normComponents</code> at
1133 * which to begin storing normalized components
1134 * @return an array containing normalized color and alpha
1135 * components.
1136 * @throws IllegalArgumentException If the component values for this
1137 * <CODE>ColorModel</CODE> are not conveniently representable in the
1138 * unnormalized form.
1139 * @throws UnsupportedOperationException if the
1140 * constructor of this <code>ColorModel</code> called the
1141 * <code>super(bits)</code> constructor, but did not
1142 * override this method. See the constructor,
1143 * {@link #ColorModel(int)}.
1144 * @throws UnsupportedOperationException if this method is unable
1145 * to determine the number of bits per component
1146 */
1147 public float[] getNormalizedComponents(int[] components, int offset,
1148 float[] normComponents,
1149 int normOffset) {
1150 // Make sure that someone isn't using a custom color model
1151 // that called the super(bits) constructor.
1152 if (colorSpace == null) {
1153 throw new UnsupportedOperationException("This method is not supported by "+
1154 "this color model.");
1155 }
1156 if (nBits == null) {
1157 throw new UnsupportedOperationException ("This method is not supported. "+
1158 "Unable to determine #bits per "+
1159 "component.");
1160 }
1161
1162 if ((components.length - offset) < numComponents) {
1163 throw new
1164 IllegalArgumentException(
1165 "Incorrect number of components. Expecting "+
1166 numComponents);
1167 }
1168
1169 if (normComponents == null) {
1170 normComponents = new float[numComponents+normOffset];
1171 }
1172
1173 if (supportsAlpha && isAlphaPremultiplied) {
1174 // Normalized coordinates are non premultiplied
1175 float normAlpha = (float)components[offset+numColorComponents];
1176 normAlpha /= (float) ((1<<nBits[numColorComponents]) - 1);
1177 if (normAlpha != 0.0f) {
1178 for (int i=0; i < numColorComponents; i++) {
1179 normComponents[normOffset+i] =
1180 ((float) components[offset+i]) /
1181 (normAlpha * ((float) ((1<<nBits[i]) - 1)));
1182 }
1183 } else {
1184 for (int i=0; i < numColorComponents; i++) {
1185 normComponents[normOffset+i] = 0.0f;
1186 }
1187 }
1188 normComponents[normOffset+numColorComponents] = normAlpha;
1189 }
1190 else {
1191 for (int i=0; i < numComponents; i++) {
1192 normComponents[normOffset+i] = ((float) components[offset+i]) /
1193 ((float) ((1<<nBits[i]) - 1));
1194 }
1195 }
1196
1197 return normComponents;
1198 }
1199
1200 /**
1201 * Returns a pixel value represented as an <code>int</code> in this
1202 * <code>ColorModel</code>, given an array of unnormalized color/alpha
1203 * components. This method will throw an
1204 * <code>IllegalArgumentException</code> if component values for this
1205 * <code>ColorModel</code> are not conveniently representable as a
1206 * single <code>int</code> or if color component values for this
1207 * <code>ColorModel</code> are not conveniently representable in the
1208 * unnormalized form. An
1209 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1210 * <code>components</code> array is not large enough to hold all the
1211 * color and alpha components (starting at <code>offset</code>).
1212 * Since <code>ColorModel</code> is an abstract class,
1213 * any instance is an instance of a subclass. Subclasses must
1214 * override this method since the implementation in this abstract
1215 * class throws an <code>UnsupportedOperationException</code>.
1216 * @param components an array of unnormalized color and alpha
1217 * components
1218 * @param offset the index into <code>components</code> at which to
1219 * begin retrieving the color and alpha components
1220 * @return an <code>int</code> pixel value in this
1221 * <code>ColorModel</code> corresponding to the specified components.
1222 * @throws IllegalArgumentException if
1223 * pixel values for this <code>ColorModel</code> are not
1224 * conveniently representable as a single <code>int</code>
1225 * @throws IllegalArgumentException if
1226 * component values for this <code>ColorModel</code> are not
1227 * conveniently representable in the unnormalized form
1228 * @throws ArrayIndexOutOfBoundsException if
1229 * the <code>components</code> array is not large enough to
1230 * hold all of the color and alpha components starting at
1231 * <code>offset</code>
1232 * @throws UnsupportedOperationException if this
1233 * method is not supported by this <code>ColorModel</code>
1234 */
1235 public int getDataElement(int[] components, int offset) {
1236 throw new UnsupportedOperationException("This method is not supported "+
1237 "by this color model.");
1238 }
1239
1240 /**
1241 * Returns a data element array representation of a pixel in this
1242 * <code>ColorModel</code>, given an array of unnormalized color/alpha
1243 * components. This array can then be passed to the
1244 * <code>setDataElements</code> method of a <code>WritableRaster</code>
1245 * object. This method will throw an <code>IllegalArgumentException</code>
1246 * if color component values for this <code>ColorModel</code> are not
1247 * conveniently representable in the unnormalized form.
1248 * An <code>ArrayIndexOutOfBoundsException</code> is thrown
1249 * if the <code>components</code> array is not large enough to hold
1250 * all the color and alpha components (starting at
1251 * <code>offset</code>). If the <code>obj</code> variable is
1252 * <code>null</code>, a new array will be allocated. If
1253 * <code>obj</code> is not <code>null</code>, it must be a primitive
1254 * array of type transferType; otherwise, a
1255 * <code>ClassCastException</code> is thrown. An
1256 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
1257 * <code>obj</code> is not large enough to hold a pixel value for this
1258 * <code>ColorModel</code>.
1259 * Since <code>ColorModel</code> is an abstract class,
1260 * any instance is an instance of a subclass. Subclasses must
1261 * override this method since the implementation in this abstract
1262 * class throws an <code>UnsupportedOperationException</code>.
1263 * @param components an array of unnormalized color and alpha
1264 * components
1265 * @param offset the index into <code>components</code> at which to
1266 * begin retrieving color and alpha components
1267 * @param obj the <code>Object</code> representing an array of color
1268 * and alpha components
1269 * @return an <code>Object</code> representing an array of color and
1270 * alpha components.
1271 * @throws ClassCastException if <code>obj</code>
1272 * is not a primitive array of type <code>transferType</code>
1273 * @throws ArrayIndexOutOfBoundsException if
1274 * <code>obj</code> is not large enough to hold a pixel value
1275 * for this <code>ColorModel</code> or the <code>components</code>
1276 * array is not large enough to hold all of the color and alpha
1277 * components starting at <code>offset</code>
1278 * @throws IllegalArgumentException if
1279 * component values for this <code>ColorModel</code> are not
1280 * conveniently representable in the unnormalized form
1281 * @throws UnsupportedOperationException if this
1282 * method is not supported by this <code>ColorModel</code>
1283 * @see WritableRaster#setDataElements
1284 * @see SampleModel#setDataElements
1285 */
1286 public Object getDataElements(int[] components, int offset, Object obj) {
1287 throw new UnsupportedOperationException("This method has not been implemented "+
1288 "for this color model.");
1289 }
1290
1291 /**
1292 * Returns a pixel value represented as an <code>int</code> in this
1293 * <code>ColorModel</code>, given an array of normalized color/alpha
1294 * components. This method will throw an
1295 * <code>IllegalArgumentException</code> if pixel values for this
1296 * <code>ColorModel</code> are not conveniently representable as a
1297 * single <code>int</code>. An
1298 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1299 * <code>normComponents</code> array is not large enough to hold all the
1300 * color and alpha components (starting at <code>normOffset</code>).
1301 * Since <code>ColorModel</code> is an abstract class,
1302 * any instance is an instance of a subclass. The default implementation
1303 * of this method in this abstract class first converts from the
1304 * normalized form to the unnormalized form and then calls
1305 * <code>getDataElement(int[], int)</code>. Subclasses which may
1306 * have instances which do not support the unnormalized form must
1307 * override this method.
1308 * @param normComponents an array of normalized color and alpha
1309 * components
1310 * @param normOffset the index into <code>normComponents</code> at which to
1311 * begin retrieving the color and alpha components
1312 * @return an <code>int</code> pixel value in this
1313 * <code>ColorModel</code> corresponding to the specified components.
1314 * @throws IllegalArgumentException if
1315 * pixel values for this <code>ColorModel</code> are not
1316 * conveniently representable as a single <code>int</code>
1317 * @throws ArrayIndexOutOfBoundsException if
1318 * the <code>normComponents</code> array is not large enough to
1319 * hold all of the color and alpha components starting at
1320 * <code>normOffset</code>
1321 * @since 1.4
1322 */
1323 public int getDataElement(float[] normComponents, int normOffset) {
1324 int components[] = getUnnormalizedComponents(normComponents,
1325 normOffset, null, 0);
1326 return getDataElement(components, 0);
1327 }
1328
1329 /**
1330 * Returns a data element array representation of a pixel in this
1331 * <code>ColorModel</code>, given an array of normalized color/alpha
1332 * components. This array can then be passed to the
1333 * <code>setDataElements</code> method of a <code>WritableRaster</code>
1334 * object. An <code>ArrayIndexOutOfBoundsException</code> is thrown
1335 * if the <code>normComponents</code> array is not large enough to hold
1336 * all the color and alpha components (starting at
1337 * <code>normOffset</code>). If the <code>obj</code> variable is
1338 * <code>null</code>, a new array will be allocated. If
1339 * <code>obj</code> is not <code>null</code>, it must be a primitive
1340 * array of type transferType; otherwise, a
1341 * <code>ClassCastException</code> is thrown. An
1342 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
1343 * <code>obj</code> is not large enough to hold a pixel value for this
1344 * <code>ColorModel</code>.
1345 * Since <code>ColorModel</code> is an abstract class,
1346 * any instance is an instance of a subclass. The default implementation
1347 * of this method in this abstract class first converts from the
1348 * normalized form to the unnormalized form and then calls
1349 * <code>getDataElement(int[], int, Object)</code>. Subclasses which may
1350 * have instances which do not support the unnormalized form must
1351 * override this method.
1352 * @param normComponents an array of normalized color and alpha
1353 * components
1354 * @param normOffset the index into <code>normComponents</code> at which to
1355 * begin retrieving color and alpha components
1356 * @param obj a primitive data array to hold the returned pixel
1357 * @return an <code>Object</code> which is a primitive data array
1358 * representation of a pixel
1359 * @throws ClassCastException if <code>obj</code>
1360 * is not a primitive array of type <code>transferType</code>
1361 * @throws ArrayIndexOutOfBoundsException if
1362 * <code>obj</code> is not large enough to hold a pixel value
1363 * for this <code>ColorModel</code> or the <code>normComponents</code>
1364 * array is not large enough to hold all of the color and alpha
1365 * components starting at <code>normOffset</code>
1366 * @see WritableRaster#setDataElements
1367 * @see SampleModel#setDataElements
1368 * @since 1.4
1369 */
1370 public Object getDataElements(float[] normComponents, int normOffset,
1371 Object obj) {
1372 int components[] = getUnnormalizedComponents(normComponents,
1373 normOffset, null, 0);
1374 return getDataElements(components, 0, obj);
1375 }
1376
1377 /**
1378 * Returns an array of all of the color/alpha components in normalized
1379 * form, given a pixel in this <code>ColorModel</code>. The pixel
1380 * value is specified by an array of data elements of type transferType
1381 * passed in as an object reference. If pixel is not a primitive array
1382 * of type transferType, a <code>ClassCastException</code> is thrown.
1383 * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
1384 * <code>pixel</code> is not large enough to hold a pixel value for this
1385 * <code>ColorModel</code>.
1386 * Normalized components are float values between a per component minimum
1387 * and maximum specified by the <code>ColorSpace</code> object for this
1388 * <code>ColorModel</code>. If the
1389 * <code>normComponents</code> array is <code>null</code>, a new array
1390 * will be allocated. The <code>normComponents</code> array
1391 * will be returned. Color/alpha components are stored in the
1392 * <code>normComponents</code> array starting at
1393 * <code>normOffset</code> (even if the array is allocated by this
1394 * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
1395 * if the <code>normComponents</code> array is not <code>null</code>
1396 * and is not large enough to hold all the color and alpha components
1397 * (starting at <code>normOffset</code>).
1398 * Since <code>ColorModel</code> is an abstract class,
1399 * any instance is an instance of a subclass. The default implementation
1400 * of this method in this abstract class first retrieves color and alpha
1401 * components in the unnormalized form using
1402 * <code>getComponents(Object, int[], int)</code> and then calls
1403 * <code>getNormalizedComponents(int[], int, float[], int)</code>.
1404 * Subclasses which may
1405 * have instances which do not support the unnormalized form must
1406 * override this method.
1407 * @param pixel the specified pixel
1408 * @param normComponents an array to receive the normalized components
1409 * @param normOffset the offset into the <code>normComponents</code>
1410 * array at which to start storing normalized components
1411 * @return an array containing normalized color and alpha
1412 * components.
1413 * @throws ClassCastException if <code>pixel</code> is not a primitive
1414 * array of type transferType
1415 * @throws ArrayIndexOutOfBoundsException if
1416 * <code>normComponents</code> is not large enough to hold all
1417 * color and alpha components starting at <code>normOffset</code>
1418 * @throws ArrayIndexOutOfBoundsException if
1419 * <code>pixel</code> is not large enough to hold a pixel
1420 * value for this <code>ColorModel</code>.
1421 * @throws UnsupportedOperationException if the
1422 * constructor of this <code>ColorModel</code> called the
1423 * <code>super(bits)</code> constructor, but did not
1424 * override this method. See the constructor,
1425 * {@link #ColorModel(int)}.
1426 * @throws UnsupportedOperationException if this method is unable
1427 * to determine the number of bits per component
1428 * @since 1.4
1429 */
1430 public float[] getNormalizedComponents(Object pixel,
1431 float[] normComponents,
1432 int normOffset) {
1433 int components[] = getComponents(pixel, null, 0);
1434 return getNormalizedComponents(components, 0,
1435 normComponents, normOffset);
1436 }
1437
1438 /**
1439 * Tests if the specified <code>Object</code> is an instance of
1440 * <code>ColorModel</code> and if it equals this
1441 * <code>ColorModel</code>.
1442 * @param obj the <code>Object</code> to test for equality
1443 * @return <code>true</code> if the specified <code>Object</code>
1444 * is an instance of <code>ColorModel</code> and equals this
1445 * <code>ColorModel</code>; <code>false</code> otherwise.
1446 */
1447 public boolean equals(Object obj) {
1448 if (!(obj instanceof ColorModel)) {
1449 return false;
1450 }
1451 ColorModel cm = (ColorModel) obj;
1452
1453 if (this == cm) {
1454 return true;
1455 }
1456 if (supportsAlpha != cm.hasAlpha() ||
1457 isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
1458 pixel_bits != cm.getPixelSize() ||
1459 transparency != cm.getTransparency() ||
1460 numComponents != cm.getNumComponents())
1461 {
1462 return false;
1463 }
1464
1465 int[] nb = cm.getComponentSize();
1466
1467 if ((nBits != null) && (nb != null)) {
1468 for (int i = 0; i < numComponents; i++) {
1469 if (nBits[i] != nb[i]) {
1470 return false;
1471 }
1472 }
1473 } else {
1474 return ((nBits == null) && (nb == null));
1475 }
1476
1477 return true;
1478 }
1479
1480 /**
1481 * Returns the hash code for this ColorModel.
1482 *
1483 * @return a hash code for this ColorModel.
1484 */
1485 public int hashCode() {
1486
1487 int result = 0;
1488
1489 result = (supportsAlpha ? 2 : 3) +
1490 (isAlphaPremultiplied ? 4 : 5) +
1491 pixel_bits * 6 +
1492 transparency * 7 +
1493 numComponents * 8;
1494
1495 if (nBits != null) {
1496 for (int i = 0; i < numComponents; i++) {
1497 result = result + nBits[i] * (i + 9);
1498 }
1499 }
1500
1501 return result;
1502 }
1503
1504 /**
1505 * Returns the <code>ColorSpace</code> associated with this
1506 * <code>ColorModel</code>.
1507 * @return the <code>ColorSpace</code> of this
1508 * <code>ColorModel</code>.
1509 */
1510 final public ColorSpace getColorSpace() {
1511 return colorSpace;
1512 }
1513
1514 /**
1515 * Forces the raster data to match the state specified in the
1516 * <code>isAlphaPremultiplied</code> variable, assuming the data is
1517 * currently correctly described by this <code>ColorModel</code>. It
1518 * may multiply or divide the color raster data by alpha, or do
1519 * nothing if the data is in the correct state. If the data needs to
1520 * be coerced, this method will also return an instance of this
1521 * <code>ColorModel</code> with the <code>isAlphaPremultiplied</code>
1522 * flag set appropriately. This method will throw a
1523 * <code>UnsupportedOperationException</code> if it is not supported
1524 * by this <code>ColorModel</code>.
1525 * Since <code>ColorModel</code> is an abstract class,
1526 * any instance is an instance of a subclass. Subclasses must
1527 * override this method since the implementation in this abstract
1528 * class throws an <code>UnsupportedOperationException</code>.
1529 * @param raster the <code>WritableRaster</code> data
1530 * @param isAlphaPremultiplied <code>true</code> if the alpha is
1531 * premultiplied; <code>false</code> otherwise
1532 * @return a <code>ColorModel</code> object that represents the
1533 * coerced data.
1534 */
1535 public ColorModel coerceData (WritableRaster raster,
1536 boolean isAlphaPremultiplied) {
1537 throw new UnsupportedOperationException
1538 ("This method is not supported by this color model");
1539 }
1540
1541 /**
1542 * Returns <code>true</code> if <code>raster</code> is compatible
1543 * with this <code>ColorModel</code> and <code>false</code> if it is
1544 * not.
1545 * Since <code>ColorModel</code> is an abstract class,
1546 * any instance is an instance of a subclass. Subclasses must
1547 * override this method since the implementation in this abstract
1548 * class throws an <code>UnsupportedOperationException</code>.
1549 * @param raster the {@link Raster} object to test for compatibility
1550 * @return <code>true</code> if <code>raster</code> is compatible
1551 * with this <code>ColorModel</code>.
1552 * @throws UnsupportedOperationException if this
1553 * method has not been implemented for this
1554 * <code>ColorModel</code>
1555 */
1556 public boolean isCompatibleRaster(Raster raster) {
1557 throw new UnsupportedOperationException(
1558 "This method has not been implemented for this ColorModel.");
1559 }
1560
1561 /**
1562 * Creates a <code>WritableRaster</code> with the specified width and
1563 * height that has a data layout (<code>SampleModel</code>) compatible
1564 * with this <code>ColorModel</code>.
1565 * Since <code>ColorModel</code> is an abstract class,
1566 * any instance is an instance of a subclass. Subclasses must
1567 * override this method since the implementation in this abstract
1568 * class throws an <code>UnsupportedOperationException</code>.
1569 * @param w the width to apply to the new <code>WritableRaster</code>
1570 * @param h the height to apply to the new <code>WritableRaster</code>
1571 * @return a <code>WritableRaster</code> object with the specified
1572 * width and height.
1573 * @throws UnsupportedOperationException if this
1574 * method is not supported by this <code>ColorModel</code>
1575 * @see WritableRaster
1576 * @see SampleModel
1577 */
1578 public WritableRaster createCompatibleWritableRaster(int w, int h) {
1579 throw new UnsupportedOperationException
1580 ("This method is not supported by this color model");
1581 }
1582
1583 /**
1584 * Creates a <code>SampleModel</code> with the specified width and
1585 * height that has a data layout compatible with this
1586 * <code>ColorModel</code>.
1587 * Since <code>ColorModel</code> is an abstract class,
1588 * any instance is an instance of a subclass. Subclasses must
1589 * override this method since the implementation in this abstract
1590 * class throws an <code>UnsupportedOperationException</code>.
1591 * @param w the width to apply to the new <code>SampleModel</code>
1592 * @param h the height to apply to the new <code>SampleModel</code>
1593 * @return a <code>SampleModel</code> object with the specified
1594 * width and height.
1595 * @throws UnsupportedOperationException if this
1596 * method is not supported by this <code>ColorModel</code>
1597 * @see SampleModel
1598 */
1599 public SampleModel createCompatibleSampleModel(int w, int h) {
1600 throw new UnsupportedOperationException
1601 ("This method is not supported by this color model");
1602 }
1603
1604 /** Checks if the <code>SampleModel</code> is compatible with this
1605 * <code>ColorModel</code>.
1606 * Since <code>ColorModel</code> is an abstract class,
1607 * any instance is an instance of a subclass. Subclasses must
1608 * override this method since the implementation in this abstract
1609 * class throws an <code>UnsupportedOperationException</code>.
1610 * @param sm the specified <code>SampleModel</code>
1611 * @return <code>true</code> if the specified <code>SampleModel</code>
1612 * is compatible with this <code>ColorModel</code>; <code>false</code>
1613 * otherwise.
1614 * @throws UnsupportedOperationException if this
1615 * method is not supported by this <code>ColorModel</code>
1616 * @see SampleModel
1617 */
1618 public boolean isCompatibleSampleModel(SampleModel sm) {
1619 throw new UnsupportedOperationException
1620 ("This method is not supported by this color model");
1621 }
1622
1623 /**
1624 * Disposes of system resources associated with this
1625 * <code>ColorModel</code> once this <code>ColorModel</code> is no
1626 * longer referenced.
1627 */
1628 public void finalize() {
1629 }
1630
1631
1632 /**
1633 * Returns a <code>Raster</code> representing the alpha channel of an
1634 * image, extracted from the input <code>Raster</code>, provided that
1635 * pixel values of this <code>ColorModel</code> represent color and
1636 * alpha information as separate spatial bands (e.g.
1637 * {@link ComponentColorModel} and <code>DirectColorModel</code>).
1638 * This method assumes that <code>Raster</code> objects associated
1639 * with such a <code>ColorModel</code> store the alpha band, if
1640 * present, as the last band of image data. Returns <code>null</code>
1641 * if there is no separate spatial alpha channel associated with this
1642 * <code>ColorModel</code>. If this is an
1643 * <code>IndexColorModel</code> which has alpha in the lookup table,
1644 * this method will return <code>null</code> since
1645 * there is no spatially discrete alpha channel.
1646 * This method will create a new <code>Raster</code> (but will share
1647 * the data array).
1648 * Since <code>ColorModel</code> is an abstract class, any instance
1649 * is an instance of a subclass. Subclasses must override this
1650 * method to get any behavior other than returning <code>null</code>
1651 * because the implementation in this abstract class returns
1652 * <code>null</code>.
1653 * @param raster the specified <code>Raster</code>
1654 * @return a <code>Raster</code> representing the alpha channel of
1655 * an image, obtained from the specified <code>Raster</code>.
1656 */
1657 public WritableRaster getAlphaRaster(WritableRaster raster) {
1658 return null;
1659 }
1660
1661 /**
1662 * Returns the <code>String</code> representation of the contents of
1663 * this <code>ColorModel</code>object.
1664 * @return a <code>String</code> representing the contents of this
1665 * <code>ColorModel</code> object.
1666 */
1667 public String toString() {
1668 return new String("ColorModel: #pixelBits = "+pixel_bits
1669 + " numComponents = "+numComponents
1670 + " color space = "+colorSpace
1671 + " transparency = "+transparency
1672 + " has alpha = "+supportsAlpha
1673 + " isAlphaPre = "+isAlphaPremultiplied
1674 );
1675 }
1676
1677 static int getDefaultTransferType(int pixel_bits) {
1678 if (pixel_bits <= 8) {
1679 return DataBuffer.TYPE_BYTE;
1680 } else if (pixel_bits <= 16) {
1681 return DataBuffer.TYPE_USHORT;
1682 } else if (pixel_bits <= 32) {
1683 return DataBuffer.TYPE_INT;
1684 } else {
1685 return DataBuffer.TYPE_UNDEFINED;
1686 }
1687 }
1688
1689 static byte[] l8Tos8 = null; // 8-bit linear to 8-bit non-linear sRGB LUT
1690 static byte[] s8Tol8 = null; // 8-bit non-linear sRGB to 8-bit linear LUT
1691 static byte[] l16Tos8 = null; // 16-bit linear to 8-bit non-linear sRGB LUT
1692 static short[] s8Tol16 = null; // 8-bit non-linear sRGB to 16-bit linear LUT
1693
1694 // Maps to hold LUTs for grayscale conversions
1695 static Map g8Tos8Map = null; // 8-bit gray values to 8-bit sRGB values
1696 static Map lg16Toog8Map = null; // 16-bit linear to 8-bit "other" gray
1697 static Map g16Tos8Map = null; // 16-bit gray values to 8-bit sRGB values
1698 static Map lg16Toog16Map = null; // 16-bit linear to 16-bit "other" gray
1699
1700 static boolean isLinearRGBspace(ColorSpace cs) {
1701 // Note: CMM.LINEAR_RGBspace will be null if the linear
1702 // RGB space has not been created yet.
1703 return (cs == CMSManager.LINEAR_RGBspace);
1704 }
1705
1706 static boolean isLinearGRAYspace(ColorSpace cs) {
1707 // Note: CMM.GRAYspace will be null if the linear
1708 // gray space has not been created yet.
1709 return (cs == CMSManager.GRAYspace);
1710 }
1711
1712 static byte[] getLinearRGB8TosRGB8LUT() {
1713 if (l8Tos8 == null) {
1714 l8Tos8 = new byte[256];
1715 float input, output;
1716 // algorithm for linear RGB to nonlinear sRGB conversion
1717 // is from the IEC 61966-2-1 International Standard,
1718 // Colour Management - Default RGB colour space - sRGB,
1719 // First Edition, 1999-10,
1720 // avaiable for order at http://www.iec.ch
1721 for (int i = 0; i <= 255; i++) {
1722 input = ((float) i) / 255.0f;
1723 if (input <= 0.0031308f) {
1724 output = input * 12.92f;
1725 } else {
1726 output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4)))
1727 - 0.055f;
1728 }
1729 l8Tos8[i] = (byte) Math.round(output * 255.0f);
1730 }
1731 }
1732 return l8Tos8;
1733 }
1734
1735 static byte[] getsRGB8ToLinearRGB8LUT() {
1736 if (s8Tol8 == null) {
1737 s8Tol8 = new byte[256];
1738 float input, output;
1739 // algorithm from IEC 61966-2-1 International Standard
1740 for (int i = 0; i <= 255; i++) {
1741 input = ((float) i) / 255.0f;
1742 if (input <= 0.04045f) {
1743 output = input / 12.92f;
1744 } else {
1745 output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4);
1746 }
1747 s8Tol8[i] = (byte) Math.round(output * 255.0f);
1748 }
1749 }
1750 return s8Tol8;
1751 }
1752
1753 static byte[] getLinearRGB16TosRGB8LUT() {
1754 if (l16Tos8 == null) {
1755 l16Tos8 = new byte[65536];
1756 float input, output;
1757 // algorithm from IEC 61966-2-1 International Standard
1758 for (int i = 0; i <= 65535; i++) {
1759 input = ((float) i) / 65535.0f;
1760 if (input <= 0.0031308f) {
1761 output = input * 12.92f;
1762 } else {
1763 output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4)))
1764 - 0.055f;
1765 }
1766 l16Tos8[i] = (byte) Math.round(output * 255.0f);
1767 }
1768 }
1769 return l16Tos8;
1770 }
1771
1772 static short[] getsRGB8ToLinearRGB16LUT() {
1773 if (s8Tol16 == null) {
1774 s8Tol16 = new short[256];
1775 float input, output;
1776 // algorithm from IEC 61966-2-1 International Standard
1777 for (int i = 0; i <= 255; i++) {
1778 input = ((float) i) / 255.0f;
1779 if (input <= 0.04045f) {
1780 output = input / 12.92f;
1781 } else {
1782 output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4);
1783 }
1784 s8Tol16[i] = (short) Math.round(output * 65535.0f);
1785 }
1786 }
1787 return s8Tol16;
1788 }
1789
1790 /*
1791 * Return a byte LUT that converts 8-bit gray values in the grayCS
1792 * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut
1793 * is the byte array returned by this method and sval = lut[gval],
1794 * then the sRGB triple (sval,sval,sval) is the best match to gval.
1795 * Cache references to any computed LUT in a Map.
1796 */
1797 static byte[] getGray8TosRGB8LUT(ICC_ColorSpace grayCS) {
1798 if (isLinearGRAYspace(grayCS)) {
1799 return getLinearRGB8TosRGB8LUT();
1800 }
1801 if (g8Tos8Map != null) {
1802 byte[] g8Tos8LUT = (byte []) g8Tos8Map.get(grayCS);
1803 if (g8Tos8LUT != null) {
1804 return g8Tos8LUT;
1805 }
1806 }
1807 byte[] g8Tos8LUT = new byte[256];
1808 for (int i = 0; i <= 255; i++) {
1809 g8Tos8LUT[i] = (byte) i;
1810 }
1811 ColorTransform[] transformList = new ColorTransform[2];
1812 PCMM mdl = CMSManager.getModule();
1813 ICC_ColorSpace srgbCS =
1814 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB);
1815 transformList[0] = mdl.createTransform(
1816 grayCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1817 transformList[1] = mdl.createTransform(
1818 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1819 ColorTransform t = mdl.createTransform(transformList);
1820 byte[] tmp = t.colorConvert(g8Tos8LUT, null);
1821 for (int i = 0, j= 2; i <= 255; i++, j += 3) {
1822 // All three components of tmp should be equal, since
1823 // the input color space to colorConvert is a gray scale
1824 // space. However, there are slight anomalies in the results.
1825 // Copy tmp starting at index 2, since colorConvert seems
1826 // to be slightly more accurate for the third component!
1827 g8Tos8LUT[i] = tmp[j];
1828 }
1829 if (g8Tos8Map == null) {
1830 g8Tos8Map = Collections.synchronizedMap(new WeakHashMap(2));
1831 }
1832 g8Tos8Map.put(grayCS, g8Tos8LUT);
1833 return g8Tos8LUT;
1834 }
1835
1836 /*
1837 * Return a byte LUT that converts 16-bit gray values in the CS_GRAY
1838 * linear gray ColorSpace to the appropriate 8-bit value in the
1839 * grayCS ColorSpace. Cache references to any computed LUT in a Map.
1840 */
1841 static byte[] getLinearGray16ToOtherGray8LUT(ICC_ColorSpace grayCS) {
1842 if (lg16Toog8Map != null) {
1843 byte[] lg16Toog8LUT = (byte []) lg16Toog8Map.get(grayCS);
1844 if (lg16Toog8LUT != null) {
1845 return lg16Toog8LUT;
1846 }
1847 }
1848 short[] tmp = new short[65536];
1849 for (int i = 0; i <= 65535; i++) {
1850 tmp[i] = (short) i;
1851 }
1852 ColorTransform[] transformList = new ColorTransform[2];
1853 PCMM mdl = CMSManager.getModule();
1854 ICC_ColorSpace lgCS =
1855 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY);
1856 transformList[0] = mdl.createTransform (
1857 lgCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1858 transformList[1] = mdl.createTransform (
1859 grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1860 ColorTransform t = mdl.createTransform(transformList);
1861 tmp = t.colorConvert(tmp, null);
1862 byte[] lg16Toog8LUT = new byte[65536];
1863 for (int i = 0; i <= 65535; i++) {
1864 // scale unsigned short (0 - 65535) to unsigned byte (0 - 255)
1865 lg16Toog8LUT[i] =
1866 (byte) (((float) (tmp[i] & 0xffff)) * (1.0f /257.0f) + 0.5f);
1867 }
1868 if (lg16Toog8Map == null) {
1869 lg16Toog8Map = Collections.synchronizedMap(new WeakHashMap(2));
1870 }
1871 lg16Toog8Map.put(grayCS, lg16Toog8LUT);
1872 return lg16Toog8LUT;
1873 }
1874
1875 /*
1876 * Return a byte LUT that converts 16-bit gray values in the grayCS
1877 * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut
1878 * is the byte array returned by this method and sval = lut[gval],
1879 * then the sRGB triple (sval,sval,sval) is the best match to gval.
1880 * Cache references to any computed LUT in a Map.
1881 */
1882 static byte[] getGray16TosRGB8LUT(ICC_ColorSpace grayCS) {
1883 if (isLinearGRAYspace(grayCS)) {
1884 return getLinearRGB16TosRGB8LUT();
1885 }
1886 if (g16Tos8Map != null) {
1887 byte[] g16Tos8LUT = (byte []) g16Tos8Map.get(grayCS);
1888 if (g16Tos8LUT != null) {
1889 return g16Tos8LUT;
1890 }
1891 }
1892 short[] tmp = new short[65536];
1893 for (int i = 0; i <= 65535; i++) {
1894 tmp[i] = (short) i;
1895 }
1896 ColorTransform[] transformList = new ColorTransform[2];
1897 PCMM mdl = CMSManager.getModule();
1898 ICC_ColorSpace srgbCS =
1899 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB);
1900 transformList[0] = mdl.createTransform (
1901 grayCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1902 transformList[1] = mdl.createTransform (
1903 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1904 ColorTransform t = mdl.createTransform(transformList);
1905 tmp = t.colorConvert(tmp, null);
1906 byte[] g16Tos8LUT = new byte[65536];
1907 for (int i = 0, j= 2; i <= 65535; i++, j += 3) {
1908 // All three components of tmp should be equal, since
1909 // the input color space to colorConvert is a gray scale
1910 // space. However, there are slight anomalies in the results.
1911 // Copy tmp starting at index 2, since colorConvert seems
1912 // to be slightly more accurate for the third component!
1913
1914 // scale unsigned short (0 - 65535) to unsigned byte (0 - 255)
1915 g16Tos8LUT[i] =
1916 (byte) (((float) (tmp[j] & 0xffff)) * (1.0f /257.0f) + 0.5f);
1917 }
1918 if (g16Tos8Map == null) {
1919 g16Tos8Map = Collections.synchronizedMap(new WeakHashMap(2));
1920 }
1921 g16Tos8Map.put(grayCS, g16Tos8LUT);
1922 return g16Tos8LUT;
1923 }
1924
1925 /*
1926 * Return a short LUT that converts 16-bit gray values in the CS_GRAY
1927 * linear gray ColorSpace to the appropriate 16-bit value in the
1928 * grayCS ColorSpace. Cache references to any computed LUT in a Map.
1929 */
1930 static short[] getLinearGray16ToOtherGray16LUT(ICC_ColorSpace grayCS) {
1931 if (lg16Toog16Map != null) {
1932 short[] lg16Toog16LUT = (short []) lg16Toog16Map.get(grayCS);
1933 if (lg16Toog16LUT != null) {
1934 return lg16Toog16LUT;
1935 }
1936 }
1937 short[] tmp = new short[65536];
1938 for (int i = 0; i <= 65535; i++) {
1939 tmp[i] = (short) i;
1940 }
1941 ColorTransform[] transformList = new ColorTransform[2];
1942 PCMM mdl = CMSManager.getModule();
1943 ICC_ColorSpace lgCS =
1944 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY);
1945 transformList[0] = mdl.createTransform (
1946 lgCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1947 transformList[1] = mdl.createTransform(
1948 grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1949 ColorTransform t = mdl.createTransform(
1950 transformList);
1951 short[] lg16Toog16LUT = t.colorConvert(tmp, null);
1952 if (lg16Toog16Map == null) {
1953 lg16Toog16Map = Collections.synchronizedMap(new WeakHashMap(2));
1954 }
1955 lg16Toog16Map.put(grayCS, lg16Toog16LUT);
1956 return lg16Toog16LUT;
1957 }
1958
1959}
java/pkg/java/awt/image/ComponentColorModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ComponentColorModel.java+2948−0
@@ -0,0 +1,2948 @@
1/*
2 * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.color.ColorSpace;
29import 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
95 * supported if two conditions hold. First, sample value value 0 must
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 */
177public 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) {
1517 intpixel[1] = (int)(grn);
1518 }
1519 else {
1520 intpixel[1] = (int) (grn * factor * ((1<<nBits[1]) - 1) + 0.5f);
1521 }
1522 if (nBits[2] == precision) {
1523 intpixel[2] = (int)(blu);
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>
2321 * This method must be overrridden by a subclass if that subclass
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}
java/pkg/java/awt/image/ComponentSampleModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ComponentSampleModel.java+1212−0
@@ -0,0 +1,1212 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26/* ****************************************************************
27 ******************************************************************
28 ******************************************************************
29 *** COPYRIGHT (c) Eastman Kodak Company, 1997
30 *** As an unpublished work pursuant to Title 17 of the United
31 *** States Code. All rights reserved.
32 ******************************************************************
33 ******************************************************************
34 ******************************************************************/
35
36package java.awt.image;
37
38import java.util.Arrays;
39
40/**
41 * This class represents image data which is stored such that each sample
42 * of a pixel occupies one data element of the DataBuffer. It stores the
43 * N samples which make up a pixel in N separate data array elements.
44 * Different bands may be in different banks of the DataBuffer.
45 * Accessor methods are provided so that image data can be manipulated
46 * directly. This class can support different kinds of interleaving, e.g.
47 * band interleaving, scanline interleaving, and pixel interleaving.
48 * Pixel stride is the number of data array elements between two samples
49 * for the same band on the same scanline. Scanline stride is the number
50 * of data array elements between a given sample and the corresponding sample
51 * in the same column of the next scanline. Band offsets denote the number
52 * of data array elements from the first data array element of the bank
53 * of the DataBuffer holding each band to the first sample of the band.
54 * The bands are numbered from 0 to N-1. This class can represent image
55 * data for which each sample is an unsigned integral number which can be
56 * stored in 8, 16, or 32 bits (using <code>DataBuffer.TYPE_BYTE</code>,
57 * <code>DataBuffer.TYPE_USHORT</code>, or <code>DataBuffer.TYPE_INT</code>,
58 * respectively), data for which each sample is a signed integral number
59 * which can be stored in 16 bits (using <code>DataBuffer.TYPE_SHORT</code>),
60 * or data for which each sample is a signed float or double quantity
61 * (using <code>DataBuffer.TYPE_FLOAT</code> or
62 * <code>DataBuffer.TYPE_DOUBLE</code>, respectively).
63 * All samples of a given ComponentSampleModel
64 * are stored with the same precision. All strides and offsets must be
65 * non-negative. This class supports
66 * {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
67 * {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
68 * {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
69 * {@link DataBuffer#TYPE_INT TYPE_INT},
70 * {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT},
71 * {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE},
72 * @see java.awt.image.PixelInterleavedSampleModel
73 * @see java.awt.image.BandedSampleModel
74 */
75
76public class ComponentSampleModel extends SampleModel
77{
78 /** Offsets for all bands in data array elements. */
79 protected int bandOffsets[];
80
81 /** Index for each bank storing a band of image data. */
82 protected int[] bankIndices;
83
84 /**
85 * The number of bands in this
86 * <code>ComponentSampleModel</code>.
87 */
88 protected int numBands = 1;
89
90 /**
91 * The number of banks in this
92 * <code>ComponentSampleModel</code>.
93 */
94 protected int numBanks = 1;
95
96 /**
97 * Line stride (in data array elements) of the region of image
98 * data described by this ComponentSampleModel.
99 */
100 protected int scanlineStride;
101
102 /** Pixel stride (in data array elements) of the region of image
103 * data described by this ComponentSampleModel.
104 */
105 protected int pixelStride;
106
107 static private native void initIDs();
108 static {
109 ColorModel.loadLibraries();
110 initIDs();
111 }
112
113 /**
114 * Constructs a ComponentSampleModel with the specified parameters.
115 * The number of bands will be given by the length of the bandOffsets array.
116 * All bands will be stored in the first bank of the DataBuffer.
117 * @param dataType the data type for storing samples
118 * @param w the width (in pixels) of the region of
119 * image data described
120 * @param h the height (in pixels) of the region of
121 * image data described
122 * @param pixelStride the pixel stride of the region of image
123 * data described
124 * @param scanlineStride the line stride of the region of image
125 * data described
126 * @param bandOffsets the offsets of all bands
127 * @throws IllegalArgumentException if <code>w</code> or
128 * <code>h</code> is not greater than 0
129 * @throws IllegalArgumentException if <code>pixelStride</code>
130 * is less than 0
131 * @throws IllegalArgumentException if <code>scanlineStride</code>
132 * is less than 0
133 * @throws IllegalArgumentException if <code>numBands</code>
134 * is less than 1
135 * @throws IllegalArgumentException if the product of <code>w</code>
136 * and <code>h</code> is greater than
137 * <code>Integer.MAX_VALUE</code>
138 * @throws IllegalArgumentException if <code>dataType</code> is not
139 * one of the supported data types
140 */
141 public ComponentSampleModel(int dataType,
142 int w, int h,
143 int pixelStride,
144 int scanlineStride,
145 int bandOffsets[]) {
146 super(dataType, w, h, bandOffsets.length);
147 this.dataType = dataType;
148 this.pixelStride = pixelStride;
149 this.scanlineStride = scanlineStride;
150 this.bandOffsets = (int[])bandOffsets.clone();
151 numBands = bandOffsets.length;
152 if (pixelStride < 0) {
153 throw new IllegalArgumentException("Pixel stride must be >= 0");
154 }
155 // TODO - bug 4296691 - remove this check
156 if (scanlineStride < 0) {
157 throw new IllegalArgumentException("Scanline stride must be >= 0");
158 }
159 if (numBands < 1) {
160 throw new IllegalArgumentException("Must have at least one band.");
161 }
162 if ((dataType < DataBuffer.TYPE_BYTE) ||
163 (dataType > DataBuffer.TYPE_DOUBLE)) {
164 throw new IllegalArgumentException("Unsupported dataType.");
165 }
166 bankIndices = new int[numBands];
167 for (int i=0; i<numBands; i++) {
168 bankIndices[i] = 0;
169 }
170 }
171
172
173 /**
174 * Constructs a ComponentSampleModel with the specified parameters.
175 * The number of bands will be given by the length of the bandOffsets array.
176 * Different bands may be stored in different banks of the DataBuffer.
177 *
178 * @param dataType the data type for storing samples
179 * @param w the width (in pixels) of the region of
180 * image data described
181 * @param h the height (in pixels) of the region of
182 * image data described
183 * @param pixelStride the pixel stride of the region of image
184 * data described
185 * @param scanlineStride The line stride of the region of image
186 * data described
187 * @param bankIndices the bank indices of all bands
188 * @param bandOffsets the band offsets of all bands
189 * @throws IllegalArgumentException if <code>w</code> or
190 * <code>h</code> is not greater than 0
191 * @throws IllegalArgumentException if <code>pixelStride</code>
192 * is less than 0
193 * @throws IllegalArgumentException if <code>scanlineStride</code>
194 * is less than 0
195 * @throws IllegalArgumentException if the length of
196 * <code>bankIndices</code> does not equal the length of
197 * <code>bankOffsets</code>
198 * @throws IllegalArgumentException if any of the bank indices
199 * of <code>bandIndices</code> is less than 0
200 * @throws IllegalArgumentException if <code>dataType</code> is not
201 * one of the supported data types
202 */
203 public ComponentSampleModel(int dataType,
204 int w, int h,
205 int pixelStride,
206 int scanlineStride,
207 int bankIndices[],
208 int bandOffsets[]) {
209 super(dataType, w, h, bandOffsets.length);
210 this.dataType = dataType;
211 this.pixelStride = pixelStride;
212 this.scanlineStride = scanlineStride;
213 this.bandOffsets = (int[])bandOffsets.clone();
214 this.bankIndices = (int[]) bankIndices.clone();
215 if (pixelStride < 0) {
216 throw new IllegalArgumentException("Pixel stride must be >= 0");
217 }
218 // TODO - bug 4296691 - remove this check
219 if (scanlineStride < 0) {
220 throw new IllegalArgumentException("Scanline stride must be >= 0");
221 }
222 if ((dataType < DataBuffer.TYPE_BYTE) ||
223 (dataType > DataBuffer.TYPE_DOUBLE)) {
224 throw new IllegalArgumentException("Unsupported dataType.");
225 }
226 int maxBank = bankIndices[0];
227 if (maxBank < 0) {
228 throw new IllegalArgumentException("Index of bank 0 is less than "+
229 "0 ("+maxBank+")");
230 }
231 for (int i=1; i < bankIndices.length; i++) {
232 if (bankIndices[i] > maxBank) {
233 maxBank = bankIndices[i];
234 }
235 else if (bankIndices[i] < 0) {
236 throw new IllegalArgumentException("Index of bank "+i+
237 " is less than 0 ("+
238 maxBank+")");
239 }
240 }
241 numBanks = maxBank+1;
242 numBands = bandOffsets.length;
243 if (bandOffsets.length != bankIndices.length) {
244 throw new IllegalArgumentException("Length of bandOffsets must "+
245 "equal length of bankIndices.");
246 }
247 }
248
249 /**
250 * Returns the size of the data buffer (in data elements) needed
251 * for a data buffer that matches this ComponentSampleModel.
252 */
253 private long getBufferSize() {
254 int maxBandOff=bandOffsets[0];
255 for (int i=1; i<bandOffsets.length; i++)
256 maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
257
258 long size = 0;
259 if (maxBandOff >= 0)
260 size += maxBandOff+1;
261 if (pixelStride > 0)
262 size += pixelStride * (width-1);
263 if (scanlineStride > 0)
264 size += scanlineStride*(height-1);
265 return size;
266 }
267
268 /**
269 * Preserves band ordering with new step factor...
270 */
271 int []orderBands(int orig[], int step) {
272 int map[] = new int[orig.length];
273 int ret[] = new int[orig.length];
274
275 for (int i=0; i<map.length; i++) map[i] = i;
276
277 for (int i = 0; i < ret.length; i++) {
278 int index = i;
279 for (int j = i+1; j < ret.length; j++) {
280 if (orig[map[index]] > orig[map[j]]) {
281 index = j;
282 }
283 }
284 ret[map[index]] = i*step;
285 map[index] = map[i];
286 }
287 return ret;
288 }
289
290 /**
291 * Creates a new <code>ComponentSampleModel</code> with the specified
292 * width and height. The new <code>SampleModel</code> will have the same
293 * number of bands, storage data type, interleaving scheme, and
294 * pixel stride as this <code>SampleModel</code>.
295 * @param w the width of the resulting <code>SampleModel</code>
296 * @param h the height of the resulting <code>SampleModel</code>
297 * @return a new <code>ComponentSampleModel</code> with the specified size
298 * @throws IllegalArgumentException if <code>w</code> or
299 * <code>h</code> is not greater than 0
300 */
301 public SampleModel createCompatibleSampleModel(int w, int h) {
302 SampleModel ret=null;
303 long size;
304 int minBandOff=bandOffsets[0];
305 int maxBandOff=bandOffsets[0];
306 for (int i=1; i<bandOffsets.length; i++) {
307 minBandOff = Math.min(minBandOff,bandOffsets[i]);
308 maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
309 }
310 maxBandOff -= minBandOff;
311
312 int bands = bandOffsets.length;
313 int bandOff[];
314 int pStride = Math.abs(pixelStride);
315 int lStride = Math.abs(scanlineStride);
316 int bStride = Math.abs(maxBandOff);
317
318 if (pStride > lStride) {
319 if (pStride > bStride) {
320 if (lStride > bStride) { // pix > line > band
321 bandOff = new int[bandOffsets.length];
322 for (int i=0; i<bands; i++)
323 bandOff[i] = bandOffsets[i]-minBandOff;
324 lStride = bStride+1;
325 pStride = lStride*h;
326 } else { // pix > band > line
327 bandOff = orderBands(bandOffsets,lStride*h);
328 pStride = bands*lStride*h;
329 }
330 } else { // band > pix > line
331 pStride = lStride*h;
332 bandOff = orderBands(bandOffsets,pStride*w);
333 }
334 } else {
335 if (pStride > bStride) { // line > pix > band
336 bandOff = new int[bandOffsets.length];
337 for (int i=0; i<bands; i++)
338 bandOff[i] = bandOffsets[i]-minBandOff;
339 pStride = bStride+1;
340 lStride = pStride*w;
341 } else {
342 if (lStride > bStride) { // line > band > pix
343 bandOff = orderBands(bandOffsets,pStride*w);
344 lStride = bands*pStride*w;
345 } else { // band > line > pix
346 lStride = pStride*w;
347 bandOff = orderBands(bandOffsets,lStride*h);
348 }
349 }
350 }
351
352 // make sure we make room for negative offsets...
353 int base = 0;
354 if (scanlineStride < 0) {
355 base += lStride*h;
356 lStride *= -1;
357 }
358 if (pixelStride < 0) {
359 base += pStride*w;
360 pStride *= -1;
361 }
362
363 for (int i=0; i<bands; i++)
364 bandOff[i] += base;
365 return new ComponentSampleModel(dataType, w, h, pStride,
366 lStride, bankIndices, bandOff);
367 }
368
369 /**
370 * Creates a new ComponentSampleModel with a subset of the bands
371 * of this ComponentSampleModel. The new ComponentSampleModel can be
372 * used with any DataBuffer that the existing ComponentSampleModel
373 * can be used with. The new ComponentSampleModel/DataBuffer
374 * combination will represent an image with a subset of the bands
375 * of the original ComponentSampleModel/DataBuffer combination.
376 * @param bands a subset of bands from this
377 * <code>ComponentSampleModel</code>
378 * @return a <code>ComponentSampleModel</code> created with a subset
379 * of bands from this <code>ComponentSampleModel</code>.
380 */
381 public SampleModel createSubsetSampleModel(int bands[]) {
382 if (bands.length > bankIndices.length)
383 throw new RasterFormatException("There are only " +
384 bankIndices.length +
385 " bands");
386 int newBankIndices[] = new int[bands.length];
387 int newBandOffsets[] = new int[bands.length];
388
389 for (int i=0; i<bands.length; i++) {
390 newBankIndices[i] = bankIndices[bands[i]];
391 newBandOffsets[i] = bandOffsets[bands[i]];
392 }
393
394 return new ComponentSampleModel(this.dataType, width, height,
395 this.pixelStride,
396 this.scanlineStride,
397 newBankIndices, newBandOffsets);
398 }
399
400 /**
401 * Creates a <code>DataBuffer</code> that corresponds to this
402 * <code>ComponentSampleModel</code>.
403 * The <code>DataBuffer</code> object's data type, number of banks,
404 * and size are be consistent with this <code>ComponentSampleModel</code>.
405 * @return a <code>DataBuffer</code> whose data type, number of banks
406 * and size are consistent with this
407 * <code>ComponentSampleModel</code>.
408 */
409 public DataBuffer createDataBuffer() {
410 DataBuffer dataBuffer = null;
411
412 int size = (int)getBufferSize();
413 switch (dataType) {
414 case DataBuffer.TYPE_BYTE:
415 dataBuffer = new DataBufferByte(size, numBanks);
416 break;
417 case DataBuffer.TYPE_USHORT:
418 dataBuffer = new DataBufferUShort(size, numBanks);
419 break;
420 case DataBuffer.TYPE_SHORT:
421 dataBuffer = new DataBufferShort(size, numBanks);
422 break;
423 case DataBuffer.TYPE_INT:
424 dataBuffer = new DataBufferInt(size, numBanks);
425 break;
426 case DataBuffer.TYPE_FLOAT:
427 dataBuffer = new DataBufferFloat(size, numBanks);
428 break;
429 case DataBuffer.TYPE_DOUBLE:
430 dataBuffer = new DataBufferDouble(size, numBanks);
431 break;
432 }
433
434 return dataBuffer;
435 }
436
437
438 /** Gets the offset for the first band of pixel (x,y).
439 * A sample of the first band can be retrieved from a
440 * <code>DataBuffer</code>
441 * <code>data</code> with a <code>ComponentSampleModel</code>
442 * <code>csm</code> as
443 * <pre>
444 * data.getElem(csm.getOffset(x, y));
445 * </pre>
446 * @param x the X location of the pixel
447 * @param y the Y location of the pixel
448 * @return the offset for the first band of the specified pixel.
449 */
450 public int getOffset(int x, int y) {
451 int offset = y*scanlineStride + x*pixelStride + bandOffsets[0];
452 return offset;
453 }
454
455 /** Gets the offset for band b of pixel (x,y).
456 * A sample of band <code>b</code> can be retrieved from a
457 * <code>DataBuffer</code> <code>data</code>
458 * with a <code>ComponentSampleModel</code> <code>csm</code> as
459 * <pre>
460 * data.getElem(csm.getOffset(x, y, b));
461 * </pre>
462 * @param x the X location of the specified pixel
463 * @param y the Y location of the specified pixel
464 * @param b the specified band
465 * @return the offset for the specified band of the specified pixel.
466 */
467 public int getOffset(int x, int y, int b) {
468 int offset = y*scanlineStride + x*pixelStride + bandOffsets[b];
469 return offset;
470 }
471
472 /** Returns the number of bits per sample for all bands.
473 * @return an array containing the number of bits per sample
474 * for all bands, where each element in the array
475 * represents a band.
476 */
477 public final int[] getSampleSize() {
478 int sampleSize[] = new int [numBands];
479 int sizeInBits = getSampleSize(0);
480
481 for (int i=0; i<numBands; i++)
482 sampleSize[i] = sizeInBits;
483
484 return sampleSize;
485 }
486
487 /** Returns the number of bits per sample for the specified band.
488 * @param band the specified band
489 * @return the number of bits per sample for the specified band.
490 */
491 public final int getSampleSize(int band) {
492 return DataBuffer.getDataTypeSize(dataType);
493 }
494
495 /** Returns the bank indices for all bands.
496 * @return the bank indices for all bands.
497 */
498 public final int [] getBankIndices() {
499 return (int[]) bankIndices.clone();
500 }
501
502 /** Returns the band offset for all bands.
503 * @return the band offsets for all bands.
504 */
505 public final int [] getBandOffsets() {
506 return (int[])bandOffsets.clone();
507 }
508
509 /** Returns the scanline stride of this ComponentSampleModel.
510 * @return the scanline stride of this <code>ComponentSampleModel</code>.
511 */
512 public final int getScanlineStride() {
513 return scanlineStride;
514 }
515
516 /** Returns the pixel stride of this ComponentSampleModel.
517 * @return the pixel stride of this <code>ComponentSampleModel</code>.
518 */
519 public final int getPixelStride() {
520 return pixelStride;
521 }
522
523 /**
524 * Returns the number of data elements needed to transfer a pixel
525 * with the
526 * {@link #getDataElements(int, int, Object, DataBuffer) } and
527 * {@link #setDataElements(int, int, Object, DataBuffer) }
528 * methods.
529 * For a <code>ComponentSampleModel</code>, this is identical to the
530 * number of bands.
531 * @return the number of data elements needed to transfer a pixel with
532 * the <code>getDataElements</code> and
533 * <code>setDataElements</code> methods.
534 * @see java.awt.image.SampleModel#getNumDataElements
535 * @see #getNumBands
536 */
537 public final int getNumDataElements() {
538 return getNumBands();
539 }
540
541 /**
542 * Returns data for a single pixel in a primitive array of type
543 * <code>TransferType</code>. For a <code>ComponentSampleModel</code>,
544 * this is the same as the data type, and samples are returned
545 * one per array element. Generally, <code>obj</code> should
546 * be passed in as <code>null</code>, so that the <code>Object</code>
547 * is created automatically and is the right primitive data type.
548 * <p>
549 * The following code illustrates transferring data for one pixel from
550 * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
551 * described by <code>ComponentSampleModel</code> <code>csm1</code>,
552 * to <code>DataBuffer</code> <code>db2</code>, whose storage layout
553 * is described by <code>ComponentSampleModel</code> <code>csm2</code>.
554 * The transfer is usually more efficient than using
555 * <code>getPixel</code> and <code>setPixel</code>.
556 * <pre>
557 * ComponentSampleModel csm1, csm2;
558 * DataBufferInt db1, db2;
559 * csm2.setDataElements(x, y,
560 * csm1.getDataElements(x, y, null, db1), db2);
561 * </pre>
562 *
563 * Using <code>getDataElements</code> and <code>setDataElements</code>
564 * to transfer between two <code>DataBuffer/SampleModel</code>
565 * pairs is legitimate if the <code>SampleModel</code> objects have
566 * the same number of bands, corresponding bands have the same number of
567 * bits per sample, and the <code>TransferType</code>s are the same.
568 * <p>
569 * If <code>obj</code> is not <code>null</code>, it should be a
570 * primitive array of type <code>TransferType</code>.
571 * Otherwise, a <code>ClassCastException</code> is thrown. An
572 * <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
573 * coordinates are not in bounds, or if <code>obj</code> is not
574 * <code>null</code> and is not large enough to hold
575 * the pixel data.
576 *
577 * @param x the X coordinate of the pixel location
578 * @param y the Y coordinate of the pixel location
579 * @param obj if non-<code>null</code>, a primitive array
580 * in which to return the pixel data
581 * @param data the <code>DataBuffer</code> containing the image data
582 * @return the data of the specified pixel
583 * @see #setDataElements(int, int, Object, DataBuffer)
584 *
585 * @throws NullPointerException if data is null.
586 * @throws ArrayIndexOutOfBoundsException if the coordinates are
587 * not in bounds, or if obj is too small to hold the ouput.
588 */
589 public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
590 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
591 throw new ArrayIndexOutOfBoundsException
592 ("Coordinate out of bounds!");
593 }
594
595 int type = getTransferType();
596 int numDataElems = getNumDataElements();
597 int pixelOffset = y*scanlineStride + x*pixelStride;
598
599 switch(type) {
600
601 case DataBuffer.TYPE_BYTE:
602
603 byte[] bdata;
604
605 if (obj == null)
606 bdata = new byte[numDataElems];
607 else
608 bdata = (byte[])obj;
609
610 for (int i=0; i<numDataElems; i++) {
611 bdata[i] = (byte)data.getElem(bankIndices[i],
612 pixelOffset + bandOffsets[i]);
613 }
614
615 obj = (Object)bdata;
616 break;
617
618 case DataBuffer.TYPE_USHORT:
619 case DataBuffer.TYPE_SHORT:
620
621 short[] sdata;
622
623 if (obj == null)
624 sdata = new short[numDataElems];
625 else
626 sdata = (short[])obj;
627
628 for (int i=0; i<numDataElems; i++) {
629 sdata[i] = (short)data.getElem(bankIndices[i],
630 pixelOffset + bandOffsets[i]);
631 }
632
633 obj = (Object)sdata;
634 break;
635
636 case DataBuffer.TYPE_INT:
637
638 int[] idata;
639
640 if (obj == null)
641 idata = new int[numDataElems];
642 else
643 idata = (int[])obj;
644
645 for (int i=0; i<numDataElems; i++) {
646 idata[i] = data.getElem(bankIndices[i],
647 pixelOffset + bandOffsets[i]);
648 }
649
650 obj = (Object)idata;
651 break;
652
653 case DataBuffer.TYPE_FLOAT:
654
655 float[] fdata;
656
657 if (obj == null)
658 fdata = new float[numDataElems];
659 else
660 fdata = (float[])obj;
661
662 for (int i=0; i<numDataElems; i++) {
663 fdata[i] = data.getElemFloat(bankIndices[i],
664 pixelOffset + bandOffsets[i]);
665 }
666
667 obj = (Object)fdata;
668 break;
669
670 case DataBuffer.TYPE_DOUBLE:
671
672 double[] ddata;
673
674 if (obj == null)
675 ddata = new double[numDataElems];
676 else
677 ddata = (double[])obj;
678
679 for (int i=0; i<numDataElems; i++) {
680 ddata[i] = data.getElemDouble(bankIndices[i],
681 pixelOffset + bandOffsets[i]);
682 }
683
684 obj = (Object)ddata;
685 break;
686 }
687
688 return obj;
689 }
690
691 /**
692 * Returns all samples for the specified pixel in an int array,
693 * one sample per array element.
694 * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
695 * the coordinates are not in bounds.
696 * @param x the X coordinate of the pixel location
697 * @param y the Y coordinate of the pixel location
698 * @param iArray If non-null, returns the samples in this array
699 * @param data The DataBuffer containing the image data
700 * @return the samples of the specified pixel.
701 * @see #setPixel(int, int, int[], DataBuffer)
702 *
703 * @throws NullPointerException if data is null.
704 * @throws ArrayIndexOutOfBoundsException if the coordinates are
705 * not in bounds, or if iArray is too small to hold the output.
706 */
707 public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
708 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
709 throw new ArrayIndexOutOfBoundsException
710 ("Coordinate out of bounds!");
711 }
712 int pixels[];
713 if (iArray != null) {
714 pixels = iArray;
715 } else {
716 pixels = new int [numBands];
717 }
718 int pixelOffset = y*scanlineStride + x*pixelStride;
719 for (int i=0; i<numBands; i++) {
720 pixels[i] = data.getElem(bankIndices[i],
721 pixelOffset + bandOffsets[i]);
722 }
723 return pixels;
724 }
725
726 /**
727 * Returns all samples for the specified rectangle of pixels in
728 * an int array, one sample per array element.
729 * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
730 * the coordinates are not in bounds.
731 * @param x The X coordinate of the upper left pixel location
732 * @param y The Y coordinate of the upper left pixel location
733 * @param w The width of the pixel rectangle
734 * @param h The height of the pixel rectangle
735 * @param iArray If non-null, returns the samples in this array
736 * @param data The DataBuffer containing the image data
737 * @return the samples of the pixels within the specified region.
738 * @see #setPixels(int, int, int, int, int[], DataBuffer)
739 */
740 public int[] getPixels(int x, int y, int w, int h,
741 int iArray[], DataBuffer data) {
742 int x1 = x + w;
743 int y1 = y + h;
744
745 if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
746 y < 0 || y >= height || y > height || y1 < 0 || y1 > height)
747 {
748 throw new ArrayIndexOutOfBoundsException
749 ("Coordinate out of bounds!");
750 }
751 int pixels[];
752 if (iArray != null) {
753 pixels = iArray;
754 } else {
755 pixels = new int [w*h*numBands];
756 }
757 int lineOffset = y*scanlineStride + x*pixelStride;
758 int srcOffset = 0;
759
760 for (int i = 0; i < h; i++) {
761 int pixelOffset = lineOffset;
762 for (int j = 0; j < w; j++) {
763 for (int k=0; k < numBands; k++) {
764 pixels[srcOffset++] =
765 data.getElem(bankIndices[k], pixelOffset + bandOffsets[k]);
766 }
767 pixelOffset += pixelStride;
768 }
769 lineOffset += scanlineStride;
770 }
771 return pixels;
772 }
773
774 /**
775 * Returns as int the sample in a specified band for the pixel
776 * located at (x,y).
777 * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
778 * the coordinates are not in bounds.
779 * @param x the X coordinate of the pixel location
780 * @param y the Y coordinate of the pixel location
781 * @param b the band to return
782 * @param data the <code>DataBuffer</code> containing the image data
783 * @return the sample in a specified band for the specified pixel
784 * @see #setSample(int, int, int, int, DataBuffer)
785 */
786 public int getSample(int x, int y, int b, DataBuffer data) {
787 // Bounds check for 'b' will be performed automatically
788 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
789 throw new ArrayIndexOutOfBoundsException
790 ("Coordinate out of bounds!");
791 }
792 int sample = data.getElem(bankIndices[b],
793 y*scanlineStride + x*pixelStride +
794 bandOffsets[b]);
795 return sample;
796 }
797
798 /**
799 * Returns the sample in a specified band
800 * for the pixel located at (x,y) as a float.
801 * An <code>ArrayIndexOutOfBoundsException</code> might be
802 * thrown if the coordinates are not in bounds.
803 * @param x The X coordinate of the pixel location
804 * @param y The Y coordinate of the pixel location
805 * @param b The band to return
806 * @param data The DataBuffer containing the image data
807 * @return a float value representing the sample in the specified
808 * band for the specified pixel.
809 */
810 public float getSampleFloat(int x, int y, int b, DataBuffer data) {
811 // Bounds check for 'b' will be performed automatically
812 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
813 throw new ArrayIndexOutOfBoundsException
814 ("Coordinate out of bounds!");
815 }
816
817 float sample = data.getElemFloat(bankIndices[b],
818 y*scanlineStride + x*pixelStride +
819 bandOffsets[b]);
820 return sample;
821 }
822
823 /**
824 * Returns the sample in a specified band
825 * for a pixel located at (x,y) as a double.
826 * An <code>ArrayIndexOutOfBoundsException</code> might be
827 * thrown if the coordinates are not in bounds.
828 * @param x The X coordinate of the pixel location
829 * @param y The Y coordinate of the pixel location
830 * @param b The band to return
831 * @param data The DataBuffer containing the image data
832 * @return a double value representing the sample in the specified
833 * band for the specified pixel.
834 */
835 public double getSampleDouble(int x, int y, int b, DataBuffer data) {
836 // Bounds check for 'b' will be performed automatically
837 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
838 throw new ArrayIndexOutOfBoundsException
839 ("Coordinate out of bounds!");
840 }
841
842 double sample = data.getElemDouble(bankIndices[b],
843 y*scanlineStride + x*pixelStride +
844 bandOffsets[b]);
845 return sample;
846 }
847
848 /**
849 * Returns the samples in a specified band for the specified rectangle
850 * of pixels in an int array, one sample per data array element.
851 * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
852 * the coordinates are not in bounds.
853 * @param x The X coordinate of the upper left pixel location
854 * @param y The Y coordinate of the upper left pixel location
855 * @param w the width of the pixel rectangle
856 * @param h the height of the pixel rectangle
857 * @param b the band to return
858 * @param iArray if non-<code>null</code>, returns the samples
859 * in this array
860 * @param data the <code>DataBuffer</code> containing the image data
861 * @return the samples in the specified band of the specified pixel
862 * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
863 */
864 public int[] getSamples(int x, int y, int w, int h, int b,
865 int iArray[], DataBuffer data) {
866 // Bounds check for 'b' will be performed automatically
867 if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
868 throw new ArrayIndexOutOfBoundsException
869 ("Coordinate out of bounds!");
870 }
871 int samples[];
872 if (iArray != null) {
873 samples = iArray;
874 } else {
875 samples = new int [w*h];
876 }
877 int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b];
878 int srcOffset = 0;
879
880 for (int i = 0; i < h; i++) {
881 int sampleOffset = lineOffset;
882 for (int j = 0; j < w; j++) {
883 samples[srcOffset++] = data.getElem(bankIndices[b],
884 sampleOffset);
885 sampleOffset += pixelStride;
886 }
887 lineOffset += scanlineStride;
888 }
889 return samples;
890 }
891
892 /**
893 * Sets the data for a single pixel in the specified
894 * <code>DataBuffer</code> from a primitive array of type
895 * <code>TransferType</code>. For a <code>ComponentSampleModel</code>,
896 * this is the same as the data type, and samples are transferred
897 * one per array element.
898 * <p>
899 * The following code illustrates transferring data for one pixel from
900 * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
901 * described by <code>ComponentSampleModel</code> <code>csm1</code>,
902 * to <code>DataBuffer</code> <code>db2</code>, whose storage layout
903 * is described by <code>ComponentSampleModel</code> <code>csm2</code>.
904 * The transfer is usually more efficient than using
905 * <code>getPixel</code> and <code>setPixel</code>.
906 * <pre>
907 * ComponentSampleModel csm1, csm2;
908 * DataBufferInt db1, db2;
909 * csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1),
910 * db2);
911 * </pre>
912 * Using <code>getDataElements</code> and <code>setDataElements</code>
913 * to transfer between two <code>DataBuffer/SampleModel</code> pairs
914 * is legitimate if the <code>SampleModel</code> objects have
915 * the same number of bands, corresponding bands have the same number of
916 * bits per sample, and the <code>TransferType</code>s are the same.
917 * <p>
918 * A <code>ClassCastException</code> is thrown if <code>obj</code> is not
919 * a primitive array of type <code>TransferType</code>.
920 * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
921 * the coordinates are not in bounds, or if <code>obj</code> is not large
922 * enough to hold the pixel data.
923 * @param x the X coordinate of the pixel location
924 * @param y the Y coordinate of the pixel location
925 * @param obj a primitive array containing pixel data
926 * @param data the DataBuffer containing the image data
927 * @see #getDataElements(int, int, Object, DataBuffer)
928 */
929 public void setDataElements(int x, int y, Object obj, DataBuffer data) {
930 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
931 throw new ArrayIndexOutOfBoundsException
932 ("Coordinate out of bounds!");
933 }
934
935 int type = getTransferType();
936 int numDataElems = getNumDataElements();
937 int pixelOffset = y*scanlineStride + x*pixelStride;
938
939 switch(type) {
940
941 case DataBuffer.TYPE_BYTE:
942
943 byte[] barray = (byte[])obj;
944
945 for (int i=0; i<numDataElems; i++) {
946 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
947 ((int)barray[i])&0xff);
948 }
949 break;
950
951 case DataBuffer.TYPE_USHORT:
952 case DataBuffer.TYPE_SHORT:
953
954 short[] sarray = (short[])obj;
955
956 for (int i=0; i<numDataElems; i++) {
957 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
958 ((int)sarray[i])&0xffff);
959 }
960 break;
961
962 case DataBuffer.TYPE_INT:
963
964 int[] iarray = (int[])obj;
965
966 for (int i=0; i<numDataElems; i++) {
967 data.setElem(bankIndices[i],
968 pixelOffset + bandOffsets[i], iarray[i]);
969 }
970 break;
971
972 case DataBuffer.TYPE_FLOAT:
973
974 float[] farray = (float[])obj;
975
976 for (int i=0; i<numDataElems; i++) {
977 data.setElemFloat(bankIndices[i],
978 pixelOffset + bandOffsets[i], farray[i]);
979 }
980 break;
981
982 case DataBuffer.TYPE_DOUBLE:
983
984 double[] darray = (double[])obj;
985
986 for (int i=0; i<numDataElems; i++) {
987 data.setElemDouble(bankIndices[i],
988 pixelOffset + bandOffsets[i], darray[i]);
989 }
990 break;
991
992 }
993 }
994
995 /**
996 * Sets a pixel in the <code>DataBuffer</code> using an int array of
997 * samples for input. An <code>ArrayIndexOutOfBoundsException</code>
998 * might be thrown if the coordinates are
999 * not in bounds.
1000 * @param x The X coordinate of the pixel location
1001 * @param y The Y coordinate of the pixel location
1002 * @param iArray The input samples in an int array
1003 * @param data The DataBuffer containing the image data
1004 * @see #getPixel(int, int, int[], DataBuffer)
1005 */
1006 public void setPixel(int x, int y, int iArray[], DataBuffer data) {
1007 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
1008 throw new ArrayIndexOutOfBoundsException
1009 ("Coordinate out of bounds!");
1010 }
1011 int pixelOffset = y*scanlineStride + x*pixelStride;
1012 for (int i=0; i<numBands; i++) {
1013 data.setElem(bankIndices[i],
1014 pixelOffset + bandOffsets[i],iArray[i]);
1015 }
1016 }
1017
1018 /**
1019 * Sets all samples for a rectangle of pixels from an int array containing
1020 * one sample per array element.
1021 * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
1022 * coordinates are not in bounds.
1023 * @param x The X coordinate of the upper left pixel location
1024 * @param y The Y coordinate of the upper left pixel location
1025 * @param w The width of the pixel rectangle
1026 * @param h The height of the pixel rectangle
1027 * @param iArray The input samples in an int array
1028 * @param data The DataBuffer containing the image data
1029 * @see #getPixels(int, int, int, int, int[], DataBuffer)
1030 */
1031 public void setPixels(int x, int y, int w, int h,
1032 int iArray[], DataBuffer data) {
1033 int x1 = x + w;
1034 int y1 = y + h;
1035
1036 if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
1037 y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
1038 {
1039 throw new ArrayIndexOutOfBoundsException
1040 ("Coordinate out of bounds!");
1041 }
1042
1043 int lineOffset = y*scanlineStride + x*pixelStride;
1044 int srcOffset = 0;
1045
1046 for (int i = 0; i < h; i++) {
1047 int pixelOffset = lineOffset;
1048 for (int j = 0; j < w; j++) {
1049 for (int k=0; k < numBands; k++) {
1050 data.setElem(bankIndices[k], pixelOffset + bandOffsets[k],
1051 iArray[srcOffset++]);
1052 }
1053 pixelOffset += pixelStride;
1054 }
1055 lineOffset += scanlineStride;
1056 }
1057 }
1058
1059 /**
1060 * Sets a sample in the specified band for the pixel located at (x,y)
1061 * in the <code>DataBuffer</code> using an int for input.
1062 * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
1063 * coordinates are not in bounds.
1064 * @param x The X coordinate of the pixel location
1065 * @param y The Y coordinate of the pixel location
1066 * @param b the band to set
1067 * @param s the input sample as an int
1068 * @param data the DataBuffer containing the image data
1069 * @see #getSample(int, int, int, DataBuffer)
1070 */
1071 public void setSample(int x, int y, int b, int s,
1072 DataBuffer data) {
1073 // Bounds check for 'b' will be performed automatically
1074 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
1075 throw new ArrayIndexOutOfBoundsException
1076 ("Coordinate out of bounds!");
1077 }
1078 data.setElem(bankIndices[b],
1079 y*scanlineStride + x*pixelStride + bandOffsets[b], s);
1080 }
1081
1082 /**
1083 * Sets a sample in the specified band for the pixel located at (x,y)
1084 * in the <code>DataBuffer</code> using a float for input.
1085 * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
1086 * the coordinates are not in bounds.
1087 * @param x The X coordinate of the pixel location
1088 * @param y The Y coordinate of the pixel location
1089 * @param b The band to set
1090 * @param s The input sample as a float
1091 * @param data The DataBuffer containing the image data
1092 * @see #getSample(int, int, int, DataBuffer)
1093 */
1094 public void setSample(int x, int y, int b,
1095 float s ,
1096 DataBuffer data) {
1097 // Bounds check for 'b' will be performed automatically
1098 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
1099 throw new ArrayIndexOutOfBoundsException
1100 ("Coordinate out of bounds!");
1101 }
1102 data.setElemFloat(bankIndices[b],
1103 y*scanlineStride + x*pixelStride + bandOffsets[b],
1104 s);
1105 }
1106
1107 /**
1108 * Sets a sample in the specified band for the pixel located at (x,y)
1109 * in the <code>DataBuffer</code> using a double for input.
1110 * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
1111 * the coordinates are not in bounds.
1112 * @param x The X coordinate of the pixel location
1113 * @param y The Y coordinate of the pixel location
1114 * @param b The band to set
1115 * @param s The input sample as a double
1116 * @param data The DataBuffer containing the image data
1117 * @see #getSample(int, int, int, DataBuffer)
1118 */
1119 public void setSample(int x, int y, int b,
1120 double s,
1121 DataBuffer data) {
1122 // Bounds check for 'b' will be performed automatically
1123 if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
1124 throw new ArrayIndexOutOfBoundsException
1125 ("Coordinate out of bounds!");
1126 }
1127 data.setElemDouble(bankIndices[b],
1128 y*scanlineStride + x*pixelStride + bandOffsets[b],
1129 s);
1130 }
1131
1132 /**
1133 * Sets the samples in the specified band for the specified rectangle
1134 * of pixels from an int array containing one sample per data array element.
1135 * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
1136 * coordinates are not in bounds.
1137 * @param x The X coordinate of the upper left pixel location
1138 * @param y The Y coordinate of the upper left pixel location
1139 * @param w The width of the pixel rectangle
1140 * @param h The height of the pixel rectangle
1141 * @param b The band to set
1142 * @param iArray The input samples in an int array
1143 * @param data The DataBuffer containing the image data
1144 * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
1145 */
1146 public void setSamples(int x, int y, int w, int h, int b,
1147 int iArray[], DataBuffer data) {
1148 // Bounds check for 'b' will be performed automatically
1149 if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
1150 throw new ArrayIndexOutOfBoundsException
1151 ("Coordinate out of bounds!");
1152 }
1153 int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b];
1154 int srcOffset = 0;
1155
1156 for (int i = 0; i < h; i++) {
1157 int sampleOffset = lineOffset;
1158 for (int j = 0; j < w; j++) {
1159 data.setElem(bankIndices[b], sampleOffset, iArray[srcOffset++]);
1160 sampleOffset += pixelStride;
1161 }
1162 lineOffset += scanlineStride;
1163 }
1164 }
1165
1166 public boolean equals(Object o) {
1167 if ((o == null) || !(o instanceof ComponentSampleModel)) {
1168 return false;
1169 }
1170
1171 ComponentSampleModel that = (ComponentSampleModel)o;
1172 return this.width == that.width &&
1173 this.height == that.height &&
1174 this.numBands == that.numBands &&
1175 this.dataType == that.dataType &&
1176 Arrays.equals(this.bandOffsets, that.bandOffsets) &&
1177 Arrays.equals(this.bankIndices, that.bankIndices) &&
1178 this.numBands == that.numBands &&
1179 this.numBanks == that.numBanks &&
1180 this.scanlineStride == that.scanlineStride &&
1181 this.pixelStride == that.pixelStride;
1182 }
1183
1184 // If we implement equals() we must also implement hashCode
1185 public int hashCode() {
1186 int hash = 0;
1187 hash = width;
1188 hash <<= 8;
1189 hash ^= height;
1190 hash <<= 8;
1191 hash ^= numBands;
1192 hash <<= 8;
1193 hash ^= dataType;
1194 hash <<= 8;
1195 for (int i = 0; i < bandOffsets.length; i++) {
1196 hash ^= bandOffsets[i];
1197 hash <<= 8;
1198 }
1199 for (int i = 0; i < bankIndices.length; i++) {
1200 hash ^= bankIndices[i];
1201 hash <<= 8;
1202 }
1203 hash ^= numBands;
1204 hash <<= 8;
1205 hash ^= numBanks;
1206 hash <<= 8;
1207 hash ^= scanlineStride;
1208 hash <<= 8;
1209 hash ^= pixelStride;
1210 return hash;
1211 }
1212}
java/pkg/java/awt/image/ConvolveOp.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ConvolveOp.java+347−0
@@ -0,0 +1,347 @@
1/*
2 * Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.color.ICC_Profile;
29import java.awt.geom.Rectangle2D;
30import java.awt.Rectangle;
31import java.awt.RenderingHints;
32import java.awt.geom.Point2D;
33import sun.awt.image.ImagingLib;
34
35/**
36 * This class implements a convolution from the source
37 * to the destination.
38 * Convolution using a convolution kernel is a spatial operation that
39 * computes the output pixel from an input pixel by multiplying the kernel
40 * with the surround of the input pixel.
41 * This allows the output pixel to be affected by the immediate neighborhood
42 * in a way that can be mathematically specified with a kernel.
43 *<p>
44 * This class operates with BufferedImage data in which color components are
45 * premultiplied with the alpha component. If the Source BufferedImage has
46 * an alpha component, and the color components are not premultiplied with
47 * the alpha component, then the data are premultiplied before being
48 * convolved. If the Destination has color components which are not
49 * premultiplied, then alpha is divided out before storing into the
50 * Destination (if alpha is 0, the color components are set to 0). If the
51 * Destination has no alpha component, then the resulting alpha is discarded
52 * after first dividing it out of the color components.
53 * <p>
54 * Rasters are treated as having no alpha channel. If the above treatment
55 * of the alpha channel in BufferedImages is not desired, it may be avoided
56 * by getting the Raster of a source BufferedImage and using the filter method
57 * of this class which works with Rasters.
58 * <p>
59 * If a RenderingHints object is specified in the constructor, the
60 * color rendering hint and the dithering hint may be used when color
61 * conversion is required.
62 *<p>
63 * Note that the Source and the Destination may not be the same object.
64 * @see Kernel
65 * @see java.awt.RenderingHints#KEY_COLOR_RENDERING
66 * @see java.awt.RenderingHints#KEY_DITHERING
67 */
68public class ConvolveOp implements BufferedImageOp, RasterOp {
69 Kernel kernel;
70 int edgeHint;
71 RenderingHints hints;
72 /**
73 * Edge condition constants.
74 */
75
76 /**
77 * Pixels at the edge of the destination image are set to zero. This
78 * is the default.
79 */
80
81 public static final int EDGE_ZERO_FILL = 0;
82
83 /**
84 * Pixels at the edge of the source image are copied to
85 * the corresponding pixels in the destination without modification.
86 */
87 public static final int EDGE_NO_OP = 1;
88
89 /**
90 * Constructs a ConvolveOp given a Kernel, an edge condition, and a
91 * RenderingHints object (which may be null).
92 * @param kernel the specified <code>Kernel</code>
93 * @param edgeCondition the specified edge condition
94 * @param hints the specified <code>RenderingHints</code> object
95 * @see Kernel
96 * @see #EDGE_NO_OP
97 * @see #EDGE_ZERO_FILL
98 * @see java.awt.RenderingHints
99 */
100 public ConvolveOp(Kernel kernel, int edgeCondition, RenderingHints hints) {
101 this.kernel = kernel;
102 this.edgeHint = edgeCondition;
103 this.hints = hints;
104 }
105
106 /**
107 * Constructs a ConvolveOp given a Kernel. The edge condition
108 * will be EDGE_ZERO_FILL.
109 * @param kernel the specified <code>Kernel</code>
110 * @see Kernel
111 * @see #EDGE_ZERO_FILL
112 */
113 public ConvolveOp(Kernel kernel) {
114 this.kernel = kernel;
115 this.edgeHint = EDGE_ZERO_FILL;
116 }
117
118 /**
119 * Returns the edge condition.
120 * @return the edge condition of this <code>ConvolveOp</code>.
121 * @see #EDGE_NO_OP
122 * @see #EDGE_ZERO_FILL
123 */
124 public int getEdgeCondition() {
125 return edgeHint;
126 }
127
128 /**
129 * Returns the Kernel.
130 * @return the <code>Kernel</code> of this <code>ConvolveOp</code>.
131 */
132 public final Kernel getKernel() {
133 return (Kernel) kernel.clone();
134 }
135
136 /**
137 * Performs a convolution on BufferedImages. Each component of the
138 * source image will be convolved (including the alpha component, if
139 * present).
140 * If the color model in the source image is not the same as that
141 * in the destination image, the pixels will be converted
142 * in the destination. If the destination image is null,
143 * a BufferedImage will be created with the source ColorModel.
144 * The IllegalArgumentException may be thrown if the source is the
145 * same as the destination.
146 * @param src the source <code>BufferedImage</code> to filter
147 * @param dst the destination <code>BufferedImage</code> for the
148 * filtered <code>src</code>
149 * @return the filtered <code>BufferedImage</code>
150 * @throws NullPointerException if <code>src</code> is <code>null</code>
151 * @throws IllegalArgumentException if <code>src</code> equals
152 * <code>dst</code>
153 * @throws ImagingOpException if <code>src</code> cannot be filtered
154 */
155 public final BufferedImage filter (BufferedImage src, BufferedImage dst) {
156 if (src == null) {
157 throw new NullPointerException("src image is null");
158 }
159 if (src == dst) {
160 throw new IllegalArgumentException("src image cannot be the "+
161 "same as the dst image");
162 }
163
164 boolean needToConvert = false;
165 ColorModel srcCM = src.getColorModel();
166 ColorModel dstCM;
167 BufferedImage origDst = dst;
168
169 // Can't convolve an IndexColorModel. Need to expand it
170 if (srcCM instanceof IndexColorModel) {
171 IndexColorModel icm = (IndexColorModel) srcCM;
172 src = icm.convertToIntDiscrete(src.getRaster(), false);
173 srcCM = src.getColorModel();
174 }
175
176 if (dst == null) {
177 dst = createCompatibleDestImage(src, null);
178 dstCM = srcCM;
179 origDst = dst;
180 }
181 else {
182 dstCM = dst.getColorModel();
183 if (srcCM.getColorSpace().getType() !=
184 dstCM.getColorSpace().getType())
185 {
186 needToConvert = true;
187 dst = createCompatibleDestImage(src, null);
188 dstCM = dst.getColorModel();
189 }
190 else if (dstCM instanceof IndexColorModel) {
191 dst = createCompatibleDestImage(src, null);
192 dstCM = dst.getColorModel();
193 }
194 }
195
196 if (ImagingLib.filter(this, src, dst) == null) {
197 throw new ImagingOpException ("Unable to convolve src image");
198 }
199
200 if (needToConvert) {
201 ColorConvertOp ccop = new ColorConvertOp(hints);
202 ccop.filter(dst, origDst);
203 }
204 else if (origDst != dst) {
205 java.awt.Graphics2D g = origDst.createGraphics();
206 try {
207 g.drawImage(dst, 0, 0, null);
208 } finally {
209 g.dispose();
210 }
211 }
212
213 return origDst;
214 }
215
216 /**
217 * Performs a convolution on Rasters. Each band of the source Raster
218 * will be convolved.
219 * The source and destination must have the same number of bands.
220 * If the destination Raster is null, a new Raster will be created.
221 * The IllegalArgumentException may be thrown if the source is
222 * the same as the destination.
223 * @param src the source <code>Raster</code> to filter
224 * @param dst the destination <code>WritableRaster</code> for the
225 * filtered <code>src</code>
226 * @return the filtered <code>WritableRaster</code>
227 * @throws NullPointerException if <code>src</code> is <code>null</code>
228 * @throws ImagingOpException if <code>src</code> and <code>dst</code>
229 * do not have the same number of bands
230 * @throws ImagingOpException if <code>src</code> cannot be filtered
231 * @throws IllegalArgumentException if <code>src</code> equals
232 * <code>dst</code>
233 */
234 public final WritableRaster filter (Raster src, WritableRaster dst) {
235 if (dst == null) {
236 dst = createCompatibleDestRaster(src);
237 }
238 else if (src == dst) {
239 throw new IllegalArgumentException("src image cannot be the "+
240 "same as the dst image");
241 }
242 else if (src.getNumBands() != dst.getNumBands()) {
243 throw new ImagingOpException("Different number of bands in src "+
244 " and dst Rasters");
245 }
246
247 if (ImagingLib.filter(this, src, dst) == null) {
248 throw new ImagingOpException ("Unable to convolve src image");
249 }
250
251 return dst;
252 }
253
254 /**
255 * Creates a zeroed destination image with the correct size and number
256 * of bands. If destCM is null, an appropriate ColorModel will be used.
257 * @param src Source image for the filter operation.
258 * @param destCM ColorModel of the destination. Can be null.
259 * @return a destination <code>BufferedImage</code> with the correct
260 * size and number of bands.
261 */
262 public BufferedImage createCompatibleDestImage(BufferedImage src,
263 ColorModel destCM) {
264 BufferedImage image;
265
266 int w = src.getWidth();
267 int h = src.getHeight();
268
269 WritableRaster wr = null;
270
271 if (destCM == null) {
272 destCM = src.getColorModel();
273 // Not much support for ICM
274 if (destCM instanceof IndexColorModel) {
275 destCM = ColorModel.getRGBdefault();
276 } else {
277 /* Create destination image as similar to the source
278 * as it possible...
279 */
280 wr = src.getData().createCompatibleWritableRaster(w, h);
281 }
282 }
283
284 if (wr == null) {
285 /* This is the case when destination color model
286 * was explicitly specified (and it may be not compatible
287 * with source raster structure) or source is indexed image.
288 * We should use destination color model to create compatible
289 * destination raster here.
290 */
291 wr = destCM.createCompatibleWritableRaster(w, h);
292 }
293
294 image = new BufferedImage (destCM, wr,
295 destCM.isAlphaPremultiplied(), null);
296
297 return image;
298 }
299
300 /**
301 * Creates a zeroed destination Raster with the correct size and number
302 * of bands, given this source.
303 */
304 public WritableRaster createCompatibleDestRaster(Raster src) {
305 return src.createCompatibleWritableRaster();
306 }
307
308 /**
309 * Returns the bounding box of the filtered destination image. Since
310 * this is not a geometric operation, the bounding box does not
311 * change.
312 */
313 public final Rectangle2D getBounds2D(BufferedImage src) {
314 return getBounds2D(src.getRaster());
315 }
316
317 /**
318 * Returns the bounding box of the filtered destination Raster. Since
319 * this is not a geometric operation, the bounding box does not
320 * change.
321 */
322 public final Rectangle2D getBounds2D(Raster src) {
323 return src.getBounds();
324 }
325
326 /**
327 * Returns the location of the destination point given a
328 * point in the source. If dstPt is non-null, it will
329 * be used to hold the return value. Since this is not a geometric
330 * operation, the srcPt will equal the dstPt.
331 */
332 public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
333 if (dstPt == null) {
334 dstPt = new Point2D.Float();
335 }
336 dstPt.setLocation(srcPt.getX(), srcPt.getY());
337
338 return dstPt;
339 }
340
341 /**
342 * Returns the rendering hints for this op.
343 */
344 public final RenderingHints getRenderingHints() {
345 return hints;
346 }
347}
java/pkg/java/awt/image/CropImageFilter.class+0−0

Binary file not shown.

java/pkg/java/awt/image/CropImageFilter.java+193−0
@@ -0,0 +1,193 @@
1/*
2 * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.image.ImageConsumer;
29import java.awt.image.ColorModel;
30import java.util.Hashtable;
31import java.awt.Rectangle;
32
33/**
34 * An ImageFilter class for cropping images.
35 * This class extends the basic ImageFilter Class to extract a given
36 * rectangular region of an existing Image and provide a source for a
37 * new image containing just the extracted region. It is meant to
38 * be used in conjunction with a FilteredImageSource object to produce
39 * cropped versions of existing images.
40 *
41 * @see FilteredImageSource
42 * @see ImageFilter
43 *
44 * @author Jim Graham
45 */
46public class CropImageFilter extends ImageFilter {
47 int cropX;
48 int cropY;
49 int cropW;
50 int cropH;
51
52 /**
53 * Constructs a CropImageFilter that extracts the absolute rectangular
54 * region of pixels from its source Image as specified by the x, y,
55 * w, and h parameters.
56 * @param x the x location of the top of the rectangle to be extracted
57 * @param y the y location of the top of the rectangle to be extracted
58 * @param w the width of the rectangle to be extracted
59 * @param h the height of the rectangle to be extracted
60 */
61 public CropImageFilter(int x, int y, int w, int h) {
62 cropX = x;
63 cropY = y;
64 cropW = w;
65 cropH = h;
66 }
67
68 /**
69 * Passes along the properties from the source object after adding a
70 * property indicating the cropped region.
71 * This method invokes <code>super.setProperties</code>,
72 * which might result in additional properties being added.
73 * <p>
74 * Note: This method is intended to be called by the
75 * <code>ImageProducer</code> of the <code>Image</code> whose pixels
76 * are being filtered. Developers using
77 * this class to filter pixels from an image should avoid calling
78 * this method directly since that operation could interfere
79 * with the filtering operation.
80 */
81 public void setProperties(Hashtable<?,?> props) {
82 Hashtable<Object,Object> p = (Hashtable<Object,Object>)props.clone();
83 p.put("croprect", new Rectangle(cropX, cropY, cropW, cropH));
84 super.setProperties(p);
85 }
86
87 /**
88 * Override the source image's dimensions and pass the dimensions
89 * of the rectangular cropped region to the ImageConsumer.
90 * <p>
91 * Note: This method is intended to be called by the
92 * <code>ImageProducer</code> of the <code>Image</code> whose
93 * pixels are being filtered. Developers using
94 * this class to filter pixels from an image should avoid calling
95 * this method directly since that operation could interfere
96 * with the filtering operation.
97 * @see ImageConsumer
98 */
99 public void setDimensions(int w, int h) {
100 consumer.setDimensions(cropW, cropH);
101 }
102
103 /**
104 * Determine whether the delivered byte pixels intersect the region to
105 * be extracted and passes through only that subset of pixels that
106 * appear in the output region.
107 * <p>
108 * Note: This method is intended to be called by the
109 * <code>ImageProducer</code> of the <code>Image</code> whose
110 * pixels are being filtered. Developers using
111 * this class to filter pixels from an image should avoid calling
112 * this method directly since that operation could interfere
113 * with the filtering operation.
114 */
115 public void setPixels(int x, int y, int w, int h,
116 ColorModel model, byte pixels[], int off,
117 int scansize) {
118 int x1 = x;
119 if (x1 < cropX) {
120 x1 = cropX;
121 }
122 int x2 = addWithoutOverflow(x, w);
123 if (x2 > cropX + cropW) {
124 x2 = cropX + cropW;
125 }
126 int y1 = y;
127 if (y1 < cropY) {
128 y1 = cropY;
129 }
130
131 int y2 = addWithoutOverflow(y, h);
132 if (y2 > cropY + cropH) {
133 y2 = cropY + cropH;
134 }
135 if (x1 >= x2 || y1 >= y2) {
136 return;
137 }
138 consumer.setPixels(x1 - cropX, y1 - cropY, (x2 - x1), (y2 - y1),
139 model, pixels,
140 off + (y1 - y) * scansize + (x1 - x), scansize);
141 }
142
143 /**
144 * Determine if the delivered int pixels intersect the region to
145 * be extracted and pass through only that subset of pixels that
146 * appear in the output region.
147 * <p>
148 * Note: This method is intended to be called by the
149 * <code>ImageProducer</code> of the <code>Image</code> whose
150 * pixels are being filtered. Developers using
151 * this class to filter pixels from an image should avoid calling
152 * this method directly since that operation could interfere
153 * with the filtering operation.
154 */
155 public void setPixels(int x, int y, int w, int h,
156 ColorModel model, int pixels[], int off,
157 int scansize) {
158 int x1 = x;
159 if (x1 < cropX) {
160 x1 = cropX;
161 }
162 int x2 = addWithoutOverflow(x, w);
163 if (x2 > cropX + cropW) {
164 x2 = cropX + cropW;
165 }
166 int y1 = y;
167 if (y1 < cropY) {
168 y1 = cropY;
169 }
170
171 int y2 = addWithoutOverflow(y, h);
172 if (y2 > cropY + cropH) {
173 y2 = cropY + cropH;
174 }
175 if (x1 >= x2 || y1 >= y2) {
176 return;
177 }
178 consumer.setPixels(x1 - cropX, y1 - cropY, (x2 - x1), (y2 - y1),
179 model, pixels,
180 off + (y1 - y) * scansize + (x1 - x), scansize);
181 }
182
183 //check for potential overflow (see bug 4801285)
184 private int addWithoutOverflow(int x, int w) {
185 int x2 = x + w;
186 if ( x > 0 && w > 0 && x2 < 0 ) {
187 x2 = Integer.MAX_VALUE;
188 } else if( x < 0 && w < 0 && x2 > 0 ) {
189 x2 = Integer.MIN_VALUE;
190 }
191 return x2;
192 }
193}
java/pkg/java/awt/image/DataBuffer$1.class+0−0

Binary file not shown.

java/pkg/java/awt/image/DataBuffer.class+0−0

Binary file not shown.

java/pkg/java/awt/image/DataBuffer.java+541−0
@@ -0,0 +1,541 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26/* ****************************************************************
27 ******************************************************************
28 ******************************************************************
29 *** COPYRIGHT (c) Eastman Kodak Company, 1997
30 *** As an unpublished work pursuant to Title 17 of the United
31 *** States Code. All rights reserved.
32 ******************************************************************
33 ******************************************************************
34 ******************************************************************/
35
36package java.awt.image;
37
38import sun.java2d.StateTrackable.State;
39import static sun.java2d.StateTrackable.State.*;
40import sun.java2d.StateTrackableDelegate;
41
42import sun.awt.image.SunWritableRaster;
43
44/**
45 * This class exists to wrap one or more data arrays. Each data array in
46 * the DataBuffer is referred to as a bank. Accessor methods for getting
47 * and setting elements of the DataBuffer's banks exist with and without
48 * a bank specifier. The methods without a bank specifier use the default 0th
49 * bank. The DataBuffer can optionally take an offset per bank, so that
50 * data in an existing array can be used even if the interesting data
51 * doesn't start at array location zero. Getting or setting the 0th
52 * element of a bank, uses the (0+offset)th element of the array. The
53 * size field specifies how much of the data array is available for
54 * use. Size + offset for a given bank should never be greater
55 * than the length of the associated data array. The data type of
56 * a data buffer indicates the type of the data array(s) and may also
57 * indicate additional semantics, e.g. storing unsigned 8-bit data
58 * in elements of a byte array. The data type may be TYPE_UNDEFINED
59 * or one of the types defined below. Other types may be added in
60 * the future. Generally, an object of class DataBuffer will be cast down
61 * to one of its data type specific subclasses to access data type specific
62 * methods for improved performance. Currently, the Java 2D(tm) API
63 * image classes use TYPE_BYTE, TYPE_USHORT, TYPE_INT, TYPE_SHORT,
64 * TYPE_FLOAT, and TYPE_DOUBLE DataBuffers to store image data.
65 * @see java.awt.image.Raster
66 * @see java.awt.image.SampleModel
67 */
68public abstract class DataBuffer {
69
70 /** Tag for unsigned byte data. */
71 public static final int TYPE_BYTE = 0;
72
73 /** Tag for unsigned short data. */
74 public static final int TYPE_USHORT = 1;
75
76 /** Tag for signed short data. Placeholder for future use. */
77 public static final int TYPE_SHORT = 2;
78
79 /** Tag for int data. */
80 public static final int TYPE_INT = 3;
81
82 /** Tag for float data. Placeholder for future use. */
83 public static final int TYPE_FLOAT = 4;
84
85 /** Tag for double data. Placeholder for future use. */
86 public static final int TYPE_DOUBLE = 5;
87
88 /** Tag for undefined data. */
89 public static final int TYPE_UNDEFINED = 32;
90
91 /** The data type of this DataBuffer. */
92 protected int dataType;
93
94 /** The number of banks in this DataBuffer. */
95 protected int banks;
96
97 /** Offset into default (first) bank from which to get the first element. */
98 protected int offset;
99
100 /** Usable size of all banks. */
101 protected int size;
102
103 /** Offsets into all banks. */
104 protected int offsets[];
105
106 /* The current StateTrackable state. */
107 StateTrackableDelegate theTrackable;
108
109 /** Size of the data types indexed by DataType tags defined above. */
110 private static final int dataTypeSize[] = {8,16,16,32,32,64};
111
112 /** Returns the size (in bits) of the data type, given a datatype tag.
113 * @param type the value of one of the defined datatype tags
114 * @return the size of the data type
115 * @throws IllegalArgumentException if <code>type</code> is less than
116 * zero or greater than {@link #TYPE_DOUBLE}
117 */
118 public static int getDataTypeSize(int type) {
119 if (type < TYPE_BYTE || type > TYPE_DOUBLE) {
120 throw new IllegalArgumentException("Unknown data type "+type);
121 }
122 return dataTypeSize[type];
123 }
124
125 /**
126 * Constructs a DataBuffer containing one bank of the specified
127 * data type and size.
128 *
129 * @param dataType the data type of this <code>DataBuffer</code>
130 * @param size the size of the banks
131 */
132 protected DataBuffer(int dataType, int size) {
133 this(UNTRACKABLE, dataType, size);
134 }
135
136 /**
137 * Constructs a DataBuffer containing one bank of the specified
138 * data type and size with the indicated initial {@link State State}.
139 *
140 * @param initialState the initial {@link State State} state of the data
141 * @param dataType the data type of this <code>DataBuffer</code>
142 * @param size the size of the banks
143 * @since 1.7
144 */
145 DataBuffer(State initialState,
146 int dataType, int size)
147 {
148 this.theTrackable = StateTrackableDelegate.createInstance(initialState);
149 this.dataType = dataType;
150 this.banks = 1;
151 this.size = size;
152 this.offset = 0;
153 this.offsets = new int[1]; // init to 0 by new
154 }
155
156 /**
157 * Constructs a DataBuffer containing the specified number of
158 * banks. Each bank has the specified size and an offset of 0.
159 *
160 * @param dataType the data type of this <code>DataBuffer</code>
161 * @param size the size of the banks
162 * @param numBanks the number of banks in this
163 * <code>DataBuffer</code>
164 */
165 protected DataBuffer(int dataType, int size, int numBanks) {
166 this(UNTRACKABLE, dataType, size, numBanks);
167 }
168
169 /**
170 * Constructs a DataBuffer containing the specified number of
171 * banks with the indicated initial {@link State State}.
172 * Each bank has the specified size and an offset of 0.
173 *
174 * @param initialState the initial {@link State State} state of the data
175 * @param dataType the data type of this <code>DataBuffer</code>
176 * @param size the size of the banks
177 * @param numBanks the number of banks in this
178 * <code>DataBuffer</code>
179 * @since 1.7
180 */
181 DataBuffer(State initialState,
182 int dataType, int size, int numBanks)
183 {
184 this.theTrackable = StateTrackableDelegate.createInstance(initialState);
185 this.dataType = dataType;
186 this.banks = numBanks;
187 this.size = size;
188 this.offset = 0;
189 this.offsets = new int[banks]; // init to 0 by new
190 }
191
192 /**
193 * Constructs a DataBuffer that contains the specified number
194 * of banks. Each bank has the specified datatype, size and offset.
195 *
196 * @param dataType the data type of this <code>DataBuffer</code>
197 * @param size the size of the banks
198 * @param numBanks the number of banks in this
199 * <code>DataBuffer</code>
200 * @param offset the offset for each bank
201 */
202 protected DataBuffer(int dataType, int size, int numBanks, int offset) {
203 this(UNTRACKABLE, dataType, size, numBanks, offset);
204 }
205
206 /**
207 * Constructs a DataBuffer that contains the specified number
208 * of banks with the indicated initial {@link State State}.
209 * Each bank has the specified datatype, size and offset.
210 *
211 * @param initialState the initial {@link State State} state of the data
212 * @param dataType the data type of this <code>DataBuffer</code>
213 * @param size the size of the banks
214 * @param numBanks the number of banks in this
215 * <code>DataBuffer</code>
216 * @param offset the offset for each bank
217 * @since 1.7
218 */
219 DataBuffer(State initialState,
220 int dataType, int size, int numBanks, int offset)
221 {
222 this.theTrackable = StateTrackableDelegate.createInstance(initialState);
223 this.dataType = dataType;
224 this.banks = numBanks;
225 this.size = size;
226 this.offset = offset;
227 this.offsets = new int[numBanks];
228 for (int i = 0; i < numBanks; i++) {
229 this.offsets[i] = offset;
230 }
231 }
232
233 /**
234 * Constructs a DataBuffer which contains the specified number
235 * of banks. Each bank has the specified datatype and size. The
236 * offset for each bank is specified by its respective entry in
237 * the offsets array.
238 *
239 * @param dataType the data type of this <code>DataBuffer</code>
240 * @param size the size of the banks
241 * @param numBanks the number of banks in this
242 * <code>DataBuffer</code>
243 * @param offsets an array containing an offset for each bank.
244 * @throws ArrayIndexOutOfBoundsException if <code>numBanks</code>
245 * does not equal the length of <code>offsets</code>
246 */
247 protected DataBuffer(int dataType, int size, int numBanks, int offsets[]) {
248 this(UNTRACKABLE, dataType, size, numBanks, offsets);
249 }
250
251 /**
252 * Constructs a DataBuffer which contains the specified number
253 * of banks with the indicated initial {@link State State}.
254 * Each bank has the specified datatype and size. The
255 * offset for each bank is specified by its respective entry in
256 * the offsets array.
257 *
258 * @param initialState the initial {@link State State} state of the data
259 * @param dataType the data type of this <code>DataBuffer</code>
260 * @param size the size of the banks
261 * @param numBanks the number of banks in this
262 * <code>DataBuffer</code>
263 * @param offsets an array containing an offset for each bank.
264 * @throws ArrayIndexOutOfBoundsException if <code>numBanks</code>
265 * does not equal the length of <code>offsets</code>
266 * @since 1.7
267 */
268 DataBuffer(State initialState,
269 int dataType, int size, int numBanks, int offsets[])
270 {
271 if (numBanks != offsets.length) {
272 throw new ArrayIndexOutOfBoundsException("Number of banks" +
273 " does not match number of bank offsets");
274 }
275 this.theTrackable = StateTrackableDelegate.createInstance(initialState);
276 this.dataType = dataType;
277 this.banks = numBanks;
278 this.size = size;
279 this.offset = offsets[0];
280 this.offsets = (int[])offsets.clone();
281 }
282
283 /** Returns the data type of this DataBuffer.
284 * @return the data type of this <code>DataBuffer</code>.
285 */
286 public int getDataType() {
287 return dataType;
288 }
289
290 /** Returns the size (in array elements) of all banks.
291 * @return the size of all banks.
292 */
293 public int getSize() {
294 return size;
295 }
296
297 /** Returns the offset of the default bank in array elements.
298 * @return the offset of the default bank.
299 */
300 public int getOffset() {
301 return offset;
302 }
303
304 /** Returns the offsets (in array elements) of all the banks.
305 * @return the offsets of all banks.
306 */
307 public int[] getOffsets() {
308 return (int[])offsets.clone();
309 }
310
311 /** Returns the number of banks in this DataBuffer.
312 * @return the number of banks.
313 */
314 public int getNumBanks() {
315 return banks;
316 }
317
318 /**
319 * Returns the requested data array element from the first (default) bank
320 * as an integer.
321 * @param i the index of the requested data array element
322 * @return the data array element at the specified index.
323 * @see #setElem(int, int)
324 * @see #setElem(int, int, int)
325 */
326 public int getElem(int i) {
327 return getElem(0,i);
328 }
329
330 /**
331 * Returns the requested data array element from the specified bank
332 * as an integer.
333 * @param bank the specified bank
334 * @param i the index of the requested data array element
335 * @return the data array element at the specified index from the
336 * specified bank at the specified index.
337 * @see #setElem(int, int)
338 * @see #setElem(int, int, int)
339 */
340 public abstract int getElem(int bank, int i);
341
342 /**
343 * Sets the requested data array element in the first (default) bank
344 * from the given integer.
345 * @param i the specified index into the data array
346 * @param val the data to set the element at the specified index in
347 * the data array
348 * @see #getElem(int)
349 * @see #getElem(int, int)
350 */
351 public void setElem(int i, int val) {
352 setElem(0,i,val);
353 }
354
355 /**
356 * Sets the requested data array element in the specified bank
357 * from the given integer.
358 * @param bank the specified bank
359 * @param i the specified index into the data array
360 * @param val the data to set the element in the specified bank
361 * at the specified index in the data array
362 * @see #getElem(int)
363 * @see #getElem(int, int)
364 */
365 public abstract void setElem(int bank, int i, int val);
366
367 /**
368 * Returns the requested data array element from the first (default) bank
369 * as a float. The implementation in this class is to cast getElem(i)
370 * to a float. Subclasses may override this method if another
371 * implementation is needed.
372 * @param i the index of the requested data array element
373 * @return a float value representing the data array element at the
374 * specified index.
375 * @see #setElemFloat(int, float)
376 * @see #setElemFloat(int, int, float)
377 */
378 public float getElemFloat(int i) {
379 return (float)getElem(i);
380 }
381
382 /**
383 * Returns the requested data array element from the specified bank
384 * as a float. The implementation in this class is to cast
385 * {@link #getElem(int, int)}
386 * to a float. Subclasses can override this method if another
387 * implementation is needed.
388 * @param bank the specified bank
389 * @param i the index of the requested data array element
390 * @return a float value representing the data array element from the
391 * specified bank at the specified index.
392 * @see #setElemFloat(int, float)
393 * @see #setElemFloat(int, int, float)
394 */
395 public float getElemFloat(int bank, int i) {
396 return (float)getElem(bank,i);
397 }
398
399 /**
400 * Sets the requested data array element in the first (default) bank
401 * from the given float. The implementation in this class is to cast
402 * val to an int and call {@link #setElem(int, int)}. Subclasses
403 * can override this method if another implementation is needed.
404 * @param i the specified index
405 * @param val the value to set the element at the specified index in
406 * the data array
407 * @see #getElemFloat(int)
408 * @see #getElemFloat(int, int)
409 */
410 public void setElemFloat(int i, float val) {
411 setElem(i,(int)val);
412 }
413
414 /**
415 * Sets the requested data array element in the specified bank
416 * from the given float. The implementation in this class is to cast
417 * val to an int and call {@link #setElem(int, int)}. Subclasses can
418 * override this method if another implementation is needed.
419 * @param bank the specified bank
420 * @param i the specified index
421 * @param val the value to set the element in the specified bank at
422 * the specified index in the data array
423 * @see #getElemFloat(int)
424 * @see #getElemFloat(int, int)
425 */
426 public void setElemFloat(int bank, int i, float val) {
427 setElem(bank,i,(int)val);
428 }
429
430 /**
431 * Returns the requested data array element from the first (default) bank
432 * as a double. The implementation in this class is to cast
433 * {@link #getElem(int)}
434 * to a double. Subclasses can override this method if another
435 * implementation is needed.
436 * @param i the specified index
437 * @return a double value representing the element at the specified
438 * index in the data array.
439 * @see #setElemDouble(int, double)
440 * @see #setElemDouble(int, int, double)
441 */
442 public double getElemDouble(int i) {
443 return (double)getElem(i);
444 }
445
446 /**
447 * Returns the requested data array element from the specified bank as
448 * a double. The implementation in this class is to cast getElem(bank, i)
449 * to a double. Subclasses may override this method if another
450 * implementation is needed.
451 * @param bank the specified bank
452 * @param i the specified index
453 * @return a double value representing the element from the specified
454 * bank at the specified index in the data array.
455 * @see #setElemDouble(int, double)
456 * @see #setElemDouble(int, int, double)
457 */
458 public double getElemDouble(int bank, int i) {
459 return (double)getElem(bank,i);
460 }
461
462 /**
463 * Sets the requested data array element in the first (default) bank
464 * from the given double. The implementation in this class is to cast
465 * val to an int and call {@link #setElem(int, int)}. Subclasses can
466 * override this method if another implementation is needed.
467 * @param i the specified index
468 * @param val the value to set the element at the specified index
469 * in the data array
470 * @see #getElemDouble(int)
471 * @see #getElemDouble(int, int)
472 */
473 public void setElemDouble(int i, double val) {
474 setElem(i,(int)val);
475 }
476
477 /**
478 * Sets the requested data array element in the specified bank
479 * from the given double. The implementation in this class is to cast
480 * val to an int and call {@link #setElem(int, int)}. Subclasses can
481 * override this method if another implementation is needed.
482 * @param bank the specified bank
483 * @param i the specified index
484 * @param val the value to set the element in the specified bank
485 * at the specified index of the data array
486 * @see #getElemDouble(int)
487 * @see #getElemDouble(int, int)
488 */
489 public void setElemDouble(int bank, int i, double val) {
490 setElem(bank,i,(int)val);
491 }
492
493 static int[] toIntArray(Object obj) {
494 if (obj instanceof int[]) {
495 return (int[])obj;
496 } else if (obj == null) {
497 return null;
498 } else if (obj instanceof short[]) {
499 short sdata[] = (short[])obj;
500 int idata[] = new int[sdata.length];
501 for (int i = 0; i < sdata.length; i++) {
502 idata[i] = (int)sdata[i] & 0xffff;
503 }
504 return idata;
505 } else if (obj instanceof byte[]) {
506 byte bdata[] = (byte[])obj;
507 int idata[] = new int[bdata.length];
508 for (int i = 0; i < bdata.length; i++) {
509 idata[i] = 0xff & (int)bdata[i];
510 }
511 return idata;
512 }
513 return null;
514 }
515
516 static {
517 SunWritableRaster.setDataStealer(new SunWritableRaster.DataStealer() {
518 public byte[] getData(DataBufferByte dbb, int bank) {
519 return dbb.bankdata[bank];
520 }
521
522 public short[] getData(DataBufferUShort dbus, int bank) {
523 return dbus.bankdata[bank];
524 }
525
526 public int[] getData(DataBufferInt dbi, int bank) {
527 return dbi.bankdata[bank];
528 }
529
530 public StateTrackableDelegate getTrackable(DataBuffer db) {
531 return db.theTrackable;
532 }
533
534 public void setTrackable(DataBuffer db,
535 StateTrackableDelegate trackable)
536 {
537 db.theTrackable = trackable;
538 }
539 });
540 }
541}
java/pkg/java/awt/image/DataBufferByte.class+0−0

Binary file not shown.

java/pkg/java/awt/image/DataBufferByte.java+286−0
@@ -0,0 +1,286 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26/* ****************************************************************
27 ******************************************************************
28 ******************************************************************
29 *** COPYRIGHT (c) Eastman Kodak Company, 1997
30 *** As an unpublished work pursuant to Title 17 of the United
31 *** States Code. All rights reserved.
32 ******************************************************************
33 ******************************************************************
34 ******************************************************************/
35
36package java.awt.image;
37
38import static sun.java2d.StateTrackable.State.*;
39
40/**
41 * This class extends <CODE>DataBuffer</CODE> and stores data internally as bytes.
42 * Values stored in the byte array(s) of this <CODE>DataBuffer</CODE> are treated as
43 * unsigned values.
44 * <p>
45 * <a name="optimizations">
46 * Note that some implementations may function more efficiently
47 * if they can maintain control over how the data for an image is
48 * stored.
49 * For example, optimizations such as caching an image in video
50 * memory require that the implementation track all modifications
51 * to that data.
52 * Other implementations may operate better if they can store the
53 * data in locations other than a Java array.
54 * To maintain optimum compatibility with various optimizations
55 * it is best to avoid constructors and methods which expose the
56 * underlying storage as a Java array, as noted below in the
57 * documentation for those methods.
58 * </a>
59 */
60public final class DataBufferByte extends DataBuffer
61{
62 /** The default data bank. */
63 byte data[];
64
65 /** All data banks */
66 byte bankdata[][];
67
68 /**
69 * Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank and the
70 * specified size.
71 *
72 * @param size The size of the <CODE>DataBuffer</CODE>.
73 */
74 public DataBufferByte(int size) {
75 super(STABLE, TYPE_BYTE, size);
76 data = new byte[size];
77 bankdata = new byte[1][];
78 bankdata[0] = data;
79 }
80
81 /**
82 * Constructs a byte based <CODE>DataBuffer</CODE> with the specified number of
83 * banks all of which are the specified size.
84 *
85 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
86 * @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
87 */
88 public DataBufferByte(int size, int numBanks) {
89 super(STABLE, TYPE_BYTE, size, numBanks);
90 bankdata = new byte[numBanks][];
91 for (int i= 0; i < numBanks; i++) {
92 bankdata[i] = new byte[size];
93 }
94 data = bankdata[0];
95 }
96
97 /**
98 * Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank using the
99 * specified array.
100 * Only the first <CODE>size</CODE> elements should be used by accessors of
101 * this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
102 * hold <CODE>size</CODE> elements.
103 * <p>
104 * Note that {@code DataBuffer} objects created by this constructor
105 * may be incompatible with <a href="#optimizations">performance
106 * optimizations</a> used by some implementations (such as caching
107 * an associated image in video memory).
108 *
109 * @param dataArray The byte array for the <CODE>DataBuffer</CODE>.
110 * @param size The size of the <CODE>DataBuffer</CODE> bank.
111 */
112 public DataBufferByte(byte dataArray[], int size) {
113 super(UNTRACKABLE, TYPE_BYTE, size);
114 data = dataArray;
115 bankdata = new byte[1][];
116 bankdata[0] = data;
117 }
118
119 /**
120 * Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank using the
121 * specified array, size, and offset. <CODE>dataArray</CODE> must have at least
122 * <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
123 * through <CODE>offset</CODE> + <CODE>size</CODE> - 1
124 * should be used by accessors of this <CODE>DataBuffer</CODE>.
125 * <p>
126 * Note that {@code DataBuffer} objects created by this constructor
127 * may be incompatible with <a href="#optimizations">performance
128 * optimizations</a> used by some implementations (such as caching
129 * an associated image in video memory).
130 *
131 * @param dataArray The byte array for the <CODE>DataBuffer</CODE>.
132 * @param size The size of the <CODE>DataBuffer</CODE> bank.
133 * @param offset The offset into the <CODE>dataArray</CODE>. <CODE>dataArray</CODE>
134 * must have at least <CODE>offset</CODE> + <CODE>size</CODE> elements.
135 */
136 public DataBufferByte(byte dataArray[], int size, int offset){
137 super(UNTRACKABLE, TYPE_BYTE, size, 1, offset);
138 data = dataArray;
139 bankdata = new byte[1][];
140 bankdata[0] = data;
141 }
142
143 /**
144 * Constructs a byte-based <CODE>DataBuffer</CODE> with the specified arrays.
145 * The number of banks is equal to <CODE>dataArray.length</CODE>.
146 * Only the first <CODE>size</CODE> elements of each array should be used by
147 * accessors of this <CODE>DataBuffer</CODE>.
148 * <p>
149 * Note that {@code DataBuffer} objects created by this constructor
150 * may be incompatible with <a href="#optimizations">performance
151 * optimizations</a> used by some implementations (such as caching
152 * an associated image in video memory).
153 *
154 * @param dataArray The byte arrays for the <CODE>DataBuffer</CODE>.
155 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
156 */
157 public DataBufferByte(byte dataArray[][], int size) {
158 super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length);
159 bankdata = (byte[][]) dataArray.clone();
160 data = bankdata[0];
161 }
162
163 /**
164 * Constructs a byte-based <CODE>DataBuffer</CODE> with the specified arrays, size,
165 * and offsets.
166 * The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
167 * be at least as large as <CODE>size</CODE> + the corresponding <CODE>offset</CODE>.
168 * There must be an entry in the <CODE>offset</CODE> array for each <CODE>dataArray</CODE>
169 * entry. For each bank, only elements <CODE>offset</CODE> through
170 * <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be used by accessors of this
171 * <CODE>DataBuffer</CODE>.
172 * <p>
173 * Note that {@code DataBuffer} objects created by this constructor
174 * may be incompatible with <a href="#optimizations">performance
175 * optimizations</a> used by some implementations (such as caching
176 * an associated image in video memory).
177 *
178 * @param dataArray The byte arrays for the <CODE>DataBuffer</CODE>.
179 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
180 * @param offsets The offsets into each array.
181 */
182 public DataBufferByte(byte dataArray[][], int size, int offsets[]) {
183 super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length, offsets);
184 bankdata = (byte[][]) dataArray.clone();
185 data = bankdata[0];
186 }
187
188 /**
189 * Returns the default (first) byte data array.
190 * <p>
191 * Note that calling this method may cause this {@code DataBuffer}
192 * object to be incompatible with <a href="#optimizations">performance
193 * optimizations</a> used by some implementations (such as caching
194 * an associated image in video memory).
195 *
196 * @return The first byte data array.
197 */
198 public byte[] getData() {
199 theTrackable.setUntrackable();
200 return data;
201 }
202
203 /**
204 * Returns the data array for the specified bank.
205 * <p>
206 * Note that calling this method may cause this {@code DataBuffer}
207 * object to be incompatible with <a href="#optimizations">performance
208 * optimizations</a> used by some implementations (such as caching
209 * an associated image in video memory).
210 *
211 * @param bank The bank whose data array you want to get.
212 * @return The data array for the specified bank.
213 */
214 public byte[] getData(int bank) {
215 theTrackable.setUntrackable();
216 return bankdata[bank];
217 }
218
219 /**
220 * Returns the data arrays for all banks.
221 * <p>
222 * Note that calling this method may cause this {@code DataBuffer}
223 * object to be incompatible with <a href="#optimizations">performance
224 * optimizations</a> used by some implementations (such as caching
225 * an associated image in video memory).
226 *
227 * @return All of the data arrays.
228 */
229 public byte[][] getBankData() {
230 theTrackable.setUntrackable();
231 return (byte[][]) bankdata.clone();
232 }
233
234 /**
235 * Returns the requested data array element from the first (default) bank.
236 *
237 * @param i The data array element you want to get.
238 * @return The requested data array element as an integer.
239 * @see #setElem(int, int)
240 * @see #setElem(int, int, int)
241 */
242 public int getElem(int i) {
243 return (int)(data[i+offset]) & 0xff;
244 }
245
246 /**
247 * Returns the requested data array element from the specified bank.
248 *
249 * @param bank The bank from which you want to get a data array element.
250 * @param i The data array element you want to get.
251 * @return The requested data array element as an integer.
252 * @see #setElem(int, int)
253 * @see #setElem(int, int, int)
254 */
255 public int getElem(int bank, int i) {
256 return (int)(bankdata[bank][i+offsets[bank]]) & 0xff;
257 }
258
259 /**
260 * Sets the requested data array element in the first (default) bank
261 * to the specified value.
262 *
263 * @param i The data array element you want to set.
264 * @param val The integer value to which you want to set the data array element.
265 * @see #getElem(int)
266 * @see #getElem(int, int)
267 */
268 public void setElem(int i, int val) {
269 data[i+offset] = (byte)val;
270 theTrackable.markDirty();
271 }
272
273 /**
274 * Sets the requested data array element in the specified bank
275 * from the given integer.
276 * @param bank The bank in which you want to set the data array element.
277 * @param i The data array element you want to set.
278 * @param val The integer value to which you want to set the specified data array element.
279 * @see #getElem(int)
280 * @see #getElem(int, int)
281 */
282 public void setElem(int bank, int i, int val) {
283 bankdata[bank][i+offsets[bank]] = (byte)val;
284 theTrackable.markDirty();
285 }
286}
java/pkg/java/awt/image/DataBufferDouble.class+0−0

Binary file not shown.

java/pkg/java/awt/image/DataBufferDouble.java+403−0
@@ -0,0 +1,403 @@
1/*
2 * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import static sun.java2d.StateTrackable.State.*;
29
30/**
31 * This class extends <code>DataBuffer</code> and stores data internally
32 * in <code>double</code> form.
33 * <p>
34 * <a name="optimizations">
35 * Note that some implementations may function more efficiently
36 * if they can maintain control over how the data for an image is
37 * stored.
38 * For example, optimizations such as caching an image in video
39 * memory require that the implementation track all modifications
40 * to that data.
41 * Other implementations may operate better if they can store the
42 * data in locations other than a Java array.
43 * To maintain optimum compatibility with various optimizations
44 * it is best to avoid constructors and methods which expose the
45 * underlying storage as a Java array as noted below in the
46 * documentation for those methods.
47 * </a>
48 *
49 * @since 1.4
50 */
51
52public final class DataBufferDouble extends DataBuffer {
53
54 /** The array of data banks. */
55 double bankdata[][];
56
57 /** A reference to the default data bank. */
58 double data[];
59
60 /**
61 * Constructs a <code>double</code>-based <code>DataBuffer</code>
62 * with a specified size.
63 *
64 * @param size The number of elements in the <code>DataBuffer</code>.
65 */
66 public DataBufferDouble(int size) {
67 super(STABLE, TYPE_DOUBLE, size);
68 data = new double[size];
69 bankdata = new double[1][];
70 bankdata[0] = data;
71 }
72
73 /**
74 * Constructs a <code>double</code>-based <code>DataBuffer</code>
75 * with a specified number of banks, all of which are of a
76 * specified size.
77 *
78 * @param size The number of elements in each bank of the
79 * <code>DataBuffer</code>.
80 * @param numBanks The number of banks in the <code>DataBuffer</code>.
81 */
82 public DataBufferDouble(int size, int numBanks) {
83 super(STABLE, TYPE_DOUBLE, size, numBanks);
84 bankdata = new double[numBanks][];
85 for (int i= 0; i < numBanks; i++) {
86 bankdata[i] = new double[size];
87 }
88 data = bankdata[0];
89 }
90
91 /**
92 * Constructs a <code>double</code>-based <code>DataBuffer</code>
93 * with the specified data array. Only the first
94 * <code>size</code> elements are available for use by this
95 * <code>DataBuffer</code>. The array must be large enough to
96 * hold <code>size</code> elements.
97 * <p>
98 * Note that {@code DataBuffer} objects created by this constructor
99 * may be incompatible with <a href="#optimizations">performance
100 * optimizations</a> used by some implementations (such as caching
101 * an associated image in video memory).
102 *
103 * @param dataArray An array of <code>double</code>s to be used as the
104 * first and only bank of this <code>DataBuffer</code>.
105 * @param size The number of elements of the array to be used.
106 */
107 public DataBufferDouble(double dataArray[], int size) {
108 super(UNTRACKABLE, TYPE_DOUBLE, size);
109 data = dataArray;
110 bankdata = new double[1][];
111 bankdata[0] = data;
112 }
113
114 /**
115 * Constructs a <code>double</code>-based <code>DataBuffer</code>
116 * with the specified data array. Only the elements between
117 * <code>offset</code> and <code>offset + size - 1</code> are
118 * available for use by this <code>DataBuffer</code>. The array
119 * must be large enough to hold <code>offset + size</code> elements.
120 * <p>
121 * Note that {@code DataBuffer} objects created by this constructor
122 * may be incompatible with <a href="#optimizations">performance
123 * optimizations</a> used by some implementations (such as caching
124 * an associated image in video memory).
125 *
126 * @param dataArray An array of <code>double</code>s to be used as the
127 * first and only bank of this <code>DataBuffer</code>.
128 * @param size The number of elements of the array to be used.
129 * @param offset The offset of the first element of the array
130 * that will be used.
131 */
132 public DataBufferDouble(double dataArray[], int size, int offset) {
133 super(UNTRACKABLE, TYPE_DOUBLE, size, 1, offset);
134 data = dataArray;
135 bankdata = new double[1][];
136 bankdata[0] = data;
137 }
138
139 /**
140 * Constructs a <code>double</code>-based <code>DataBuffer</code>
141 * with the specified data arrays. Only the first
142 * <code>size</code> elements of each array are available for use
143 * by this <code>DataBuffer</code>. The number of banks will be
144 * equal <code>to dataArray.length</code>.
145 * <p>
146 * Note that {@code DataBuffer} objects created by this constructor
147 * may be incompatible with <a href="#optimizations">performance
148 * optimizations</a> used by some implementations (such as caching
149 * an associated image in video memory).
150 *
151 * @param dataArray An array of arrays of <code>double</code>s to be
152 * used as the banks of this <code>DataBuffer</code>.
153 * @param size The number of elements of each array to be used.
154 */
155 public DataBufferDouble(double dataArray[][], int size) {
156 super(UNTRACKABLE, TYPE_DOUBLE, size, dataArray.length);
157 bankdata = (double[][]) dataArray.clone();
158 data = bankdata[0];
159 }
160
161 /**
162 * Constructs a <code>double</code>-based <code>DataBuffer</code>
163 * with the specified data arrays, size, and per-bank offsets.
164 * The number of banks is equal to dataArray.length. Each array
165 * must be at least as large as <code>size</code> plus the
166 * corresponding offset. There must be an entry in the
167 * <code>offsets</code> array for each data array.
168 * <p>
169 * Note that {@code DataBuffer} objects created by this constructor
170 * may be incompatible with <a href="#optimizations">performance
171 * optimizations</a> used by some implementations (such as caching
172 * an associated image in video memory).
173 *
174 * @param dataArray An array of arrays of <code>double</code>s to be
175 * used as the banks of this <code>DataBuffer</code>.
176 * @param size The number of elements of each array to be used.
177 * @param offsets An array of integer offsets, one for each bank.
178 */
179 public DataBufferDouble(double dataArray[][], int size, int offsets[]) {
180 super(UNTRACKABLE, TYPE_DOUBLE, size, dataArray.length, offsets);
181 bankdata = (double[][]) dataArray.clone();
182 data = bankdata[0];
183 }
184
185 /**
186 * Returns the default (first) <code>double</code> data array.
187 * <p>
188 * Note that calling this method may cause this {@code DataBuffer}
189 * object to be incompatible with <a href="#optimizations">performance
190 * optimizations</a> used by some implementations (such as caching
191 * an associated image in video memory).
192 *
193 * @return the first double data array.
194 */
195 public double[] getData() {
196 theTrackable.setUntrackable();
197 return data;
198 }
199
200 /**
201 * Returns the data array for the specified bank.
202 * <p>
203 * Note that calling this method may cause this {@code DataBuffer}
204 * object to be incompatible with <a href="#optimizations">performance
205 * optimizations</a> used by some implementations (such as caching
206 * an associated image in video memory).
207 *
208 * @param bank the data array
209 * @return the data array specified by <code>bank</code>.
210 */
211 public double[] getData(int bank) {
212 theTrackable.setUntrackable();
213 return bankdata[bank];
214 }
215
216 /**
217 * Returns the data array for all banks.
218 * <p>
219 * Note that calling this method may cause this {@code DataBuffer}
220 * object to be incompatible with <a href="#optimizations">performance
221 * optimizations</a> used by some implementations (such as caching
222 * an associated image in video memory).
223 *
224 * @return all data arrays from this data buffer.
225 */
226 public double[][] getBankData() {
227 theTrackable.setUntrackable();
228 return (double[][]) bankdata.clone();
229 }
230
231 /**
232 * Returns the requested data array element from the first
233 * (default) bank as an <code>int</code>.
234 *
235 * @param i The desired data array element.
236 * @return The data entry as an <code>int</code>.
237 * @see #setElem(int, int)
238 * @see #setElem(int, int, int)
239 */
240 public int getElem(int i) {
241 return (int)(data[i+offset]);
242 }
243
244 /**
245 * Returns the requested data array element from the specified
246 * bank as an <code>int</code>.
247 *
248 * @param bank The bank number.
249 * @param i The desired data array element.
250 *
251 * @return The data entry as an <code>int</code>.
252 * @see #setElem(int, int)
253 * @see #setElem(int, int, int)
254 */
255 public int getElem(int bank, int i) {
256 return (int)(bankdata[bank][i+offsets[bank]]);
257 }
258
259 /**
260 * Sets the requested data array element in the first (default)
261 * bank to the given <code>int</code>.
262 *
263 * @param i The desired data array element.
264 * @param val The value to be set.
265 * @see #getElem(int)
266 * @see #getElem(int, int)
267 */
268 public void setElem(int i, int val) {
269 data[i+offset] = (double)val;
270 theTrackable.markDirty();
271 }
272
273 /**
274 * Sets the requested data array element in the specified bank
275 * to the given <code>int</code>.
276 *
277 * @param bank The bank number.
278 * @param i The desired data array element.
279 * @param val The value to be set.
280 * @see #getElem(int)
281 * @see #getElem(int, int)
282 */
283 public void setElem(int bank, int i, int val) {
284 bankdata[bank][i+offsets[bank]] = (double)val;
285 theTrackable.markDirty();
286 }
287
288 /**
289 * Returns the requested data array element from the first
290 * (default) bank as a <code>float</code>.
291 *
292 * @param i The desired data array element.
293 *
294 * @return The data entry as a <code>float</code>.
295 * @see #setElemFloat(int, float)
296 * @see #setElemFloat(int, int, float)
297 */
298 public float getElemFloat(int i) {
299 return (float)data[i+offset];
300 }
301
302 /**
303 * Returns the requested data array element from the specified
304 * bank as a <code>float</code>.
305 *
306 * @param bank The bank number.
307 * @param i The desired data array element.
308 *
309 * @return The data entry as a <code>float</code>.
310 * @see #setElemFloat(int, float)
311 * @see #setElemFloat(int, int, float)
312 */
313 public float getElemFloat(int bank, int i) {
314 return (float)bankdata[bank][i+offsets[bank]];
315 }
316
317 /**
318 * Sets the requested data array element in the first (default)
319 * bank to the given <code>float</code>.
320 *
321 * @param i The desired data array element.
322 * @param val The value to be set.
323 * @see #getElemFloat(int)
324 * @see #getElemFloat(int, int)
325 */
326 public void setElemFloat(int i, float val) {
327 data[i+offset] = (double)val;
328 theTrackable.markDirty();
329 }
330
331 /**
332 * Sets the requested data array element in the specified bank to
333 * the given <code>float</code>.
334 *
335 * @param bank The bank number.
336 * @param i The desired data array element.
337 * @param val The value to be set.
338 * @see #getElemFloat(int)
339 * @see #getElemFloat(int, int)
340 */
341 public void setElemFloat(int bank, int i, float val) {
342 bankdata[bank][i+offsets[bank]] = (double)val;
343 theTrackable.markDirty();
344 }
345
346 /**
347 * Returns the requested data array element from the first
348 * (default) bank as a <code>double</code>.
349 *
350 * @param i The desired data array element.
351 *
352 * @return The data entry as a <code>double</code>.
353 * @see #setElemDouble(int, double)
354 * @see #setElemDouble(int, int, double)
355 */
356 public double getElemDouble(int i) {
357 return data[i+offset];
358 }
359
360 /**
361 * Returns the requested data array element from the specified
362 * bank as a <code>double</code>.
363 *
364 * @param bank The bank number.
365 * @param i The desired data array element.
366 *
367 * @return The data entry as a <code>double</code>.
368 * @see #setElemDouble(int, double)
369 * @see #setElemDouble(int, int, double)
370 */
371 public double getElemDouble(int bank, int i) {
372 return bankdata[bank][i+offsets[bank]];
373 }
374
375 /**
376 * Sets the requested data array element in the first (default)
377 * bank to the given <code>double</code>.
378 *
379 * @param i The desired data array element.
380 * @param val The value to be set.
381 * @see #getElemDouble(int)
382 * @see #getElemDouble(int, int)
383 */
384 public void setElemDouble(int i, double val) {
385 data[i+offset] = val;
386 theTrackable.markDirty();
387 }
388
389 /**
390 * Sets the requested data array element in the specified bank to
391 * the given <code>double</code>.
392 *
393 * @param bank The bank number.
394 * @param i The desired data array element.
395 * @param val The value to be set.
396 * @see #getElemDouble(int)
397 * @see #getElemDouble(int, int)
398 */
399 public void setElemDouble(int bank, int i, double val) {
400 bankdata[bank][i+offsets[bank]] = val;
401 theTrackable.markDirty();
402 }
403}
java/pkg/java/awt/image/DataBufferFloat.class+0−0

Binary file not shown.

java/pkg/java/awt/image/DataBufferFloat.java+406−0
@@ -0,0 +1,406 @@
1/*
2 * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import static sun.java2d.StateTrackable.State.*;
29
30/**
31 * This class extends <code>DataBuffer</code> and stores data internally
32 * in <code>float</code> form.
33 * <p>
34 * <a name="optimizations">
35 * Note that some implementations may function more efficiently
36 * if they can maintain control over how the data for an image is
37 * stored.
38 * For example, optimizations such as caching an image in video
39 * memory require that the implementation track all modifications
40 * to that data.
41 * Other implementations may operate better if they can store the
42 * data in locations other than a Java array.
43 * To maintain optimum compatibility with various optimizations
44 * it is best to avoid constructors and methods which expose the
45 * underlying storage as a Java array as noted below in the
46 * documentation for those methods.
47 * </a>
48 *
49 * @since 1.4
50 */
51
52public final class DataBufferFloat extends DataBuffer {
53
54 /** The array of data banks. */
55 float bankdata[][];
56
57 /** A reference to the default data bank. */
58 float data[];
59
60 /**
61 * Constructs a <code>float</code>-based <code>DataBuffer</code>
62 * with a specified size.
63 *
64 * @param size The number of elements in the DataBuffer.
65 */
66 public DataBufferFloat(int size) {
67 super(STABLE, TYPE_FLOAT, size);
68 data = new float[size];
69 bankdata = new float[1][];
70 bankdata[0] = data;
71 }
72
73 /**
74 * Constructs a <code>float</code>-based <code>DataBuffer</code>
75 * with a specified number of banks, all of which are of a
76 * specified size.
77 *
78 * @param size The number of elements in each bank of the
79 * <code>DataBuffer</code>.
80 * @param numBanks The number of banks in the
81 * <code>DataBuffer</code>.
82 */
83 public DataBufferFloat(int size, int numBanks) {
84 super(STABLE, TYPE_FLOAT, size, numBanks);
85 bankdata = new float[numBanks][];
86 for (int i= 0; i < numBanks; i++) {
87 bankdata[i] = new float[size];
88 }
89 data = bankdata[0];
90 }
91
92 /**
93 * Constructs a <code>float</code>-based <code>DataBuffer</code>
94 * with the specified data array. Only the first
95 * <code>size</code> elements are available for use by this
96 * <code>DataBuffer</code>. The array must be large enough to
97 * hold <code>size</code> elements.
98 * <p>
99 * Note that {@code DataBuffer} objects created by this constructor
100 * may be incompatible with <a href="#optimizations">performance
101 * optimizations</a> used by some implementations (such as caching
102 * an associated image in video memory).
103 *
104 * @param dataArray An array of <code>float</code>s to be used as the
105 * first and only bank of this <code>DataBuffer</code>.
106 * @param size The number of elements of the array to be used.
107 */
108 public DataBufferFloat(float dataArray[], int size) {
109 super(UNTRACKABLE, TYPE_FLOAT, size);
110 data = dataArray;
111 bankdata = new float[1][];
112 bankdata[0] = data;
113 }
114
115 /**
116 * Constructs a <code>float</code>-based <code>DataBuffer</code>
117 * with the specified data array. Only the elements between
118 * <code>offset</code> and <code>offset + size - 1</code> are
119 * available for use by this <code>DataBuffer</code>. The array
120 * must be large enough to hold <code>offset + size</code>
121 * elements.
122 * <p>
123 * Note that {@code DataBuffer} objects created by this constructor
124 * may be incompatible with <a href="#optimizations">performance
125 * optimizations</a> used by some implementations (such as caching
126 * an associated image in video memory).
127 *
128 * @param dataArray An array of <code>float</code>s to be used as the
129 * first and only bank of this <code>DataBuffer</code>.
130 * @param size The number of elements of the array to be used.
131 * @param offset The offset of the first element of the array
132 * that will be used.
133 */
134 public DataBufferFloat(float dataArray[], int size, int offset) {
135 super(UNTRACKABLE, TYPE_FLOAT, size, 1, offset);
136 data = dataArray;
137 bankdata = new float[1][];
138 bankdata[0] = data;
139 }
140
141 /**
142 * Constructs a <code>float</code>-based <code>DataBuffer</code>
143 * with the specified data arrays. Only the first
144 * <code>size</code> elements of each array are available for use
145 * by this <code>DataBuffer</code>. The number of banks will be
146 * equal to <code>dataArray.length</code>.
147 * <p>
148 * Note that {@code DataBuffer} objects created by this constructor
149 * may be incompatible with <a href="#optimizations">performance
150 * optimizations</a> used by some implementations (such as caching
151 * an associated image in video memory).
152 *
153 * @param dataArray An array of arrays of <code>float</code>s to be
154 * used as the banks of this <code>DataBuffer</code>.
155 * @param size The number of elements of each array to be used.
156 */
157 public DataBufferFloat(float dataArray[][], int size) {
158 super(UNTRACKABLE, TYPE_FLOAT, size, dataArray.length);
159 bankdata = (float[][]) dataArray.clone();
160 data = bankdata[0];
161 }
162
163 /**
164 * Constructs a <code>float</code>-based <code>DataBuffer</code>
165 * with the specified data arrays, size, and per-bank offsets.
166 * The number of banks is equal to <code>dataArray.length</code>.
167 * Each array must be at least as large as <code>size</code> plus the
168 * corresponding offset. There must be an entry in the offsets
169 * array for each data array.
170 * <p>
171 * Note that {@code DataBuffer} objects created by this constructor
172 * may be incompatible with <a href="#optimizations">performance
173 * optimizations</a> used by some implementations (such as caching
174 * an associated image in video memory).
175 *
176 * @param dataArray An array of arrays of <code>float</code>s to be
177 * used as the banks of this <code>DataBuffer</code>.
178 * @param size The number of elements of each array to be used.
179 * @param offsets An array of integer offsets, one for each bank.
180 */
181 public DataBufferFloat(float dataArray[][], int size, int offsets[]) {
182 super(UNTRACKABLE, TYPE_FLOAT, size,dataArray.length, offsets);
183 bankdata = (float[][]) dataArray.clone();
184 data = bankdata[0];
185 }
186
187 /**
188 * Returns the default (first) <code>float</code> data array.
189 * <p>
190 * Note that calling this method may cause this {@code DataBuffer}
191 * object to be incompatible with <a href="#optimizations">performance
192 * optimizations</a> used by some implementations (such as caching
193 * an associated image in video memory).
194 *
195 * @return the first float data array.
196 */
197 public float[] getData() {
198 theTrackable.setUntrackable();
199 return data;
200 }
201
202 /**
203 * Returns the data array for the specified bank.
204 * <p>
205 * Note that calling this method may cause this {@code DataBuffer}
206 * object to be incompatible with <a href="#optimizations">performance
207 * optimizations</a> used by some implementations (such as caching
208 * an associated image in video memory).
209 *
210 * @param bank the data array
211 * @return the data array specified by <code>bank</code>.
212 */
213 public float[] getData(int bank) {
214 theTrackable.setUntrackable();
215 return bankdata[bank];
216 }
217
218 /**
219 * Returns the data array for all banks.
220 * <p>
221 * Note that calling this method may cause this {@code DataBuffer}
222 * object to be incompatible with <a href="#optimizations">performance
223 * optimizations</a> used by some implementations (such as caching
224 * an associated image in video memory).
225 *
226 * @return all data arrays for this data buffer.
227 */
228 public float[][] getBankData() {
229 theTrackable.setUntrackable();
230 return (float[][]) bankdata.clone();
231 }
232
233 /**
234 * Returns the requested data array element from the first
235 * (default) bank as an <code>int</code>.
236 *
237 * @param i The desired data array element.
238 *
239 * @return The data entry as an <code>int</code>.
240 * @see #setElem(int, int)
241 * @see #setElem(int, int, int)
242 */
243 public int getElem(int i) {
244 return (int)(data[i+offset]);
245 }
246
247 /**
248 * Returns the requested data array element from the specified
249 * bank as an <code>int</code>.
250 *
251 * @param bank The bank number.
252 * @param i The desired data array element.
253 *
254 * @return The data entry as an <code>int</code>.
255 * @see #setElem(int, int)
256 * @see #setElem(int, int, int)
257 */
258 public int getElem(int bank, int i) {
259 return (int)(bankdata[bank][i+offsets[bank]]);
260 }
261
262 /**
263 * Sets the requested data array element in the first (default)
264 * bank to the given <code>int</code>.
265 *
266 * @param i The desired data array element.
267 * @param val The value to be set.
268 * @see #getElem(int)
269 * @see #getElem(int, int)
270 */
271 public void setElem(int i, int val) {
272 data[i+offset] = (float)val;
273 theTrackable.markDirty();
274 }
275
276 /**
277 * Sets the requested data array element in the specified bank to
278 * the given <code>int</code>.
279 *
280 * @param bank The bank number.
281 * @param i The desired data array element.
282 * @param val The value to be set.
283 * @see #getElem(int)
284 * @see #getElem(int, int)
285 */
286 public void setElem(int bank, int i, int val) {
287 bankdata[bank][i+offsets[bank]] = (float)val;
288 theTrackable.markDirty();
289 }
290
291 /**
292 * Returns the requested data array element from the first
293 * (default) bank as a <code>float</code>.
294 *
295 * @param i The desired data array element.
296 *
297 * @return The data entry as a <code>float</code>.
298 * @see #setElemFloat(int, float)
299 * @see #setElemFloat(int, int, float)
300 */
301 public float getElemFloat(int i) {
302 return data[i+offset];
303 }
304
305 /**
306 * Returns the requested data array element from the specified
307 * bank as a <code>float</code>.
308 *
309 * @param bank The bank number.
310 * @param i The desired data array element.
311 *
312 * @return The data entry as a <code>float</code>.
313 * @see #setElemFloat(int, float)
314 * @see #setElemFloat(int, int, float)
315 */
316 public float getElemFloat(int bank, int i) {
317 return bankdata[bank][i+offsets[bank]];
318 }
319
320 /**
321 * Sets the requested data array element in the first (default)
322 * bank to the given <code>float</code>.
323 *
324 * @param i The desired data array element.
325 * @param val The value to be set.
326 * @see #getElemFloat(int)
327 * @see #getElemFloat(int, int)
328 */
329 public void setElemFloat(int i, float val) {
330 data[i+offset] = val;
331 theTrackable.markDirty();
332 }
333
334 /**
335 * Sets the requested data array element in the specified bank to
336 * the given <code>float</code>.
337 *
338 * @param bank The bank number.
339 * @param i The desired data array element.
340 * @param val The value to be set.
341 * @see #getElemFloat(int)
342 * @see #getElemFloat(int, int)
343 */
344 public void setElemFloat(int bank, int i, float val) {
345 bankdata[bank][i+offsets[bank]] = val;
346 theTrackable.markDirty();
347 }
348
349 /**
350 * Returns the requested data array element from the first
351 * (default) bank as a <code>double</code>.
352 *
353 * @param i The desired data array element.
354 *
355 * @return The data entry as a <code>double</code>.
356 * @see #setElemDouble(int, double)
357 * @see #setElemDouble(int, int, double)
358 */
359 public double getElemDouble(int i) {
360 return (double)data[i+offset];
361 }
362
363 /**
364 * Returns the requested data array element from the specified
365 * bank as a <code>double</code>.
366 *
367 * @param bank The bank number.
368 * @param i The desired data array element.
369 *
370 * @return The data entry as a <code>double</code>.
371 * @see #setElemDouble(int, double)
372 * @see #setElemDouble(int, int, double)
373 */
374 public double getElemDouble(int bank, int i) {
375 return (double)bankdata[bank][i+offsets[bank]];
376 }
377
378 /**
379 * Sets the requested data array element in the first (default)
380 * bank to the given <code>double</code>.
381 *
382 * @param i The desired data array element.
383 * @param val The value to be set.
384 * @see #getElemDouble(int)
385 * @see #getElemDouble(int, int)
386 */
387 public void setElemDouble(int i, double val) {
388 data[i+offset] = (float)val;
389 theTrackable.markDirty();
390 }
391
392 /**
393 * Sets the requested data array element in the specified bank to
394 * the given <code>double</code>.
395 *
396 * @param bank The bank number.
397 * @param i The desired data array element.
398 * @param val The value to be set.
399 * @see #getElemDouble(int)
400 * @see #getElemDouble(int, int)
401 */
402 public void setElemDouble(int bank, int i, double val) {
403 bankdata[bank][i+offsets[bank]] = (float)val;
404 theTrackable.markDirty();
405 }
406}
java/pkg/java/awt/image/DataBufferInt.class+0−0

Binary file not shown.

java/pkg/java/awt/image/DataBufferInt.java+284−0
@@ -0,0 +1,284 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26/* ****************************************************************
27 ******************************************************************
28 ******************************************************************
29 *** COPYRIGHT (c) Eastman Kodak Company, 1997
30 *** As an unpublished work pursuant to Title 17 of the United
31 *** States Code. All rights reserved.
32 ******************************************************************
33 ******************************************************************
34 ******************************************************************/
35
36package java.awt.image;
37
38import static sun.java2d.StateTrackable.State.*;
39
40/**
41 * This class extends <CODE>DataBuffer</CODE> and stores data internally
42 * as integers.
43 * <p>
44 * <a name="optimizations">
45 * Note that some implementations may function more efficiently
46 * if they can maintain control over how the data for an image is
47 * stored.
48 * For example, optimizations such as caching an image in video
49 * memory require that the implementation track all modifications
50 * to that data.
51 * Other implementations may operate better if they can store the
52 * data in locations other than a Java array.
53 * To maintain optimum compatibility with various optimizations
54 * it is best to avoid constructors and methods which expose the
55 * underlying storage as a Java array as noted below in the
56 * documentation for those methods.
57 * </a>
58 */
59public final class DataBufferInt extends DataBuffer
60{
61 /** The default data bank. */
62 int data[];
63
64 /** All data banks */
65 int bankdata[][];
66
67 /**
68 * Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank
69 * and the specified size.
70 *
71 * @param size The size of the <CODE>DataBuffer</CODE>.
72 */
73 public DataBufferInt(int size) {
74 super(STABLE, TYPE_INT, size);
75 data = new int[size];
76 bankdata = new int[1][];
77 bankdata[0] = data;
78 }
79
80 /**
81 * Constructs an integer-based <CODE>DataBuffer</CODE> with the specified number of
82 * banks, all of which are the specified size.
83 *
84 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
85 * @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
86 */
87 public DataBufferInt(int size, int numBanks) {
88 super(STABLE, TYPE_INT, size, numBanks);
89 bankdata = new int[numBanks][];
90 for (int i= 0; i < numBanks; i++) {
91 bankdata[i] = new int[size];
92 }
93 data = bankdata[0];
94 }
95
96 /**
97 * Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank using the
98 * specified array.
99 * Only the first <CODE>size</CODE> elements should be used by accessors of
100 * this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
101 * hold <CODE>size</CODE> elements.
102 * <p>
103 * Note that {@code DataBuffer} objects created by this constructor
104 * may be incompatible with <a href="#optimizations">performance
105 * optimizations</a> used by some implementations (such as caching
106 * an associated image in video memory).
107 *
108 * @param dataArray The integer array for the <CODE>DataBuffer</CODE>.
109 * @param size The size of the <CODE>DataBuffer</CODE> bank.
110 */
111 public DataBufferInt(int dataArray[], int size) {
112 super(UNTRACKABLE, TYPE_INT, size);
113 data = dataArray;
114 bankdata = new int[1][];
115 bankdata[0] = data;
116 }
117
118 /**
119 * Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank using the
120 * specified array, size, and offset. <CODE>dataArray</CODE> must have at least
121 * <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
122 * through <CODE>offset</CODE> + <CODE>size</CODE> - 1
123 * should be used by accessors of this <CODE>DataBuffer</CODE>.
124 * <p>
125 * Note that {@code DataBuffer} objects created by this constructor
126 * may be incompatible with <a href="#optimizations">performance
127 * optimizations</a> used by some implementations (such as caching
128 * an associated image in video memory).
129 *
130 * @param dataArray The integer array for the <CODE>DataBuffer</CODE>.
131 * @param size The size of the <CODE>DataBuffer</CODE> bank.
132 * @param offset The offset into the <CODE>dataArray</CODE>.
133 */
134 public DataBufferInt(int dataArray[], int size, int offset) {
135 super(UNTRACKABLE, TYPE_INT, size, 1, offset);
136 data = dataArray;
137 bankdata = new int[1][];
138 bankdata[0] = data;
139 }
140
141 /**
142 * Constructs an integer-based <CODE>DataBuffer</CODE> with the specified arrays.
143 * The number of banks will be equal to <CODE>dataArray.length</CODE>.
144 * Only the first <CODE>size</CODE> elements of each array should be used by
145 * accessors of this <CODE>DataBuffer</CODE>.
146 * <p>
147 * Note that {@code DataBuffer} objects created by this constructor
148 * may be incompatible with <a href="#optimizations">performance
149 * optimizations</a> used by some implementations (such as caching
150 * an associated image in video memory).
151 *
152 * @param dataArray The integer arrays for the <CODE>DataBuffer</CODE>.
153 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
154 */
155 public DataBufferInt(int dataArray[][], int size) {
156 super(UNTRACKABLE, TYPE_INT, size, dataArray.length);
157 bankdata = (int [][]) dataArray.clone();
158 data = bankdata[0];
159 }
160
161 /**
162 * Constructs an integer-based <CODE>DataBuffer</CODE> with the specified arrays, size,
163 * and offsets.
164 * The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
165 * be at least as large as <CODE>size</CODE> + the corresponding offset. There must
166 * be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
167 * bank, only elements <CODE>offset</CODE> through
168 * <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
169 * used by accessors of this <CODE>DataBuffer</CODE>.
170 * <p>
171 * Note that {@code DataBuffer} objects created by this constructor
172 * may be incompatible with <a href="#optimizations">performance
173 * optimizations</a> used by some implementations (such as caching
174 * an associated image in video memory).
175 *
176 * @param dataArray The integer arrays for the <CODE>DataBuffer</CODE>.
177 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
178 * @param offsets The offsets into each array.
179 */
180 public DataBufferInt(int dataArray[][], int size, int offsets[]) {
181 super(UNTRACKABLE, TYPE_INT, size, dataArray.length, offsets);
182 bankdata = (int [][]) dataArray.clone();
183 data = bankdata[0];
184 }
185
186 /**
187 * Returns the default (first) int data array in <CODE>DataBuffer</CODE>.
188 * <p>
189 * Note that calling this method may cause this {@code DataBuffer}
190 * object to be incompatible with <a href="#optimizations">performance
191 * optimizations</a> used by some implementations (such as caching
192 * an associated image in video memory).
193 *
194 * @return The first integer data array.
195 */
196 public int[] getData() {
197 theTrackable.setUntrackable();
198 return data;
199 }
200
201 /**
202 * Returns the data array for the specified bank.
203 * <p>
204 * Note that calling this method may cause this {@code DataBuffer}
205 * object to be incompatible with <a href="#optimizations">performance
206 * optimizations</a> used by some implementations (such as caching
207 * an associated image in video memory).
208 *
209 * @param bank The bank whose data array you want to get.
210 * @return The data array for the specified bank.
211 */
212 public int[] getData(int bank) {
213 theTrackable.setUntrackable();
214 return bankdata[bank];
215 }
216
217 /**
218 * Returns the data arrays for all banks.
219 * <p>
220 * Note that calling this method may cause this {@code DataBuffer}
221 * object to be incompatible with <a href="#optimizations">performance
222 * optimizations</a> used by some implementations (such as caching
223 * an associated image in video memory).
224 *
225 * @return All of the data arrays.
226 */
227 public int[][] getBankData() {
228 theTrackable.setUntrackable();
229 return (int [][]) bankdata.clone();
230 }
231
232 /**
233 * Returns the requested data array element from the first (default) bank.
234 *
235 * @param i The data array element you want to get.
236 * @return The requested data array element as an integer.
237 * @see #setElem(int, int)
238 * @see #setElem(int, int, int)
239 */
240 public int getElem(int i) {
241 return data[i+offset];
242 }
243
244 /**
245 * Returns the requested data array element from the specified bank.
246 *
247 * @param bank The bank from which you want to get a data array element.
248 * @param i The data array element you want to get.
249 * @return The requested data array element as an integer.
250 * @see #setElem(int, int)
251 * @see #setElem(int, int, int)
252 */
253 public int getElem(int bank, int i) {
254 return bankdata[bank][i+offsets[bank]];
255 }
256
257 /**
258 * Sets the requested data array element in the first (default) bank
259 * to the specified value.
260 *
261 * @param i The data array element you want to set.
262 * @param val The integer value to which you want to set the data array element.
263 * @see #getElem(int)
264 * @see #getElem(int, int)
265 */
266 public void setElem(int i, int val) {
267 data[i+offset] = val;
268 theTrackable.markDirty();
269 }
270
271 /**
272 * Sets the requested data array element in the specified bank
273 * to the integer value <CODE>i</CODE>.
274 * @param bank The bank in which you want to set the data array element.
275 * @param i The data array element you want to set.
276 * @param val The integer value to which you want to set the specified data array element.
277 * @see #getElem(int)
278 * @see #getElem(int, int)
279 */
280 public void setElem(int bank, int i, int val) {
281 bankdata[bank][i+offsets[bank]] = (int)val;
282 theTrackable.markDirty();
283 }
284}
java/pkg/java/awt/image/DataBufferShort.class+0−0

Binary file not shown.

java/pkg/java/awt/image/DataBufferShort.java+283−0
@@ -0,0 +1,283 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26/* ****************************************************************
27 ******************************************************************
28 ******************************************************************
29 *** COPYRIGHT (c) Eastman Kodak Company, 1997
30 *** As an unpublished work pursuant to Title 17 of the United
31 *** States Code. All rights reserved.
32 ******************************************************************
33 ******************************************************************
34 ******************************************************************/
35
36package java.awt.image;
37
38import static sun.java2d.StateTrackable.State.*;
39
40/**
41 * This class extends <CODE>DataBuffer</CODE> and stores data internally as shorts.
42 * <p>
43 * <a name="optimizations">
44 * Note that some implementations may function more efficiently
45 * if they can maintain control over how the data for an image is
46 * stored.
47 * For example, optimizations such as caching an image in video
48 * memory require that the implementation track all modifications
49 * to that data.
50 * Other implementations may operate better if they can store the
51 * data in locations other than a Java array.
52 * To maintain optimum compatibility with various optimizations
53 * it is best to avoid constructors and methods which expose the
54 * underlying storage as a Java array as noted below in the
55 * documentation for those methods.
56 * </a>
57 */
58public final class DataBufferShort extends DataBuffer
59{
60 /** The default data bank. */
61 short data[];
62
63 /** All data banks */
64 short bankdata[][];
65
66 /**
67 * Constructs a short-based <CODE>DataBuffer</CODE> with a single bank and the
68 * specified size.
69 *
70 * @param size The size of the <CODE>DataBuffer</CODE>.
71 */
72 public DataBufferShort(int size) {
73 super(STABLE, TYPE_SHORT,size);
74 data = new short[size];
75 bankdata = new short[1][];
76 bankdata[0] = data;
77 }
78
79 /**
80 * Constructs a short-based <CODE>DataBuffer</CODE> with the specified number of
81 * banks all of which are the specified size.
82 *
83 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
84 * @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
85 */
86 public DataBufferShort(int size, int numBanks) {
87 super(STABLE, TYPE_SHORT,size,numBanks);
88 bankdata = new short[numBanks][];
89 for (int i= 0; i < numBanks; i++) {
90 bankdata[i] = new short[size];
91 }
92 data = bankdata[0];
93 }
94
95 /**
96 * Constructs a short-based <CODE>DataBuffer</CODE> with a single bank using the
97 * specified array.
98 * Only the first <CODE>size</CODE> elements should be used by accessors of
99 * this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
100 * hold <CODE>size</CODE> elements.
101 * <p>
102 * Note that {@code DataBuffer} objects created by this constructor
103 * may be incompatible with <a href="#optimizations">performance
104 * optimizations</a> used by some implementations (such as caching
105 * an associated image in video memory).
106 *
107 * @param dataArray The short array for the <CODE>DataBuffer</CODE>.
108 * @param size The size of the <CODE>DataBuffer</CODE> bank.
109 */
110 public DataBufferShort(short dataArray[], int size) {
111 super(UNTRACKABLE, TYPE_SHORT, size);
112 data = dataArray;
113 bankdata = new short[1][];
114 bankdata[0] = data;
115 }
116
117 /**
118 * Constructs a short-based <CODE>DataBuffer</CODE> with a single bank using the
119 * specified array, size, and offset. <CODE>dataArray</CODE> must have at least
120 * <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
121 * through <CODE>offset</CODE> + <CODE>size</CODE> - 1
122 * should be used by accessors of this <CODE>DataBuffer</CODE>.
123 * <p>
124 * Note that {@code DataBuffer} objects created by this constructor
125 * may be incompatible with <a href="#optimizations">performance
126 * optimizations</a> used by some implementations (such as caching
127 * an associated image in video memory).
128 *
129 * @param dataArray The short array for the <CODE>DataBuffer</CODE>.
130 * @param size The size of the <CODE>DataBuffer</CODE> bank.
131 * @param offset The offset into the <CODE>dataArray</CODE>.
132 */
133 public DataBufferShort(short dataArray[], int size, int offset) {
134 super(UNTRACKABLE, TYPE_SHORT, size, 1, offset);
135 data = dataArray;
136 bankdata = new short[1][];
137 bankdata[0] = data;
138 }
139
140 /**
141 * Constructs a short-based <CODE>DataBuffer</CODE> with the specified arrays.
142 * The number of banks will be equal to <CODE>dataArray.length</CODE>.
143 * Only the first <CODE>size</CODE> elements of each array should be used by
144 * accessors of this <CODE>DataBuffer</CODE>.
145 * <p>
146 * Note that {@code DataBuffer} objects created by this constructor
147 * may be incompatible with <a href="#optimizations">performance
148 * optimizations</a> used by some implementations (such as caching
149 * an associated image in video memory).
150 *
151 * @param dataArray The short arrays for the <CODE>DataBuffer</CODE>.
152 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
153 */
154 public DataBufferShort(short dataArray[][], int size) {
155 super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length);
156 bankdata = (short[][]) dataArray.clone();
157 data = bankdata[0];
158 }
159
160 /**
161 * Constructs a short-based <CODE>DataBuffer</CODE> with the specified arrays, size,
162 * and offsets.
163 * The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
164 * be at least as large as <CODE>size</CODE> + the corresponding offset. There must
165 * be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
166 * bank, only elements <CODE>offset</CODE> through
167 * <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
168 * used by accessors of this <CODE>DataBuffer</CODE>.
169 * <p>
170 * Note that {@code DataBuffer} objects created by this constructor
171 * may be incompatible with <a href="#optimizations">performance
172 * optimizations</a> used by some implementations (such as caching
173 * an associated image in video memory).
174 *
175 * @param dataArray The short arrays for the <CODE>DataBuffer</CODE>.
176 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
177 * @param offsets The offsets into each array.
178 */
179 public DataBufferShort(short dataArray[][], int size, int offsets[]) {
180 super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length, offsets);
181 bankdata = (short[][]) dataArray.clone();
182 data = bankdata[0];
183 }
184
185 /**
186 * Returns the default (first) byte data array.
187 * <p>
188 * Note that calling this method may cause this {@code DataBuffer}
189 * object to be incompatible with <a href="#optimizations">performance
190 * optimizations</a> used by some implementations (such as caching
191 * an associated image in video memory).
192 *
193 * @return The first short data array.
194 */
195 public short[] getData() {
196 theTrackable.setUntrackable();
197 return data;
198 }
199
200 /**
201 * Returns the data array for the specified bank.
202 * <p>
203 * Note that calling this method may cause this {@code DataBuffer}
204 * object to be incompatible with <a href="#optimizations">performance
205 * optimizations</a> used by some implementations (such as caching
206 * an associated image in video memory).
207 *
208 * @param bank The bank whose data array you want to get.
209 * @return The data array for the specified bank.
210 */
211 public short[] getData(int bank) {
212 theTrackable.setUntrackable();
213 return bankdata[bank];
214 }
215
216 /**
217 * Returns the data arrays for all banks.
218 * <p>
219 * Note that calling this method may cause this {@code DataBuffer}
220 * object to be incompatible with <a href="#optimizations">performance
221 * optimizations</a> used by some implementations (such as caching
222 * an associated image in video memory).
223 *
224 * @return All of the data arrays.
225 */
226 public short[][] getBankData() {
227 theTrackable.setUntrackable();
228 return (short[][]) bankdata.clone();
229 }
230
231 /**
232 * Returns the requested data array element from the first (default) bank.
233 *
234 * @param i The data array element you want to get.
235 * @return The requested data array element as an integer.
236 * @see #setElem(int, int)
237 * @see #setElem(int, int, int)
238 */
239 public int getElem(int i) {
240 return (int)(data[i+offset]);
241 }
242
243 /**
244 * Returns the requested data array element from the specified bank.
245 *
246 * @param bank The bank from which you want to get a data array element.
247 * @param i The data array element you want to get.
248 * @return The requested data array element as an integer.
249 * @see #setElem(int, int)
250 * @see #setElem(int, int, int)
251 */
252 public int getElem(int bank, int i) {
253 return (int)(bankdata[bank][i+offsets[bank]]);
254 }
255
256 /**
257 * Sets the requested data array element in the first (default) bank
258 * to the specified value.
259 *
260 * @param i The data array element you want to set.
261 * @param val The integer value to which you want to set the data array element.
262 * @see #getElem(int)
263 * @see #getElem(int, int)
264 */
265 public void setElem(int i, int val) {
266 data[i+offset] = (short)val;
267 theTrackable.markDirty();
268 }
269
270 /**
271 * Sets the requested data array element in the specified bank
272 * from the given integer.
273 * @param bank The bank in which you want to set the data array element.
274 * @param i The data array element you want to set.
275 * @param val The integer value to which you want to set the specified data array element.
276 * @see #getElem(int)
277 * @see #getElem(int, int)
278 */
279 public void setElem(int bank, int i, int val) {
280 bankdata[bank][i+offsets[bank]] = (short)val;
281 theTrackable.markDirty();
282 }
283}
java/pkg/java/awt/image/DataBufferUShort.class+0−0

Binary file not shown.

java/pkg/java/awt/image/DataBufferUShort.java+318−0
@@ -0,0 +1,318 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26/* ****************************************************************
27 ******************************************************************
28 ******************************************************************
29 *** COPYRIGHT (c) Eastman Kodak Company, 1997
30 *** As an unpublished work pursuant to Title 17 of the United
31 *** States Code. All rights reserved.
32 ******************************************************************
33 ******************************************************************
34 ******************************************************************/
35
36package java.awt.image;
37
38import static sun.java2d.StateTrackable.State.*;
39
40/**
41 * This class extends <CODE>DataBuffer</CODE> and stores data internally as
42 * shorts. Values stored in the short array(s) of this <CODE>DataBuffer</CODE>
43 * are treated as unsigned values.
44 * <p>
45 * <a name="optimizations">
46 * Note that some implementations may function more efficiently
47 * if they can maintain control over how the data for an image is
48 * stored.
49 * For example, optimizations such as caching an image in video
50 * memory require that the implementation track all modifications
51 * to that data.
52 * Other implementations may operate better if they can store the
53 * data in locations other than a Java array.
54 * To maintain optimum compatibility with various optimizations
55 * it is best to avoid constructors and methods which expose the
56 * underlying storage as a Java array as noted below in the
57 * documentation for those methods.
58 * </a>
59 */
60public final class DataBufferUShort extends DataBuffer
61{
62 /** The default data bank. */
63 short data[];
64
65 /** All data banks */
66 short bankdata[][];
67
68 /**
69 * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank and the
70 * specified size.
71 *
72 * @param size The size of the <CODE>DataBuffer</CODE>.
73 */
74 public DataBufferUShort(int size) {
75 super(STABLE, TYPE_USHORT, size);
76 data = new short[size];
77 bankdata = new short[1][];
78 bankdata[0] = data;
79 }
80
81 /**
82 * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with the specified number of
83 * banks, all of which are the specified size.
84 *
85 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
86 * @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
87 */
88 public DataBufferUShort(int size, int numBanks) {
89 super(STABLE, TYPE_USHORT, size, numBanks);
90 bankdata = new short[numBanks][];
91 for (int i= 0; i < numBanks; i++) {
92 bankdata[i] = new short[size];
93 }
94 data = bankdata[0];
95 }
96
97 /**
98 * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank
99 * using the specified array.
100 * Only the first <CODE>size</CODE> elements should be used by accessors of
101 * this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
102 * hold <CODE>size</CODE> elements.
103 * <p>
104 * Note that {@code DataBuffer} objects created by this constructor
105 * may be incompatible with <a href="#optimizations">performance
106 * optimizations</a> used by some implementations (such as caching
107 * an associated image in video memory).
108 *
109 * @param dataArray The unsigned-short array for the <CODE>DataBuffer</CODE>.
110 * @param size The size of the <CODE>DataBuffer</CODE> bank.
111 */
112 public DataBufferUShort(short dataArray[], int size) {
113 super(UNTRACKABLE, TYPE_USHORT, size);
114 if (dataArray == null) {
115 throw new NullPointerException("dataArray is null");
116 }
117 data = dataArray;
118 bankdata = new short[1][];
119 bankdata[0] = data;
120 }
121
122 /**
123 * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank
124 * using the specified array, size, and offset. <CODE>dataArray</CODE> must have at
125 * least <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements
126 * <CODE>offset</CODE> through <CODE>offset</CODE> + <CODE>size</CODE> - 1 should
127 * be used by accessors of this <CODE>DataBuffer</CODE>.
128 * <p>
129 * Note that {@code DataBuffer} objects created by this constructor
130 * may be incompatible with <a href="#optimizations">performance
131 * optimizations</a> used by some implementations (such as caching
132 * an associated image in video memory).
133 *
134 * @param dataArray The unsigned-short array for the <CODE>DataBuffer</CODE>.
135 * @param size The size of the <CODE>DataBuffer</CODE> bank.
136 * @param offset The offset into the <CODE>dataArray</CODE>.
137 */
138 public DataBufferUShort(short dataArray[], int size, int offset) {
139 super(UNTRACKABLE, TYPE_USHORT, size, 1, offset);
140 if (dataArray == null) {
141 throw new NullPointerException("dataArray is null");
142 }
143 if ((size+offset) > dataArray.length) {
144 throw new IllegalArgumentException("Length of dataArray is less "+
145 " than size+offset.");
146 }
147 data = dataArray;
148 bankdata = new short[1][];
149 bankdata[0] = data;
150 }
151
152 /**
153 * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with the specified arrays.
154 * The number of banks will be equal to <CODE>dataArray.length</CODE>.
155 * Only the first <CODE>size</CODE> elements of each array should be used by
156 * accessors of this <CODE>DataBuffer</CODE>.
157 * <p>
158 * Note that {@code DataBuffer} objects created by this constructor
159 * may be incompatible with <a href="#optimizations">performance
160 * optimizations</a> used by some implementations (such as caching
161 * an associated image in video memory).
162 *
163 * @param dataArray The unsigned-short arrays for the <CODE>DataBuffer</CODE>.
164 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
165 */
166 public DataBufferUShort(short dataArray[][], int size) {
167 super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length);
168 if (dataArray == null) {
169 throw new NullPointerException("dataArray is null");
170 }
171 for (int i=0; i < dataArray.length; i++) {
172 if (dataArray[i] == null) {
173 throw new NullPointerException("dataArray["+i+"] is null");
174 }
175 }
176
177 bankdata = (short[][]) dataArray.clone();
178 data = bankdata[0];
179 }
180
181 /**
182 * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with specified arrays,
183 * size, and offsets.
184 * The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
185 * be at least as large as <CODE>size</CODE> + the corresponding offset. There must
186 * be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
187 * bank, only elements <CODE>offset</CODE> through
188 * <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
189 * used by accessors of this <CODE>DataBuffer</CODE>.
190 * <p>
191 * Note that {@code DataBuffer} objects created by this constructor
192 * may be incompatible with <a href="#optimizations">performance
193 * optimizations</a> used by some implementations (such as caching
194 * an associated image in video memory).
195 *
196 * @param dataArray The unsigned-short arrays for the <CODE>DataBuffer</CODE>.
197 * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
198 * @param offsets The offsets into each array.
199 */
200 public DataBufferUShort(short dataArray[][], int size, int offsets[]) {
201 super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length, offsets);
202 if (dataArray == null) {
203 throw new NullPointerException("dataArray is null");
204 }
205 for (int i=0; i < dataArray.length; i++) {
206 if (dataArray[i] == null) {
207 throw new NullPointerException("dataArray["+i+"] is null");
208 }
209 if ((size+offsets[i]) > dataArray[i].length) {
210 throw new IllegalArgumentException("Length of dataArray["+i+
211 "] is less than size+"+
212 "offsets["+i+"].");
213 }
214
215 }
216 bankdata = (short[][]) dataArray.clone();
217 data = bankdata[0];
218 }
219
220 /**
221 * Returns the default (first) unsigned-short data array.
222 * <p>
223 * Note that calling this method may cause this {@code DataBuffer}
224 * object to be incompatible with <a href="#optimizations">performance
225 * optimizations</a> used by some implementations (such as caching
226 * an associated image in video memory).
227 *
228 * @return The first unsigned-short data array.
229 */
230 public short[] getData() {
231 theTrackable.setUntrackable();
232 return data;
233 }
234
235 /**
236 * Returns the data array for the specified bank.
237 * <p>
238 * Note that calling this method may cause this {@code DataBuffer}
239 * object to be incompatible with <a href="#optimizations">performance
240 * optimizations</a> used by some implementations (such as caching
241 * an associated image in video memory).
242 *
243 * @param bank The bank whose data array you want to get.
244 * @return The data array for the specified bank.
245 */
246 public short[] getData(int bank) {
247 theTrackable.setUntrackable();
248 return bankdata[bank];
249 }
250
251 /**
252 * Returns the data arrays for all banks.
253 * <p>
254 * Note that calling this method may cause this {@code DataBuffer}
255 * object to be incompatible with <a href="#optimizations">performance
256 * optimizations</a> used by some implementations (such as caching
257 * an associated image in video memory).
258 *
259 * @return All of the data arrays.
260 */
261 public short[][] getBankData() {
262 theTrackable.setUntrackable();
263 return (short[][]) bankdata.clone();
264 }
265
266 /**
267 * Returns the requested data array element from the first (default) bank.
268 *
269 * @param i The data array element you want to get.
270 * @return The requested data array element as an integer.
271 * @see #setElem(int, int)
272 * @see #setElem(int, int, int)
273 */
274 public int getElem(int i) {
275 return (int)(data[i+offset]&0xffff);
276 }
277
278 /**
279 * Returns the requested data array element from the specified bank.
280 *
281 * @param bank The bank from which you want to get a data array element.
282 * @param i The data array element you want to get.
283 * @return The requested data array element as an integer.
284 * @see #setElem(int, int)
285 * @see #setElem(int, int, int)
286 */
287 public int getElem(int bank, int i) {
288 return (int)(bankdata[bank][i+offsets[bank]]&0xffff);
289 }
290
291 /**
292 * Sets the requested data array element in the first (default) bank
293 * to the specified value.
294 *
295 * @param i The data array element you want to set.
296 * @param val The integer value to which you want to set the data array element.
297 * @see #getElem(int)
298 * @see #getElem(int, int)
299 */
300 public void setElem(int i, int val) {
301 data[i+offset] = (short)(val&0xffff);
302 theTrackable.markDirty();
303 }
304
305 /**
306 * Sets the requested data array element in the specified bank
307 * from the given integer.
308 * @param bank The bank in which you want to set the data array element.
309 * @param i The data array element you want to set.
310 * @param val The integer value to which you want to set the specified data array element.
311 * @see #getElem(int)
312 * @see #getElem(int, int)
313 */
314 public void setElem(int bank, int i, int val) {
315 bankdata[bank][i+offsets[bank]] = (short)(val&0xffff);
316 theTrackable.markDirty();
317 }
318}
java/pkg/java/awt/image/DirectColorModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/DirectColorModel.java+1416−0
@@ -0,0 +1,1416 @@
1/*
2 * Copyright (c) 1995, 2001, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.color.ColorSpace;
29import java.awt.Transparency;
30
31/**
32 * The <code>DirectColorModel</code> class is a <code>ColorModel</code>
33 * class that works with pixel values that represent RGB
34 * color and alpha information as separate samples and that pack all
35 * samples for a single pixel into a single int, short, or byte quantity.
36 * This class can be used only with ColorSpaces of type ColorSpace.TYPE_RGB.
37 * In addition, for each component of the ColorSpace, the minimum
38 * normalized component value obtained via the <code>getMinValue()</code>
39 * method of ColorSpace must be 0.0, and the maximum value obtained via
40 * the <code>getMaxValue()</code> method must be 1.0 (these min/max
41 * values are typical for RGB spaces).
42 * There must be three color samples in the pixel values and there can
43 * be a single alpha sample. For those methods that use a primitive array
44 * pixel representation of type <code>transferType</code>, the array
45 * length is always one. The transfer
46 * types supported are DataBuffer.TYPE_BYTE,
47 * DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT.
48 * Color and alpha samples are stored in the single
49 * element of the array in bits indicated by bit masks. Each bit mask
50 * must be contiguous and masks must not overlap. The same masks apply to
51 * the single int pixel representation used by other methods. The
52 * correspondence of masks and color/alpha samples is as follows:
53 * <ul>
54 * <li> Masks are identified by indices running from 0 through 2
55 * if no alpha is present, or 3 if an alpha is present.
56 * <li> The first three indices refer to color samples;
57 * index 0 corresponds to red, index 1 to green, and index 2 to blue.
58 * <li> Index 3 corresponds to the alpha sample, if present.
59 * </ul>
60 * <p>
61 * The translation from pixel values to color/alpha components for
62 * display or processing purposes is a one-to-one correspondence of
63 * samples to components. A <code>DirectColorModel</code> is
64 * typically used with image data which uses masks to define packed
65 * samples. For example, a <code>DirectColorModel</code> can be used in
66 * conjunction with a <code>SinglePixelPackedSampleModel</code> to
67 * construct a {@link BufferedImage}. Normally the masks used by the
68 * {@link SampleModel} and the <code>ColorModel</code> would be the
69 * same. However, if they are different, the color interpretation
70 * of pixel data will be done according to the masks of the
71 * <code>ColorModel</code>.
72 * <p>
73 * A single int pixel representation is valid for all objects of this
74 * class, since it is always possible to represent pixel values used with
75 * this class in a single int. Therefore, methods which use this
76 * representation will not throw an <code>IllegalArgumentException</code>
77 * due to an invalid pixel value.
78 * <p>
79 * This color model is similar to an X11 TrueColor visual.
80 * The default RGB ColorModel specified by the
81 * {@link ColorModel#getRGBdefault() getRGBdefault} method is a
82 * <code>DirectColorModel</code> with the following parameters:
83 * <pre>
84 * Number of bits: 32
85 * Red mask: 0x00ff0000
86 * Green mask: 0x0000ff00
87 * Blue mask: 0x000000ff
88 * Alpha mask: 0xff000000
89 * Color space: sRGB
90 * isAlphaPremultiplied: False
91 * Transparency: Transparency.TRANSLUCENT
92 * transferType: DataBuffer.TYPE_INT
93 * </pre>
94 * <p>
95 * Many of the methods in this class are final. This is because the
96 * underlying native graphics code makes assumptions about the layout
97 * and operation of this class and those assumptions are reflected in
98 * the implementations of the methods here that are marked final. You
99 * can subclass this class for other reasons, but you cannot override
100 * or modify the behavior of those methods.
101 *
102 * @see ColorModel
103 * @see ColorSpace
104 * @see SinglePixelPackedSampleModel
105 * @see BufferedImage
106 * @see ColorModel#getRGBdefault
107 *
108 */
109public class DirectColorModel extends PackedColorModel {
110 private int red_mask;
111 private int green_mask;
112 private int blue_mask;
113 private int alpha_mask;
114 private int red_offset;
115 private int green_offset;
116 private int blue_offset;
117 private int alpha_offset;
118 private int red_scale;
119 private int green_scale;
120 private int blue_scale;
121 private int alpha_scale;
122 private boolean is_LinearRGB;
123 private int lRGBprecision;
124 private byte[] tosRGB8LUT;
125 private byte[] fromsRGB8LUT8;
126 private short[] fromsRGB8LUT16;
127
128 /**
129 * Constructs a <code>DirectColorModel</code> from the specified masks
130 * that indicate which bits in an <code>int</code> pixel representation
131 * contain the red, green and blue color samples. As pixel values do not
132 * contain alpha information, all pixels are treated as opaque, which
133 * means that alpha&nbsp;=&nbsp;1.0. All of the bits
134 * in each mask must be contiguous and fit in the specified number
135 * of least significant bits of an <code>int</code> pixel representation.
136 * The <code>ColorSpace</code> is the default sRGB space. The
137 * transparency value is Transparency.OPAQUE. The transfer type
138 * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
139 * or DataBuffer.TYPE_INT that can hold a single pixel.
140 * @param bits the number of bits in the pixel values; for example,
141 * the sum of the number of bits in the masks.
142 * @param rmask specifies a mask indicating which bits in an
143 * integer pixel contain the red component
144 * @param gmask specifies a mask indicating which bits in an
145 * integer pixel contain the green component
146 * @param bmask specifies a mask indicating which bits in an
147 * integer pixel contain the blue component
148 *
149 */
150 public DirectColorModel(int bits,
151 int rmask, int gmask, int bmask) {
152 this(bits, rmask, gmask, bmask, 0);
153 }
154
155 /**
156 * Constructs a <code>DirectColorModel</code> from the specified masks
157 * that indicate which bits in an <code>int</code> pixel representation
158 * contain the red, green and blue color samples and the alpha sample,
159 * if present. If <code>amask</code> is 0, pixel values do not contain
160 * alpha information and all pixels are treated as opaque, which means
161 * that alpha&nbsp;=&nbsp;1.0. All of the bits in each mask must
162 * be contiguous and fit in the specified number of least significant bits
163 * of an <code>int</code> pixel representation. Alpha, if present, is not
164 * premultiplied. The <code>ColorSpace</code> is the default sRGB space.
165 * The transparency value is Transparency.OPAQUE if no alpha is
166 * present, or Transparency.TRANSLUCENT otherwise. The transfer type
167 * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
168 * or DataBuffer.TYPE_INT that can hold a single pixel.
169 * @param bits the number of bits in the pixel values; for example,
170 * the sum of the number of bits in the masks.
171 * @param rmask specifies a mask indicating which bits in an
172 * integer pixel contain the red component
173 * @param gmask specifies a mask indicating which bits in an
174 * integer pixel contain the green component
175 * @param bmask specifies a mask indicating which bits in an
176 * integer pixel contain the blue component
177 * @param amask specifies a mask indicating which bits in an
178 * integer pixel contain the alpha component
179 */
180 public DirectColorModel(int bits, int rmask, int gmask,
181 int bmask, int amask) {
182 super (ColorSpace.getInstance(ColorSpace.CS_sRGB),
183 bits, rmask, gmask, bmask, amask, false,
184 amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
185 ColorModel.getDefaultTransferType(bits));
186 setFields();
187 }
188
189 /**
190 * Constructs a <code>DirectColorModel</code> from the specified
191 * parameters. Color components are in the specified
192 * <code>ColorSpace</code>, which must be of type ColorSpace.TYPE_RGB
193 * and have minimum normalized component values which are all 0.0
194 * and maximum values which are all 1.0.
195 * The masks specify which bits in an <code>int</code> pixel
196 * representation contain the red, green and blue color samples and
197 * the alpha sample, if present. If <code>amask</code> is 0, pixel
198 * values do not contain alpha information and all pixels are treated
199 * as opaque, which means that alpha&nbsp;=&nbsp;1.0. All of the
200 * bits in each mask must be contiguous and fit in the specified number
201 * of least significant bits of an <code>int</code> pixel
202 * representation. If there is alpha, the <code>boolean</code>
203 * <code>isAlphaPremultiplied</code> specifies how to interpret
204 * color and alpha samples in pixel values. If the <code>boolean</code>
205 * is <code>true</code>, color samples are assumed to have been
206 * multiplied by the alpha sample. The transparency value is
207 * Transparency.OPAQUE, if no alpha is present, or
208 * Transparency.TRANSLUCENT otherwise. The transfer type
209 * is the type of primitive array used to represent pixel values and
210 * must be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or
211 * DataBuffer.TYPE_INT.
212 * @param space the specified <code>ColorSpace</code>
213 * @param bits the number of bits in the pixel values; for example,
214 * the sum of the number of bits in the masks.
215 * @param rmask specifies a mask indicating which bits in an
216 * integer pixel contain the red component
217 * @param gmask specifies a mask indicating which bits in an
218 * integer pixel contain the green component
219 * @param bmask specifies a mask indicating which bits in an
220 * integer pixel contain the blue component
221 * @param amask specifies a mask indicating which bits in an
222 * integer pixel contain the alpha component
223 * @param isAlphaPremultiplied <code>true</code> if color samples are
224 * premultiplied by the alpha sample; <code>false</code> otherwise
225 * @param transferType the type of array used to represent pixel values
226 * @throws IllegalArgumentException if <code>space</code> is not a
227 * TYPE_RGB space or if the min/max normalized component
228 * values are not 0.0/1.0.
229 */
230 public DirectColorModel(ColorSpace space, int bits, int rmask,
231 int gmask, int bmask, int amask,
232 boolean isAlphaPremultiplied,
233 int transferType) {
234 super (space, bits, rmask, gmask, bmask, amask,
235 isAlphaPremultiplied,
236 amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
237 transferType);
238 if (ColorModel.isLinearRGBspace(colorSpace)) {
239 is_LinearRGB = true;
240 if (maxBits <= 8) {
241 lRGBprecision = 8;
242 tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
243 fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
244 } else {
245 lRGBprecision = 16;
246 tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
247 fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
248 }
249 } else if (!is_sRGB) {
250 for (int i = 0; i < 3; i++) {
251 // super constructor checks that space is TYPE_RGB
252 // check here that min/max are all 0.0/1.0
253 if ((space.getMinValue(i) != 0.0f) ||
254 (space.getMaxValue(i) != 1.0f)) {
255 throw new IllegalArgumentException(
256 "Illegal min/max RGB component value");
257 }
258 }
259 }
260 setFields();
261 }
262
263 /**
264 * Returns the mask indicating which bits in an <code>int</code> pixel
265 * representation contain the red color component.
266 * @return the mask, which indicates which bits of the <code>int</code>
267 * pixel representation contain the red color sample.
268 */
269 final public int getRedMask() {
270 return maskArray[0];
271 }
272
273 /**
274 * Returns the mask indicating which bits in an <code>int</code> pixel
275 * representation contain the green color component.
276 * @return the mask, which indicates which bits of the <code>int</code>
277 * pixel representation contain the green color sample.
278 */
279 final public int getGreenMask() {
280 return maskArray[1];
281 }
282
283 /**
284 * Returns the mask indicating which bits in an <code>int</code> pixel
285 * representation contain the blue color component.
286 * @return the mask, which indicates which bits of the <code>int</code>
287 * pixel representation contain the blue color sample.
288 */
289 final public int getBlueMask() {
290 return maskArray[2];
291 }
292
293 /**
294 * Returns the mask indicating which bits in an <code>int</code> pixel
295 * representation contain the alpha component.
296 * @return the mask, which indicates which bits of the <code>int</code>
297 * pixel representation contain the alpha sample.
298 */
299 final public int getAlphaMask() {
300 if (supportsAlpha) {
301 return maskArray[3];
302 } else {
303 return 0;
304 }
305 }
306
307
308 /*
309 * Given an int pixel in this ColorModel's ColorSpace, converts
310 * it to the default sRGB ColorSpace and returns the R, G, and B
311 * components as float values between 0.0 and 1.0.
312 */
313 private float[] getDefaultRGBComponents(int pixel) {
314 int components[] = getComponents(pixel, null, 0);
315 float norm[] = getNormalizedComponents(components, 0, null, 0);
316 // Note that getNormalizedComponents returns non-premultiplied values
317 return colorSpace.toRGB(norm);
318 }
319
320
321 private int getsRGBComponentFromsRGB(int pixel, int idx) {
322 int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
323 if (isAlphaPremultiplied) {
324 int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
325 c = (a == 0) ? 0 :
326 (int) (((c * scaleFactors[idx]) * 255.0f /
327 (a * scaleFactors[3])) + 0.5f);
328 } else if (scaleFactors[idx] != 1.0f) {
329 c = (int) ((c * scaleFactors[idx]) + 0.5f);
330 }
331 return c;
332 }
333
334
335 private int getsRGBComponentFromLinearRGB(int pixel, int idx) {
336 int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
337 if (isAlphaPremultiplied) {
338 float factor = (float) ((1 << lRGBprecision) - 1);
339 int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
340 c = (a == 0) ? 0 :
341 (int) (((c * scaleFactors[idx]) * factor /
342 (a * scaleFactors[3])) + 0.5f);
343 } else if (nBits[idx] != lRGBprecision) {
344 if (lRGBprecision == 16) {
345 c = (int) ((c * scaleFactors[idx] * 257.0f) + 0.5f);
346 } else {
347 c = (int) ((c * scaleFactors[idx]) + 0.5f);
348 }
349 }
350 // now range of c is 0-255 or 0-65535, depending on lRGBprecision
351 return tosRGB8LUT[c] & 0xff;
352 }
353
354
355 /**
356 * Returns the red color component for the specified pixel, scaled
357 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
358 * color conversion is done if necessary. The pixel value is specified
359 * as an <code>int</code>.
360 * The returned value is a non pre-multiplied value. Thus, if the
361 * alpha is premultiplied, this method divides it out before returning
362 * the value. If the alpha value is 0, for example, the red value
363 * is 0.
364 * @param pixel the specified pixel
365 * @return the red color component for the specified pixel, from
366 * 0 to 255 in the sRGB <code>ColorSpace</code>.
367 */
368 final public int getRed(int pixel) {
369 if (is_sRGB) {
370 return getsRGBComponentFromsRGB(pixel, 0);
371 } else if (is_LinearRGB) {
372 return getsRGBComponentFromLinearRGB(pixel, 0);
373 }
374 float rgb[] = getDefaultRGBComponents(pixel);
375 return (int) (rgb[0] * 255.0f + 0.5f);
376 }
377
378 /**
379 * Returns the green color component for the specified pixel, scaled
380 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
381 * color conversion is done if necessary. The pixel value is specified
382 * as an <code>int</code>.
383 * The returned value is a non pre-multiplied value. Thus, if the
384 * alpha is premultiplied, this method divides it out before returning
385 * the value. If the alpha value is 0, for example, the green value
386 * is 0.
387 * @param pixel the specified pixel
388 * @return the green color component for the specified pixel, from
389 * 0 to 255 in the sRGB <code>ColorSpace</code>.
390 */
391 final public int getGreen(int pixel) {
392 if (is_sRGB) {
393 return getsRGBComponentFromsRGB(pixel, 1);
394 } else if (is_LinearRGB) {
395 return getsRGBComponentFromLinearRGB(pixel, 1);
396 }
397 float rgb[] = getDefaultRGBComponents(pixel);
398 return (int) (rgb[1] * 255.0f + 0.5f);
399 }
400
401 /**
402 * Returns the blue color component for the specified pixel, scaled
403 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
404 * color conversion is done if necessary. The pixel value is specified
405 * as an <code>int</code>.
406 * The returned value is a non pre-multiplied value. Thus, if the
407 * alpha is premultiplied, this method divides it out before returning
408 * the value. If the alpha value is 0, for example, the blue value
409 * is 0.
410 * @param pixel the specified pixel
411 * @return the blue color component for the specified pixel, from
412 * 0 to 255 in the sRGB <code>ColorSpace</code>.
413 */
414 final public int getBlue(int pixel) {
415 if (is_sRGB) {
416 return getsRGBComponentFromsRGB(pixel, 2);
417 } else if (is_LinearRGB) {
418 return getsRGBComponentFromLinearRGB(pixel, 2);
419 }
420 float rgb[] = getDefaultRGBComponents(pixel);
421 return (int) (rgb[2] * 255.0f + 0.5f);
422 }
423
424 /**
425 * Returns the alpha component for the specified pixel, scaled
426 * from 0 to 255. The pixel value is specified as an <code>int</code>.
427 * @param pixel the specified pixel
428 * @return the value of the alpha component of <code>pixel</code>
429 * from 0 to 255.
430 */
431 final public int getAlpha(int pixel) {
432 if (!supportsAlpha) return 255;
433 int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
434 if (scaleFactors[3] != 1.0f) {
435 a = (int)(a * scaleFactors[3] + 0.5f);
436 }
437 return a;
438 }
439
440 /**
441 * Returns the color/alpha components of the pixel in the default
442 * RGB color model format. A color conversion is done if necessary.
443 * The pixel value is specified as an <code>int</code>.
444 * The returned value is in a non pre-multiplied format. Thus, if
445 * the alpha is premultiplied, this method divides it out of the
446 * color components. If the alpha value is 0, for example, the color
447 * values are each 0.
448 * @param pixel the specified pixel
449 * @return the RGB value of the color/alpha components of the specified
450 * pixel.
451 * @see ColorModel#getRGBdefault
452 */
453 final public int getRGB(int pixel) {
454 if (is_sRGB || is_LinearRGB) {
455 return (getAlpha(pixel) << 24)
456 | (getRed(pixel) << 16)
457 | (getGreen(pixel) << 8)
458 | (getBlue(pixel) << 0);
459 }
460 float rgb[] = getDefaultRGBComponents(pixel);
461 return (getAlpha(pixel) << 24)
462 | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
463 | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
464 | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
465 }
466
467 /**
468 * Returns the red color component for the specified pixel, scaled
469 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
470 * color conversion is done if necessary. The pixel value is specified
471 * by an array of data elements of type <code>transferType</code> passed
472 * in as an object reference.
473 * The returned value is a non pre-multiplied value. Thus, if the
474 * alpha is premultiplied, this method divides it out before returning
475 * the value. If the alpha value is 0, for example, the red value
476 * is 0.
477 * If <code>inData</code> is not a primitive array of type
478 * <code>transferType</code>, a <code>ClassCastException</code> is
479 * thrown. An <code>ArrayIndexOutOfBoundsException</code> is
480 * thrown if <code>inData</code> is not large enough to hold a
481 * pixel value for this <code>ColorModel</code>. Since
482 * <code>DirectColorModel</code> can be subclassed, subclasses inherit
483 * the implementation of this method and if they don't override it
484 * then they throw an exception if they use an unsupported
485 * <code>transferType</code>.
486 * An <code>UnsupportedOperationException</code> is thrown if this
487 * <code>transferType</code> is not supported by this
488 * <code>ColorModel</code>.
489 * @param inData the array containing the pixel value
490 * @return the value of the red component of the specified pixel.
491 * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
492 * large enough to hold a pixel value for this color model
493 * @throws ClassCastException if <code>inData</code> is not a
494 * primitive array of type <code>transferType</code>
495 * @throws UnsupportedOperationException if this <code>transferType</code>
496 * is not supported by this color model
497 */
498 public int getRed(Object inData) {
499 int pixel=0;
500 switch (transferType) {
501 case DataBuffer.TYPE_BYTE:
502 byte bdata[] = (byte[])inData;
503 pixel = bdata[0] & 0xff;
504 break;
505 case DataBuffer.TYPE_USHORT:
506 short sdata[] = (short[])inData;
507 pixel = sdata[0] & 0xffff;
508 break;
509 case DataBuffer.TYPE_INT:
510 int idata[] = (int[])inData;
511 pixel = idata[0];
512 break;
513 default:
514 throw new UnsupportedOperationException("This method has not been "+
515 "implemented for transferType " + transferType);
516 }
517 return getRed(pixel);
518 }
519
520
521 /**
522 * Returns the green color component for the specified pixel, scaled
523 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
524 * color conversion is done if necessary. The pixel value is specified
525 * by an array of data elements of type <code>transferType</code> passed
526 * in as an object reference.
527 * The returned value is a non pre-multiplied value. Thus, if the
528 * alpha is premultiplied, this method divides it out before returning
529 * the value. If the alpha value is 0, for example, the green value
530 * is 0. If <code>inData</code> is not a primitive array of type
531 * <code>transferType</code>, a <code>ClassCastException</code> is thrown.
532 * An <code>ArrayIndexOutOfBoundsException</code> is
533 * thrown if <code>inData</code> is not large enough to hold a pixel
534 * value for this <code>ColorModel</code>. Since
535 * <code>DirectColorModel</code> can be subclassed, subclasses inherit
536 * the implementation of this method and if they don't override it
537 * then they throw an exception if they use an unsupported
538 * <code>transferType</code>.
539 * An <code>UnsupportedOperationException</code> is
540 * thrown if this <code>transferType</code> is not supported by this
541 * <code>ColorModel</code>.
542 * @param inData the array containing the pixel value
543 * @return the value of the green component of the specified pixel.
544 * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
545 * large enough to hold a pixel value for this color model
546 * @throws ClassCastException if <code>inData</code> is not a
547 * primitive array of type <code>transferType</code>
548 * @throws UnsupportedOperationException if this <code>transferType</code>
549 * is not supported by this color model
550 */
551 public int getGreen(Object inData) {
552 int pixel=0;
553 switch (transferType) {
554 case DataBuffer.TYPE_BYTE:
555 byte bdata[] = (byte[])inData;
556 pixel = bdata[0] & 0xff;
557 break;
558 case DataBuffer.TYPE_USHORT:
559 short sdata[] = (short[])inData;
560 pixel = sdata[0] & 0xffff;
561 break;
562 case DataBuffer.TYPE_INT:
563 int idata[] = (int[])inData;
564 pixel = idata[0];
565 break;
566 default:
567 throw new UnsupportedOperationException("This method has not been "+
568 "implemented for transferType " + transferType);
569 }
570 return getGreen(pixel);
571 }
572
573
574 /**
575 * Returns the blue color component for the specified pixel, scaled
576 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
577 * color conversion is done if necessary. The pixel value is specified
578 * by an array of data elements of type <code>transferType</code> passed
579 * in as an object reference.
580 * The returned value is a non pre-multiplied value. Thus, if the
581 * alpha is premultiplied, this method divides it out before returning
582 * the value. If the alpha value is 0, for example, the blue value
583 * is 0. If <code>inData</code> is not a primitive array of type
584 * <code>transferType</code>, a <code>ClassCastException</code> is thrown.
585 * An <code>ArrayIndexOutOfBoundsException</code> is
586 * thrown if <code>inData</code> is not large enough to hold a pixel
587 * value for this <code>ColorModel</code>. Since
588 * <code>DirectColorModel</code> can be subclassed, subclasses inherit
589 * the implementation of this method and if they don't override it
590 * then they throw an exception if they use an unsupported
591 * <code>transferType</code>.
592 * An <code>UnsupportedOperationException</code> is
593 * thrown if this <code>transferType</code> is not supported by this
594 * <code>ColorModel</code>.
595 * @param inData the array containing the pixel value
596 * @return the value of the blue component of the specified pixel.
597 * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
598 * large enough to hold a pixel value for this color model
599 * @throws ClassCastException if <code>inData</code> is not a
600 * primitive array of type <code>transferType</code>
601 * @throws UnsupportedOperationException if this <code>transferType</code>
602 * is not supported by this color model
603 */
604 public int getBlue(Object inData) {
605 int pixel=0;
606 switch (transferType) {
607 case DataBuffer.TYPE_BYTE:
608 byte bdata[] = (byte[])inData;
609 pixel = bdata[0] & 0xff;
610 break;
611 case DataBuffer.TYPE_USHORT:
612 short sdata[] = (short[])inData;
613 pixel = sdata[0] & 0xffff;
614 break;
615 case DataBuffer.TYPE_INT:
616 int idata[] = (int[])inData;
617 pixel = idata[0];
618 break;
619 default:
620 throw new UnsupportedOperationException("This method has not been "+
621 "implemented for transferType " + transferType);
622 }
623 return getBlue(pixel);
624 }
625
626 /**
627 * Returns the alpha component for the specified pixel, scaled
628 * from 0 to 255. The pixel value is specified by an array of data
629 * elements of type <code>transferType</code> passed in as an object
630 * reference.
631 * If <code>inData</code> is not a primitive array of type
632 * <code>transferType</code>, a <code>ClassCastException</code> is
633 * thrown. An <code>ArrayIndexOutOfBoundsException</code> is
634 * thrown if <code>inData</code> is not large enough to hold a pixel
635 * value for this <code>ColorModel</code>. Since
636 * <code>DirectColorModel</code> can be subclassed, subclasses inherit
637 * the implementation of this method and if they don't override it
638 * then they throw an exception if they use an unsupported
639 * <code>transferType</code>.
640 * If this <code>transferType</code> is not supported, an
641 * <code>UnsupportedOperationException</code> is thrown.
642 * @param inData the specified pixel
643 * @return the alpha component of the specified pixel, scaled from
644 * 0 to 255.
645 * @exception <code>ClassCastException</code> if <code>inData</code>
646 * is not a primitive array of type <code>transferType</code>
647 * @exception <code>ArrayIndexOutOfBoundsException</code> if
648 * <code>inData</code> is not large enough to hold a pixel value
649 * for this <code>ColorModel</code>
650 * @exception <code>UnsupportedOperationException</code> if this
651 * <code>tranferType</code> is not supported by this
652 * <code>ColorModel</code>
653 */
654 public int getAlpha(Object inData) {
655 int pixel=0;
656 switch (transferType) {
657 case DataBuffer.TYPE_BYTE:
658 byte bdata[] = (byte[])inData;
659 pixel = bdata[0] & 0xff;
660 break;
661 case DataBuffer.TYPE_USHORT:
662 short sdata[] = (short[])inData;
663 pixel = sdata[0] & 0xffff;
664 break;
665 case DataBuffer.TYPE_INT:
666 int idata[] = (int[])inData;
667 pixel = idata[0];
668 break;
669 default:
670 throw new UnsupportedOperationException("This method has not been "+
671 "implemented for transferType " + transferType);
672 }
673 return getAlpha(pixel);
674 }
675
676 /**
677 * Returns the color/alpha components for the specified pixel in the
678 * default RGB color model format. A color conversion is done if
679 * necessary. The pixel value is specified by an array of data
680 * elements of type <code>transferType</code> passed in as an object
681 * reference. If <code>inData</code> is not a primitive array of type
682 * <code>transferType</code>, a <code>ClassCastException</code> is
683 * thrown. An <code>ArrayIndexOutOfBoundsException</code> is
684 * thrown if <code>inData</code> is not large enough to hold a pixel
685 * value for this <code>ColorModel</code>.
686 * The returned value is in a non pre-multiplied format. Thus, if
687 * the alpha is premultiplied, this method divides it out of the
688 * color components. If the alpha value is 0, for example, the color
689 * values is 0. Since <code>DirectColorModel</code> can be
690 * subclassed, subclasses inherit the implementation of this method
691 * and if they don't override it then
692 * they throw an exception if they use an unsupported
693 * <code>transferType</code>.
694 *
695 * @param inData the specified pixel
696 * @return the color and alpha components of the specified pixel.
697 * @exception UnsupportedOperationException if this
698 * <code>transferType</code> is not supported by this
699 * <code>ColorModel</code>
700 * @see ColorModel#getRGBdefault
701 */
702 public int getRGB(Object inData) {
703 int pixel=0;
704 switch (transferType) {
705 case DataBuffer.TYPE_BYTE:
706 byte bdata[] = (byte[])inData;
707 pixel = bdata[0] & 0xff;
708 break;
709 case DataBuffer.TYPE_USHORT:
710 short sdata[] = (short[])inData;
711 pixel = sdata[0] & 0xffff;
712 break;
713 case DataBuffer.TYPE_INT:
714 int idata[] = (int[])inData;
715 pixel = idata[0];
716 break;
717 default:
718 throw new UnsupportedOperationException("This method has not been "+
719 "implemented for transferType " + transferType);
720 }
721 return getRGB(pixel);
722 }
723
724 /**
725 * Returns a data element array representation of a pixel in this
726 * <code>ColorModel</code>, given an integer pixel representation in the
727 * default RGB color model.
728 * This array can then be passed to the <code>setDataElements</code>
729 * method of a <code>WritableRaster</code> object. If the pixel variable
730 * is <code>null</code>, a new array is allocated. If <code>pixel</code>
731 * is not <code>null</code>, it must be a primitive array of type
732 * <code>transferType</code>; otherwise, a
733 * <code>ClassCastException</code> is thrown. An
734 * <code>ArrayIndexOutOfBoundsException</code> is
735 * thrown if <code>pixel</code> is not large enough to hold a pixel
736 * value for this <code>ColorModel</code>. The pixel array is returned.
737 * Since <code>DirectColorModel</code> can be subclassed, subclasses
738 * inherit the implementation of this method and if they don't
739 * override it then they throw an exception if they use an unsupported
740 * <code>transferType</code>.
741 *
742 * @param rgb the integer pixel representation in the default RGB
743 * color model
744 * @param pixel the specified pixel
745 * @return an array representation of the specified pixel in this
746 * <code>ColorModel</code>
747 * @exception ClassCastException if <code>pixel</code>
748 * is not a primitive array of type <code>transferType</code>
749 * @exception ArrayIndexOutOfBoundsException if
750 * <code>pixel</code> is not large enough to hold a pixel value
751 * for this <code>ColorModel</code>
752 * @exception UnsupportedOperationException if this
753 * <code>transferType</code> is not supported by this
754 * <code>ColorModel</code>
755 * @see WritableRaster#setDataElements
756 * @see SampleModel#setDataElements
757 */
758 public Object getDataElements(int rgb, Object pixel) {
759 //REMIND: maybe more efficient not to use int array for
760 //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
761 int intpixel[] = null;
762 if (transferType == DataBuffer.TYPE_INT &&
763 pixel != null) {
764 intpixel = (int[])pixel;
765 intpixel[0] = 0;
766 } else {
767 intpixel = new int[1];
768 }
769
770 ColorModel defaultCM = ColorModel.getRGBdefault();
771 if (this == defaultCM || equals(defaultCM)) {
772 intpixel[0] = rgb;
773 return intpixel;
774 }
775
776 int red, grn, blu, alp;
777 red = (rgb>>16) & 0xff;
778 grn = (rgb>>8) & 0xff;
779 blu = rgb & 0xff;
780 if (is_sRGB || is_LinearRGB) {
781 int precision;
782 float factor;
783 if (is_LinearRGB) {
784 if (lRGBprecision == 8) {
785 red = fromsRGB8LUT8[red] & 0xff;
786 grn = fromsRGB8LUT8[grn] & 0xff;
787 blu = fromsRGB8LUT8[blu] & 0xff;
788 precision = 8;
789 factor = 1.0f / 255.0f;
790 } else {
791 red = fromsRGB8LUT16[red] & 0xffff;
792 grn = fromsRGB8LUT16[grn] & 0xffff;
793 blu = fromsRGB8LUT16[blu] & 0xffff;
794 precision = 16;
795 factor = 1.0f / 65535.0f;
796 }
797 } else {
798 precision = 8;
799 factor = 1.0f / 255.0f;
800 }
801 if (supportsAlpha) {
802 alp = (rgb>>24) & 0xff;
803 if (isAlphaPremultiplied) {
804 factor *= (alp * (1.0f / 255.0f));
805 precision = -1; // force component calculations below
806 }
807 if (nBits[3] != 8) {
808 alp = (int)
809 ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
810 if (alp > ((1<<nBits[3]) - 1)) {
811 // fix 4412670 - see comment below
812 alp = (1<<nBits[3]) - 1;
813 }
814 }
815 intpixel[0] = alp << maskOffsets[3];
816 }
817 if (nBits[0] != precision) {
818 red = (int) ((red * factor * ((1<<nBits[0]) - 1)) + 0.5f);
819 }
820 if (nBits[1] != precision) {
821 grn = (int) ((grn * factor * ((1<<nBits[1]) - 1)) + 0.5f);
822 }
823 if (nBits[2] != precision) {
824 blu = (int) ((blu * factor * ((1<<nBits[2]) - 1)) + 0.5f);
825 }
826 } else {
827 // Need to convert the color
828 float[] norm = new float[3];
829 float factor = 1.0f / 255.0f;
830 norm[0] = red * factor;
831 norm[1] = grn * factor;
832 norm[2] = blu * factor;
833 norm = colorSpace.fromRGB(norm);
834 if (supportsAlpha) {
835 alp = (rgb>>24) & 0xff;
836 if (isAlphaPremultiplied) {
837 factor *= alp;
838 for (int i = 0; i < 3; i++) {
839 norm[i] *= factor;
840 }
841 }
842 if (nBits[3] != 8) {
843 alp = (int)
844 ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
845 if (alp > ((1<<nBits[3]) - 1)) {
846 // fix 4412670 - see comment below
847 alp = (1<<nBits[3]) - 1;
848 }
849 }
850 intpixel[0] = alp << maskOffsets[3];
851 }
852 red = (int) ((norm[0] * ((1<<nBits[0]) - 1)) + 0.5f);
853 grn = (int) ((norm[1] * ((1<<nBits[1]) - 1)) + 0.5f);
854 blu = (int) ((norm[2] * ((1<<nBits[2]) - 1)) + 0.5f);
855 }
856
857 if (maxBits > 23) {
858 // fix 4412670 - for components of 24 or more bits
859 // some calculations done above with float precision
860 // may lose enough precision that the integer result
861 // overflows nBits, so we need to clamp.
862 if (red > ((1<<nBits[0]) - 1)) {
863 red = (1<<nBits[0]) - 1;
864 }
865 if (grn > ((1<<nBits[1]) - 1)) {
866 grn = (1<<nBits[1]) - 1;
867 }
868 if (blu > ((1<<nBits[2]) - 1)) {
869 blu = (1<<nBits[2]) - 1;
870 }
871 }
872
873 intpixel[0] |= (red << maskOffsets[0]) |
874 (grn << maskOffsets[1]) |
875 (blu << maskOffsets[2]);
876
877 switch (transferType) {
878 case DataBuffer.TYPE_BYTE: {
879 byte bdata[];
880 if (pixel == null) {
881 bdata = new byte[1];
882 } else {
883 bdata = (byte[])pixel;
884 }
885 bdata[0] = (byte)(0xff&intpixel[0]);
886 return bdata;
887 }
888 case DataBuffer.TYPE_USHORT:{
889 short sdata[];
890 if (pixel == null) {
891 sdata = new short[1];
892 } else {
893 sdata = (short[])pixel;
894 }
895 sdata[0] = (short)(intpixel[0]&0xffff);
896 return sdata;
897 }
898 case DataBuffer.TYPE_INT:
899 return intpixel;
900 }
901 throw new UnsupportedOperationException("This method has not been "+
902 "implemented for transferType " + transferType);
903
904 }
905
906 /**
907 * Returns an array of unnormalized color/alpha components given a pixel
908 * in this <code>ColorModel</code>. The pixel value is specified as an
909 * <code>int</code>. If the <code>components</code> array is
910 * <code>null</code>, a new array is allocated. The
911 * <code>components</code> array is returned. Color/alpha components are
912 * stored in the <code>components</code> array starting at
913 * <code>offset</code>, even if the array is allocated by this method.
914 * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
915 * <code>components</code> array is not <code>null</code> and is not large
916 * enough to hold all the color and alpha components, starting at
917 * <code>offset</code>.
918 * @param pixel the specified pixel
919 * @param components the array to receive the color and alpha
920 * components of the specified pixel
921 * @param offset the offset into the <code>components</code> array at
922 * which to start storing the color and alpha components
923 * @return an array containing the color and alpha components of the
924 * specified pixel starting at the specified offset.
925 */
926 final public int[] getComponents(int pixel, int[] components, int offset) {
927 if (components == null) {
928 components = new int[offset+numComponents];
929 }
930
931 for (int i=0; i < numComponents; i++) {
932 components[offset+i] = (pixel & maskArray[i]) >>> maskOffsets[i];
933 }
934
935 return components;
936 }
937
938 /**
939 * Returns an array of unnormalized color/alpha components given a pixel
940 * in this <code>ColorModel</code>. The pixel value is specified by an
941 * array of data elements of type <code>transferType</code> passed in as
942 * an object reference. If <code>pixel</code> is not a primitive array
943 * of type <code>transferType</code>, a <code>ClassCastException</code>
944 * is thrown. An <code>ArrayIndexOutOfBoundsException</code> is
945 * thrown if <code>pixel</code> is not large enough to hold a
946 * pixel value for this <code>ColorModel</code>. If the
947 * <code>components</code> array is <code>null</code>, a new
948 * array is allocated. The <code>components</code> array is returned.
949 * Color/alpha components are stored in the <code>components</code> array
950 * starting at <code>offset</code>, even if the array is allocated by
951 * this method. An <code>ArrayIndexOutOfBoundsException</code>
952 * is thrown if the <code>components</code> array is not
953 * <code>null</code> and is not large enough to hold all the color and
954 * alpha components, starting at <code>offset</code>.
955 * Since <code>DirectColorModel</code> can be subclassed, subclasses
956 * inherit the implementation of this method and if they don't
957 * override it then they throw an exception if they use an unsupported
958 * <code>transferType</code>.
959 * @param pixel the specified pixel
960 * @param components the array to receive the color and alpha
961 * components of the specified pixel
962 * @param offset the offset into the <code>components</code> array at
963 * which to start storing the color and alpha components
964 * @return an array containing the color and alpha components of the
965 * specified pixel starting at the specified offset.
966 * @exception ClassCastException if <code>pixel</code>
967 * is not a primitive array of type <code>transferType</code>
968 * @exception ArrayIndexOutOfBoundsException if
969 * <code>pixel</code> is not large enough to hold a pixel value
970 * for this <code>ColorModel</code>, or if <code>components</code>
971 * is not <code>null</code> and is not large enough to hold all the
972 * color and alpha components, starting at <code>offset</code>
973 * @exception UnsupportedOperationException if this
974 * <code>transferType</code> is not supported by this
975 * color model
976 */
977 final public int[] getComponents(Object pixel, int[] components,
978 int offset) {
979 int intpixel=0;
980 switch (transferType) {
981 case DataBuffer.TYPE_BYTE:
982 byte bdata[] = (byte[])pixel;
983 intpixel = bdata[0] & 0xff;
984 break;
985 case DataBuffer.TYPE_USHORT:
986 short sdata[] = (short[])pixel;
987 intpixel = sdata[0] & 0xffff;
988 break;
989 case DataBuffer.TYPE_INT:
990 int idata[] = (int[])pixel;
991 intpixel = idata[0];
992 break;
993 default:
994 throw new UnsupportedOperationException("This method has not been "+
995 "implemented for transferType " + transferType);
996 }
997 return getComponents(intpixel, components, offset);
998 }
999
1000 /**
1001 * Creates a <code>WritableRaster</code> with the specified width and
1002 * height that has a data layout (<code>SampleModel</code>) compatible
1003 * with this <code>ColorModel</code>.
1004 * @param w the width to apply to the new <code>WritableRaster</code>
1005 * @param h the height to apply to the new <code>WritableRaster</code>
1006 * @return a <code>WritableRaster</code> object with the specified
1007 * width and height.
1008 * @throws IllegalArgumentException if <code>w</code> or <code>h</code>
1009 * is less than or equal to zero
1010 * @see WritableRaster
1011 * @see SampleModel
1012 */
1013 final public WritableRaster createCompatibleWritableRaster (int w,
1014 int h) {
1015 if ((w <= 0) || (h <= 0)) {
1016 throw new IllegalArgumentException("Width (" + w + ") and height (" + h +
1017 ") cannot be <= 0");
1018 }
1019 int[] bandmasks;
1020 if (supportsAlpha) {
1021 bandmasks = new int[4];
1022 bandmasks[3] = alpha_mask;
1023 }
1024 else {
1025 bandmasks = new int[3];
1026 }
1027 bandmasks[0] = red_mask;
1028 bandmasks[1] = green_mask;
1029 bandmasks[2] = blue_mask;
1030
1031 if (pixel_bits > 16) {
1032 return Raster.createPackedRaster(DataBuffer.TYPE_INT,
1033 w,h,bandmasks,null);
1034 }
1035 else if (pixel_bits > 8) {
1036 return Raster.createPackedRaster(DataBuffer.TYPE_USHORT,
1037 w,h,bandmasks,null);
1038 }
1039 else {
1040 return Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
1041 w,h,bandmasks,null);
1042 }
1043 }
1044
1045 /**
1046 * Returns a pixel value represented as an <code>int</code> in this
1047 * <code>ColorModel</code>, given an array of unnormalized color/alpha
1048 * components. An <code>ArrayIndexOutOfBoundsException</code> is
1049 * thrown if the <code>components</code> array is
1050 * not large enough to hold all the color and alpha components, starting
1051 * at <code>offset</code>.
1052 * @param components an array of unnormalized color and alpha
1053 * components
1054 * @param offset the index into <code>components</code> at which to
1055 * begin retrieving the color and alpha components
1056 * @return an <code>int</code> pixel value in this
1057 * <code>ColorModel</code> corresponding to the specified components.
1058 * @exception <code>ArrayIndexOutOfBoundsException</code> if
1059 * the <code>components</code> array is not large enough to
1060 * hold all of the color and alpha components starting at
1061 * <code>offset</code>
1062 */
1063 public int getDataElement(int[] components, int offset) {
1064 int pixel = 0;
1065 for (int i=0; i < numComponents; i++) {
1066 pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
1067 }
1068 return pixel;
1069 }
1070
1071 /**
1072 * Returns a data element array representation of a pixel in this
1073 * <code>ColorModel</code>, given an array of unnormalized color/alpha
1074 * components.
1075 * This array can then be passed to the <code>setDataElements</code>
1076 * method of a <code>WritableRaster</code> object.
1077 * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1078 * <code>components</code> array
1079 * is not large enough to hold all the color and alpha components,
1080 * starting at offset. If the <code>obj</code> variable is
1081 * <code>null</code>, a new array is allocated. If <code>obj</code> is
1082 * not <code>null</code>, it must be a primitive array
1083 * of type <code>transferType</code>; otherwise, a
1084 * <code>ClassCastException</code> is thrown.
1085 * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
1086 * <code>obj</code> is not large enough to hold a pixel value for this
1087 * <code>ColorModel</code>.
1088 * Since <code>DirectColorModel</code> can be subclassed, subclasses
1089 * inherit the implementation of this method and if they don't
1090 * override it then they throw an exception if they use an unsupported
1091 * <code>transferType</code>.
1092 * @param components an array of unnormalized color and alpha
1093 * components
1094 * @param offset the index into <code>components</code> at which to
1095 * begin retrieving color and alpha components
1096 * @param obj the <code>Object</code> representing an array of color
1097 * and alpha components
1098 * @return an <code>Object</code> representing an array of color and
1099 * alpha components.
1100 * @exception <code>ClassCastException</code> if <code>obj</code>
1101 * is not a primitive array of type <code>transferType</code>
1102 * @exception <code>ArrayIndexOutOfBoundsException</code> if
1103 * <code>obj</code> is not large enough to hold a pixel value
1104 * for this <code>ColorModel</code> or the <code>components</code>
1105 * array is not large enough to hold all of the color and alpha
1106 * components starting at <code>offset</code>
1107 * @exception UnsupportedOperationException if this
1108 * <code>transferType</code> is not supported by this
1109 * color model
1110 * @see WritableRaster#setDataElements
1111 * @see SampleModel#setDataElements
1112 */
1113 public Object getDataElements(int[] components, int offset, Object obj) {
1114 int pixel = 0;
1115 for (int i=0; i < numComponents; i++) {
1116 pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
1117 }
1118 switch (transferType) {
1119 case DataBuffer.TYPE_BYTE:
1120 if (obj instanceof byte[]) {
1121 byte bdata[] = (byte[])obj;
1122 bdata[0] = (byte)(pixel&0xff);
1123 return bdata;
1124 } else {
1125 byte bdata[] = {(byte)(pixel&0xff)};
1126 return bdata;
1127 }
1128 case DataBuffer.TYPE_USHORT:
1129 if (obj instanceof short[]) {
1130 short sdata[] = (short[])obj;
1131 sdata[0] = (short)(pixel&0xffff);
1132 return sdata;
1133 } else {
1134 short sdata[] = {(short)(pixel&0xffff)};
1135 return sdata;
1136 }
1137 case DataBuffer.TYPE_INT:
1138 if (obj instanceof int[]) {
1139 int idata[] = (int[])obj;
1140 idata[0] = pixel;
1141 return idata;
1142 } else {
1143 int idata[] = {pixel};
1144 return idata;
1145 }
1146 default:
1147 throw new ClassCastException("This method has not been "+
1148 "implemented for transferType " + transferType);
1149 }
1150 }
1151
1152 /**
1153 * Forces the raster data to match the state specified in the
1154 * <code>isAlphaPremultiplied</code> variable, assuming the data is
1155 * currently correctly described by this <code>ColorModel</code>. It
1156 * may multiply or divide the color raster data by alpha, or do
1157 * nothing if the data is in the correct state. If the data needs to
1158 * be coerced, this method will also return an instance of this
1159 * <code>ColorModel</code> with the <code>isAlphaPremultiplied</code>
1160 * flag set appropriately. This method will throw a
1161 * <code>UnsupportedOperationException</code> if this transferType is
1162 * not supported by this <code>ColorModel</code>. Since
1163 * <code>ColorModel</code> can be subclassed, subclasses inherit the
1164 * implementation of this method and if they don't override it then
1165 * they throw an exception if they use an unsupported transferType.
1166 *
1167 * @param raster the <code>WritableRaster</code> data
1168 * @param isAlphaPremultiplied <code>true</code> if the alpha is
1169 * premultiplied; <code>false</code> otherwise
1170 * @return a <code>ColorModel</code> object that represents the
1171 * coerced data.
1172 * @exception UnsupportedOperationException if this
1173 * <code>transferType</code> is not supported by this
1174 * color model
1175 */
1176 final public ColorModel coerceData (WritableRaster raster,
1177 boolean isAlphaPremultiplied)
1178 {
1179 if (!supportsAlpha ||
1180 this.isAlphaPremultiplied() == isAlphaPremultiplied) {
1181 return this;
1182 }
1183
1184 int w = raster.getWidth();
1185 int h = raster.getHeight();
1186 int aIdx = numColorComponents;
1187 float normAlpha;
1188 float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
1189
1190 int rminX = raster.getMinX();
1191 int rY = raster.getMinY();
1192 int rX;
1193 int pixel[] = null;
1194 int zpixel[] = null;
1195
1196 if (isAlphaPremultiplied) {
1197 // Must mean that we are currently not premultiplied so
1198 // multiply by alpha
1199 switch (transferType) {
1200 case DataBuffer.TYPE_BYTE: {
1201 for (int y = 0; y < h; y++, rY++) {
1202 rX = rminX;
1203 for (int x = 0; x < w; x++, rX++) {
1204 pixel = raster.getPixel(rX, rY, pixel);
1205 normAlpha = pixel[aIdx] * alphaScale;
1206 if (normAlpha != 0.f) {
1207 for (int c=0; c < aIdx; c++) {
1208 pixel[c] = (int) (pixel[c] * normAlpha +
1209 0.5f);
1210 }
1211 raster.setPixel(rX, rY, pixel);
1212 } else {
1213 if (zpixel == null) {
1214 zpixel = new int[numComponents];
1215 java.util.Arrays.fill(zpixel, 0);
1216 }
1217 raster.setPixel(rX, rY, zpixel);
1218 }
1219 }
1220 }
1221 }
1222 break;
1223 case DataBuffer.TYPE_USHORT: {
1224 for (int y = 0; y < h; y++, rY++) {
1225 rX = rminX;
1226 for (int x = 0; x < w; x++, rX++) {
1227 pixel = raster.getPixel(rX, rY, pixel);
1228 normAlpha = pixel[aIdx] * alphaScale;
1229 if (normAlpha != 0.f) {
1230 for (int c=0; c < aIdx; c++) {
1231 pixel[c] = (int) (pixel[c] * normAlpha +
1232 0.5f);
1233 }
1234 raster.setPixel(rX, rY, pixel);
1235 } else {
1236 if (zpixel == null) {
1237 zpixel = new int[numComponents];
1238 java.util.Arrays.fill(zpixel, 0);
1239 }
1240 raster.setPixel(rX, rY, zpixel);
1241 }
1242 }
1243 }
1244 }
1245 break;
1246 case DataBuffer.TYPE_INT: {
1247 for (int y = 0; y < h; y++, rY++) {
1248 rX = rminX;
1249 for (int x = 0; x < w; x++, rX++) {
1250 pixel = raster.getPixel(rX, rY, pixel);
1251 normAlpha = pixel[aIdx] * alphaScale;
1252 if (normAlpha != 0.f) {
1253 for (int c=0; c < aIdx; c++) {
1254 pixel[c] = (int) (pixel[c] * normAlpha +
1255 0.5f);
1256 }
1257 raster.setPixel(rX, rY, pixel);
1258 } else {
1259 if (zpixel == null) {
1260 zpixel = new int[numComponents];
1261 java.util.Arrays.fill(zpixel, 0);
1262 }
1263 raster.setPixel(rX, rY, zpixel);
1264 }
1265 }
1266 }
1267 }
1268 break;
1269 default:
1270 throw new UnsupportedOperationException("This method has not been "+
1271 "implemented for transferType " + transferType);
1272 }
1273 }
1274 else {
1275 // We are premultiplied and want to divide it out
1276 switch (transferType) {
1277 case DataBuffer.TYPE_BYTE: {
1278 for (int y = 0; y < h; y++, rY++) {
1279 rX = rminX;
1280 for (int x = 0; x < w; x++, rX++) {
1281 pixel = raster.getPixel(rX, rY, pixel);
1282 normAlpha = pixel[aIdx] * alphaScale;
1283 if (normAlpha != 0.0f) {
1284 float invAlpha = 1.0f / normAlpha;
1285 for (int c=0; c < aIdx; c++) {
1286 pixel[c] = (int) (pixel[c] * invAlpha +
1287 0.5f);
1288 }
1289 raster.setPixel(rX, rY, pixel);
1290 }
1291 }
1292 }
1293 }
1294 break;
1295 case DataBuffer.TYPE_USHORT: {
1296 for (int y = 0; y < h; y++, rY++) {
1297 rX = rminX;
1298 for (int x = 0; x < w; x++, rX++) {
1299 pixel = raster.getPixel(rX, rY, pixel);
1300 normAlpha = pixel[aIdx] * alphaScale;
1301 if (normAlpha != 0) {
1302 float invAlpha = 1.0f / normAlpha;
1303 for (int c=0; c < aIdx; c++) {
1304 pixel[c] = (int) (pixel[c] * invAlpha +
1305 0.5f);
1306 }
1307 raster.setPixel(rX, rY, pixel);
1308 }
1309 }
1310 }
1311 }
1312 break;
1313 case DataBuffer.TYPE_INT: {
1314 for (int y = 0; y < h; y++, rY++) {
1315 rX = rminX;
1316 for (int x = 0; x < w; x++, rX++) {
1317 pixel = raster.getPixel(rX, rY, pixel);
1318 normAlpha = pixel[aIdx] * alphaScale;
1319 if (normAlpha != 0) {
1320 float invAlpha = 1.0f / normAlpha;
1321 for (int c=0; c < aIdx; c++) {
1322 pixel[c] = (int) (pixel[c] * invAlpha +
1323 0.5f);
1324 }
1325 raster.setPixel(rX, rY, pixel);
1326 }
1327 }
1328 }
1329 }
1330 break;
1331 default:
1332 throw new UnsupportedOperationException("This method has not been "+
1333 "implemented for transferType " + transferType);
1334 }
1335 }
1336
1337 // Return a new color model
1338 return new DirectColorModel(colorSpace, pixel_bits, maskArray[0],
1339 maskArray[1], maskArray[2], maskArray[3],
1340 isAlphaPremultiplied,
1341 transferType);
1342
1343 }
1344
1345 /**
1346 * Returns <code>true</code> if <code>raster</code> is compatible
1347 * with this <code>ColorModel</code> and <code>false</code> if it is
1348 * not.
1349 * @param raster the {@link Raster} object to test for compatibility
1350 * @return <code>true</code> if <code>raster</code> is compatible
1351 * with this <code>ColorModel</code>; <code>false</code> otherwise.
1352 */
1353 public boolean isCompatibleRaster(Raster raster) {
1354 SampleModel sm = raster.getSampleModel();
1355 SinglePixelPackedSampleModel spsm;
1356 if (sm instanceof SinglePixelPackedSampleModel) {
1357 spsm = (SinglePixelPackedSampleModel) sm;
1358 }
1359 else {
1360 return false;
1361 }
1362 if (spsm.getNumBands() != getNumComponents()) {
1363 return false;
1364 }
1365
1366 int[] bitMasks = spsm.getBitMasks();
1367 for (int i=0; i<numComponents; i++) {
1368 if (bitMasks[i] != maskArray[i]) {
1369 return false;
1370 }
1371 }
1372
1373 return (raster.getTransferType() == transferType);
1374 }
1375
1376 private void setFields() {
1377 // Set the private fields
1378 // REMIND: Get rid of these from the native code
1379 red_mask = maskArray[0];
1380 red_offset = maskOffsets[0];
1381 green_mask = maskArray[1];
1382 green_offset = maskOffsets[1];
1383 blue_mask = maskArray[2];
1384 blue_offset = maskOffsets[2];
1385 if (nBits[0] < 8) {
1386 red_scale = (1 << nBits[0]) - 1;
1387 }
1388 if (nBits[1] < 8) {
1389 green_scale = (1 << nBits[1]) - 1;
1390 }
1391 if (nBits[2] < 8) {
1392 blue_scale = (1 << nBits[2]) - 1;
1393 }
1394 if (supportsAlpha) {
1395 alpha_mask = maskArray[3];
1396 alpha_offset = maskOffsets[3];
1397 if (nBits[3] < 8) {
1398 alpha_scale = (1 << nBits[3]) - 1;
1399 }
1400 }
1401 }
1402
1403 /**
1404 * Returns a <code>String</code> that represents this
1405 * <code>DirectColorModel</code>.
1406 * @return a <code>String</code> representing this
1407 * <code>DirectColorModel</code>.
1408 */
1409 public String toString() {
1410 return new String("DirectColorModel: rmask="
1411 +Integer.toHexString(red_mask)+" gmask="
1412 +Integer.toHexString(green_mask)+" bmask="
1413 +Integer.toHexString(blue_mask)+" amask="
1414 +Integer.toHexString(alpha_mask));
1415 }
1416}
java/pkg/java/awt/image/FilteredImageSource.class+0−0

Binary file not shown.

java/pkg/java/awt/image/FilteredImageSource.java+209−0
@@ -0,0 +1,209 @@
1/*
2 * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.Image;
29import java.awt.image.ImageFilter;
30import java.awt.image.ImageConsumer;
31import java.awt.image.ImageProducer;
32import java.util.Hashtable;
33import java.awt.image.ColorModel;
34
35/**
36 * This class is an implementation of the ImageProducer interface which
37 * takes an existing image and a filter object and uses them to produce
38 * image data for a new filtered version of the original image.
39 * Here is an example which filters an image by swapping the red and
40 * blue compents:
41 * <pre>
42 *
43 * Image src = getImage("doc:///demo/images/duke/T1.gif");
44 * ImageFilter colorfilter = new RedBlueSwapFilter();
45 * Image img = createImage(new FilteredImageSource(src.getSource(),
46 * colorfilter));
47 *
48 * </pre>
49 *
50 * @see ImageProducer
51 *
52 * @author Jim Graham
53 */
54public class FilteredImageSource implements ImageProducer {
55 ImageProducer src;
56 ImageFilter filter;
57
58 /**
59 * Constructs an ImageProducer object from an existing ImageProducer
60 * and a filter object.
61 * @param orig the specified <code>ImageProducer</code>
62 * @param imgf the specified <code>ImageFilter</code>
63 * @see ImageFilter
64 * @see java.awt.Component#createImage
65 */
66 public FilteredImageSource(ImageProducer orig, ImageFilter imgf) {
67 src = orig;
68 filter = imgf;
69 }
70
71 private Hashtable proxies;
72
73 /**
74 * Adds the specified <code>ImageConsumer</code>
75 * to the list of consumers interested in data for the filtered image.
76 * An instance of the original <code>ImageFilter</code>
77 * is created
78 * (using the filter's <code>getFilterInstance</code> method)
79 * to manipulate the image data
80 * for the specified <code>ImageConsumer</code>.
81 * The newly created filter instance
82 * is then passed to the <code>addConsumer</code> method
83 * of the original <code>ImageProducer</code>.
84 *
85 * <p>
86 * This method is public as a side effect
87 * of this class implementing
88 * the <code>ImageProducer</code> interface.
89 * It should not be called from user code,
90 * and its behavior if called from user code is unspecified.
91 *
92 * @param ic the consumer for the filtered image
93 * @see ImageConsumer
94 */
95 public synchronized void addConsumer(ImageConsumer ic) {
96 if (proxies == null) {
97 proxies = new Hashtable();
98 }
99 if (!proxies.containsKey(ic)) {
100 ImageFilter imgf = filter.getFilterInstance(ic);
101 proxies.put(ic, imgf);
102 src.addConsumer(imgf);
103 }
104 }
105
106 /**
107 * Determines whether an ImageConsumer is on the list of consumers
108 * currently interested in data for this image.
109 *
110 * <p>
111 * This method is public as a side effect
112 * of this class implementing
113 * the <code>ImageProducer</code> interface.
114 * It should not be called from user code,
115 * and its behavior if called from user code is unspecified.
116 *
117 * @param ic the specified <code>ImageConsumer</code>
118 * @return true if the ImageConsumer is on the list; false otherwise
119 * @see ImageConsumer
120 */
121 public synchronized boolean isConsumer(ImageConsumer ic) {
122 return (proxies != null && proxies.containsKey(ic));
123 }
124
125 /**
126 * Removes an ImageConsumer from the list of consumers interested in
127 * data for this image.
128 *
129 * <p>
130 * This method is public as a side effect
131 * of this class implementing
132 * the <code>ImageProducer</code> interface.
133 * It should not be called from user code,
134 * and its behavior if called from user code is unspecified.
135 *
136 * @see ImageConsumer
137 */
138 public synchronized void removeConsumer(ImageConsumer ic) {
139 if (proxies != null) {
140 ImageFilter imgf = (ImageFilter) proxies.get(ic);
141 if (imgf != null) {
142 src.removeConsumer(imgf);
143 proxies.remove(ic);
144 if (proxies.isEmpty()) {
145 proxies = null;
146 }
147 }
148 }
149 }
150
151 /**
152 * Starts production of the filtered image.
153 * If the specified <code>ImageConsumer</code>
154 * isn't already a consumer of the filtered image,
155 * an instance of the original <code>ImageFilter</code>
156 * is created
157 * (using the filter's <code>getFilterInstance</code> method)
158 * to manipulate the image data
159 * for the <code>ImageConsumer</code>.
160 * The filter instance for the <code>ImageConsumer</code>
161 * is then passed to the <code>startProduction</code> method
162 * of the original <code>ImageProducer</code>.
163 *
164 * <p>
165 * This method is public as a side effect
166 * of this class implementing
167 * the <code>ImageProducer</code> interface.
168 * It should not be called from user code,
169 * and its behavior if called from user code is unspecified.
170 *
171 * @param ic the consumer for the filtered image
172 * @see ImageConsumer
173 */
174 public void startProduction(ImageConsumer ic) {
175 if (proxies == null) {
176 proxies = new Hashtable();
177 }
178 ImageFilter imgf = (ImageFilter) proxies.get(ic);
179 if (imgf == null) {
180 imgf = filter.getFilterInstance(ic);
181 proxies.put(ic, imgf);
182 }
183 src.startProduction(imgf);
184 }
185
186 /**
187 * Requests that a given ImageConsumer have the image data delivered
188 * one more time in top-down, left-right order. The request is
189 * handed to the ImageFilter for further processing, since the
190 * ability to preserve the pixel ordering depends on the filter.
191 *
192 * <p>
193 * This method is public as a side effect
194 * of this class implementing
195 * the <code>ImageProducer</code> interface.
196 * It should not be called from user code,
197 * and its behavior if called from user code is unspecified.
198 *
199 * @see ImageConsumer
200 */
201 public void requestTopDownLeftRightResend(ImageConsumer ic) {
202 if (proxies != null) {
203 ImageFilter imgf = (ImageFilter) proxies.get(ic);
204 if (imgf != null) {
205 imgf.resendTopDownLeftRight(src);
206 }
207 }
208 }
209}
java/pkg/java/awt/image/ImageConsumer.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ImageConsumer.java+226−0
@@ -0,0 +1,226 @@
1/*
2 * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.util.Hashtable;
29
30/**
31 * The interface for objects expressing interest in image data through
32 * the ImageProducer interfaces. When a consumer is added to an image
33 * producer, the producer delivers all of the data about the image
34 * using the method calls defined in this interface.
35 *
36 * @see ImageProducer
37 *
38 * @author Jim Graham
39 */
40public interface ImageConsumer {
41 /**
42 * The dimensions of the source image are reported using the
43 * setDimensions method call.
44 * @param width the width of the source image
45 * @param height the height of the source image
46 */
47 void setDimensions(int width, int height);
48
49 /**
50 * Sets the extensible list of properties associated with this image.
51 * @param props the list of properties to be associated with this
52 * image
53 */
54 void setProperties(Hashtable<?,?> props);
55
56 /**
57 * Sets the ColorModel object used for the majority of
58 * the pixels reported using the setPixels method
59 * calls. Note that each set of pixels delivered using setPixels
60 * contains its own ColorModel object, so no assumption should
61 * be made that this model will be the only one used in delivering
62 * pixel values. A notable case where multiple ColorModel objects
63 * may be seen is a filtered image when for each set of pixels
64 * that it filters, the filter
65 * determines whether the
66 * pixels can be sent on untouched, using the original ColorModel,
67 * or whether the pixels should be modified (filtered) and passed
68 * on using a ColorModel more convenient for the filtering process.
69 * @param model the specified <code>ColorModel</code>
70 * @see ColorModel
71 */
72 void setColorModel(ColorModel model);
73
74 /**
75 * Sets the hints that the ImageConsumer uses to process the
76 * pixels delivered by the ImageProducer.
77 * The ImageProducer can deliver the pixels in any order, but
78 * the ImageConsumer may be able to scale or convert the pixels
79 * to the destination ColorModel more efficiently or with higher
80 * quality if it knows some information about how the pixels will
81 * be delivered up front. The setHints method should be called
82 * before any calls to any of the setPixels methods with a bit mask
83 * of hints about the manner in which the pixels will be delivered.
84 * If the ImageProducer does not follow the guidelines for the
85 * indicated hint, the results are undefined.
86 * @param hintflags a set of hints that the ImageConsumer uses to
87 * process the pixels
88 */
89 void setHints(int hintflags);
90
91 /**
92 * The pixels will be delivered in a random order. This tells the
93 * ImageConsumer not to use any optimizations that depend on the
94 * order of pixel delivery, which should be the default assumption
95 * in the absence of any call to the setHints method.
96 * @see #setHints
97 */
98 int RANDOMPIXELORDER = 1;
99
100 /**
101 * The pixels will be delivered in top-down, left-to-right order.
102 * @see #setHints
103 */
104 int TOPDOWNLEFTRIGHT = 2;
105
106 /**
107 * The pixels will be delivered in (multiples of) complete scanlines
108 * at a time.
109 * @see #setHints
110 */
111 int COMPLETESCANLINES = 4;
112
113 /**
114 * The pixels will be delivered in a single pass. Each pixel will
115 * appear in only one call to any of the setPixels methods. An
116 * example of an image format which does not meet this criterion
117 * is a progressive JPEG image which defines pixels in multiple
118 * passes, each more refined than the previous.
119 * @see #setHints
120 */
121 int SINGLEPASS = 8;
122
123 /**
124 * The image contain a single static image. The pixels will be defined
125 * in calls to the setPixels methods and then the imageComplete method
126 * will be called with the STATICIMAGEDONE flag after which no more
127 * image data will be delivered. An example of an image type which
128 * would not meet these criteria would be the output of a video feed,
129 * or the representation of a 3D rendering being manipulated
130 * by the user. The end of each frame in those types of images will
131 * be indicated by calling imageComplete with the SINGLEFRAMEDONE flag.
132 * @see #setHints
133 * @see #imageComplete
134 */
135 int SINGLEFRAME = 16;
136
137 /**
138 * Delivers the pixels of the image with one or more calls
139 * to this method. Each call specifies the location and
140 * size of the rectangle of source pixels that are contained in
141 * the array of pixels. The specified ColorModel object should
142 * be used to convert the pixels into their corresponding color
143 * and alpha components. Pixel (m,n) is stored in the pixels array
144 * at index (n * scansize + m + off). The pixels delivered using
145 * this method are all stored as bytes.
146 * @param x the X coordinate of the upper-left corner of the
147 * area of pixels to be set
148 * @param y the Y coordinate of the upper-left corner of the
149 * area of pixels to be set
150 * @param w the width of the area of pixels
151 * @param h the height of the area of pixels
152 * @param model the specified <code>ColorModel</code>
153 * @param pixels the array of pixels
154 * @param off the offset into the <code>pixels</code> array
155 * @param scansize the distance from one row of pixels to the next in
156 * the <code>pixels</code> array
157 * @see ColorModel
158 */
159 void setPixels(int x, int y, int w, int h,
160 ColorModel model, byte pixels[], int off, int scansize);
161
162 /**
163 * The pixels of the image are delivered using one or more calls
164 * to the setPixels method. Each call specifies the location and
165 * size of the rectangle of source pixels that are contained in
166 * the array of pixels. The specified ColorModel object should
167 * be used to convert the pixels into their corresponding color
168 * and alpha components. Pixel (m,n) is stored in the pixels array
169 * at index (n * scansize + m + off). The pixels delivered using
170 * this method are all stored as ints.
171 * this method are all stored as ints.
172 * @param x the X coordinate of the upper-left corner of the
173 * area of pixels to be set
174 * @param y the Y coordinate of the upper-left corner of the
175 * area of pixels to be set
176 * @param w the width of the area of pixels
177 * @param h the height of the area of pixels
178 * @param model the specified <code>ColorModel</code>
179 * @param pixels the array of pixels
180 * @param off the offset into the <code>pixels</code> array
181 * @param scansize the distance from one row of pixels to the next in
182 * the <code>pixels</code> array
183 * @see ColorModel
184 */
185 void setPixels(int x, int y, int w, int h,
186 ColorModel model, int pixels[], int off, int scansize);
187
188 /**
189 * The imageComplete method is called when the ImageProducer is
190 * finished delivering all of the pixels that the source image
191 * contains, or when a single frame of a multi-frame animation has
192 * been completed, or when an error in loading or producing the
193 * image has occured. The ImageConsumer should remove itself from the
194 * list of consumers registered with the ImageProducer at this time,
195 * unless it is interested in successive frames.
196 * @param status the status of image loading
197 * @see ImageProducer#removeConsumer
198 */
199 void imageComplete(int status);
200
201 /**
202 * An error was encountered while producing the image.
203 * @see #imageComplete
204 */
205 int IMAGEERROR = 1;
206
207 /**
208 * One frame of the image is complete but there are more frames
209 * to be delivered.
210 * @see #imageComplete
211 */
212 int SINGLEFRAMEDONE = 2;
213
214 /**
215 * The image is complete and there are no more pixels or frames
216 * to be delivered.
217 * @see #imageComplete
218 */
219 int STATICIMAGEDONE = 3;
220
221 /**
222 * The image creation process was deliberately aborted.
223 * @see #imageComplete
224 */
225 int IMAGEABORTED = 4;
226}
java/pkg/java/awt/image/ImageFilter.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ImageFilter.java+258−0
@@ -0,0 +1,258 @@
1/*
2 * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.util.Hashtable;
29
30/**
31 * This class implements a filter for the set of interface methods that
32 * are used to deliver data from an ImageProducer to an ImageConsumer.
33 * It is meant to be used in conjunction with a FilteredImageSource
34 * object to produce filtered versions of existing images. It is a
35 * base class that provides the calls needed to implement a "Null filter"
36 * which has no effect on the data being passed through. Filters should
37 * subclass this class and override the methods which deal with the
38 * data that needs to be filtered and modify it as necessary.
39 *
40 * @see FilteredImageSource
41 * @see ImageConsumer
42 *
43 * @author Jim Graham
44 */
45public class ImageFilter implements ImageConsumer, Cloneable {
46 /**
47 * The consumer of the particular image data stream for which this
48 * instance of the ImageFilter is filtering data. It is not
49 * initialized during the constructor, but rather during the
50 * getFilterInstance() method call when the FilteredImageSource
51 * is creating a unique instance of this object for a particular
52 * image data stream.
53 * @see #getFilterInstance
54 * @see ImageConsumer
55 */
56 protected ImageConsumer consumer;
57
58 /**
59 * Returns a unique instance of an ImageFilter object which will
60 * actually perform the filtering for the specified ImageConsumer.
61 * The default implementation just clones this object.
62 * <p>
63 * Note: This method is intended to be called by the ImageProducer
64 * of the Image whose pixels are being filtered. Developers using
65 * this class to filter pixels from an image should avoid calling
66 * this method directly since that operation could interfere
67 * with the filtering operation.
68 * @param ic the specified <code>ImageConsumer</code>
69 * @return an <code>ImageFilter</code> used to perform the
70 * filtering for the specified <code>ImageConsumer</code>.
71 */
72 public ImageFilter getFilterInstance(ImageConsumer ic) {
73 ImageFilter instance = (ImageFilter) clone();
74 instance.consumer = ic;
75 return instance;
76 }
77
78 /**
79 * Filters the information provided in the setDimensions method
80 * of the ImageConsumer interface.
81 * <p>
82 * Note: This method is intended to be called by the ImageProducer
83 * of the Image whose pixels are being filtered. Developers using
84 * this class to filter pixels from an image should avoid calling
85 * this method directly since that operation could interfere
86 * with the filtering operation.
87 * @see ImageConsumer#setDimensions
88 */
89 public void setDimensions(int width, int height) {
90 consumer.setDimensions(width, height);
91 }
92
93 /**
94 * Passes the properties from the source object along after adding a
95 * property indicating the stream of filters it has been run through.
96 * <p>
97 * Note: This method is intended to be called by the ImageProducer
98 * of the Image whose pixels are being filtered. Developers using
99 * this class to filter pixels from an image should avoid calling
100 * this method directly since that operation could interfere
101 * with the filtering operation.
102 *
103 * @param props the properties from the source object
104 * @exception NullPointerException if <code>props</code> is null
105 */
106 public void setProperties(Hashtable<?,?> props) {
107 Hashtable<Object,Object> p = (Hashtable<Object,Object>)props.clone();
108 Object o = p.get("filters");
109 if (o == null) {
110 p.put("filters", toString());
111 } else if (o instanceof String) {
112 p.put("filters", ((String) o)+toString());
113 }
114 consumer.setProperties(p);
115 }
116
117 /**
118 * Filter the information provided in the setColorModel method
119 * of the ImageConsumer interface.
120 * <p>
121 * Note: This method is intended to be called by the ImageProducer
122 * of the Image whose pixels are being filtered. Developers using
123 * this class to filter pixels from an image should avoid calling
124 * this method directly since that operation could interfere
125 * with the filtering operation.
126 * @see ImageConsumer#setColorModel
127 */
128 public void setColorModel(ColorModel model) {
129 consumer.setColorModel(model);
130 }
131
132 /**
133 * Filters the information provided in the setHints method
134 * of the ImageConsumer interface.
135 * <p>
136 * Note: This method is intended to be called by the ImageProducer
137 * of the Image whose pixels are being filtered. Developers using
138 * this class to filter pixels from an image should avoid calling
139 * this method directly since that operation could interfere
140 * with the filtering operation.
141 * @see ImageConsumer#setHints
142 */
143 public void setHints(int hints) {
144 consumer.setHints(hints);
145 }
146
147 /**
148 * Filters the information provided in the setPixels method of the
149 * ImageConsumer interface which takes an array of bytes.
150 * <p>
151 * Note: This method is intended to be called by the ImageProducer
152 * of the Image whose pixels are being filtered. Developers using
153 * this class to filter pixels from an image should avoid calling
154 * this method directly since that operation could interfere
155 * with the filtering operation.
156 * @see ImageConsumer#setPixels
157 */
158 public void setPixels(int x, int y, int w, int h,
159 ColorModel model, byte pixels[], int off,
160 int scansize) {
161 consumer.setPixels(x, y, w, h, model, pixels, off, scansize);
162 }
163
164 /**
165 * Filters the information provided in the setPixels method of the
166 * ImageConsumer interface which takes an array of integers.
167 * <p>
168 * Note: This method is intended to be called by the ImageProducer
169 * of the Image whose pixels are being filtered. Developers using
170 * this class to filter pixels from an image should avoid calling
171 * this method directly since that operation could interfere
172 * with the filtering operation.
173 * @see ImageConsumer#setPixels
174 */
175 public void setPixels(int x, int y, int w, int h,
176 ColorModel model, int pixels[], int off,
177 int scansize) {
178 consumer.setPixels(x, y, w, h, model, pixels, off, scansize);
179 }
180
181 /**
182 * Filters the information provided in the imageComplete method of
183 * the ImageConsumer interface.
184 * <p>
185 * Note: This method is intended to be called by the ImageProducer
186 * of the Image whose pixels are being filtered. Developers using
187 * this class to filter pixels from an image should avoid calling
188 * this method directly since that operation could interfere
189 * with the filtering operation.
190 * @see ImageConsumer#imageComplete
191 */
192 public void imageComplete(int status) {
193 consumer.imageComplete(status);
194 }
195
196 /**
197 * Responds to a request for a TopDownLeftRight (TDLR) ordered resend
198 * of the pixel data from an <code>ImageConsumer</code>.
199 * When an <code>ImageConsumer</code> being fed
200 * by an instance of this <code>ImageFilter</code>
201 * requests a resend of the data in TDLR order,
202 * the <code>FilteredImageSource</code>
203 * invokes this method of the <code>ImageFilter</code>.
204 *
205 * <p>
206 *
207 * An <code>ImageFilter</code> subclass might override this method or not,
208 * depending on if and how it can send data in TDLR order.
209 * Three possibilities exist:
210 *
211 * <ul>
212 * <li>
213 * Do not override this method.
214 * This makes the subclass use the default implementation,
215 * which is to
216 * forward the request
217 * to the indicated <code>ImageProducer</code>
218 * using this filter as the requesting <code>ImageConsumer</code>.
219 * This behavior
220 * is appropriate if the filter can determine
221 * that it will forward the pixels
222 * in TDLR order if its upstream producer object
223 * sends them in TDLR order.
224 *
225 * <li>
226 * Override the method to simply send the data.
227 * This is appropriate if the filter can handle the request itself &#151;
228 * for example,
229 * if the generated pixels have been saved in some sort of buffer.
230 *
231 * <li>
232 * Override the method to do nothing.
233 * This is appropriate
234 * if the filter cannot produce filtered data in TDLR order.
235 * </ul>
236 *
237 * @see ImageProducer#requestTopDownLeftRightResend
238 * @param ip the ImageProducer that is feeding this instance of
239 * the filter - also the ImageProducer that the request should be
240 * forwarded to if necessary
241 * @exception NullPointerException if <code>ip</code> is null
242 */
243 public void resendTopDownLeftRight(ImageProducer ip) {
244 ip.requestTopDownLeftRightResend(this);
245 }
246
247 /**
248 * Clones this object.
249 */
250 public Object clone() {
251 try {
252 return super.clone();
253 } catch (CloneNotSupportedException e) {
254 // this shouldn't happen, since we are Cloneable
255 throw new InternalError();
256 }
257 }
258}
java/pkg/java/awt/image/ImageObserver.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ImageObserver.java+170−0
@@ -0,0 +1,170 @@
1/*
2 * Copyright (c) 1995, 1999, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.Image;
29
30/**
31 * An asynchronous update interface for receiving notifications about
32 * Image information as the Image is constructed.
33 *
34 * @author Jim Graham
35 */
36public interface ImageObserver {
37 /**
38 * This method is called when information about an image which was
39 * previously requested using an asynchronous interface becomes
40 * available. Asynchronous interfaces are method calls such as
41 * getWidth(ImageObserver) and drawImage(img, x, y, ImageObserver)
42 * which take an ImageObserver object as an argument. Those methods
43 * register the caller as interested either in information about
44 * the overall image itself (in the case of getWidth(ImageObserver))
45 * or about an output version of an image (in the case of the
46 * drawImage(img, x, y, [w, h,] ImageObserver) call).
47 *
48 * <p>This method
49 * should return true if further updates are needed or false if the
50 * required information has been acquired. The image which was being
51 * tracked is passed in using the img argument. Various constants
52 * are combined to form the infoflags argument which indicates what
53 * information about the image is now available. The interpretation
54 * of the x, y, width, and height arguments depends on the contents
55 * of the infoflags argument.
56 * <p>
57 * The <code>infoflags</code> argument should be the bitwise inclusive
58 * <b>OR</b> of the following flags: <code>WIDTH</code>,
59 * <code>HEIGHT</code>, <code>PROPERTIES</code>, <code>SOMEBITS</code>,
60 * <code>FRAMEBITS</code>, <code>ALLBITS</code>, <code>ERROR</code>,
61 * <code>ABORT</code>.
62 *
63 * @param img the image being observed.
64 * @param infoflags the bitwise inclusive OR of the following
65 * flags: <code>WIDTH</code>, <code>HEIGHT</code>,
66 * <code>PROPERTIES</code>, <code>SOMEBITS</code>,
67 * <code>FRAMEBITS</code>, <code>ALLBITS</code>,
68 * <code>ERROR</code>, <code>ABORT</code>.
69 * @param x the <i>x</i> coordinate.
70 * @param y the <i>y</i> coordinate.
71 * @param width the width.
72 * @param height the height.
73 * @return <code>false</code> if the infoflags indicate that the
74 * image is completely loaded; <code>true</code> otherwise.
75 *
76 * @see #WIDTH
77 * @see #HEIGHT
78 * @see #PROPERTIES
79 * @see #SOMEBITS
80 * @see #FRAMEBITS
81 * @see #ALLBITS
82 * @see #ERROR
83 * @see #ABORT
84 * @see Image#getWidth
85 * @see Image#getHeight
86 * @see java.awt.Graphics#drawImage
87 */
88 public boolean imageUpdate(Image img, int infoflags,
89 int x, int y, int width, int height);
90
91 /**
92 * This flag in the infoflags argument to imageUpdate indicates that
93 * the width of the base image is now available and can be taken
94 * from the width argument to the imageUpdate callback method.
95 * @see Image#getWidth
96 * @see #imageUpdate
97 */
98 public static final int WIDTH = 1;
99
100 /**
101 * This flag in the infoflags argument to imageUpdate indicates that
102 * the height of the base image is now available and can be taken
103 * from the height argument to the imageUpdate callback method.
104 * @see Image#getHeight
105 * @see #imageUpdate
106 */
107 public static final int HEIGHT = 2;
108
109 /**
110 * This flag in the infoflags argument to imageUpdate indicates that
111 * the properties of the image are now available.
112 * @see Image#getProperty
113 * @see #imageUpdate
114 */
115 public static final int PROPERTIES = 4;
116
117 /**
118 * This flag in the infoflags argument to imageUpdate indicates that
119 * more pixels needed for drawing a scaled variation of the image
120 * are available. The bounding box of the new pixels can be taken
121 * from the x, y, width, and height arguments to the imageUpdate
122 * callback method.
123 * @see java.awt.Graphics#drawImage
124 * @see #imageUpdate
125 */
126 public static final int SOMEBITS = 8;
127
128 /**
129 * This flag in the infoflags argument to imageUpdate indicates that
130 * another complete frame of a multi-frame image which was previously
131 * drawn is now available to be drawn again. The x, y, width, and height
132 * arguments to the imageUpdate callback method should be ignored.
133 * @see java.awt.Graphics#drawImage
134 * @see #imageUpdate
135 */
136 public static final int FRAMEBITS = 16;
137
138 /**
139 * This flag in the infoflags argument to imageUpdate indicates that
140 * a static image which was previously drawn is now complete and can
141 * be drawn again in its final form. The x, y, width, and height
142 * arguments to the imageUpdate callback method should be ignored.
143 * @see java.awt.Graphics#drawImage
144 * @see #imageUpdate
145 */
146 public static final int ALLBITS = 32;
147
148 /**
149 * This flag in the infoflags argument to imageUpdate indicates that
150 * an image which was being tracked asynchronously has encountered
151 * an error. No further information will become available and
152 * drawing the image will fail.
153 * As a convenience, the ABORT flag will be indicated at the same
154 * time to indicate that the image production was aborted.
155 * @see #imageUpdate
156 */
157 public static final int ERROR = 64;
158
159 /**
160 * This flag in the infoflags argument to imageUpdate indicates that
161 * an image which was being tracked asynchronously was aborted before
162 * production was complete. No more information will become available
163 * without further action to trigger another image production sequence.
164 * If the ERROR flag was not also set in this image update, then
165 * accessing any of the data in the image will restart the production
166 * again, probably from the beginning.
167 * @see #imageUpdate
168 */
169 public static final int ABORT = 128;
170}
java/pkg/java/awt/image/ImageProducer.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ImageProducer.java+112−0
@@ -0,0 +1,112 @@
1/*
2 * Copyright (c) 1995, 2000, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28/**
29 * The interface for objects which can produce the image data for Images.
30 * Each image contains an ImageProducer which is used to reconstruct
31 * the image whenever it is needed, for example, when a new size of the
32 * Image is scaled, or when the width or height of the Image is being
33 * requested.
34 *
35 * @see ImageConsumer
36 *
37 * @author Jim Graham
38 */
39public interface ImageProducer {
40 /**
41 * Registers an <code>ImageConsumer</code> with the
42 * <code>ImageProducer</code> for access to the image data
43 * during a later reconstruction of the <code>Image</code>.
44 * The <code>ImageProducer</code> may, at its discretion,
45 * start delivering the image data to the consumer
46 * using the <code>ImageConsumer</code> interface immediately,
47 * or when the next available image reconstruction is triggered
48 * by a call to the <code>startProduction</code> method.
49 * @param ic the specified <code>ImageConsumer</code>
50 * @see #startProduction
51 */
52 public void addConsumer(ImageConsumer ic);
53
54 /**
55 * Determines if a specified <code>ImageConsumer</code>
56 * object is currently registered with this
57 * <code>ImageProducer</code> as one of its consumers.
58 * @param ic the specified <code>ImageConsumer</code>
59 * @return <code>true</code> if the specified
60 * <code>ImageConsumer</code> is registered with
61 * this <code>ImageProducer</code>;
62 * <code>false</code> otherwise.
63 */
64 public boolean isConsumer(ImageConsumer ic);
65
66 /**
67 * Removes the specified <code>ImageConsumer</code> object
68 * from the list of consumers currently registered to
69 * receive image data. It is not considered an error
70 * to remove a consumer that is not currently registered.
71 * The <code>ImageProducer</code> should stop sending data
72 * to this consumer as soon as is feasible.
73 * @param ic the specified <code>ImageConsumer</code>
74 */
75 public void removeConsumer(ImageConsumer ic);
76
77 /**
78 * Registers the specified <code>ImageConsumer</code> object
79 * as a consumer and starts an immediate reconstruction of
80 * the image data which will then be delivered to this
81 * consumer and any other consumer which might have already
82 * been registered with the producer. This method differs
83 * from the addConsumer method in that a reproduction of
84 * the image data should be triggered as soon as possible.
85 * @param ic the specified <code>ImageConsumer</code>
86 * @see #addConsumer
87 */
88 public void startProduction(ImageConsumer ic);
89
90 /**
91 * Requests, on behalf of the <code>ImageConsumer</code>,
92 * that the <code>ImageProducer</code> attempt to resend
93 * the image data one more time in TOPDOWNLEFTRIGHT order
94 * so that higher quality conversion algorithms which
95 * depend on receiving pixels in order can be used to
96 * produce a better output version of the image. The
97 * <code>ImageProducer</code> is free to
98 * ignore this call if it cannot resend the data in that
99 * order. If the data can be resent, the
100 * <code>ImageProducer</code> should respond by executing
101 * the following minimum set of <code>ImageConsumer</code>
102 * method calls:
103 * <pre>
104 * ic.setHints(TOPDOWNLEFTRIGHT | < otherhints >);
105 * ic.setPixels(...); // As many times as needed
106 * ic.imageComplete();
107 * </pre>
108 * @param ic the specified <code>ImageConsumer</code>
109 * @see ImageConsumer#setHints
110 */
111 public void requestTopDownLeftRightResend(ImageConsumer ic);
112}
java/pkg/java/awt/image/ImagingOpException.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ImagingOpException.java+45−0
@@ -0,0 +1,45 @@
1/*
2 * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28
29/**
30 * The <code>ImagingOpException</code> is thrown if one of the
31 * {@link BufferedImageOp} or {@link RasterOp} filter methods cannot
32 * process the image.
33 */
34public class ImagingOpException extends java.lang.RuntimeException {
35
36 /**
37 * Constructs an <code>ImagingOpException</code> object with the
38 * specified message.
39 * @param s the message to generate when a
40 * <code>ImagingOpException</code> is thrown
41 */
42 public ImagingOpException(String s) {
43 super (s);
44 }
45}
java/pkg/java/awt/image/IndexColorModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/IndexColorModel.java+1534−0
@@ -0,0 +1,1534 @@
1/*
2 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.Transparency;
29import java.awt.color.ColorSpace;
30import java.math.BigInteger;
31
32/**
33 * The <code>IndexColorModel</code> class is a <code>ColorModel</code>
34 * class that works with pixel values consisting of a
35 * single sample that is an index into a fixed colormap in the default
36 * sRGB color space. The colormap specifies red, green, blue, and
37 * optional alpha components corresponding to each index. All components
38 * are represented in the colormap as 8-bit unsigned integral values.
39 * Some constructors allow the caller to specify "holes" in the colormap
40 * by indicating which colormap entries are valid and which represent
41 * unusable colors via the bits set in a <code>BigInteger</code> object.
42 * This color model is similar to an X11 PseudoColor visual.
43 * <p>
44 * Some constructors provide a means to specify an alpha component
45 * for each pixel in the colormap, while others either provide no
46 * such means or, in some cases, a flag to indicate whether the
47 * colormap data contains alpha values. If no alpha is supplied to
48 * the constructor, an opaque alpha component (alpha = 1.0) is
49 * assumed for each entry.
50 * An optional transparent pixel value can be supplied that indicates a
51 * pixel to be made completely transparent, regardless of any alpha
52 * component supplied or assumed for that pixel value.
53 * Note that the color components in the colormap of an
54 * <code>IndexColorModel</code> objects are never pre-multiplied with
55 * the alpha components.
56 * <p>
57 * <a name="transparency">
58 * The transparency of an <code>IndexColorModel</code> object is
59 * determined by examining the alpha components of the colors in the
60 * colormap and choosing the most specific value after considering
61 * the optional alpha values and any transparent index specified.
62 * The transparency value is <code>Transparency.OPAQUE</code>
63 * only if all valid colors in
64 * the colormap are opaque and there is no valid transparent pixel.
65 * If all valid colors
66 * in the colormap are either completely opaque (alpha = 1.0) or
67 * completely transparent (alpha = 0.0), which typically occurs when
68 * a valid transparent pixel is specified,
69 * the value is <code>Transparency.BITMASK</code>.
70 * Otherwise, the value is <code>Transparency.TRANSLUCENT</code>, indicating
71 * that some valid color has an alpha component that is
72 * neither completely transparent nor completely opaque
73 * (0.0 &lt; alpha &lt; 1.0).
74 * </a>
75 *
76 * <p>
77 * If an <code>IndexColorModel</code> object has
78 * a transparency value of <code>Transparency.OPAQUE</code>,
79 * then the <code>hasAlpha</code>
80 * and <code>getNumComponents</code> methods
81 * (both inherited from <code>ColorModel</code>)
82 * return false and 3, respectively.
83 * For any other transparency value,
84 * <code>hasAlpha</code> returns true
85 * and <code>getNumComponents</code> returns 4.
86 *
87 * <p>
88 * <a name="index_values">
89 * The values used to index into the colormap are taken from the least
90 * significant <em>n</em> bits of pixel representations where
91 * <em>n</em> is based on the pixel size specified in the constructor.
92 * For pixel sizes smaller than 8 bits, <em>n</em> is rounded up to a
93 * power of two (3 becomes 4 and 5,6,7 become 8).
94 * For pixel sizes between 8 and 16 bits, <em>n</em> is equal to the
95 * pixel size.
96 * Pixel sizes larger than 16 bits are not supported by this class.
97 * Higher order bits beyond <em>n</em> are ignored in pixel representations.
98 * Index values greater than or equal to the map size, but less than
99 * 2<sup><em>n</em></sup>, are undefined and return 0 for all color and
100 * alpha components.
101 * <p>
102 * For those methods that use a primitive array pixel representation of
103 * type <code>transferType</code>, the array length is always one.
104 * The transfer types supported are <code>DataBuffer.TYPE_BYTE</code> and
105 * <code>DataBuffer.TYPE_USHORT</code>. A single int pixel
106 * representation is valid for all objects of this class, since it is
107 * always possible to represent pixel values used with this class in a
108 * single int. Therefore, methods that use this representation do
109 * not throw an <code>IllegalArgumentException</code> due to an invalid
110 * pixel value.
111 * <p>
112 * Many of the methods in this class are final. The reason for
113 * this is that the underlying native graphics code makes assumptions
114 * about the layout and operation of this class and those assumptions
115 * are reflected in the implementations of the methods here that are
116 * marked final. You can subclass this class for other reasons, but
117 * you cannot override or modify the behaviour of those methods.
118 *
119 * @see ColorModel
120 * @see ColorSpace
121 * @see DataBuffer
122 *
123 */
124public class IndexColorModel extends ColorModel {
125 private int rgb[];
126 private int map_size;
127 private int pixel_mask;
128 private int transparent_index = -1;
129 private boolean allgrayopaque;
130 private BigInteger validBits;
131
132 private sun.awt.image.BufImgSurfaceData.ICMColorData colorData = null;
133
134 private static int[] opaqueBits = {8, 8, 8};
135 private static int[] alphaBits = {8, 8, 8, 8};
136
137 static private native void initIDs();
138 static {
139 ColorModel.loadLibraries();
140 initIDs();
141 }
142 /**
143 * Constructs an <code>IndexColorModel</code> from the specified
144 * arrays of red, green, and blue components. Pixels described
145 * by this color model all have alpha components of 255
146 * unnormalized (1.0&nbsp;normalized), which means they
147 * are fully opaque. All of the arrays specifying the color
148 * components must have at least the specified number of entries.
149 * The <code>ColorSpace</code> is the default sRGB space.
150 * Since there is no alpha information in any of the arguments
151 * to this constructor, the transparency value is always
152 * <code>Transparency.OPAQUE</code>.
153 * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
154 * or <code>DataBuffer.TYPE_USHORT</code> that can hold a single pixel.
155 * @param bits the number of bits each pixel occupies
156 * @param size the size of the color component arrays
157 * @param r the array of red color components
158 * @param g the array of green color components
159 * @param b the array of blue color components
160 * @throws IllegalArgumentException if <code>bits</code> is less
161 * than 1 or greater than 16
162 * @throws IllegalArgumentException if <code>size</code> is less
163 * than 1
164 */
165 public IndexColorModel(int bits, int size,
166 byte r[], byte g[], byte b[]) {
167 super(bits, opaqueBits,
168 ColorSpace.getInstance(ColorSpace.CS_sRGB),
169 false, false, OPAQUE,
170 ColorModel.getDefaultTransferType(bits));
171 if (bits < 1 || bits > 16) {
172 throw new IllegalArgumentException("Number of bits must be between"
173 +" 1 and 16.");
174 }
175 setRGBs(size, r, g, b, null);
176 calculatePixelMask();
177 }
178
179 /**
180 * Constructs an <code>IndexColorModel</code> from the given arrays
181 * of red, green, and blue components. Pixels described by this color
182 * model all have alpha components of 255 unnormalized
183 * (1.0&nbsp;normalized), which means they are fully opaque, except
184 * for the indicated pixel to be made transparent. All of the arrays
185 * specifying the color components must have at least the specified
186 * number of entries.
187 * The <code>ColorSpace</code> is the default sRGB space.
188 * The transparency value may be <code>Transparency.OPAQUE</code> or
189 * <code>Transparency.BITMASK</code> depending on the arguments, as
190 * specified in the <a href="#transparency">class description</a> above.
191 * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
192 * or <code>DataBuffer.TYPE_USHORT</code> that can hold a
193 * single pixel.
194 * @param bits the number of bits each pixel occupies
195 * @param size the size of the color component arrays
196 * @param r the array of red color components
197 * @param g the array of green color components
198 * @param b the array of blue color components
199 * @param trans the index of the transparent pixel
200 * @throws IllegalArgumentException if <code>bits</code> is less than
201 * 1 or greater than 16
202 * @throws IllegalArgumentException if <code>size</code> is less than
203 * 1
204 */
205 public IndexColorModel(int bits, int size,
206 byte r[], byte g[], byte b[], int trans) {
207 super(bits, opaqueBits,
208 ColorSpace.getInstance(ColorSpace.CS_sRGB),
209 false, false, OPAQUE,
210 ColorModel.getDefaultTransferType(bits));
211 if (bits < 1 || bits > 16) {
212 throw new IllegalArgumentException("Number of bits must be between"
213 +" 1 and 16.");
214 }
215 setRGBs(size, r, g, b, null);
216 setTransparentPixel(trans);
217 calculatePixelMask();
218 }
219
220 /**
221 * Constructs an <code>IndexColorModel</code> from the given
222 * arrays of red, green, blue and alpha components. All of the
223 * arrays specifying the components must have at least the specified
224 * number of entries.
225 * The <code>ColorSpace</code> is the default sRGB space.
226 * The transparency value may be any of <code>Transparency.OPAQUE</code>,
227 * <code>Transparency.BITMASK</code>,
228 * or <code>Transparency.TRANSLUCENT</code>
229 * depending on the arguments, as specified
230 * in the <a href="#transparency">class description</a> above.
231 * The transfer type is the smallest of <code>DataBuffer.TYPE_BYTE</code>
232 * or <code>DataBuffer.TYPE_USHORT</code> that can hold a single pixel.
233 * @param bits the number of bits each pixel occupies
234 * @param size the size of the color component arrays
235 * @param r the array of red color components
236 * @param g the array of green color components
237 * @param b the array of blue color components
238 * @param a the array of alpha value components
239 * @throws IllegalArgumentException if <code>bits</code> is less
240 * than 1 or greater than 16
241 * @throws IllegalArgumentException if <code>size</code> is less
242 * than 1
243 */
244 public IndexColorModel(int bits, int size,
245 byte r[], byte g[], byte b[], byte a[]) {
246 super (bits, alphaBits,
247 ColorSpace.getInstance(ColorSpace.CS_sRGB),
248 true, false, TRANSLUCENT,
249 ColorModel.getDefaultTransferType(bits));
250 if (bits < 1 || bits > 16) {
251 throw new IllegalArgumentException("Number of bits must be between"
252 +" 1 and 16.");
253 }
254 setRGBs (size, r, g, b, a);
255 calculatePixelMask();
256 }
257
258 /**
259 * Constructs an <code>IndexColorModel</code> from a single
260 * array of interleaved red, green, blue and optional alpha
261 * components. The array must have enough values in it to
262 * fill all of the needed component arrays of the specified
263 * size. The <code>ColorSpace</code> is the default sRGB space.
264 * The transparency value may be any of <code>Transparency.OPAQUE</code>,
265 * <code>Transparency.BITMASK</code>,
266 * or <code>Transparency.TRANSLUCENT</code>
267 * depending on the arguments, as specified
268 * in the <a href="#transparency">class description</a> above.
269 * The transfer type is the smallest of
270 * <code>DataBuffer.TYPE_BYTE</code> or <code>DataBuffer.TYPE_USHORT</code>
271 * that can hold a single pixel.
272 *
273 * @param bits the number of bits each pixel occupies
274 * @param size the size of the color component arrays
275 * @param cmap the array of color components
276 * @param start the starting offset of the first color component
277 * @param hasalpha indicates whether alpha values are contained in
278 * the <code>cmap</code> array
279 * @throws IllegalArgumentException if <code>bits</code> is less
280 * than 1 or greater than 16
281 * @throws IllegalArgumentException if <code>size</code> is less
282 * than 1
283 */
284 public IndexColorModel(int bits, int size, byte cmap[], int start,
285 boolean hasalpha) {
286 this(bits, size, cmap, start, hasalpha, -1);
287 if (bits < 1 || bits > 16) {
288 throw new IllegalArgumentException("Number of bits must be between"
289 +" 1 and 16.");
290 }
291 }
292
293 /**
294 * Constructs an <code>IndexColorModel</code> from a single array of
295 * interleaved red, green, blue and optional alpha components. The
296 * specified transparent index represents a pixel that is made
297 * entirely transparent regardless of any alpha value specified
298 * for it. The array must have enough values in it to fill all
299 * of the needed component arrays of the specified size.
300 * The <code>ColorSpace</code> is the default sRGB space.
301 * The transparency value may be any of <code>Transparency.OPAQUE</code>,
302 * <code>Transparency.BITMASK</code>,
303 * or <code>Transparency.TRANSLUCENT</code>
304 * depending on the arguments, as specified
305 * in the <a href="#transparency">class description</a> above.
306 * The transfer type is the smallest of
307 * <code>DataBuffer.TYPE_BYTE</code> or <code>DataBuffer.TYPE_USHORT</code>
308 * that can hold a single pixel.
309 * @param bits the number of bits each pixel occupies
310 * @param size the size of the color component arrays
311 * @param cmap the array of color components
312 * @param start the starting offset of the first color component
313 * @param hasalpha indicates whether alpha values are contained in
314 * the <code>cmap</code> array
315 * @param trans the index of the fully transparent pixel
316 * @throws IllegalArgumentException if <code>bits</code> is less than
317 * 1 or greater than 16
318 * @throws IllegalArgumentException if <code>size</code> is less than
319 * 1
320 */
321 public IndexColorModel(int bits, int size, byte cmap[], int start,
322 boolean hasalpha, int trans) {
323 // REMIND: This assumes the ordering: RGB[A]
324 super(bits, opaqueBits,
325 ColorSpace.getInstance(ColorSpace.CS_sRGB),
326 false, false, OPAQUE,
327 ColorModel.getDefaultTransferType(bits));
328
329 if (bits < 1 || bits > 16) {
330 throw new IllegalArgumentException("Number of bits must be between"
331 +" 1 and 16.");
332 }
333 if (size < 1) {
334 throw new IllegalArgumentException("Map size ("+size+
335 ") must be >= 1");
336 }
337 map_size = size;
338 rgb = new int[calcRealMapSize(bits, size)];
339 int j = start;
340 int alpha = 0xff;
341 boolean allgray = true;
342 int transparency = OPAQUE;
343 for (int i = 0; i < size; i++) {
344 int r = cmap[j++] & 0xff;
345 int g = cmap[j++] & 0xff;
346 int b = cmap[j++] & 0xff;
347 allgray = allgray && (r == g) && (g == b);
348 if (hasalpha) {
349 alpha = cmap[j++] & 0xff;
350 if (alpha != 0xff) {
351 if (alpha == 0x00) {
352 if (transparency == OPAQUE) {
353 transparency = BITMASK;
354 }
355 if (transparent_index < 0) {
356 transparent_index = i;
357 }
358 } else {
359 transparency = TRANSLUCENT;
360 }
361 allgray = false;
362 }
363 }
364 rgb[i] = (alpha << 24) | (r << 16) | (g << 8) | b;
365 }
366 this.allgrayopaque = allgray;
367 setTransparency(transparency);
368 setTransparentPixel(trans);
369 calculatePixelMask();
370 }
371
372 /**
373 * Constructs an <code>IndexColorModel</code> from an array of
374 * ints where each int is comprised of red, green, blue, and
375 * optional alpha components in the default RGB color model format.
376 * The specified transparent index represents a pixel that is made
377 * entirely transparent regardless of any alpha value specified
378 * for it. The array must have enough values in it to fill all
379 * of the needed component arrays of the specified size.
380 * The <code>ColorSpace</code> is the default sRGB space.
381 * The transparency value may be any of <code>Transparency.OPAQUE</code>,
382 * <code>Transparency.BITMASK</code>,
383 * or <code>Transparency.TRANSLUCENT</code>
384 * depending on the arguments, as specified
385 * in the <a href="#transparency">class description</a> above.
386 * @param bits the number of bits each pixel occupies
387 * @param size the size of the color component arrays
388 * @param cmap the array of color components
389 * @param start the starting offset of the first color component
390 * @param hasalpha indicates whether alpha values are contained in
391 * the <code>cmap</code> array
392 * @param trans the index of the fully transparent pixel
393 * @param transferType the data type of the array used to represent
394 * pixel values. The data type must be either
395 * <code>DataBuffer.TYPE_BYTE</code> or
396 * <code>DataBuffer.TYPE_USHORT</code>.
397 * @throws IllegalArgumentException if <code>bits</code> is less
398 * than 1 or greater than 16
399 * @throws IllegalArgumentException if <code>size</code> is less
400 * than 1
401 * @throws IllegalArgumentException if <code>transferType</code> is not
402 * one of <code>DataBuffer.TYPE_BYTE</code> or
403 * <code>DataBuffer.TYPE_USHORT</code>
404 */
405 public IndexColorModel(int bits, int size,
406 int cmap[], int start,
407 boolean hasalpha, int trans, int transferType) {
408 // REMIND: This assumes the ordering: RGB[A]
409 super(bits, opaqueBits,
410 ColorSpace.getInstance(ColorSpace.CS_sRGB),
411 false, false, OPAQUE,
412 transferType);
413
414 if (bits < 1 || bits > 16) {
415 throw new IllegalArgumentException("Number of bits must be between"
416 +" 1 and 16.");
417 }
418 if (size < 1) {
419 throw new IllegalArgumentException("Map size ("+size+
420 ") must be >= 1");
421 }
422 if ((transferType != DataBuffer.TYPE_BYTE) &&
423 (transferType != DataBuffer.TYPE_USHORT)) {
424 throw new IllegalArgumentException("transferType must be either" +
425 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT");
426 }
427
428 setRGBs(size, cmap, start, hasalpha);
429 setTransparentPixel(trans);
430 calculatePixelMask();
431 }
432
433 /**
434 * Constructs an <code>IndexColorModel</code> from an
435 * <code>int</code> array where each <code>int</code> is
436 * comprised of red, green, blue, and alpha
437 * components in the default RGB color model format.
438 * The array must have enough values in it to fill all
439 * of the needed component arrays of the specified size.
440 * The <code>ColorSpace</code> is the default sRGB space.
441 * The transparency value may be any of <code>Transparency.OPAQUE</code>,
442 * <code>Transparency.BITMASK</code>,
443 * or <code>Transparency.TRANSLUCENT</code>
444 * depending on the arguments, as specified
445 * in the <a href="#transparency">class description</a> above.
446 * The transfer type must be one of <code>DataBuffer.TYPE_BYTE</code>
447 * <code>DataBuffer.TYPE_USHORT</code>.
448 * The <code>BigInteger</code> object specifies the valid/invalid pixels
449 * in the <code>cmap</code> array. A pixel is valid if the
450 * <code>BigInteger</code> value at that index is set, and is invalid
451 * if the <code>BigInteger</code> bit at that index is not set.
452 * @param bits the number of bits each pixel occupies
453 * @param size the size of the color component array
454 * @param cmap the array of color components
455 * @param start the starting offset of the first color component
456 * @param transferType the specified data type
457 * @param validBits a <code>BigInteger</code> object. If a bit is
458 * set in the BigInteger, the pixel at that index is valid.
459 * If a bit is not set, the pixel at that index
460 * is considered invalid. If null, all pixels are valid.
461 * Only bits from 0 to the map size are considered.
462 * @throws IllegalArgumentException if <code>bits</code> is less
463 * than 1 or greater than 16
464 * @throws IllegalArgumentException if <code>size</code> is less
465 * than 1
466 * @throws IllegalArgumentException if <code>transferType</code> is not
467 * one of <code>DataBuffer.TYPE_BYTE</code> or
468 * <code>DataBuffer.TYPE_USHORT</code>
469 *
470 * @since 1.3
471 */
472 public IndexColorModel(int bits, int size, int cmap[], int start,
473 int transferType, BigInteger validBits) {
474 super (bits, alphaBits,
475 ColorSpace.getInstance(ColorSpace.CS_sRGB),
476 true, false, TRANSLUCENT,
477 transferType);
478
479 if (bits < 1 || bits > 16) {
480 throw new IllegalArgumentException("Number of bits must be between"
481 +" 1 and 16.");
482 }
483 if (size < 1) {
484 throw new IllegalArgumentException("Map size ("+size+
485 ") must be >= 1");
486 }
487 if ((transferType != DataBuffer.TYPE_BYTE) &&
488 (transferType != DataBuffer.TYPE_USHORT)) {
489 throw new IllegalArgumentException("transferType must be either" +
490 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT");
491 }
492
493 if (validBits != null) {
494 // Check to see if it is all valid
495 for (int i=0; i < size; i++) {
496 if (!validBits.testBit(i)) {
497 this.validBits = validBits;
498 break;
499 }
500 }
501 }
502
503 setRGBs(size, cmap, start, true);
504 calculatePixelMask();
505 }
506
507 private void setRGBs(int size, byte r[], byte g[], byte b[], byte a[]) {
508 if (size < 1) {
509 throw new IllegalArgumentException("Map size ("+size+
510 ") must be >= 1");
511 }
512 map_size = size;
513 rgb = new int[calcRealMapSize(pixel_bits, size)];
514 int alpha = 0xff;
515 int transparency = OPAQUE;
516 boolean allgray = true;
517 for (int i = 0; i < size; i++) {
518 int rc = r[i] & 0xff;
519 int gc = g[i] & 0xff;
520 int bc = b[i] & 0xff;
521 allgray = allgray && (rc == gc) && (gc == bc);
522 if (a != null) {
523 alpha = a[i] & 0xff;
524 if (alpha != 0xff) {
525 if (alpha == 0x00) {
526 if (transparency == OPAQUE) {
527 transparency = BITMASK;
528 }
529 if (transparent_index < 0) {
530 transparent_index = i;
531 }
532 } else {
533 transparency = TRANSLUCENT;
534 }
535 allgray = false;
536 }
537 }
538 rgb[i] = (alpha << 24) | (rc << 16) | (gc << 8) | bc;
539 }
540 this.allgrayopaque = allgray;
541 setTransparency(transparency);
542 }
543
544 private void setRGBs(int size, int cmap[], int start, boolean hasalpha) {
545 map_size = size;
546 rgb = new int[calcRealMapSize(pixel_bits, size)];
547 int j = start;
548 int transparency = OPAQUE;
549 boolean allgray = true;
550 BigInteger validBits = this.validBits;
551 for (int i = 0; i < size; i++, j++) {
552 if (validBits != null && !validBits.testBit(i)) {
553 continue;
554 }
555 int cmaprgb = cmap[j];
556 int r = (cmaprgb >> 16) & 0xff;
557 int g = (cmaprgb >> 8) & 0xff;
558 int b = (cmaprgb ) & 0xff;
559 allgray = allgray && (r == g) && (g == b);
560 if (hasalpha) {
561 int alpha = cmaprgb >>> 24;
562 if (alpha != 0xff) {
563 if (alpha == 0x00) {
564 if (transparency == OPAQUE) {
565 transparency = BITMASK;
566 }
567 if (transparent_index < 0) {
568 transparent_index = i;
569 }
570 } else {
571 transparency = TRANSLUCENT;
572 }
573 allgray = false;
574 }
575 } else {
576 cmaprgb |= 0xff000000;
577 }
578 rgb[i] = cmaprgb;
579 }
580 this.allgrayopaque = allgray;
581 setTransparency(transparency);
582 }
583
584 private int calcRealMapSize(int bits, int size) {
585 int newSize = Math.max(1 << bits, size);
586 return Math.max(newSize, 256);
587 }
588
589 private BigInteger getAllValid() {
590 int numbytes = (map_size+7)/8;
591 byte[] valid = new byte[numbytes];
592 java.util.Arrays.fill(valid, (byte)0xff);
593 valid[0] = (byte)(0xff >>> (numbytes*8 - map_size));
594
595 return new BigInteger(1, valid);
596 }
597
598 /**
599 * Returns the transparency. Returns either OPAQUE, BITMASK,
600 * or TRANSLUCENT
601 * @return the transparency of this <code>IndexColorModel</code>
602 * @see Transparency#OPAQUE
603 * @see Transparency#BITMASK
604 * @see Transparency#TRANSLUCENT
605 */
606 public int getTransparency() {
607 return transparency;
608 }
609
610 /**
611 * Returns an array of the number of bits for each color/alpha component.
612 * The array contains the color components in the order red, green,
613 * blue, followed by the alpha component, if present.
614 * @return an array containing the number of bits of each color
615 * and alpha component of this <code>IndexColorModel</code>
616 */
617 public int[] getComponentSize() {
618 if (nBits == null) {
619 if (supportsAlpha) {
620 nBits = new int[4];
621 nBits[3] = 8;
622 }
623 else {
624 nBits = new int[3];
625 }
626 nBits[0] = nBits[1] = nBits[2] = 8;
627 }
628 return nBits.clone();
629 }
630
631 /**
632 * Returns the size of the color/alpha component arrays in this
633 * <code>IndexColorModel</code>.
634 * @return the size of the color and alpha component arrays.
635 */
636 final public int getMapSize() {
637 return map_size;
638 }
639
640 /**
641 * Returns the index of a transparent pixel in this
642 * <code>IndexColorModel</code> or -1 if there is no pixel
643 * with an alpha value of 0. If a transparent pixel was
644 * explicitly specified in one of the constructors by its
645 * index, then that index will be preferred, otherwise,
646 * the index of any pixel which happens to be fully transparent
647 * may be returned.
648 * @return the index of a transparent pixel in this
649 * <code>IndexColorModel</code> object, or -1 if there
650 * is no such pixel
651 */
652 final public int getTransparentPixel() {
653 return transparent_index;
654 }
655
656 /**
657 * Copies the array of red color components into the specified array.
658 * Only the initial entries of the array as specified by
659 * {@link #getMapSize() getMapSize} are written.
660 * @param r the specified array into which the elements of the
661 * array of red color components are copied
662 */
663 final public void getReds(byte r[]) {
664 for (int i = 0; i < map_size; i++) {
665 r[i] = (byte) (rgb[i] >> 16);
666 }
667 }
668
669 /**
670 * Copies the array of green color components into the specified array.
671 * Only the initial entries of the array as specified by
672 * <code>getMapSize</code> are written.
673 * @param g the specified array into which the elements of the
674 * array of green color components are copied
675 */
676 final public void getGreens(byte g[]) {
677 for (int i = 0; i < map_size; i++) {
678 g[i] = (byte) (rgb[i] >> 8);
679 }
680 }
681
682 /**
683 * Copies the array of blue color components into the specified array.
684 * Only the initial entries of the array as specified by
685 * <code>getMapSize</code> are written.
686 * @param b the specified array into which the elements of the
687 * array of blue color components are copied
688 */
689 final public void getBlues(byte b[]) {
690 for (int i = 0; i < map_size; i++) {
691 b[i] = (byte) rgb[i];
692 }
693 }
694
695 /**
696 * Copies the array of alpha transparency components into the
697 * specified array. Only the initial entries of the array as specified
698 * by <code>getMapSize</code> are written.
699 * @param a the specified array into which the elements of the
700 * array of alpha components are copied
701 */
702 final public void getAlphas(byte a[]) {
703 for (int i = 0; i < map_size; i++) {
704 a[i] = (byte) (rgb[i] >> 24);
705 }
706 }
707
708 /**
709 * Converts data for each index from the color and alpha component
710 * arrays to an int in the default RGB ColorModel format and copies
711 * the resulting 32-bit ARGB values into the specified array. Only
712 * the initial entries of the array as specified by
713 * <code>getMapSize</code> are
714 * written.
715 * @param rgb the specified array into which the converted ARGB
716 * values from this array of color and alpha components
717 * are copied.
718 */
719 final public void getRGBs(int rgb[]) {
720 System.arraycopy(this.rgb, 0, rgb, 0, map_size);
721 }
722
723 private void setTransparentPixel(int trans) {
724 if (trans >= 0 && trans < map_size) {
725 rgb[trans] &= 0x00ffffff;
726 transparent_index = trans;
727 allgrayopaque = false;
728 if (this.transparency == OPAQUE) {
729 setTransparency(BITMASK);
730 }
731 }
732 }
733
734 private void setTransparency(int transparency) {
735 if (this.transparency != transparency) {
736 this.transparency = transparency;
737 if (transparency == OPAQUE) {
738 supportsAlpha = false;
739 numComponents = 3;
740 nBits = opaqueBits;
741 } else {
742 supportsAlpha = true;
743 numComponents = 4;
744 nBits = alphaBits;
745 }
746 }
747 }
748
749 /**
750 * This method is called from the constructors to set the pixel_mask
751 * value, which is based on the value of pixel_bits. The pixel_mask
752 * value is used to mask off the pixel parameters for methods such
753 * as getRed(), getGreen(), getBlue(), getAlpha(), and getRGB().
754 */
755 private final void calculatePixelMask() {
756 // Note that we adjust the mask so that our masking behavior here
757 // is consistent with that of our native rendering loops.
758 int maskbits = pixel_bits;
759 if (maskbits == 3) {
760 maskbits = 4;
761 } else if (maskbits > 4 && maskbits < 8) {
762 maskbits = 8;
763 }
764 pixel_mask = (1 << maskbits) - 1;
765 }
766
767 /**
768 * Returns the red color component for the specified pixel, scaled
769 * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
770 * is specified as an int.
771 * Only the lower <em>n</em> bits of the pixel value, as specified in the
772 * <a href="#index_values">class description</a> above, are used to
773 * calculate the returned value.
774 * The returned value is a non pre-multiplied value.
775 * @param pixel the specified pixel
776 * @return the value of the red color component for the specified pixel
777 */
778 final public int getRed(int pixel) {
779 return (rgb[pixel & pixel_mask] >> 16) & 0xff;
780 }
781
782 /**
783 * Returns the green color component for the specified pixel, scaled
784 * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
785 * is specified as an int.
786 * Only the lower <em>n</em> bits of the pixel value, as specified in the
787 * <a href="#index_values">class description</a> above, are used to
788 * calculate the returned value.
789 * The returned value is a non pre-multiplied value.
790 * @param pixel the specified pixel
791 * @return the value of the green color component for the specified pixel
792 */
793 final public int getGreen(int pixel) {
794 return (rgb[pixel & pixel_mask] >> 8) & 0xff;
795 }
796
797 /**
798 * Returns the blue color component for the specified pixel, scaled
799 * from 0 to 255 in the default RGB ColorSpace, sRGB. The pixel value
800 * is specified as an int.
801 * Only the lower <em>n</em> bits of the pixel value, as specified in the
802 * <a href="#index_values">class description</a> above, are used to
803 * calculate the returned value.
804 * The returned value is a non pre-multiplied value.
805 * @param pixel the specified pixel
806 * @return the value of the blue color component for the specified pixel
807 */
808 final public int getBlue(int pixel) {
809 return rgb[pixel & pixel_mask] & 0xff;
810 }
811
812 /**
813 * Returns the alpha component for the specified pixel, scaled
814 * from 0 to 255. The pixel value is specified as an int.
815 * Only the lower <em>n</em> bits of the pixel value, as specified in the
816 * <a href="#index_values">class description</a> above, are used to
817 * calculate the returned value.
818 * @param pixel the specified pixel
819 * @return the value of the alpha component for the specified pixel
820 */
821 final public int getAlpha(int pixel) {
822 return (rgb[pixel & pixel_mask] >> 24) & 0xff;
823 }
824
825 /**
826 * Returns the color/alpha components of the pixel in the default
827 * RGB color model format. The pixel value is specified as an int.
828 * Only the lower <em>n</em> bits of the pixel value, as specified in the
829 * <a href="#index_values">class description</a> above, are used to
830 * calculate the returned value.
831 * The returned value is in a non pre-multiplied format.
832 * @param pixel the specified pixel
833 * @return the color and alpha components of the specified pixel
834 * @see ColorModel#getRGBdefault
835 */
836 final public int getRGB(int pixel) {
837 return rgb[pixel & pixel_mask];
838 }
839
840 private static final int CACHESIZE = 40;
841 private int lookupcache[] = new int[CACHESIZE];
842
843 /**
844 * Returns a data element array representation of a pixel in this
845 * ColorModel, given an integer pixel representation in the
846 * default RGB color model. This array can then be passed to the
847 * {@link WritableRaster#setDataElements(int, int, java.lang.Object) setDataElements}
848 * method of a {@link WritableRaster} object. If the pixel variable is
849 * <code>null</code>, a new array is allocated. If <code>pixel</code>
850 * is not <code>null</code>, it must be
851 * a primitive array of type <code>transferType</code>; otherwise, a
852 * <code>ClassCastException</code> is thrown. An
853 * <code>ArrayIndexOutOfBoundsException</code> is
854 * thrown if <code>pixel</code> is not large enough to hold a pixel
855 * value for this <code>ColorModel</code>. The pixel array is returned.
856 * <p>
857 * Since <code>IndexColorModel</code> can be subclassed, subclasses
858 * inherit the implementation of this method and if they don't
859 * override it then they throw an exception if they use an
860 * unsupported <code>transferType</code>.
861 *
862 * @param rgb the integer pixel representation in the default RGB
863 * color model
864 * @param pixel the specified pixel
865 * @return an array representation of the specified pixel in this
866 * <code>IndexColorModel</code>.
867 * @throws ClassCastException if <code>pixel</code>
868 * is not a primitive array of type <code>transferType</code>
869 * @throws ArrayIndexOutOfBoundsException if
870 * <code>pixel</code> is not large enough to hold a pixel value
871 * for this <code>ColorModel</code>
872 * @throws UnsupportedOperationException if <code>transferType</code>
873 * is invalid
874 * @see WritableRaster#setDataElements
875 * @see SampleModel#setDataElements
876 */
877 public synchronized Object getDataElements(int rgb, Object pixel) {
878 int red = (rgb>>16) & 0xff;
879 int green = (rgb>>8) & 0xff;
880 int blue = rgb & 0xff;
881 int alpha = (rgb>>>24);
882 int pix = 0;
883
884 // Note that pixels are stored at lookupcache[2*i]
885 // and the rgb that was searched is stored at
886 // lookupcache[2*i+1]. Also, the pixel is first
887 // inverted using the unary complement operator
888 // before storing in the cache so it can never be 0.
889 for (int i = CACHESIZE - 2; i >= 0; i -= 2) {
890 if ((pix = lookupcache[i]) == 0) {
891 break;
892 }
893 if (rgb == lookupcache[i+1]) {
894 return installpixel(pixel, ~pix);
895 }
896 }
897
898 if (allgrayopaque) {
899 // IndexColorModel objects are all tagged as
900 // non-premultiplied so ignore the alpha value
901 // of the incoming color, convert the
902 // non-premultiplied color components to a
903 // grayscale value and search for the closest
904 // gray value in the palette. Since all colors
905 // in the palette are gray, we only need compare
906 // to one of the color components for a match
907 // using a simple linear distance formula.
908
909 int minDist = 256;
910 int d;
911 int gray = (int) (red*77 + green*150 + blue*29 + 128)/256;
912
913 for (int i = 0; i < map_size; i++) {
914 if (this.rgb[i] == 0x0) {
915 // For allgrayopaque colormaps, entries are 0
916 // iff they are an invalid color and should be
917 // ignored during color searches.
918 continue;
919 }
920 d = (this.rgb[i] & 0xff) - gray;
921 if (d < 0) d = -d;
922 if (d < minDist) {
923 pix = i;
924 if (d == 0) {
925 break;
926 }
927 minDist = d;
928 }
929 }
930 } else if (transparency == OPAQUE) {
931 // IndexColorModel objects are all tagged as
932 // non-premultiplied so ignore the alpha value
933 // of the incoming color and search for closest
934 // color match independently using a 3 component
935 // Euclidean distance formula.
936 // For opaque colormaps, palette entries are 0
937 // iff they are an invalid color and should be
938 // ignored during color searches.
939 // As an optimization, exact color searches are
940 // likely to be fairly common in opaque colormaps
941 // so first we will do a quick search for an
942 // exact match.
943
944 int smallestError = Integer.MAX_VALUE;
945 int lut[] = this.rgb;
946 int lutrgb;
947 for (int i=0; i < map_size; i++) {
948 lutrgb = lut[i];
949 if (lutrgb == rgb && lutrgb != 0) {
950 pix = i;
951 smallestError = 0;
952 break;
953 }
954 }
955
956 if (smallestError != 0) {
957 for (int i=0; i < map_size; i++) {
958 lutrgb = lut[i];
959 if (lutrgb == 0) {
960 continue;
961 }
962
963 int tmp = ((lutrgb >> 16) & 0xff) - red;
964 int currentError = tmp*tmp;
965 if (currentError < smallestError) {
966 tmp = ((lutrgb >> 8) & 0xff) - green;
967 currentError += tmp * tmp;
968 if (currentError < smallestError) {
969 tmp = (lutrgb & 0xff) - blue;
970 currentError += tmp * tmp;
971 if (currentError < smallestError) {
972 pix = i;
973 smallestError = currentError;
974 }
975 }
976 }
977 }
978 }
979 } else if (alpha == 0 && transparent_index >= 0) {
980 // Special case - transparent color maps to the
981 // specified transparent pixel, if there is one
982
983 pix = transparent_index;
984 } else {
985 // IndexColorModel objects are all tagged as
986 // non-premultiplied so use non-premultiplied
987 // color components in the distance calculations.
988 // Look for closest match using a 4 component
989 // Euclidean distance formula.
990
991 int smallestError = Integer.MAX_VALUE;
992 int lut[] = this.rgb;
993 for (int i=0; i < map_size; i++) {
994 int lutrgb = lut[i];
995 if (lutrgb == rgb) {
996 if (validBits != null && !validBits.testBit(i)) {
997 continue;
998 }
999 pix = i;
1000 break;
1001 }
1002
1003 int tmp = ((lutrgb >> 16) & 0xff) - red;
1004 int currentError = tmp*tmp;
1005 if (currentError < smallestError) {
1006 tmp = ((lutrgb >> 8) & 0xff) - green;
1007 currentError += tmp * tmp;
1008 if (currentError < smallestError) {
1009 tmp = (lutrgb & 0xff) - blue;
1010 currentError += tmp * tmp;
1011 if (currentError < smallestError) {
1012 tmp = (lutrgb >>> 24) - alpha;
1013 currentError += tmp * tmp;
1014 if (currentError < smallestError &&
1015 (validBits == null || validBits.testBit(i)))
1016 {
1017 pix = i;
1018 smallestError = currentError;
1019 }
1020 }
1021 }
1022 }
1023 }
1024 }
1025 System.arraycopy(lookupcache, 2, lookupcache, 0, CACHESIZE - 2);
1026 lookupcache[CACHESIZE - 1] = rgb;
1027 lookupcache[CACHESIZE - 2] = ~pix;
1028 return installpixel(pixel, pix);
1029 }
1030
1031 private Object installpixel(Object pixel, int pix) {
1032 switch (transferType) {
1033 case DataBuffer.TYPE_INT:
1034 int[] intObj;
1035 if (pixel == null) {
1036 pixel = intObj = new int[1];
1037 } else {
1038 intObj = (int[]) pixel;
1039 }
1040 intObj[0] = pix;
1041 break;
1042 case DataBuffer.TYPE_BYTE:
1043 byte[] byteObj;
1044 if (pixel == null) {
1045 pixel = byteObj = new byte[1];
1046 } else {
1047 byteObj = (byte[]) pixel;
1048 }
1049 byteObj[0] = (byte) pix;
1050 break;
1051 case DataBuffer.TYPE_USHORT:
1052 short[] shortObj;
1053 if (pixel == null) {
1054 pixel = shortObj = new short[1];
1055 } else {
1056 shortObj = (short[]) pixel;
1057 }
1058 shortObj[0] = (short) pix;
1059 break;
1060 default:
1061 throw new UnsupportedOperationException("This method has not been "+
1062 "implemented for transferType " + transferType);
1063 }
1064 return pixel;
1065 }
1066
1067 /**
1068 * Returns an array of unnormalized color/alpha components for a
1069 * specified pixel in this <code>ColorModel</code>. The pixel value
1070 * is specified as an int. If the <code>components</code> array is <code>null</code>,
1071 * a new array is allocated that contains
1072 * <code>offset + getNumComponents()</code> elements.
1073 * The <code>components</code> array is returned,
1074 * with the alpha component included
1075 * only if <code>hasAlpha</code> returns true.
1076 * Color/alpha components are stored in the <code>components</code> array starting
1077 * at <code>offset</code> even if the array is allocated by this method.
1078 * An <code>ArrayIndexOutOfBoundsException</code>
1079 * is thrown if the <code>components</code> array is not <code>null</code> and is
1080 * not large enough to hold all the color and alpha components
1081 * starting at <code>offset</code>.
1082 * @param pixel the specified pixel
1083 * @param components the array to receive the color and alpha
1084 * components of the specified pixel
1085 * @param offset the offset into the <code>components</code> array at
1086 * which to start storing the color and alpha components
1087 * @return an array containing the color and alpha components of the
1088 * specified pixel starting at the specified offset.
1089 * @see ColorModel#hasAlpha
1090 * @see ColorModel#getNumComponents
1091 */
1092 public int[] getComponents(int pixel, int[] components, int offset) {
1093 if (components == null) {
1094 components = new int[offset+numComponents];
1095 }
1096
1097 // REMIND: Needs to change if different color space
1098 components[offset+0] = getRed(pixel);
1099 components[offset+1] = getGreen(pixel);
1100 components[offset+2] = getBlue(pixel);
1101 if (supportsAlpha && (components.length-offset) > 3) {
1102 components[offset+3] = getAlpha(pixel);
1103 }
1104
1105 return components;
1106 }
1107
1108 /**
1109 * Returns an array of unnormalized color/alpha components for
1110 * a specified pixel in this <code>ColorModel</code>. The pixel
1111 * value is specified by an array of data elements of type
1112 * <code>transferType</code> passed in as an object reference.
1113 * If <code>pixel</code> is not a primitive array of type
1114 * <code>transferType</code>, a <code>ClassCastException</code>
1115 * is thrown. An <code>ArrayIndexOutOfBoundsException</code>
1116 * is thrown if <code>pixel</code> is not large enough to hold
1117 * a pixel value for this <code>ColorModel</code>. If the
1118 * <code>components</code> array is <code>null</code>, a new array
1119 * is allocated that contains
1120 * <code>offset + getNumComponents()</code> elements.
1121 * The <code>components</code> array is returned,
1122 * with the alpha component included
1123 * only if <code>hasAlpha</code> returns true.
1124 * Color/alpha components are stored in the <code>components</code>
1125 * array starting at <code>offset</code> even if the array is
1126 * allocated by this method. An
1127 * <code>ArrayIndexOutOfBoundsException</code> is also
1128 * thrown if the <code>components</code> array is not
1129 * <code>null</code> and is not large enough to hold all the color
1130 * and alpha components starting at <code>offset</code>.
1131 * <p>
1132 * Since <code>IndexColorModel</code> can be subclassed, subclasses
1133 * inherit the implementation of this method and if they don't
1134 * override it then they throw an exception if they use an
1135 * unsupported <code>transferType</code>.
1136 *
1137 * @param pixel the specified pixel
1138 * @param components an array that receives the color and alpha
1139 * components of the specified pixel
1140 * @param offset the index into the <code>components</code> array at
1141 * which to begin storing the color and alpha components of the
1142 * specified pixel
1143 * @return an array containing the color and alpha components of the
1144 * specified pixel starting at the specified offset.
1145 * @throws ArrayIndexOutOfBoundsException if <code>pixel</code>
1146 * is not large enough to hold a pixel value for this
1147 * <code>ColorModel</code> or if the
1148 * <code>components</code> array is not <code>null</code>
1149 * and is not large enough to hold all the color
1150 * and alpha components starting at <code>offset</code>
1151 * @throws ClassCastException if <code>pixel</code> is not a
1152 * primitive array of type <code>transferType</code>
1153 * @throws UnsupportedOperationException if <code>transferType</code>
1154 * is not one of the supported transer types
1155 * @see ColorModel#hasAlpha
1156 * @see ColorModel#getNumComponents
1157 */
1158 public int[] getComponents(Object pixel, int[] components, int offset) {
1159 int intpixel;
1160 switch (transferType) {
1161 case DataBuffer.TYPE_BYTE:
1162 byte bdata[] = (byte[])pixel;
1163 intpixel = bdata[0] & 0xff;
1164 break;
1165 case DataBuffer.TYPE_USHORT:
1166 short sdata[] = (short[])pixel;
1167 intpixel = sdata[0] & 0xffff;
1168 break;
1169 case DataBuffer.TYPE_INT:
1170 int idata[] = (int[])pixel;
1171 intpixel = idata[0];
1172 break;
1173 default:
1174 throw new UnsupportedOperationException("This method has not been "+
1175 "implemented for transferType " + transferType);
1176 }
1177 return getComponents(intpixel, components, offset);
1178 }
1179
1180 /**
1181 * Returns a pixel value represented as an int in this
1182 * <code>ColorModel</code> given an array of unnormalized
1183 * color/alpha components. An
1184 * <code>ArrayIndexOutOfBoundsException</code>
1185 * is thrown if the <code>components</code> array is not large
1186 * enough to hold all of the color and alpha components starting
1187 * at <code>offset</code>. Since
1188 * <code>ColorModel</code> can be subclassed, subclasses inherit the
1189 * implementation of this method and if they don't override it then
1190 * they throw an exception if they use an unsupported transferType.
1191 * @param components an array of unnormalized color and alpha
1192 * components
1193 * @param offset the index into <code>components</code> at which to
1194 * begin retrieving the color and alpha components
1195 * @return an <code>int</code> pixel value in this
1196 * <code>ColorModel</code> corresponding to the specified components.
1197 * @throws ArrayIndexOutOfBoundsException if
1198 * the <code>components</code> array is not large enough to
1199 * hold all of the color and alpha components starting at
1200 * <code>offset</code>
1201 * @throws UnsupportedOperationException if <code>transferType</code>
1202 * is invalid
1203 */
1204 public int getDataElement(int[] components, int offset) {
1205 int rgb = (components[offset+0]<<16)
1206 | (components[offset+1]<<8) | (components[offset+2]);
1207 if (supportsAlpha) {
1208 rgb |= (components[offset+3]<<24);
1209 }
1210 else {
1211 rgb |= 0xff000000;
1212 }
1213 Object inData = getDataElements(rgb, null);
1214 int pixel;
1215 switch (transferType) {
1216 case DataBuffer.TYPE_BYTE:
1217 byte bdata[] = (byte[])inData;
1218 pixel = bdata[0] & 0xff;
1219 break;
1220 case DataBuffer.TYPE_USHORT:
1221 short sdata[] = (short[])inData;
1222 pixel = sdata[0];
1223 break;
1224 case DataBuffer.TYPE_INT:
1225 int idata[] = (int[])inData;
1226 pixel = idata[0];
1227 break;
1228 default:
1229 throw new UnsupportedOperationException("This method has not been "+
1230 "implemented for transferType " + transferType);
1231 }
1232 return pixel;
1233 }
1234
1235 /**
1236 * Returns a data element array representation of a pixel in this
1237 * <code>ColorModel</code> given an array of unnormalized color/alpha
1238 * components. This array can then be passed to the
1239 * <code>setDataElements</code> method of a <code>WritableRaster</code>
1240 * object. An <code>ArrayIndexOutOfBoundsException</code> is
1241 * thrown if the
1242 * <code>components</code> array is not large enough to hold all of the
1243 * color and alpha components starting at <code>offset</code>.
1244 * If the pixel variable is <code>null</code>, a new array
1245 * is allocated. If <code>pixel</code> is not <code>null</code>,
1246 * it must be a primitive array of type <code>transferType</code>;
1247 * otherwise, a <code>ClassCastException</code> is thrown.
1248 * An <code>ArrayIndexOutOfBoundsException</code> is thrown if pixel
1249 * is not large enough to hold a pixel value for this
1250 * <code>ColorModel</code>.
1251 * <p>
1252 * Since <code>IndexColorModel</code> can be subclassed, subclasses
1253 * inherit the implementation of this method and if they don't
1254 * override it then they throw an exception if they use an
1255 * unsupported <code>transferType</code>
1256 *
1257 * @param components an array of unnormalized color and alpha
1258 * components
1259 * @param offset the index into <code>components</code> at which to
1260 * begin retrieving color and alpha components
1261 * @param pixel the <code>Object</code> representing an array of color
1262 * and alpha components
1263 * @return an <code>Object</code> representing an array of color and
1264 * alpha components.
1265 * @throws ClassCastException if <code>pixel</code>
1266 * is not a primitive array of type <code>transferType</code>
1267 * @throws ArrayIndexOutOfBoundsException if
1268 * <code>pixel</code> is not large enough to hold a pixel value
1269 * for this <code>ColorModel</code> or the <code>components</code>
1270 * array is not large enough to hold all of the color and alpha
1271 * components starting at <code>offset</code>
1272 * @throws UnsupportedOperationException if <code>transferType</code>
1273 * is not one of the supported transer types
1274 * @see WritableRaster#setDataElements
1275 * @see SampleModel#setDataElements
1276 */
1277 public Object getDataElements(int[] components, int offset, Object pixel) {
1278 int rgb = (components[offset+0]<<16) | (components[offset+1]<<8)
1279 | (components[offset+2]);
1280 if (supportsAlpha) {
1281 rgb |= (components[offset+3]<<24);
1282 }
1283 else {
1284 rgb &= 0xff000000;
1285 }
1286 return getDataElements(rgb, pixel);
1287 }
1288
1289 /**
1290 * Creates a <code>WritableRaster</code> with the specified width
1291 * and height that has a data layout (<code>SampleModel</code>)
1292 * compatible with this <code>ColorModel</code>. This method
1293 * only works for color models with 16 or fewer bits per pixel.
1294 * <p>
1295 * Since <code>IndexColorModel</code> can be subclassed, any
1296 * subclass that supports greater than 16 bits per pixel must
1297 * override this method.
1298 *
1299 * @param w the width to apply to the new <code>WritableRaster</code>
1300 * @param h the height to apply to the new <code>WritableRaster</code>
1301 * @return a <code>WritableRaster</code> object with the specified
1302 * width and height.
1303 * @throws UnsupportedOperationException if the number of bits in a
1304 * pixel is greater than 16
1305 * @see WritableRaster
1306 * @see SampleModel
1307 */
1308 public WritableRaster createCompatibleWritableRaster(int w, int h) {
1309 WritableRaster raster;
1310
1311 if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
1312 // TYPE_BINARY
1313 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
1314 w, h, 1, pixel_bits, null);
1315 }
1316 else if (pixel_bits <= 8) {
1317 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
1318 w,h,1,null);
1319 }
1320 else if (pixel_bits <= 16) {
1321 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT,
1322 w,h,1,null);
1323 }
1324 else {
1325 throw new
1326 UnsupportedOperationException("This method is not supported "+
1327 " for pixel bits > 16.");
1328 }
1329 return raster;
1330 }
1331
1332 /**
1333 * Returns <code>true</code> if <code>raster</code> is compatible
1334 * with this <code>ColorModel</code> or <code>false</code> if it
1335 * is not compatible with this <code>ColorModel</code>.
1336 * @param raster the {@link Raster} object to test for compatibility
1337 * @return <code>true</code> if <code>raster</code> is compatible
1338 * with this <code>ColorModel</code>; <code>false</code> otherwise.
1339 *
1340 */
1341 public boolean isCompatibleRaster(Raster raster) {
1342
1343 int size = raster.getSampleModel().getSampleSize(0);
1344 return ((raster.getTransferType() == transferType) &&
1345 (raster.getNumBands() == 1) && ((1 << size) >= map_size));
1346 }
1347
1348 /**
1349 * Creates a <code>SampleModel</code> with the specified
1350 * width and height that has a data layout compatible with
1351 * this <code>ColorModel</code>.
1352 * @param w the width to apply to the new <code>SampleModel</code>
1353 * @param h the height to apply to the new <code>SampleModel</code>
1354 * @return a <code>SampleModel</code> object with the specified
1355 * width and height.
1356 * @throws IllegalArgumentException if <code>w</code> or
1357 * <code>h</code> is not greater than 0
1358 * @see SampleModel
1359 */
1360 public SampleModel createCompatibleSampleModel(int w, int h) {
1361 int[] off = new int[1];
1362 off[0] = 0;
1363 if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
1364 return new MultiPixelPackedSampleModel(transferType, w, h,
1365 pixel_bits);
1366 }
1367 else {
1368 return new ComponentSampleModel(transferType, w, h, 1, w,
1369 off);
1370 }
1371 }
1372
1373 /**
1374 * Checks if the specified <code>SampleModel</code> is compatible
1375 * with this <code>ColorModel</code>. If <code>sm</code> is
1376 * <code>null</code>, this method returns <code>false</code>.
1377 * @param sm the specified <code>SampleModel</code>,
1378 * or <code>null</code>
1379 * @return <code>true</code> if the specified <code>SampleModel</code>
1380 * is compatible with this <code>ColorModel</code>; <code>false</code>
1381 * otherwise.
1382 * @see SampleModel
1383 */
1384 public boolean isCompatibleSampleModel(SampleModel sm) {
1385 // fix 4238629
1386 if (! (sm instanceof ComponentSampleModel) &&
1387 ! (sm instanceof MultiPixelPackedSampleModel) ) {
1388 return false;
1389 }
1390
1391 // Transfer type must be the same
1392 if (sm.getTransferType() != transferType) {
1393 return false;
1394 }
1395
1396 if (sm.getNumBands() != 1) {
1397 return false;
1398 }
1399
1400 return true;
1401 }
1402
1403 /**
1404 * Returns a new <code>BufferedImage</code> of TYPE_INT_ARGB or
1405 * TYPE_INT_RGB that has a <code>Raster</code> with pixel data
1406 * computed by expanding the indices in the source <code>Raster</code>
1407 * using the color/alpha component arrays of this <code>ColorModel</code>.
1408 * Only the lower <em>n</em> bits of each index value in the source
1409 * <code>Raster</code>, as specified in the
1410 * <a href="#index_values">class description</a> above, are used to
1411 * compute the color/alpha values in the returned image.
1412 * If <code>forceARGB</code> is <code>true</code>, a TYPE_INT_ARGB image is
1413 * returned regardless of whether or not this <code>ColorModel</code>
1414 * has an alpha component array or a transparent pixel.
1415 * @param raster the specified <code>Raster</code>
1416 * @param forceARGB if <code>true</code>, the returned
1417 * <code>BufferedImage</code> is TYPE_INT_ARGB; otherwise it is
1418 * TYPE_INT_RGB
1419 * @return a <code>BufferedImage</code> created with the specified
1420 * <code>Raster</code>
1421 * @throws IllegalArgumentException if the raster argument is not
1422 * compatible with this IndexColorModel
1423 */
1424 public BufferedImage convertToIntDiscrete(Raster raster,
1425 boolean forceARGB) {
1426 ColorModel cm;
1427
1428 if (!isCompatibleRaster(raster)) {
1429 throw new IllegalArgumentException("This raster is not compatible" +
1430 "with this IndexColorModel.");
1431 }
1432 if (forceARGB || transparency == TRANSLUCENT) {
1433 cm = ColorModel.getRGBdefault();
1434 }
1435 else if (transparency == BITMASK) {
1436 cm = new DirectColorModel(25, 0xff0000, 0x00ff00, 0x0000ff,
1437 0x1000000);
1438 }
1439 else {
1440 cm = new DirectColorModel(24, 0xff0000, 0x00ff00, 0x0000ff);
1441 }
1442
1443 int w = raster.getWidth();
1444 int h = raster.getHeight();
1445 WritableRaster discreteRaster =
1446 cm.createCompatibleWritableRaster(w, h);
1447 Object obj = null;
1448 int[] data = null;
1449
1450 int rX = raster.getMinX();
1451 int rY = raster.getMinY();
1452
1453 for (int y=0; y < h; y++, rY++) {
1454 obj = raster.getDataElements(rX, rY, w, 1, obj);
1455 if (obj instanceof int[]) {
1456 data = (int[])obj;
1457 } else {
1458 data = DataBuffer.toIntArray(obj);
1459 }
1460 for (int x=0; x < w; x++) {
1461 data[x] = rgb[data[x] & pixel_mask];
1462 }
1463 discreteRaster.setDataElements(0, y, w, 1, data);
1464 }
1465
1466 return new BufferedImage(cm, discreteRaster, false, null);
1467 }
1468
1469 /**
1470 * Returns whether or not the pixel is valid.
1471 * @param pixel the specified pixel value
1472 * @return <code>true</code> if <code>pixel</code>
1473 * is valid; <code>false</code> otherwise.
1474 * @since 1.3
1475 */
1476 public boolean isValid(int pixel) {
1477 return ((pixel >= 0 && pixel < map_size) &&
1478 (validBits == null || validBits.testBit(pixel)));
1479 }
1480
1481 /**
1482 * Returns whether or not all of the pixels are valid.
1483 * @return <code>true</code> if all pixels are valid;
1484 * <code>false</code> otherwise.
1485 * @since 1.3
1486 */
1487 public boolean isValid() {
1488 return (validBits == null);
1489 }
1490
1491 /**
1492 * Returns a <code>BigInteger</code> that indicates the valid/invalid
1493 * pixels in the colormap. A bit is valid if the
1494 * <code>BigInteger</code> value at that index is set, and is invalid
1495 * if the <code>BigInteger</code> value at that index is not set.
1496 * The only valid ranges to query in the <code>BigInteger</code> are
1497 * between 0 and the map size.
1498 * @return a <code>BigInteger</code> indicating the valid/invalid pixels.
1499 * @since 1.3
1500 */
1501 public BigInteger getValidPixels() {
1502 if (validBits == null) {
1503 return getAllValid();
1504 }
1505 else {
1506 return validBits;
1507 }
1508 }
1509
1510 /**
1511 * Disposes of system resources associated with this
1512 * <code>ColorModel</code> once this <code>ColorModel</code> is no
1513 * longer referenced.
1514 */
1515 public void finalize() {
1516 }
1517
1518 /**
1519 * Returns the <code>String</code> representation of the contents of
1520 * this <code>ColorModel</code>object.
1521 * @return a <code>String</code> representing the contents of this
1522 * <code>ColorModel</code> object.
1523 */
1524 public String toString() {
1525 return new String("IndexColorModel: #pixelBits = "+pixel_bits
1526 + " numComponents = "+numComponents
1527 + " color space = "+colorSpace
1528 + " transparency = "+transparency
1529 + " transIndex = "+transparent_index
1530 + " has alpha = "+supportsAlpha
1531 + " isAlphaPre = "+isAlphaPremultiplied
1532 );
1533 }
1534}
java/pkg/java/awt/image/Kernel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/Kernel.java+153−0
@@ -0,0 +1,153 @@
1/*
2 * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28
29/**
30 * The <code>Kernel</code> class defines a matrix that describes how a
31 * specified pixel and its surrounding pixels affect the value
32 * computed for the pixel's position in the output image of a filtering
33 * operation. The X origin and Y origin indicate the kernel matrix element
34 * that corresponds to the pixel position for which an output value is
35 * being computed.
36 *
37 * @see ConvolveOp
38 */
39public class Kernel implements Cloneable {
40 private int width;
41 private int height;
42 private int xOrigin;
43 private int yOrigin;
44 private float data[];
45
46 private static native void initIDs();
47 static {
48 ColorModel.loadLibraries();
49 initIDs();
50 }
51
52 /**
53 * Constructs a <code>Kernel</code> object from an array of floats.
54 * The first <code>width</code>*<code>height</code> elements of
55 * the <code>data</code> array are copied.
56 * If the length of the <code>data</code> array is less
57 * than width*height, an <code>IllegalArgumentException</code> is thrown.
58 * The X origin is (width-1)/2 and the Y origin is (height-1)/2.
59 * @param width width of the kernel
60 * @param height height of the kernel
61 * @param data kernel data in row major order
62 * @throws IllegalArgumentException if the length of <code>data</code>
63 * is less than the product of <code>width</code> and
64 * <code>height</code>
65 */
66 public Kernel(int width, int height, float data[]) {
67 this.width = width;
68 this.height = height;
69 this.xOrigin = (width-1)>>1;
70 this.yOrigin = (height-1)>>1;
71 int len = width*height;
72 if (data.length < len) {
73 throw new IllegalArgumentException("Data array too small "+
74 "(is "+data.length+
75 " and should be "+len);
76 }
77 this.data = new float[len];
78 System.arraycopy(data, 0, this.data, 0, len);
79
80 }
81
82 /**
83 * Returns the X origin of this <code>Kernel</code>.
84 * @return the X origin.
85 */
86 final public int getXOrigin(){
87 return xOrigin;
88 }
89
90 /**
91 * Returns the Y origin of this <code>Kernel</code>.
92 * @return the Y origin.
93 */
94 final public int getYOrigin() {
95 return yOrigin;
96 }
97
98 /**
99 * Returns the width of this <code>Kernel</code>.
100 * @return the width of this <code>Kernel</code>.
101 */
102 final public int getWidth() {
103 return width;
104 }
105
106 /**
107 * Returns the height of this <code>Kernel</code>.
108 * @return the height of this <code>Kernel</code>.
109 */
110 final public int getHeight() {
111 return height;
112 }
113
114 /**
115 * Returns the kernel data in row major order.
116 * The <code>data</code> array is returned. If <code>data</code>
117 * is <code>null</code>, a new array is allocated.
118 * @param data if non-null, contains the returned kernel data
119 * @return the <code>data</code> array containing the kernel data
120 * in row major order or, if <code>data</code> is
121 * <code>null</code>, a newly allocated array containing
122 * the kernel data in row major order
123 * @throws IllegalArgumentException if <code>data</code> is less
124 * than the size of this <code>Kernel</code>
125 */
126 final public float[] getKernelData(float[] data) {
127 if (data == null) {
128 data = new float[this.data.length];
129 }
130 else if (data.length < this.data.length) {
131 throw new IllegalArgumentException("Data array too small "+
132 "(should be "+this.data.length+
133 " but is "+
134 data.length+" )");
135 }
136 System.arraycopy(this.data, 0, data, 0, this.data.length);
137
138 return data;
139 }
140
141 /**
142 * Clones this object.
143 * @return a clone of this object.
144 */
145 public Object clone() {
146 try {
147 return super.clone();
148 } catch (CloneNotSupportedException e) {
149 // this shouldn't happen, since we are Cloneable
150 throw new InternalError();
151 }
152 }
153}
java/pkg/java/awt/image/LookupOp.class+0−0

Binary file not shown.

java/pkg/java/awt/image/LookupOp.java+567−0
@@ -0,0 +1,567 @@
1/*
2 * Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26
27package java.awt.image;
28
29import java.awt.color.ColorSpace;
30import java.awt.geom.Rectangle2D;
31import java.awt.Rectangle;
32import java.awt.RenderingHints;
33import java.awt.geom.Point2D;
34import sun.awt.image.ImagingLib;
35
36/**
37 * This class implements a lookup operation from the source
38 * to the destination. The LookupTable object may contain a single array
39 * or multiple arrays, subject to the restrictions below.
40 * <p>
41 * For Rasters, the lookup operates on bands. The number of
42 * lookup arrays may be one, in which case the same array is
43 * applied to all bands, or it must equal the number of Source
44 * Raster bands.
45 * <p>
46 * For BufferedImages, the lookup operates on color and alpha components.
47 * The number of lookup arrays may be one, in which case the
48 * same array is applied to all color (but not alpha) components.
49 * Otherwise, the number of lookup arrays may
50 * equal the number of Source color components, in which case no
51 * lookup of the alpha component (if present) is performed.
52 * If neither of these cases apply, the number of lookup arrays
53 * must equal the number of Source color components plus alpha components,
54 * in which case lookup is performed for all color and alpha components.
55 * This allows non-uniform rescaling of multi-band BufferedImages.
56 * <p>
57 * BufferedImage sources with premultiplied alpha data are treated in the same
58 * manner as non-premultiplied images for purposes of the lookup. That is,
59 * the lookup is done per band on the raw data of the BufferedImage source
60 * without regard to whether the data is premultiplied. If a color conversion
61 * is required to the destination ColorModel, the premultiplied state of
62 * both source and destination will be taken into account for this step.
63 * <p>
64 * Images with an IndexColorModel cannot be used.
65 * <p>
66 * If a RenderingHints object is specified in the constructor, the
67 * color rendering hint and the dithering hint may be used when color
68 * conversion is required.
69 * <p>
70 * This class allows the Source to be the same as the Destination.
71 *
72 * @see LookupTable
73 * @see java.awt.RenderingHints#KEY_COLOR_RENDERING
74 * @see java.awt.RenderingHints#KEY_DITHERING
75 */
76
77public class LookupOp implements BufferedImageOp, RasterOp {
78 private LookupTable ltable;
79 private int numComponents;
80 RenderingHints hints;
81
82 /**
83 * Constructs a <code>LookupOp</code> object given the lookup
84 * table and a <code>RenderingHints</code> object, which might
85 * be <code>null</code>.
86 * @param lookup the specified <code>LookupTable</code>
87 * @param hints the specified <code>RenderingHints</code>,
88 * or <code>null</code>
89 */
90 public LookupOp(LookupTable lookup, RenderingHints hints) {
91 this.ltable = lookup;
92 this.hints = hints;
93 numComponents = ltable.getNumComponents();
94 }
95
96 /**
97 * Returns the <code>LookupTable</code>.
98 * @return the <code>LookupTable</code> of this
99 * <code>LookupOp</code>.
100 */
101 public final LookupTable getTable() {
102 return ltable;
103 }
104
105 /**
106 * Performs a lookup operation on a <code>BufferedImage</code>.
107 * If the color model in the source image is not the same as that
108 * in the destination image, the pixels will be converted
109 * in the destination. If the destination image is <code>null</code>,
110 * a <code>BufferedImage</code> will be created with an appropriate
111 * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
112 * might be thrown if the number of arrays in the
113 * <code>LookupTable</code> does not meet the restrictions
114 * stated in the class comment above, or if the source image
115 * has an <code>IndexColorModel</code>.
116 * @param src the <code>BufferedImage</code> to be filtered
117 * @param dst the <code>BufferedImage</code> in which to
118 * store the results of the filter operation
119 * @return the filtered <code>BufferedImage</code>.
120 * @throws IllegalArgumentException if the number of arrays in the
121 * <code>LookupTable</code> does not meet the restrictions
122 * described in the class comments, or if the source image
123 * has an <code>IndexColorModel</code>.
124 */
125 public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
126 ColorModel srcCM = src.getColorModel();
127 int numBands = srcCM.getNumColorComponents();
128 ColorModel dstCM;
129 if (srcCM instanceof IndexColorModel) {
130 throw new
131 IllegalArgumentException("LookupOp cannot be "+
132 "performed on an indexed image");
133 }
134 int numComponents = ltable.getNumComponents();
135 if (numComponents != 1 &&
136 numComponents != srcCM.getNumComponents() &&
137 numComponents != srcCM.getNumColorComponents())
138 {
139 throw new IllegalArgumentException("Number of arrays in the "+
140 " lookup table ("+
141 numComponents+
142 " is not compatible with the "+
143 " src image: "+src);
144 }
145
146
147 boolean needToConvert = false;
148
149 int width = src.getWidth();
150 int height = src.getHeight();
151
152 if (dst == null) {
153 dst = createCompatibleDestImage(src, null);
154 dstCM = srcCM;
155 }
156 else {
157 if (width != dst.getWidth()) {
158 throw new
159 IllegalArgumentException("Src width ("+width+
160 ") not equal to dst width ("+
161 dst.getWidth()+")");
162 }
163 if (height != dst.getHeight()) {
164 throw new
165 IllegalArgumentException("Src height ("+height+
166 ") not equal to dst height ("+
167 dst.getHeight()+")");
168 }
169
170 dstCM = dst.getColorModel();
171 if (srcCM.getColorSpace().getType() !=
172 dstCM.getColorSpace().getType())
173 {
174 needToConvert = true;
175 dst = createCompatibleDestImage(src, null);
176 }
177
178 }
179
180 BufferedImage origDst = dst;
181
182 if (ImagingLib.filter(this, src, dst) == null) {
183 // Do it the slow way
184 WritableRaster srcRaster = src.getRaster();
185 WritableRaster dstRaster = dst.getRaster();
186
187 if (srcCM.hasAlpha()) {
188 if (numBands-1 == numComponents || numComponents == 1) {
189 int minx = srcRaster.getMinX();
190 int miny = srcRaster.getMinY();
191 int[] bands = new int[numBands-1];
192 for (int i=0; i < numBands-1; i++) {
193 bands[i] = i;
194 }
195 srcRaster =
196 srcRaster.createWritableChild(minx, miny,
197 srcRaster.getWidth(),
198 srcRaster.getHeight(),
199 minx, miny,
200 bands);
201 }
202 }
203 if (dstCM.hasAlpha()) {
204 int dstNumBands = dstRaster.getNumBands();
205 if (dstNumBands-1 == numComponents || numComponents == 1) {
206 int minx = dstRaster.getMinX();
207 int miny = dstRaster.getMinY();
208 int[] bands = new int[numBands-1];
209 for (int i=0; i < numBands-1; i++) {
210 bands[i] = i;
211 }
212 dstRaster =
213 dstRaster.createWritableChild(minx, miny,
214 dstRaster.getWidth(),
215 dstRaster.getHeight(),
216 minx, miny,
217 bands);
218 }
219 }
220
221 filter(srcRaster, dstRaster);
222 }
223
224 if (needToConvert) {
225 // ColorModels are not the same
226 ColorConvertOp ccop = new ColorConvertOp(hints);
227 ccop.filter(dst, origDst);
228 }
229
230 return origDst;
231 }
232
233 /**
234 * Performs a lookup operation on a <code>Raster</code>.
235 * If the destination <code>Raster</code> is <code>null</code>,
236 * a new <code>Raster</code> will be created.
237 * The <code>IllegalArgumentException</code> might be thrown
238 * if the source <code>Raster</code> and the destination
239 * <code>Raster</code> do not have the same
240 * number of bands or if the number of arrays in the
241 * <code>LookupTable</code> does not meet the
242 * restrictions stated in the class comment above.
243 * @param src the source <code>Raster</code> to filter
244 * @param dst the destination <code>WritableRaster</code> for the
245 * filtered <code>src</code>
246 * @return the filtered <code>WritableRaster</code>.
247 * @throws IllegalArgumentException if the source and destinations
248 * rasters do not have the same number of bands, or the
249 * number of arrays in the <code>LookupTable</code> does
250 * not meet the restrictions described in the class comments.
251 *
252 */
253 public final WritableRaster filter (Raster src, WritableRaster dst) {
254 int numBands = src.getNumBands();
255 int dstLength = dst.getNumBands();
256 int height = src.getHeight();
257 int width = src.getWidth();
258 int srcPix[] = new int[numBands];
259
260 // Create a new destination Raster, if needed
261
262 if (dst == null) {
263 dst = createCompatibleDestRaster(src);
264 }
265 else if (height != dst.getHeight() || width != dst.getWidth()) {
266 throw new
267 IllegalArgumentException ("Width or height of Rasters do not "+
268 "match");
269 }
270 dstLength = dst.getNumBands();
271
272 if (numBands != dstLength) {
273 throw new
274 IllegalArgumentException ("Number of channels in the src ("
275 + numBands +
276 ") does not match number of channels"
277 + " in the destination ("
278 + dstLength + ")");
279 }
280 int numComponents = ltable.getNumComponents();
281 if (numComponents != 1 && numComponents != src.getNumBands()) {
282 throw new IllegalArgumentException("Number of arrays in the "+
283 " lookup table ("+
284 numComponents+
285 " is not compatible with the "+
286 " src Raster: "+src);
287 }
288
289
290 if (ImagingLib.filter(this, src, dst) != null) {
291 return dst;
292 }
293
294 // Optimize for cases we know about
295 if (ltable instanceof ByteLookupTable) {
296 byteFilter ((ByteLookupTable) ltable, src, dst,
297 width, height, numBands);
298 }
299 else if (ltable instanceof ShortLookupTable) {
300 shortFilter ((ShortLookupTable) ltable, src, dst, width,
301 height, numBands);
302 }
303 else {
304 // Not one we recognize so do it slowly
305 int sminX = src.getMinX();
306 int sY = src.getMinY();
307 int dminX = dst.getMinX();
308 int dY = dst.getMinY();
309 for (int y=0; y < height; y++, sY++, dY++) {
310 int sX = sminX;
311 int dX = dminX;
312 for (int x=0; x < width; x++, sX++, dX++) {
313 // Find data for all bands at this x,y position
314 src.getPixel(sX, sY, srcPix);
315
316 // Lookup the data for all bands at this x,y position
317 ltable.lookupPixel(srcPix, srcPix);
318
319 // Put it back for all bands
320 dst.setPixel(dX, dY, srcPix);
321 }
322 }
323 }
324
325 return dst;
326 }
327
328 /**
329 * Returns the bounding box of the filtered destination image. Since
330 * this is not a geometric operation, the bounding box does not
331 * change.
332 * @param src the <code>BufferedImage</code> to be filtered
333 * @return the bounds of the filtered definition image.
334 */
335 public final Rectangle2D getBounds2D (BufferedImage src) {
336 return getBounds2D(src.getRaster());
337 }
338
339 /**
340 * Returns the bounding box of the filtered destination Raster. Since
341 * this is not a geometric operation, the bounding box does not
342 * change.
343 * @param src the <code>Raster</code> to be filtered
344 * @return the bounds of the filtered definition <code>Raster</code>.
345 */
346 public final Rectangle2D getBounds2D (Raster src) {
347 return src.getBounds();
348
349 }
350
351 /**
352 * Creates a zeroed destination image with the correct size and number of
353 * bands. If destCM is <code>null</code>, an appropriate
354 * <code>ColorModel</code> will be used.
355 * @param src Source image for the filter operation.
356 * @param destCM the destination's <code>ColorModel</code>, which
357 * can be <code>null</code>.
358 * @return a filtered destination <code>BufferedImage</code>.
359 */
360 public BufferedImage createCompatibleDestImage (BufferedImage src,
361 ColorModel destCM) {
362 BufferedImage image;
363 int w = src.getWidth();
364 int h = src.getHeight();
365 int transferType = DataBuffer.TYPE_BYTE;
366 if (destCM == null) {
367 ColorModel cm = src.getColorModel();
368 Raster raster = src.getRaster();
369 if (cm instanceof ComponentColorModel) {
370 DataBuffer db = raster.getDataBuffer();
371 boolean hasAlpha = cm.hasAlpha();
372 boolean isPre = cm.isAlphaPremultiplied();
373 int trans = cm.getTransparency();
374 int[] nbits = null;
375 if (ltable instanceof ByteLookupTable) {
376 if (db.getDataType() == db.TYPE_USHORT) {
377 // Dst raster should be of type byte
378 if (hasAlpha) {
379 nbits = new int[2];
380 if (trans == cm.BITMASK) {
381 nbits[1] = 1;
382 }
383 else {
384 nbits[1] = 8;
385 }
386 }
387 else {
388 nbits = new int[1];
389 }
390 nbits[0] = 8;
391 }
392 // For byte, no need to change the cm
393 }
394 else if (ltable instanceof ShortLookupTable) {
395 transferType = DataBuffer.TYPE_USHORT;
396 if (db.getDataType() == db.TYPE_BYTE) {
397 if (hasAlpha) {
398 nbits = new int[2];
399 if (trans == cm.BITMASK) {
400 nbits[1] = 1;
401 }
402 else {
403 nbits[1] = 16;
404 }
405 }
406 else {
407 nbits = new int[1];
408 }
409 nbits[0] = 16;
410 }
411 }
412 if (nbits != null) {
413 cm = new ComponentColorModel(cm.getColorSpace(),
414 nbits, hasAlpha, isPre,
415 trans, transferType);
416 }
417 }
418 image = new BufferedImage(cm,
419 cm.createCompatibleWritableRaster(w, h),
420 cm.isAlphaPremultiplied(),
421 null);
422 }
423 else {
424 image = new BufferedImage(destCM,
425 destCM.createCompatibleWritableRaster(w,
426 h),
427 destCM.isAlphaPremultiplied(),
428 null);
429 }
430
431 return image;
432 }
433
434 /**
435 * Creates a zeroed-destination <code>Raster</code> with the
436 * correct size and number of bands, given this source.
437 * @param src the <code>Raster</code> to be transformed
438 * @return the zeroed-destination <code>Raster</code>.
439 */
440 public WritableRaster createCompatibleDestRaster (Raster src) {
441 return src.createCompatibleWritableRaster();
442 }
443
444 /**
445 * Returns the location of the destination point given a
446 * point in the source. If <code>dstPt</code> is not
447 * <code>null</code>, it will be used to hold the return value.
448 * Since this is not a geometric operation, the <code>srcPt</code>
449 * will equal the <code>dstPt</code>.
450 * @param srcPt a <code>Point2D</code> that represents a point
451 * in the source image
452 * @param dstPt a <code>Point2D</code>that represents the location
453 * in the destination
454 * @return the <code>Point2D</code> in the destination that
455 * corresponds to the specified point in the source.
456 */
457 public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) {
458 if (dstPt == null) {
459 dstPt = new Point2D.Float();
460 }
461 dstPt.setLocation(srcPt.getX(), srcPt.getY());
462
463 return dstPt;
464 }
465
466 /**
467 * Returns the rendering hints for this op.
468 * @return the <code>RenderingHints</code> object associated
469 * with this op.
470 */
471 public final RenderingHints getRenderingHints() {
472 return hints;
473 }
474
475 private final void byteFilter(ByteLookupTable lookup, Raster src,
476 WritableRaster dst,
477 int width, int height, int numBands) {
478 int[] srcPix = null;
479
480 // Find the ref to the table and the offset
481 byte[][] table = lookup.getTable();
482 int offset = lookup.getOffset();
483 int tidx;
484 int step=1;
485
486 // Check if it is one lookup applied to all bands
487 if (table.length == 1) {
488 step=0;
489 }
490
491 int x;
492 int y;
493 int band;
494 int len = table[0].length;
495
496 // Loop through the data
497 for ( y=0; y < height; y++) {
498 tidx = 0;
499 for ( band=0; band < numBands; band++, tidx+=step) {
500 // Find data for this band, scanline
501 srcPix = src.getSamples(0, y, width, 1, band, srcPix);
502
503 for ( x=0; x < width; x++) {
504 int index = srcPix[x]-offset;
505 if (index < 0 || index > len) {
506 throw new
507 IllegalArgumentException("index ("+index+
508 "(out of range: "+
509 " srcPix["+x+
510 "]="+ srcPix[x]+
511 " offset="+ offset);
512 }
513 // Do the lookup
514 srcPix[x] = table[tidx][index];
515 }
516 // Put it back
517 dst.setSamples(0, y, width, 1, band, srcPix);
518 }
519 }
520 }
521
522 private final void shortFilter(ShortLookupTable lookup, Raster src,
523 WritableRaster dst,
524 int width, int height, int numBands) {
525 int band;
526 int[] srcPix = null;
527
528 // Find the ref to the table and the offset
529 short[][] table = lookup.getTable();
530 int offset = lookup.getOffset();
531 int tidx;
532 int step=1;
533
534 // Check if it is one lookup applied to all bands
535 if (table.length == 1) {
536 step=0;
537 }
538
539 int x = 0;
540 int y = 0;
541 int index;
542 int maxShort = (1<<16)-1;
543 // Loop through the data
544 for (y=0; y < height; y++) {
545 tidx = 0;
546 for ( band=0; band < numBands; band++, tidx+=step) {
547 // Find data for this band, scanline
548 srcPix = src.getSamples(0, y, width, 1, band, srcPix);
549
550 for ( x=0; x < width; x++) {
551 index = srcPix[x]-offset;
552 if (index < 0 || index > maxShort) {
553 throw new
554 IllegalArgumentException("index out of range "+
555 index+" x is "+x+
556 "srcPix[x]="+srcPix[x]
557 +" offset="+ offset);
558 }
559 // Do the lookup
560 srcPix[x] = table[tidx][index];
561 }
562 // Put it back
563 dst.setSamples(0, y, width, 1, band, srcPix);
564 }
565 }
566 }
567}
java/pkg/java/awt/image/LookupTable.class+0−0

Binary file not shown.

java/pkg/java/awt/image/LookupTable.java+109−0
@@ -0,0 +1,109 @@
1/*
2 * Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28
29/**
30 * This abstract class defines a lookup table object. ByteLookupTable
31 * and ShortLookupTable are subclasses, which
32 * contain byte and short data, respectively. A lookup table
33 * contains data arrays for one or more bands (or components) of an image
34 * (for example, separate arrays for R, G, and B),
35 * and it contains an offset which will be subtracted from the
36 * input values before indexing into the arrays. This allows an array
37 * smaller than the native data size to be provided for a
38 * constrained input. If there is only one array in the lookup
39 * table, it will be applied to all bands. All arrays must be the
40 * same size.
41 *
42 * @see ByteLookupTable
43 * @see ShortLookupTable
44 * @see LookupOp
45 */
46public abstract class LookupTable extends Object{
47
48 /**
49 * Constants
50 */
51
52 int numComponents;
53 int offset;
54 int numEntries;
55
56 /**
57 * Constructs a new LookupTable from the number of components and an offset
58 * into the lookup table.
59 * @param offset the offset to subtract from input values before indexing
60 * into the data arrays for this <code>LookupTable</code>
61 * @param numComponents the number of data arrays in this
62 * <code>LookupTable</code>
63 * @throws IllegalArgumentException if <code>offset</code> is less than 0
64 * or if <code>numComponents</code> is less than 1
65 */
66 protected LookupTable(int offset, int numComponents) {
67 if (offset < 0) {
68 throw new
69 IllegalArgumentException("Offset must be greater than 0");
70 }
71 if (numComponents < 1) {
72 throw new IllegalArgumentException("Number of components must "+
73 " be at least 1");
74 }
75 this.numComponents = numComponents;
76 this.offset = offset;
77 }
78
79 /**
80 * Returns the number of components in the lookup table.
81 * @return the number of components in this <code>LookupTable</code>.
82 */
83 public int getNumComponents() {
84 return numComponents;
85 }
86
87 /**
88 * Returns the offset.
89 * @return the offset of this <code>LookupTable</code>.
90 */
91 public int getOffset() {
92 return offset;
93 }
94
95 /**
96 * Returns an <code>int</code> array of components for
97 * one pixel. The <code>dest</code> array contains the
98 * result of the lookup and is returned. If dest is
99 * <code>null</code>, a new array is allocated. The
100 * source and destination can be equal.
101 * @param src the source array of components of one pixel
102 * @param dest the destination array of components for one pixel,
103 * translated with this <code>LookupTable</code>
104 * @return an <code>int</code> array of components for one
105 * pixel.
106 */
107 public abstract int[] lookupPixel(int[] src, int[] dest);
108
109}
java/pkg/java/awt/image/MemoryImageSource.class+0−0

Binary file not shown.

java/pkg/java/awt/image/MemoryImageSource.java+571−0
@@ -0,0 +1,571 @@
1/*
2 * Copyright (c) 1995, 2007, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25
26package java.awt.image;
27
28import java.awt.image.ImageConsumer;
29import java.awt.image.ImageProducer;
30import java.awt.image.ColorModel;
31import java.util.Hashtable;
32import java.util.Vector;
33import java.util.Enumeration;
34
35/**
36 * This class is an implementation of the ImageProducer interface which
37 * uses an array to produce pixel values for an Image. Here is an example
38 * which calculates a 100x100 image representing a fade from black to blue
39 * along the X axis and a fade from black to red along the Y axis:
40 * <pre>
41 *
42 * int w = 100;
43 * int h = 100;
44 * int pix[] = new int[w * h];
45 * int index = 0;
46 * for (int y = 0; y < h; y++) {
47 * int red = (y * 255) / (h - 1);
48 * for (int x = 0; x < w; x++) {
49 * int blue = (x * 255) / (w - 1);
50 * pix[index++] = (255 << 24) | (red << 16) | blue;
51 * }
52 * }
53 * Image img = createImage(new MemoryImageSource(w, h, pix, 0, w));
54 *
55 * </pre>
56 * The MemoryImageSource is also capable of managing a memory image which
57 * varies over time to allow animation or custom rendering. Here is an
58 * example showing how to set up the animation source and signal changes
59 * in the data (adapted from the MemoryAnimationSourceDemo by Garth Dickie):
60 * <pre>
61 *
62 * int pixels[];
63 * MemoryImageSource source;
64 *
65 * public void init() {
66 * int width = 50;
67 * int height = 50;
68 * int size = width * height;
69 * pixels = new int[size];
70 *
71 * int value = getBackground().getRGB();
72 * for (int i = 0; i < size; i++) {
73 * pixels[i] = value;
74 * }
75 *
76 * source = new MemoryImageSource(width, height, pixels, 0, width);
77 * source.setAnimated(true);
78 * image = createImage(source);
79 * }
80 *
81 * public void run() {
82 * Thread me = Thread.currentThread( );
83 * me.setPriority(Thread.MIN_PRIORITY);
84 *
85 * while (true) {
86 * try {
87 * Thread.sleep(10);
88 * } catch( InterruptedException e ) {
89 * return;
90 * }
91 *
92 * // Modify the values in the pixels array at (x, y, w, h)
93 *
94 * // Send the new data to the interested ImageConsumers
95 * source.newPixels(x, y, w, h);
96 * }
97 * }
98 *
99 * </pre>
100 *
101 * @see ImageProducer
102 *
103 * @author Jim Graham
104 * @author Animation capabilities inspired by the
105 * MemoryAnimationSource class written by Garth Dickie
106 */
107public class MemoryImageSource implements ImageProducer {
108 int width;
109 int height;
110 ColorModel model;
111 Object pixels;
112 int pixeloffset;
113 int pixelscan;
114 Hashtable properties;
115 Vector theConsumers = new Vector();
116 boolean animating;
117 boolean fullbuffers;
118
119 /**
120 * Constructs an ImageProducer object which uses an array of bytes
121 * to produce data for an Image object.
122 * @param w the width of the rectangle of pixels
123 * @param h the height of the rectangle of pixels
124 * @param cm the specified <code>ColorModel</code>
125 * @param pix an array of pixels
126 * @param off the offset into the array of where to store the
127 * first pixel
128 * @param scan the distance from one row of pixels to the next in
129 * the array
130 * @see java.awt.Component#createImage
131 */
132 public MemoryImageSource(int w, int h, ColorModel cm,
133 byte[] pix, int off, int scan) {
134 initialize(w, h, cm, (Object) pix, off, scan, null);
135 }
136
137 /**
138 * Constructs an ImageProducer object which uses an array of bytes
139 * to produce data for an Image object.
140 * @param w the width of the rectangle of pixels
141 * @param h the height of the rectangle of pixels
142 * @param cm the specified <code>ColorModel</code>
143 * @param pix an array of pixels
144 * @param off the offset into the array of where to store the
145 * first pixel
146 * @param scan the distance from one row of pixels to the next in
147 * the array
148 * @param props a list of properties that the <code>ImageProducer</code>
149 * uses to process an image
150 * @see java.awt.Component#createImage
151 */
152 public MemoryImageSource(int w, int h, ColorModel cm,
153 byte[] pix, int off, int scan,
154 Hashtable<?,?> props)
155 {
156 initialize(w, h, cm, (Object) pix, off, scan, props);
157 }
158
159 /**
160 * Constructs an ImageProducer object which uses an array of integers
161 * to produce data for an Image object.
162 * @param w the width of the rectangle of pixels
163 * @param h the height of the rectangle of pixels
164 * @param cm the specified <code>ColorModel</code>
165 * @param pix an array of pixels
166 * @param off the offset into the array of where to store the
167 * first pixel
168 * @param scan the distance from one row of pixels to the next in
169 * the array
170 * @see java.awt.Component#createImage
171 */
172 public MemoryImageSource(int w, int h, ColorModel cm,
173 int[] pix, int off, int scan) {
174 initialize(w, h, cm, (Object) pix, off, scan, null);
175 }
176
177 /**
178 * Constructs an ImageProducer object which uses an array of integers
179 * to produce data for an Image object.
180 * @param w the width of the rectangle of pixels
181 * @param h the height of the rectangle of pixels
182 * @param cm the specified <code>ColorModel</code>
183 * @param pix an array of pixels
184 * @param off the offset into the array of where to store the
185 * first pixel
186 * @param scan the distance from one row of pixels to the next in
187 * the array
188 * @param props a list of properties that the <code>ImageProducer</code>
189 * uses to process an image
190 * @see java.awt.Component#createImage
191 */
192 public MemoryImageSource(int w, int h, ColorModel cm,
193 int[] pix, int off, int scan,
194 Hashtable<?,?> props)
195 {
196 initialize(w, h, cm, (Object) pix, off, scan, props);
197 }
198
199 private void initialize(int w, int h, ColorModel cm,
200 Object pix, int off, int scan, Hashtable props) {
201 width = w;
202 height = h;
203 model = cm;
204 pixels = pix;
205 pixeloffset = off;
206 pixelscan = scan;
207 if (props == null) {
208 props = new Hashtable();
209 }
210 properties = props;
211 }
212
213 /**
214 * Constructs an ImageProducer object which uses an array of integers
215 * in the default RGB ColorModel to produce data for an Image object.
216 * @param w the width of the rectangle of pixels
217 * @param h the height of the rectangle of pixels
218 * @param pix an array of pixels
219 * @param off the offset into the array of where to store the
220 * first pixel
221 * @param scan the distance from one row of pixels to the next in
222 * the array
223 * @see java.awt.Component#createImage
224 * @see ColorModel#getRGBdefault
225 */
226 public MemoryImageSource(int w, int h, int pix[], int off, int scan) {
227 initialize(w, h, ColorModel.getRGBdefault(),
228 (Object) pix, off, scan, null);
229 }
230
231 /**
232 * Constructs an ImageProducer object which uses an array of integers
233 * in the default RGB ColorModel to produce data for an Image object.
234 * @param w the width of the rectangle of pixels
235 * @param h the height of the rectangle of pixels
236 * @param pix an array of pixels
237 * @param off the offset into the array of where to store the
238 * first pixel
239 * @param scan the distance from one row of pixels to the next in
240 * the array
241 * @param props a list of properties that the <code>ImageProducer</code>
242 * uses to process an image
243 * @see java.awt.Component#createImage
244 * @see ColorModel#getRGBdefault
245 */
246 public MemoryImageSource(int w, int h, int pix[], int off, int scan,
247 Hashtable<?,?> props)
248 {
249 initialize(w, h, ColorModel.getRGBdefault(),
250 (Object) pix, off, scan, props);
251 }
252
253 /**
254 * Adds an ImageConsumer to the list of consumers interested in
255 * data for this image.
256 * @param ic the specified <code>ImageConsumer</code>
257 * @throws NullPointerException if the specified
258 * <code>ImageConsumer</code> is null
259 * @see ImageConsumer
260 */
261 public synchronized void addConsumer(ImageConsumer ic) {
262 if (theConsumers.contains(ic)) {
263 return;
264 }
265 theConsumers.addElement(ic);
266 try {
267 initConsumer(ic);
268 sendPixels(ic, 0, 0, width, height);
269 if (isConsumer(ic)) {
270 ic.imageComplete(animating
271 ? ImageConsumer.SINGLEFRAMEDONE
272 : ImageConsumer.STATICIMAGEDONE);
273 if (!animating && isConsumer(ic)) {
274 ic.imageComplete(ImageConsumer.IMAGEERROR);
275 removeConsumer(ic);
276 }
277 }
278 } catch (Exception e) {
279 if (isConsumer(ic)) {
280 ic.imageComplete(ImageConsumer.IMAGEERROR);
281 }
282 }
283 }
284
285 /**
286 * Determines if an ImageConsumer is on the list of consumers currently
287 * interested in data for this image.
288 * @param ic the specified <code>ImageConsumer</code>
289 * @return <code>true</code> if the <code>ImageConsumer</code>
290 * is on the list; <code>false</code> otherwise.
291 * @see ImageConsumer
292 */
293 public synchronized boolean isConsumer(ImageConsumer ic) {
294 return theConsumers.contains(ic);
295 }
296
297 /**
298 * Removes an ImageConsumer from the list of consumers interested in
299 * data for this image.
300 * @param ic the specified <code>ImageConsumer</code>
301 * @see ImageConsumer
302 */
303 public synchronized void removeConsumer(ImageConsumer ic) {
304 theConsumers.removeElement(ic);
305 }
306
307 /**
308 * Adds an ImageConsumer to the list of consumers interested in
309 * data for this image and immediately starts delivery of the
310 * image data through the ImageConsumer interface.
311 * @param ic the specified <code>ImageConsumer</code>
312 * image data through the ImageConsumer interface.
313 * @see ImageConsumer
314 */
315 public void startProduction(ImageConsumer ic) {
316 addConsumer(ic);
317 }
318
319 /**
320 * Requests that a given ImageConsumer have the image data delivered
321 * one more time in top-down, left-right order.
322 * @param ic the specified <code>ImageConsumer</code>

249 more lines aren’t shown here.

java/pkg/java/awt/image/MultiPixelPackedSampleModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/MultiPixelPackedSampleModel.java+699−0

This diff is large: its 700 lines aren’t shown here.

java/pkg/java/awt/image/PackedColorModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/PackedColorModel.java+486−0

This diff is large: its 487 lines aren’t shown here.

java/pkg/java/awt/image/PixelGrabber.class+0−0

Binary file not shown.

java/pkg/java/awt/image/PixelGrabber.java+672−0

This diff is large: its 673 lines aren’t shown here.

java/pkg/java/awt/image/PixelInterleavedSampleModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/PixelInterleavedSampleModel.java+171−0

This diff is large: its 172 lines aren’t shown here.

java/pkg/java/awt/image/RGBImageFilter.class+0−0

Binary file not shown.

java/pkg/java/awt/image/RGBImageFilter.java+292−0

This diff is large: its 293 lines aren’t shown here.

java/pkg/java/awt/image/Raster.class+0−0

Binary file not shown.

java/pkg/java/awt/image/Raster.java+1777−0

This diff is large: its 1778 lines aren’t shown here.

java/pkg/java/awt/image/RasterFormatException.class+0−0

Binary file not shown.

java/pkg/java/awt/image/RasterFormatException.java+44−0

This diff is large: its 45 lines aren’t shown here.

java/pkg/java/awt/image/RasterOp.class+0−0

Binary file not shown.

java/pkg/java/awt/image/RasterOp.java+107−0

This diff is large: its 108 lines aren’t shown here.

java/pkg/java/awt/image/RenderedImage.class+0−0

Binary file not shown.

java/pkg/java/awt/image/RenderedImage.java+217−0

This diff is large: its 218 lines aren’t shown here.

java/pkg/java/awt/image/ReplicateScaleFilter.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ReplicateScaleFilter.java+255−0

This diff is large: its 256 lines aren’t shown here.

java/pkg/java/awt/image/RescaleOp.class+0−0

Binary file not shown.

java/pkg/java/awt/image/RescaleOp.java+666−0

This diff is large: its 667 lines aren’t shown here.

java/pkg/java/awt/image/SampleModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/SampleModel.java+1507−0

This diff is large: its 1508 lines aren’t shown here.

java/pkg/java/awt/image/ShortLookupTable.class+0−0

Binary file not shown.

java/pkg/java/awt/image/ShortLookupTable.java+204−0

This diff is large: its 205 lines aren’t shown here.

java/pkg/java/awt/image/SinglePixelPackedSampleModel.class+0−0

Binary file not shown.

java/pkg/java/awt/image/SinglePixelPackedSampleModel.java+801−0

This diff is large: its 802 lines aren’t shown here.

java/pkg/java/awt/image/TileObserver.class+0−0

Binary file not shown.

java/pkg/java/awt/image/TileObserver.java+55−0

This diff is large: its 56 lines aren’t shown here.

java/pkg/java/awt/image/VolatileImage.class+0−0

Binary file not shown.

java/pkg/java/awt/image/VolatileImage.java+342−0

This diff is large: its 343 lines aren’t shown here.

java/pkg/java/awt/image/WritableRaster.class+0−0

Binary file not shown.

java/pkg/java/awt/image/WritableRaster.java+741−0

This diff is large: its 742 lines aren’t shown here.

java/pkg/java/awt/image/WritableRenderedImage.class+0−0

Binary file not shown.

java/pkg/java/awt/image/WritableRenderedImage.java+151−0

This diff is large: its 152 lines aren’t shown here.

java/pkg/java/awt/image/mkfile+63−0

This diff is large: its 64 lines aren’t shown here.

java/pkg/java/awt/image/package.html+57−0

This diff is large: its 58 lines aren’t shown here.

java/pkg/java/awt/image/renderable/ContextualRenderedImageFactory.class+0−0

Binary file not shown.

java/pkg/java/awt/image/renderable/ContextualRenderedImageFactory.java+143−0

This diff is large: its 144 lines aren’t shown here.

java/pkg/java/awt/image/renderable/ParameterBlock.class+0−0

Binary file not shown.

java/pkg/java/awt/image/renderable/ParameterBlock.java+725−0

This diff is large: its 726 lines aren’t shown here.

java/pkg/java/awt/image/renderable/RenderContext.class+0−0

Binary file not shown.

java/pkg/java/awt/image/renderable/RenderContext.java+272−0

This diff is large: its 273 lines aren’t shown here.

java/pkg/java/awt/image/renderable/RenderableImage.class+0−0

Binary file not shown.

java/pkg/java/awt/image/renderable/RenderableImage.java+198−0

This diff is large: its 199 lines aren’t shown here.

java/pkg/java/awt/image/renderable/RenderableImageOp.class+0−0

Binary file not shown.

java/pkg/java/awt/image/renderable/RenderableImageOp.java+350−0

This diff is large: its 351 lines aren’t shown here.

java/pkg/java/awt/image/renderable/RenderableImageProducer.class+0−0

Binary file not shown.

java/pkg/java/awt/image/renderable/RenderableImageProducer.java+219−0

This diff is large: its 220 lines aren’t shown here.

java/pkg/java/awt/image/renderable/RenderedImageFactory.class+0−0

Binary file not shown.

java/pkg/java/awt/image/renderable/RenderedImageFactory.java+78−0

This diff is large: its 79 lines aren’t shown here.

java/pkg/java/awt/image/renderable/mkfile+14−0

This diff is large: its 15 lines aren’t shown here.

java/pkg/java/awt/image/renderable/package.html+51−0

This diff is large: its 52 lines aren’t shown here.