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+
26+package java.awt.image;
27+
28+import java.awt.geom.AffineTransform;
29+import java.awt.geom.NoninvertibleTransformException;
30+import java.awt.geom.Rectangle2D;
31+import java.awt.geom.Point2D;
32+import java.awt.AlphaComposite;
33+import java.awt.GraphicsEnvironment;
34+import java.awt.Rectangle;
35+import java.awt.RenderingHints;
36+import java.awt.Transparency;
37+import 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+ */
65+public 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+
26+package java.awt.image;
27+
28+import java.awt.image.ImageConsumer;
29+import java.awt.image.ColorModel;
30+import java.util.Hashtable;
31+import 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+ */
60+public 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+
26+package java.awt.image;
27+
28+import java.awt.GraphicsEnvironment;
29+import java.awt.color.ICC_Profile;
30+import java.awt.geom.Rectangle2D;
31+import java.awt.Rectangle;
32+import java.awt.geom.Point2D;
33+import java.awt.RenderingHints;
34+import sun.awt.image.ImagingLib;
35+import 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+ */
60+public 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+
36+package 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+
67+public 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+
26+package java.awt.image;
27+
28+import java.awt.BufferCapabilities;
29+import java.awt.Graphics;
30+import 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+ */
136+public 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+
26+package java.awt.image;
27+
28+import java.awt.Transparency;
29+import java.awt.color.ColorSpace;
30+import java.awt.Graphics2D;
31+import java.awt.GraphicsConfiguration;
32+import java.awt.GraphicsEnvironment;
33+import java.awt.ImageCapabilities;
34+import java.awt.geom.Rectangle2D;
35+import java.awt.geom.Point2D;
36+import java.awt.Point;
37+import java.awt.Rectangle;
38+import java.util.Hashtable;
39+import java.util.Vector;
40+
41+import sun.awt.image.BytePackedRaster;
42+import sun.awt.image.ShortComponentRaster;
43+import sun.awt.image.ByteComponentRaster;
44+import sun.awt.image.IntegerComponentRaster;
45+import 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+
70+public 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+
26+package java.awt.image;
27+
28+import java.util.Hashtable;
29+import java.awt.image.ImageConsumer;
30+import 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+
46+public 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+
26+package java.awt.image;
27+
28+import java.awt.geom.Rectangle2D;
29+import java.awt.geom.Point2D;
30+import 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+ */
61+public 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+
26+package 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+ */
43+public 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+
36+package java.awt.image;
37+
38+import java.awt.Point;
39+import java.awt.Graphics2D;
40+import java.awt.color.*;
41+import sun.java2d.cmm.ColorTransform;
42+import sun.java2d.cmm.CMSManager;
43+import sun.java2d.cmm.ProfileDeferralMgr;
44+import sun.java2d.cmm.PCMM;
45+import java.awt.geom.Rectangle2D;
46+import java.awt.geom.Point2D;
47+import 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+ */
71+public 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+
26+package java.awt.image;
27+
28+import java.awt.Transparency;
29+import java.awt.color.ColorSpace;
30+import java.awt.color.ICC_ColorSpace;
31+import sun.java2d.cmm.CMSManager;
32+import sun.java2d.cmm.ColorTransform;
33+import sun.java2d.cmm.PCMM;
34+import java.awt.Toolkit;
35+import java.util.Collections;
36+import java.util.Map;
37+import 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+ */
156+public 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+
26+package java.awt.image;
27+
28+import java.awt.color.ColorSpace;
29+import java.awt.color.ICC_ColorSpace;
30+
31+/**
32+ * A <CODE>ColorModel</CODE> class that works with pixel values that
33+ * represent color and alpha information as separate samples and that
34+ * store each sample in a separate data element. This class can be
35+ * used with an arbitrary <CODE>ColorSpace</CODE>. The number of
36+ * color samples in the pixel values must be same as the number of
37+ * color components in the <CODE>ColorSpace</CODE>. There may be a
38+ * single alpha sample.
39+ * <p>
40+ * For those methods that use
41+ * a primitive array pixel representation of type <CODE>transferType</CODE>,
42+ * the array length is the same as the number of color and alpha samples.
43+ * Color samples are stored first in the array followed by the alpha
44+ * sample, if present. The order of the color samples is specified
45+ * by the <CODE>ColorSpace</CODE>. Typically, this order reflects the
46+ * name of the color space type. For example, for <CODE>TYPE_RGB</CODE>,
47+ * index 0 corresponds to red, index 1 to green, and index 2 to blue.
48+ * <p>
49+ * The translation from pixel sample values to color/alpha components for
50+ * display or processing purposes is based on a one-to-one correspondence of
51+ * samples to components.
52+ * Depending on the transfer type used to create an instance of
53+ * <code>ComponentColorModel</code>, the pixel sample values
54+ * represented by that instance may be signed or unsigned and may
55+ * be of integral type or float or double (see below for details).
56+ * The translation from sample values to normalized color/alpha components
57+ * must follow certain rules. For float and double samples, the translation
58+ * is an identity, i.e. normalized component values are equal to the
59+ * corresponding sample values. For integral samples, the translation
60+ * should be only a simple scale and offset, where the scale and offset
61+ * constants may be different for each component. The result of
62+ * applying the scale and offset constants is a set of color/alpha
63+ * component values, which are guaranteed to fall within a certain
64+ * range. Typically, the range for a color component will be the range
65+ * defined by the <code>getMinValue</code> and <code>getMaxValue</code>
66+ * methods of the <code>ColorSpace</code> class. The range for an
67+ * alpha component should be 0.0 to 1.0.
68+ * <p>
69+ * Instances of <code>ComponentColorModel</code> created with transfer types
70+ * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
71+ * and <CODE>DataBuffer.TYPE_INT</CODE> have pixel sample values which
72+ * are treated as unsigned integral values.
73+ * The number of bits in a color or alpha sample of a pixel value might not
74+ * be the same as the number of bits for the corresponding color or alpha
75+ * sample passed to the
76+ * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code>
77+ * constructor. In
78+ * that case, this class assumes that the least significant n bits of a sample
79+ * value hold the component value, where n is the number of significant bits
80+ * for the component passed to the constructor. It also assumes that
81+ * any higher-order bits in a sample value are zero. Thus, sample values
82+ * range from 0 to 2<sup>n</sup> - 1. This class maps these sample values
83+ * to normalized color component values such that 0 maps to the value
84+ * obtained from the <code>ColorSpace's</code> <code>getMinValue</code>
85+ * method for each component and 2<sup>n</sup> - 1 maps to the value
86+ * obtained from <code>getMaxValue</code>. To create a
87+ * <code>ComponentColorModel</code> with a different color sample mapping
88+ * requires subclassing this class and overriding the
89+ * <code>getNormalizedComponents(Object, float[], int)</code> method.
90+ * The mapping for an alpha sample always maps 0 to 0.0 and
91+ * 2<sup>n</sup> - 1 to 1.0.
92+ * <p>
93+ * For instances with unsigned sample values,
94+ * the unnormalized color/alpha component representation is only
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+ */
177+public class ComponentColorModel extends ColorModel {
178+
179+ /**
180+ * <code>signed</code> is <code>true</code> for <code>short</code>,
181+ * <code>float</code>, and <code>double</code> transfer types; it
182+ * is <code>false</code> for <code>byte</code>, <code>ushort</code>,
183+ * and <code>int</code> transfer types.
184+ */
185+ private boolean signed; // true for transfer types short, float, double
186+ // false for byte, ushort, int
187+ private boolean is_sRGB_stdScale;
188+ private boolean is_LinearRGB_stdScale;
189+ private boolean is_LinearGray_stdScale;
190+ private boolean is_ICCGray_stdScale;
191+ private byte[] tosRGB8LUT;
192+ private byte[] fromsRGB8LUT8;
193+ private short[] fromsRGB8LUT16;
194+ private byte[] fromLinearGray16ToOtherGray8LUT;
195+ private short[] fromLinearGray16ToOtherGray16LUT;
196+ private boolean needScaleInit;
197+ private boolean noUnnorm;
198+ private boolean nonStdScale;
199+ private float[] min;
200+ private float[] diffMinMax;
201+ private float[] compOffset;
202+ private float[] compScale;
203+
204+ /**
205+ * Constructs a <CODE>ComponentColorModel</CODE> from the specified
206+ * parameters. Color components will be in the specified
207+ * <CODE>ColorSpace</CODE>. The supported transfer types are
208+ * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
209+ * <CODE>DataBuffer.TYPE_INT</CODE>,
210+ * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
211+ * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
212+ * If not null, the <CODE>bits</CODE> array specifies the
213+ * number of significant bits per color and alpha component and its
214+ * length should be at least the number of components in the
215+ * <CODE>ColorSpace</CODE> if there is no alpha
216+ * information in the pixel values, or one more than this number if
217+ * there is alpha information. When the <CODE>transferType</CODE> is
218+ * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
219+ * or <CODE>DataBuffer.TYPE_DOUBLE</CODE> the <CODE>bits</CODE> array
220+ * argument is ignored. <CODE>hasAlpha</CODE> indicates whether alpha
221+ * information is present. If <CODE>hasAlpha</CODE> is true, then
222+ * the boolean <CODE>isAlphaPremultiplied</CODE>
223+ * specifies how to interpret color and alpha samples in pixel values.
224+ * If the boolean is true, color samples are assumed to have been
225+ * multiplied by the alpha sample. The <CODE>transparency</CODE>
226+ * specifies what alpha values can be represented by this color model.
227+ * The acceptable <code>transparency</code> values are
228+ * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
229+ * The <CODE>transferType</CODE> is the type of primitive array used
230+ * to represent pixel values.
231+ *
232+ * @param colorSpace The <CODE>ColorSpace</CODE> associated
233+ * with this color model.
234+ * @param bits The number of significant bits per component.
235+ * May be null, in which case all bits of all
236+ * component samples will be significant.
237+ * Ignored if transferType is one of
238+ * <CODE>DataBuffer.TYPE_SHORT</CODE>,
239+ * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
240+ * <CODE>DataBuffer.TYPE_DOUBLE</CODE>,
241+ * in which case all bits of all component
242+ * samples will be significant.
243+ * @param hasAlpha If true, this color model supports alpha.
244+ * @param isAlphaPremultiplied If true, alpha is premultiplied.
245+ * @param transparency Specifies what alpha values can be represented
246+ * by this color model.
247+ * @param transferType Specifies the type of primitive array used to
248+ * represent pixel values.
249+ *
250+ * @throws IllegalArgumentException If the <CODE>bits</CODE> array
251+ * argument is not null, its length is less than the number of
252+ * color and alpha components, and transferType is one of
253+ * <CODE>DataBuffer.TYPE_BYTE</CODE>,
254+ * <CODE>DataBuffer.TYPE_USHORT</CODE>, or
255+ * <CODE>DataBuffer.TYPE_INT</CODE>.
256+ * @throws IllegalArgumentException If transferType is not one of
257+ * <CODE>DataBuffer.TYPE_BYTE</CODE>,
258+ * <CODE>DataBuffer.TYPE_USHORT</CODE>,
259+ * <CODE>DataBuffer.TYPE_INT</CODE>,
260+ * <CODE>DataBuffer.TYPE_SHORT</CODE>,
261+ * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
262+ * <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
263+ *
264+ * @see ColorSpace
265+ * @see java.awt.Transparency
266+ */
267+ public ComponentColorModel (ColorSpace colorSpace,
268+ int[] bits,
269+ boolean hasAlpha,
270+ boolean isAlphaPremultiplied,
271+ int transparency,
272+ int transferType) {
273+ super (bitsHelper(transferType, colorSpace, hasAlpha),
274+ bitsArrayHelper(bits, transferType, colorSpace, hasAlpha),
275+ colorSpace, hasAlpha, isAlphaPremultiplied, transparency,
276+ transferType);
277+ switch(transferType) {
278+ case DataBuffer.TYPE_BYTE:
279+ case DataBuffer.TYPE_USHORT:
280+ case DataBuffer.TYPE_INT:
281+ signed = false;
282+ needScaleInit = true;
283+ break;
284+ case DataBuffer.TYPE_SHORT:
285+ signed = true;
286+ needScaleInit = true;
287+ break;
288+ case DataBuffer.TYPE_FLOAT:
289+ case DataBuffer.TYPE_DOUBLE:
290+ signed = true;
291+ needScaleInit = false;
292+ noUnnorm = true;
293+ nonStdScale = false;
294+ break;
295+ default:
296+ throw new IllegalArgumentException("This constructor is not "+
297+ "compatible with transferType " + transferType);
298+ }
299+ setupLUTs();
300+ }
301+
302+ /**
303+ * Constructs a <CODE>ComponentColorModel</CODE> from the specified
304+ * parameters. Color components will be in the specified
305+ * <CODE>ColorSpace</CODE>. The supported transfer types are
306+ * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
307+ * <CODE>DataBuffer.TYPE_INT</CODE>,
308+ * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>,
309+ * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>. The number of significant
310+ * bits per color and alpha component will be 8, 16, 32, 16, 32, or 64,
311+ * respectively. The number of color components will be the
312+ * number of components in the <CODE>ColorSpace</CODE>. There will be
313+ * an alpha component if <CODE>hasAlpha</CODE> is <CODE>true</CODE>.
314+ * If <CODE>hasAlpha</CODE> is true, then
315+ * the boolean <CODE>isAlphaPremultiplied</CODE>
316+ * specifies how to interpret color and alpha samples in pixel values.
317+ * If the boolean is true, color samples are assumed to have been
318+ * multiplied by the alpha sample. The <CODE>transparency</CODE>
319+ * specifies what alpha values can be represented by this color model.
320+ * The acceptable <code>transparency</code> values are
321+ * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>.
322+ * The <CODE>transferType</CODE> is the type of primitive array used
323+ * to represent pixel values.
324+ *
325+ * @param colorSpace The <CODE>ColorSpace</CODE> associated
326+ * with this color model.
327+ * @param hasAlpha If true, this color model supports alpha.
328+ * @param isAlphaPremultiplied If true, alpha is premultiplied.
329+ * @param transparency Specifies what alpha values can be represented
330+ * by this color model.
331+ * @param transferType Specifies the type of primitive array used to
332+ * represent pixel values.
333+ *
334+ * @throws IllegalArgumentException If transferType is not one of
335+ * <CODE>DataBuffer.TYPE_BYTE</CODE>,
336+ * <CODE>DataBuffer.TYPE_USHORT</CODE>,
337+ * <CODE>DataBuffer.TYPE_INT</CODE>,
338+ * <CODE>DataBuffer.TYPE_SHORT</CODE>,
339+ * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or
340+ * <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
341+ *
342+ * @see ColorSpace
343+ * @see java.awt.Transparency
344+ * @since 1.4
345+ */
346+ public ComponentColorModel (ColorSpace colorSpace,
347+ boolean hasAlpha,
348+ boolean isAlphaPremultiplied,
349+ int transparency,
350+ int transferType) {
351+ this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
352+ transparency, transferType);
353+ }
354+
355+ private static int bitsHelper(int transferType,
356+ ColorSpace colorSpace,
357+ boolean hasAlpha) {
358+ int numBits = DataBuffer.getDataTypeSize(transferType);
359+ int numComponents = colorSpace.getNumComponents();
360+ if (hasAlpha) {
361+ ++numComponents;
362+ }
363+ return numBits * numComponents;
364+ }
365+
366+ private static int[] bitsArrayHelper(int[] origBits,
367+ int transferType,
368+ ColorSpace colorSpace,
369+ boolean hasAlpha) {
370+ switch(transferType) {
371+ case DataBuffer.TYPE_BYTE:
372+ case DataBuffer.TYPE_USHORT:
373+ case DataBuffer.TYPE_INT:
374+ if (origBits != null) {
375+ return origBits;
376+ }
377+ break;
378+ default:
379+ break;
380+ }
381+ int numBits = DataBuffer.getDataTypeSize(transferType);
382+ int numComponents = colorSpace.getNumComponents();
383+ if (hasAlpha) {
384+ ++numComponents;
385+ }
386+ int[] bits = new int[numComponents];
387+ for (int i = 0; i < numComponents; i++) {
388+ bits[i] = numBits;
389+ }
390+ return bits;
391+ }
392+
393+ private void setupLUTs() {
394+ // REMIND: there is potential to accelerate sRGB, LinearRGB,
395+ // LinearGray, ICCGray, and non-ICC Gray spaces with non-standard
396+ // scaling, if that becomes important
397+ //
398+ // NOTE: The is_xxx_stdScale and nonStdScale booleans are provisionally
399+ // set here when this method is called at construction time. These
400+ // variables may be set again when initScale is called later.
401+ // When setupLUTs returns, nonStdScale is true if (the transferType
402+ // is not float or double) AND (some minimum ColorSpace component
403+ // value is not 0.0 OR some maximum ColorSpace component value
404+ // is not 1.0). This is correct for the calls to
405+ // getNormalizedComponents(Object, float[], int) from initScale().
406+ // initScale() may change the value nonStdScale based on the
407+ // return value of getNormalizedComponents() - this will only
408+ // happen if getNormalizedComponents() has been overridden by a
409+ // subclass to make the mapping of min/max pixel sample values
410+ // something different from min/max color component values.
411+ if (is_sRGB) {
412+ is_sRGB_stdScale = true;
413+ nonStdScale = false;
414+ } else if (ColorModel.isLinearRGBspace(colorSpace)) {
415+ // Note that the built-in Linear RGB space has a normalized
416+ // range of 0.0 - 1.0 for each coordinate. Usage of these
417+ // LUTs makes that assumption.
418+ is_LinearRGB_stdScale = true;
419+ nonStdScale = false;
420+ if (transferType == DataBuffer.TYPE_BYTE) {
421+ tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
422+ fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
423+ } else {
424+ tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
425+ fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
426+ }
427+ } else if ((colorSpaceType == ColorSpace.TYPE_GRAY) &&
428+ (colorSpace instanceof ICC_ColorSpace) &&
429+ (colorSpace.getMinValue(0) == 0.0f) &&
430+ (colorSpace.getMaxValue(0) == 1.0f)) {
431+ // Note that a normalized range of 0.0 - 1.0 for the gray
432+ // component is required, because usage of these LUTs makes
433+ // that assumption.
434+ ICC_ColorSpace ics = (ICC_ColorSpace) colorSpace;
435+ is_ICCGray_stdScale = true;
436+ nonStdScale = false;
437+ fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
438+ if (ColorModel.isLinearGRAYspace(ics)) {
439+ is_LinearGray_stdScale = true;
440+ if (transferType == DataBuffer.TYPE_BYTE) {
441+ tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
442+ } else {
443+ tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
444+ }
445+ } else {
446+ if (transferType == DataBuffer.TYPE_BYTE) {
447+ tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics);
448+ fromLinearGray16ToOtherGray8LUT =
449+ ColorModel.getLinearGray16ToOtherGray8LUT(ics);
450+ } else {
451+ tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics);
452+ fromLinearGray16ToOtherGray16LUT =
453+ ColorModel.getLinearGray16ToOtherGray16LUT(ics);
454+ }
455+ }
456+ } else if (needScaleInit) {
457+ // if transferType is byte, ushort, int, or short and we
458+ // don't already know the ColorSpace has minVlaue == 0.0f and
459+ // maxValue == 1.0f for all components, we need to check that
460+ // now and setup the min[] and diffMinMax[] arrays if necessary.
461+ nonStdScale = false;
462+ for (int i = 0; i < numColorComponents; i++) {
463+ if ((colorSpace.getMinValue(i) != 0.0f) ||
464+ (colorSpace.getMaxValue(i) != 1.0f)) {
465+ nonStdScale = true;
466+ break;
467+ }
468+ }
469+ if (nonStdScale) {
470+ min = new float[numColorComponents];
471+ diffMinMax = new float[numColorComponents];
472+ for (int i = 0; i < numColorComponents; i++) {
473+ min[i] = colorSpace.getMinValue(i);
474+ diffMinMax[i] = colorSpace.getMaxValue(i) - min[i];
475+ }
476+ }
477+ }
478+ }
479+
480+ private void initScale() {
481+ // This method is called the first time any method which uses
482+ // pixel sample value to color component value scaling information
483+ // is called if the transferType supports non-standard scaling
484+ // as defined above (byte, ushort, int, and short), unless the
485+ // method is getNormalizedComponents(Object, float[], int) (that
486+ // method must be overridden to use non-standard scaling). This
487+ // method also sets up the noUnnorm boolean variable for these
488+ // transferTypes. After this method is called, the nonStdScale
489+ // variable will be true if getNormalizedComponents() maps a
490+ // sample value of 0 to anything other than 0.0f OR maps a
491+ // sample value of 2^^n - 1 (2^^15 - 1 for short transferType)
492+ // to anything other than 1.0f. Note that this can be independent
493+ // of the colorSpace min/max component values, if the
494+ // getNormalizedComponents() method has been overridden for some
495+ // reason, e.g. to provide greater dynamic range in the sample
496+ // values than in the color component values. Unfortunately,
497+ // this method can't be called at construction time, since a
498+ // subclass may still have uninitialized state that would cause
499+ // getNormalizedComponents() to return an incorrect result.
500+ needScaleInit = false; // only needs to called once
501+ if (nonStdScale || signed) {
502+ // The unnormalized form is only supported for unsigned
503+ // transferTypes and when the ColorSpace min/max values
504+ // are 0.0/1.0. When this method is called nonStdScale is
505+ // true if the latter condition does not hold. In addition,
506+ // the unnormalized form requires that the full range of
507+ // the pixel sample values map to the full 0.0 - 1.0 range
508+ // of color component values. That condition is checked
509+ // later in this method.
510+ noUnnorm = true;
511+ } else {
512+ noUnnorm = false;
513+ }
514+ float[] lowVal, highVal;
515+ switch (transferType) {
516+ case DataBuffer.TYPE_BYTE:
517+ {
518+ byte[] bpixel = new byte[numComponents];
519+ for (int i = 0; i < numColorComponents; i++) {
520+ bpixel[i] = 0;
521+ }
522+ if (supportsAlpha) {
523+ bpixel[numColorComponents] =
524+ (byte) ((1 << nBits[numColorComponents]) - 1);
525+ }
526+ lowVal = getNormalizedComponents(bpixel, null, 0);
527+ for (int i = 0; i < numColorComponents; i++) {
528+ bpixel[i] = (byte) ((1 << nBits[i]) - 1);
529+ }
530+ highVal = getNormalizedComponents(bpixel, null, 0);
531+ }
532+ break;
533+ case DataBuffer.TYPE_USHORT:
534+ {
535+ short[] uspixel = new short[numComponents];
536+ for (int i = 0; i < numColorComponents; i++) {
537+ uspixel[i] = 0;
538+ }
539+ if (supportsAlpha) {
540+ uspixel[numColorComponents] =
541+ (short) ((1 << nBits[numColorComponents]) - 1);
542+ }
543+ lowVal = getNormalizedComponents(uspixel, null, 0);
544+ for (int i = 0; i < numColorComponents; i++) {
545+ uspixel[i] = (short) ((1 << nBits[i]) - 1);
546+ }
547+ highVal = getNormalizedComponents(uspixel, null, 0);
548+ }
549+ break;
550+ case DataBuffer.TYPE_INT:
551+ {
552+ int[] ipixel = new int[numComponents];
553+ for (int i = 0; i < numColorComponents; i++) {
554+ ipixel[i] = 0;
555+ }
556+ if (supportsAlpha) {
557+ ipixel[numColorComponents] =
558+ ((1 << nBits[numColorComponents]) - 1);
559+ }
560+ lowVal = getNormalizedComponents(ipixel, null, 0);
561+ for (int i = 0; i < numColorComponents; i++) {
562+ ipixel[i] = ((1 << nBits[i]) - 1);
563+ }
564+ highVal = getNormalizedComponents(ipixel, null, 0);
565+ }
566+ break;
567+ case DataBuffer.TYPE_SHORT:
568+ {
569+ short[] spixel = new short[numComponents];
570+ for (int i = 0; i < numColorComponents; i++) {
571+ spixel[i] = 0;
572+ }
573+ if (supportsAlpha) {
574+ spixel[numColorComponents] = 32767;
575+ }
576+ lowVal = getNormalizedComponents(spixel, null, 0);
577+ for (int i = 0; i < numColorComponents; i++) {
578+ spixel[i] = 32767;
579+ }
580+ highVal = getNormalizedComponents(spixel, null, 0);
581+ }
582+ break;
583+ default:
584+ lowVal = highVal = null; // to keep the compiler from complaining
585+ break;
586+ }
587+ nonStdScale = false;
588+ for (int i = 0; i < numColorComponents; i++) {
589+ if ((lowVal[i] != 0.0f) || (highVal[i] != 1.0f)) {
590+ nonStdScale = true;
591+ break;
592+ }
593+ }
594+ if (nonStdScale) {
595+ noUnnorm = true;
596+ is_sRGB_stdScale = false;
597+ is_LinearRGB_stdScale = false;
598+ is_LinearGray_stdScale = false;
599+ is_ICCGray_stdScale = false;
600+ compOffset = new float[numColorComponents];
601+ compScale = new float[numColorComponents];
602+ for (int i = 0; i < numColorComponents; i++) {
603+ compOffset[i] = lowVal[i];
604+ compScale[i] = 1.0f / (highVal[i] - lowVal[i]);
605+ }
606+ }
607+ }
608+
609+ private int getRGBComponent(int pixel, int idx) {
610+ if (numComponents > 1) {
611+ throw new
612+ IllegalArgumentException("More than one component per pixel");
613+ }
614+ if (signed) {
615+ throw new
616+ IllegalArgumentException("Component value is signed");
617+ }
618+ if (needScaleInit) {
619+ initScale();
620+ }
621+ // Since there is only 1 component, there is no alpha
622+
623+ // Normalize the pixel in order to convert it
624+ Object opixel = null;
625+ switch (transferType) {
626+ case DataBuffer.TYPE_BYTE:
627+ {
628+ byte[] bpixel = { (byte) pixel };
629+ opixel = bpixel;
630+ }
631+ break;
632+ case DataBuffer.TYPE_USHORT:
633+ {
634+ short[] spixel = { (short) pixel };
635+ opixel = spixel;
636+ }
637+ break;
638+ case DataBuffer.TYPE_INT:
639+ {
640+ int[] ipixel = { pixel };
641+ opixel = ipixel;
642+ }
643+ break;
644+ }
645+ float[] norm = getNormalizedComponents(opixel, null, 0);
646+ float[] rgb = colorSpace.toRGB(norm);
647+
648+ return (int) (rgb[idx] * 255.0f + 0.5f);
649+ }
650+
651+ /**
652+ * Returns the red color component for the specified pixel, scaled
653+ * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
654+ * is done if necessary. The pixel value is specified as an int.
655+ * The returned value will be a non pre-multiplied value.
656+ * If the alpha is premultiplied, this method divides
657+ * it out before returning the value (if the alpha value is 0,
658+ * the red value will be 0).
659+ *
660+ * @param pixel The pixel from which you want to get the red color component.
661+ *
662+ * @return The red color component for the specified pixel, as an int.
663+ *
664+ * @throws IllegalArgumentException If there is more than
665+ * one component in this <CODE>ColorModel</CODE>.
666+ * @throws IllegalArgumentException If the component value for this
667+ * <CODE>ColorModel</CODE> is signed
668+ */
669+ public int getRed(int pixel) {
670+ return getRGBComponent(pixel, 0);
671+ }
672+
673+ /**
674+ * Returns the green color component for the specified pixel, scaled
675+ * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
676+ * is done if necessary. The pixel value is specified as an int.
677+ * The returned value will be a non
678+ * pre-multiplied value. If the alpha is premultiplied, this method
679+ * divides it out before returning the value (if the alpha value is 0,
680+ * the green value will be 0).
681+ *
682+ * @param pixel The pixel from which you want to get the green color component.
683+ *
684+ * @return The green color component for the specified pixel, as an int.
685+ *
686+ * @throws IllegalArgumentException If there is more than
687+ * one component in this <CODE>ColorModel</CODE>.
688+ * @throws IllegalArgumentException If the component value for this
689+ * <CODE>ColorModel</CODE> is signed
690+ */
691+ public int getGreen(int pixel) {
692+ return getRGBComponent(pixel, 1);
693+ }
694+
695+ /**
696+ * Returns the blue color component for the specified pixel, scaled
697+ * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
698+ * is done if necessary. The pixel value is specified as an int.
699+ * The returned value will be a non
700+ * pre-multiplied value. If the alpha is premultiplied, this method
701+ * divides it out before returning the value (if the alpha value is 0,
702+ * the blue value will be 0).
703+ *
704+ * @param pixel The pixel from which you want to get the blue color component.
705+ *
706+ * @return The blue color component for the specified pixel, as an int.
707+ *
708+ * @throws IllegalArgumentException If there is more than
709+ * one component in this <CODE>ColorModel</CODE>.
710+ * @throws IllegalArgumentException If the component value for this
711+ * <CODE>ColorModel</CODE> is signed
712+ */
713+ public int getBlue(int pixel) {
714+ return getRGBComponent(pixel, 2);
715+ }
716+
717+ /**
718+ * Returns the alpha component for the specified pixel, scaled
719+ * from 0 to 255. The pixel value is specified as an int.
720+ *
721+ * @param pixel The pixel from which you want to get the alpha component.
722+ *
723+ * @return The alpha component for the specified pixel, as an int.
724+ *
725+ * @throws IllegalArgumentException If there is more than
726+ * one component in this <CODE>ColorModel</CODE>.
727+ * @throws IllegalArgumentException If the component value for this
728+ * <CODE>ColorModel</CODE> is signed
729+ */
730+ public int getAlpha(int pixel) {
731+ if (supportsAlpha == false) {
732+ return 255;
733+ }
734+ if (numComponents > 1) {
735+ throw new
736+ IllegalArgumentException("More than one component per pixel");
737+ }
738+ if (signed) {
739+ throw new
740+ IllegalArgumentException("Component value is signed");
741+ }
742+
743+ return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f);
744+ }
745+
746+ /**
747+ * Returns the color/alpha components of the pixel in the default
748+ * RGB color model format. A color conversion is done if necessary.
749+ * The returned value will be in a non pre-multiplied format. If
750+ * the alpha is premultiplied, this method divides it out of the
751+ * color components (if the alpha value is 0, the color values will be 0).
752+ *
753+ * @param pixel The pixel from which you want to get the color/alpha components.
754+ *
755+ * @return The color/alpha components for the specified pixel, as an int.
756+ *
757+ * @throws IllegalArgumentException If there is more than
758+ * one component in this <CODE>ColorModel</CODE>.
759+ * @throws IllegalArgumentException If the component value for this
760+ * <CODE>ColorModel</CODE> is signed
761+ */
762+ public int getRGB(int pixel) {
763+ if (numComponents > 1) {
764+ throw new
765+ IllegalArgumentException("More than one component per pixel");
766+ }
767+ if (signed) {
768+ throw new
769+ IllegalArgumentException("Component value is signed");
770+ }
771+
772+ return (getAlpha(pixel) << 24)
773+ | (getRed(pixel) << 16)
774+ | (getGreen(pixel) << 8)
775+ | (getBlue(pixel) << 0);
776+ }
777+
778+ private int extractComponent(Object inData, int idx, int precision) {
779+ // Extract component idx from inData. The precision argument
780+ // should be either 8 or 16. If it's 8, this method will return
781+ // an 8-bit value. If it's 16, this method will return a 16-bit
782+ // value for transferTypes other than TYPE_BYTE. For TYPE_BYTE,
783+ // an 8-bit value will be returned.
784+
785+ // This method maps the input value corresponding to a
786+ // normalized ColorSpace component value of 0.0 to 0, and the
787+ // input value corresponding to a normalized ColorSpace
788+ // component value of 1.0 to 2^n - 1 (where n is 8 or 16), so
789+ // it is appropriate only for ColorSpaces with min/max component
790+ // values of 0.0/1.0. This will be true for sRGB, the built-in
791+ // Linear RGB and Linear Gray spaces, and any other ICC grayscale
792+ // spaces for which we have precomputed LUTs.
793+
794+ boolean needAlpha = (supportsAlpha && isAlphaPremultiplied);
795+ int alp = 0;
796+ int comp;
797+ int mask = (1 << nBits[idx]) - 1;
798+
799+ switch (transferType) {
800+ // Note: we do no clamping of the pixel data here - we
801+ // assume that the data is scaled properly
802+ case DataBuffer.TYPE_SHORT: {
803+ short sdata[] = (short[]) inData;
804+ float scalefactor = (float) ((1 << precision) - 1);
805+ if (needAlpha) {
806+ short s = sdata[numColorComponents];
807+ if (s != (short) 0) {
808+ return (int) ((((float) sdata[idx]) /
809+ ((float) s)) * scalefactor + 0.5f);
810+ } else {
811+ return 0;
812+ }
813+ } else {
814+ return (int) ((sdata[idx] / 32767.0f) * scalefactor + 0.5f);
815+ }
816+ }
817+ case DataBuffer.TYPE_FLOAT: {
818+ float fdata[] = (float[]) inData;
819+ float scalefactor = (float) ((1 << precision) - 1);
820+ if (needAlpha) {
821+ float f = fdata[numColorComponents];
822+ if (f != 0.0f) {
823+ return (int) (((fdata[idx] / f) * scalefactor) + 0.5f);
824+ } else {
825+ return 0;
826+ }
827+ } else {
828+ return (int) (fdata[idx] * scalefactor + 0.5f);
829+ }
830+ }
831+ case DataBuffer.TYPE_DOUBLE: {
832+ double ddata[] = (double[]) inData;
833+ double scalefactor = (double) ((1 << precision) - 1);
834+ if (needAlpha) {
835+ double d = ddata[numColorComponents];
836+ if (d != 0.0) {
837+ return (int) (((ddata[idx] / d) * scalefactor) + 0.5);
838+ } else {
839+ return 0;
840+ }
841+ } else {
842+ return (int) (ddata[idx] * scalefactor + 0.5);
843+ }
844+ }
845+ case DataBuffer.TYPE_BYTE:
846+ byte bdata[] = (byte[])inData;
847+ comp = bdata[idx] & mask;
848+ precision = 8;
849+ if (needAlpha) {
850+ alp = bdata[numColorComponents] & mask;
851+ }
852+ break;
853+ case DataBuffer.TYPE_USHORT:
854+ short usdata[] = (short[])inData;
855+ comp = usdata[idx] & mask;
856+ if (needAlpha) {
857+ alp = usdata[numColorComponents] & mask;
858+ }
859+ break;
860+ case DataBuffer.TYPE_INT:
861+ int idata[] = (int[])inData;
862+ comp = idata[idx];
863+ if (needAlpha) {
864+ alp = idata[numColorComponents];
865+ }
866+ break;
867+ default:
868+ throw new
869+ UnsupportedOperationException("This method has not "+
870+ "been implemented for transferType " + transferType);
871+ }
872+ if (needAlpha) {
873+ if (alp != 0) {
874+ float scalefactor = (float) ((1 << precision) - 1);
875+ float fcomp = ((float) comp) / ((float)mask);
876+ float invalp = ((float) ((1<<nBits[numColorComponents]) - 1)) /
877+ ((float) alp);
878+ return (int) (fcomp * invalp * scalefactor + 0.5f);
879+ } else {
880+ return 0;
881+ }
882+ } else {
883+ if (nBits[idx] != precision) {
884+ float scalefactor = (float) ((1 << precision) - 1);
885+ float fcomp = ((float) comp) / ((float)mask);
886+ return (int) (fcomp * scalefactor + 0.5f);
887+ }
888+ return comp;
889+ }
890+ }
891+
892+ private int getRGBComponent(Object inData, int idx) {
893+ if (needScaleInit) {
894+ initScale();
895+ }
896+ if (is_sRGB_stdScale) {
897+ return extractComponent(inData, idx, 8);
898+ } else if (is_LinearRGB_stdScale) {
899+ int lutidx = extractComponent(inData, idx, 16);
900+ return tosRGB8LUT[lutidx] & 0xff;
901+ } else if (is_ICCGray_stdScale) {
902+ int lutidx = extractComponent(inData, 0, 16);
903+ return tosRGB8LUT[lutidx] & 0xff;
904+ }
905+
906+ // Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace
907+ float[] norm = getNormalizedComponents(inData, null, 0);
908+ // Note that getNormalizedComponents returns non-premultiplied values
909+ float[] rgb = colorSpace.toRGB(norm);
910+ return (int) (rgb[idx] * 255.0f + 0.5f);
911+ }
912+
913+ /**
914+ * Returns the red color component for the specified pixel, scaled
915+ * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
916+ * is done if necessary. The <CODE>pixel</CODE> value is specified by an array
917+ * of data elements of type <CODE>transferType</CODE> passed in as an object
918+ * reference. The returned value will be a non pre-multiplied value. If the
919+ * alpha is premultiplied, this method divides it out before returning
920+ * the value (if the alpha value is 0, the red value will be 0). Since
921+ * <code>ComponentColorModel</code> can be subclassed, subclasses
922+ * inherit the implementation of this method and if they don't override
923+ * it then they throw an exception if they use an unsupported
924+ * <code>transferType</code>.
925+ *
926+ * @param inData The pixel from which you want to get the red color component,
927+ * specified by an array of data elements of type <CODE>transferType</CODE>.
928+ *
929+ * @return The red color component for the specified pixel, as an int.
930+ *
931+ * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
932+ * of type <CODE>transferType</CODE>.
933+ * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
934+ * large enough to hold a pixel value for this
935+ * <CODE>ColorModel</CODE>.
936+ * @throws UnsupportedOperationException If the transfer type of
937+ * this <CODE>ComponentColorModel</CODE>
938+ * is not one of the supported transfer types:
939+ * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
940+ * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
941+ * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
942+ */
943+ public int getRed(Object inData) {
944+ return getRGBComponent(inData, 0);
945+ }
946+
947+
948+ /**
949+ * Returns the green color component for the specified pixel, scaled
950+ * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
951+ * A color conversion is done if necessary. The <CODE>pixel</CODE> value
952+ * is specified by an array of data elements of type <CODE>transferType</CODE>
953+ * passed in as an object reference. The returned value is a non pre-multiplied
954+ * value. If the alpha is premultiplied, this method divides it out before
955+ * returning the value (if the alpha value is 0, the green value will be 0).
956+ * Since <code>ComponentColorModel</code> can be subclassed,
957+ * subclasses inherit the implementation of this method and if they
958+ * don't override it then they throw an exception if they use an
959+ * unsupported <code>transferType</code>.
960+ *
961+ * @param inData The pixel from which you want to get the green color component,
962+ * specified by an array of data elements of type <CODE>transferType</CODE>.
963+ *
964+ * @return The green color component for the specified pixel, as an int.
965+ *
966+ * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
967+ * of type <CODE>transferType</CODE>.
968+ * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
969+ * large enough to hold a pixel value for this
970+ * <CODE>ColorModel</CODE>.
971+ * @throws UnsupportedOperationException If the transfer type of
972+ * this <CODE>ComponentColorModel</CODE>
973+ * is not one of the supported transfer types:
974+ * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
975+ * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
976+ * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
977+ */
978+ public int getGreen(Object inData) {
979+ return getRGBComponent(inData, 1);
980+ }
981+
982+
983+ /**
984+ * Returns the blue color component for the specified pixel, scaled
985+ * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB.
986+ * A color conversion is done if necessary. The <CODE>pixel</CODE> value is
987+ * specified by an array of data elements of type <CODE>transferType</CODE>
988+ * passed in as an object reference. The returned value is a non pre-multiplied
989+ * value. If the alpha is premultiplied, this method divides it out before
990+ * returning the value (if the alpha value is 0, the blue value will be 0).
991+ * Since <code>ComponentColorModel</code> can be subclassed,
992+ * subclasses inherit the implementation of this method and if they
993+ * don't override it then they throw an exception if they use an
994+ * unsupported <code>transferType</code>.
995+ *
996+ * @param inData The pixel from which you want to get the blue color component,
997+ * specified by an array of data elements of type <CODE>transferType</CODE>.
998+ *
999+ * @return The blue color component for the specified pixel, as an int.
1000+ *
1001+ * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
1002+ * of type <CODE>transferType</CODE>.
1003+ * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
1004+ * large enough to hold a pixel value for this
1005+ * <CODE>ColorModel</CODE>.
1006+ * @throws UnsupportedOperationException If the transfer type of
1007+ * this <CODE>ComponentColorModel</CODE>
1008+ * is not one of the supported transfer types:
1009+ * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1010+ * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1011+ * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1012+ */
1013+ public int getBlue(Object inData) {
1014+ return getRGBComponent(inData, 2);
1015+ }
1016+
1017+ /**
1018+ * Returns the alpha component for the specified pixel, scaled from
1019+ * 0 to 255. The pixel value is specified by an array of data
1020+ * elements of type <CODE>transferType</CODE> passed in as an
1021+ * object reference. Since <code>ComponentColorModel</code> can be
1022+ * subclassed, subclasses inherit the
1023+ * implementation of this method and if they don't override it then
1024+ * they throw an exception if they use an unsupported
1025+ * <code>transferType</code>.
1026+ *
1027+ * @param inData The pixel from which you want to get the alpha component,
1028+ * specified by an array of data elements of type <CODE>transferType</CODE>.
1029+ *
1030+ * @return The alpha component for the specified pixel, as an int.
1031+ *
1032+ * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
1033+ * of type <CODE>transferType</CODE>.
1034+ * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
1035+ * large enough to hold a pixel value for this
1036+ * <CODE>ColorModel</CODE>.
1037+ * @throws UnsupportedOperationException If the transfer type of
1038+ * this <CODE>ComponentColorModel</CODE>
1039+ * is not one of the supported transfer types:
1040+ * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1041+ * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1042+ * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1043+ */
1044+ public int getAlpha(Object inData) {
1045+ if (supportsAlpha == false) {
1046+ return 255;
1047+ }
1048+
1049+ int alpha = 0;
1050+ int aIdx = numColorComponents;
1051+ int mask = (1 << nBits[aIdx]) - 1;
1052+
1053+ switch (transferType) {
1054+ case DataBuffer.TYPE_SHORT:
1055+ short sdata[] = (short[])inData;
1056+ alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f);
1057+ return alpha;
1058+ case DataBuffer.TYPE_FLOAT:
1059+ float fdata[] = (float[])inData;
1060+ alpha = (int) (fdata[aIdx] * 255.0f + 0.5f);
1061+ return alpha;
1062+ case DataBuffer.TYPE_DOUBLE:
1063+ double ddata[] = (double[])inData;
1064+ alpha = (int) (ddata[aIdx] * 255.0 + 0.5);
1065+ return alpha;
1066+ case DataBuffer.TYPE_BYTE:
1067+ byte bdata[] = (byte[])inData;
1068+ alpha = bdata[aIdx] & mask;
1069+ break;
1070+ case DataBuffer.TYPE_USHORT:
1071+ short usdata[] = (short[])inData;
1072+ alpha = usdata[aIdx] & mask;
1073+ break;
1074+ case DataBuffer.TYPE_INT:
1075+ int idata[] = (int[])inData;
1076+ alpha = idata[aIdx];
1077+ break;
1078+ default:
1079+ throw new
1080+ UnsupportedOperationException("This method has not "+
1081+ "been implemented for transferType " + transferType);
1082+ }
1083+
1084+ if (nBits[aIdx] == 8) {
1085+ return alpha;
1086+ } else {
1087+ return (int)
1088+ ((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) *
1089+ 255.0f + 0.5f);
1090+ }
1091+ }
1092+
1093+ /**
1094+ * Returns the color/alpha components for the specified pixel in the
1095+ * default RGB color model format. A color conversion is done if
1096+ * necessary. The pixel value is specified by an
1097+ * array of data elements of type <CODE>transferType</CODE> passed
1098+ * in as an object reference.
1099+ * The returned value is in a non pre-multiplied format. If
1100+ * the alpha is premultiplied, this method divides it out of the
1101+ * color components (if the alpha value is 0, the color values will be 0).
1102+ * Since <code>ComponentColorModel</code> can be subclassed,
1103+ * subclasses inherit the implementation of this method and if they
1104+ * don't override it then they throw an exception if they use an
1105+ * unsupported <code>transferType</code>.
1106+ *
1107+ * @param inData The pixel from which you want to get the color/alpha components,
1108+ * specified by an array of data elements of type <CODE>transferType</CODE>.
1109+ *
1110+ * @return The color/alpha components for the specified pixel, as an int.
1111+ *
1112+ * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array
1113+ * of type <CODE>transferType</CODE>.
1114+ * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not
1115+ * large enough to hold a pixel value for this
1116+ * <CODE>ColorModel</CODE>.
1117+ * @throws UnsupportedOperationException If the transfer type of
1118+ * this <CODE>ComponentColorModel</CODE>
1119+ * is not one of the supported transfer types:
1120+ * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1121+ * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1122+ * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1123+ * @see ColorModel#getRGBdefault
1124+ */
1125+ public int getRGB(Object inData) {
1126+ if (needScaleInit) {
1127+ initScale();
1128+ }
1129+ if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1130+ return (getAlpha(inData) << 24)
1131+ | (getRed(inData) << 16)
1132+ | (getGreen(inData) << 8)
1133+ | (getBlue(inData));
1134+ } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
1135+ int gray = getRed(inData); // Red sRGB component should equal
1136+ // green and blue components
1137+ return (getAlpha(inData) << 24)
1138+ | (gray << 16)
1139+ | (gray << 8)
1140+ | gray;
1141+ }
1142+ float[] norm = getNormalizedComponents(inData, null, 0);
1143+ // Note that getNormalizedComponents returns non-premult values
1144+ float[] rgb = colorSpace.toRGB(norm);
1145+ return (getAlpha(inData) << 24)
1146+ | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
1147+ | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
1148+ | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
1149+ }
1150+
1151+ /**
1152+ * Returns a data element array representation of a pixel in this
1153+ * <CODE>ColorModel</CODE>, given an integer pixel representation
1154+ * in the default RGB color model.
1155+ * This array can then be passed to the <CODE>setDataElements</CODE>
1156+ * method of a <CODE>WritableRaster</CODE> object. If the
1157+ * <CODE>pixel</CODE>
1158+ * parameter is null, a new array is allocated. Since
1159+ * <code>ComponentColorModel</code> can be subclassed, subclasses
1160+ * inherit the implementation of this method and if they don't
1161+ * override it then
1162+ * they throw an exception if they use an unsupported
1163+ * <code>transferType</code>.
1164+ *
1165+ * @param rgb the integer representation of the pixel in the RGB
1166+ * color model
1167+ * @param pixel the specified pixel
1168+ * @return The data element array representation of a pixel
1169+ * in this <CODE>ColorModel</CODE>.
1170+ * @throws ClassCastException If <CODE>pixel</CODE> is not null and
1171+ * is not a primitive array of type <CODE>transferType</CODE>.
1172+ * @throws ArrayIndexOutOfBoundsException If <CODE>pixel</CODE> is
1173+ * not large enough to hold a pixel value for this
1174+ * <CODE>ColorModel</CODE>.
1175+ * @throws UnsupportedOperationException If the transfer type of
1176+ * this <CODE>ComponentColorModel</CODE>
1177+ * is not one of the supported transfer types:
1178+ * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>,
1179+ * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>,
1180+ * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>.
1181+ *
1182+ * @see WritableRaster#setDataElements
1183+ * @see SampleModel#setDataElements
1184+ */
1185+ public Object getDataElements(int rgb, Object pixel) {
1186+ // REMIND: Use rendering hints?
1187+
1188+ int red, grn, blu, alp;
1189+ red = (rgb>>16) & 0xff;
1190+ grn = (rgb>>8) & 0xff;
1191+ blu = rgb & 0xff;
1192+
1193+ if (needScaleInit) {
1194+ initScale();
1195+ }
1196+ if (signed) {
1197+ // Handle SHORT, FLOAT, & DOUBLE here
1198+
1199+ switch(transferType) {
1200+ case DataBuffer.TYPE_SHORT:
1201+ {
1202+ short sdata[];
1203+ if (pixel == null) {
1204+ sdata = new short[numComponents];
1205+ } else {
1206+ sdata = (short[])pixel;
1207+ }
1208+ float factor;
1209+ if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1210+ factor = 32767.0f / 255.0f;
1211+ if (is_LinearRGB_stdScale) {
1212+ red = fromsRGB8LUT16[red] & 0xffff;
1213+ grn = fromsRGB8LUT16[grn] & 0xffff;
1214+ blu = fromsRGB8LUT16[blu] & 0xffff;
1215+ factor = 32767.0f / 65535.0f;
1216+ }
1217+ if (supportsAlpha) {
1218+ alp = (rgb>>24) & 0xff;
1219+ sdata[3] =
1220+ (short) (alp * (32767.0f / 255.0f) + 0.5f);
1221+ if (isAlphaPremultiplied) {
1222+ factor = alp * factor * (1.0f / 255.0f);
1223+ }
1224+ }
1225+ sdata[0] = (short) (red * factor + 0.5f);
1226+ sdata[1] = (short) (grn * factor + 0.5f);
1227+ sdata[2] = (short) (blu * factor + 0.5f);
1228+ } else if (is_LinearGray_stdScale) {
1229+ red = fromsRGB8LUT16[red] & 0xffff;
1230+ grn = fromsRGB8LUT16[grn] & 0xffff;
1231+ blu = fromsRGB8LUT16[blu] & 0xffff;
1232+ float gray = ((0.2125f * red) +
1233+ (0.7154f * grn) +
1234+ (0.0721f * blu)) / 65535.0f;
1235+ factor = 32767.0f;
1236+ if (supportsAlpha) {
1237+ alp = (rgb>>24) & 0xff;
1238+ sdata[1] =
1239+ (short) (alp * (32767.0f / 255.0f) + 0.5f);
1240+ if (isAlphaPremultiplied) {
1241+ factor = alp * factor * (1.0f / 255.0f);
1242+ }
1243+ }
1244+ sdata[0] = (short) (gray * factor + 0.5f);
1245+ } else if (is_ICCGray_stdScale) {
1246+ red = fromsRGB8LUT16[red] & 0xffff;
1247+ grn = fromsRGB8LUT16[grn] & 0xffff;
1248+ blu = fromsRGB8LUT16[blu] & 0xffff;
1249+ int gray = (int) ((0.2125f * red) +
1250+ (0.7154f * grn) +
1251+ (0.0721f * blu) + 0.5f);
1252+ gray = fromLinearGray16ToOtherGray16LUT[gray] & 0xffff;
1253+ factor = 32767.0f / 65535.0f;
1254+ if (supportsAlpha) {
1255+ alp = (rgb>>24) & 0xff;
1256+ sdata[1] =
1257+ (short) (alp * (32767.0f / 255.0f) + 0.5f);
1258+ if (isAlphaPremultiplied) {
1259+ factor = alp * factor * (1.0f / 255.0f);
1260+ }
1261+ }
1262+ sdata[0] = (short) (gray * factor + 0.5f);
1263+ } else {
1264+ factor = 1.0f / 255.0f;
1265+ float norm[] = new float[3];
1266+ norm[0] = red * factor;
1267+ norm[1] = grn * factor;
1268+ norm[2] = blu * factor;
1269+ norm = colorSpace.fromRGB(norm);
1270+ if (nonStdScale) {
1271+ for (int i = 0; i < numColorComponents; i++) {
1272+ norm[i] = (norm[i] - compOffset[i]) *
1273+ compScale[i];
1274+ // REMIND: need to analyze whether this
1275+ // clamping is necessary
1276+ if (norm[i] < 0.0f) {
1277+ norm[i] = 0.0f;
1278+ }
1279+ if (norm[i] > 1.0f) {
1280+ norm[i] = 1.0f;
1281+ }
1282+ }
1283+ }
1284+ factor = 32767.0f;
1285+ if (supportsAlpha) {
1286+ alp = (rgb>>24) & 0xff;
1287+ sdata[numColorComponents] =
1288+ (short) (alp * (32767.0f / 255.0f) + 0.5f);
1289+ if (isAlphaPremultiplied) {
1290+ factor *= alp * (1.0f / 255.0f);
1291+ }
1292+ }
1293+ for (int i = 0; i < numColorComponents; i++) {
1294+ sdata[i] = (short) (norm[i] * factor + 0.5f);
1295+ }
1296+ }
1297+ return sdata;
1298+ }
1299+ case DataBuffer.TYPE_FLOAT:
1300+ {
1301+ float fdata[];
1302+ if (pixel == null) {
1303+ fdata = new float[numComponents];
1304+ } else {
1305+ fdata = (float[])pixel;
1306+ }
1307+ float factor;
1308+ if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1309+ if (is_LinearRGB_stdScale) {
1310+ red = fromsRGB8LUT16[red] & 0xffff;
1311+ grn = fromsRGB8LUT16[grn] & 0xffff;
1312+ blu = fromsRGB8LUT16[blu] & 0xffff;
1313+ factor = 1.0f / 65535.0f;
1314+ } else {
1315+ factor = 1.0f / 255.0f;
1316+ }
1317+ if (supportsAlpha) {
1318+ alp = (rgb>>24) & 0xff;
1319+ fdata[3] = alp * (1.0f / 255.0f);
1320+ if (isAlphaPremultiplied) {
1321+ factor *= fdata[3];
1322+ }
1323+ }
1324+ fdata[0] = red * factor;
1325+ fdata[1] = grn * factor;
1326+ fdata[2] = blu * factor;
1327+ } else if (is_LinearGray_stdScale) {
1328+ red = fromsRGB8LUT16[red] & 0xffff;
1329+ grn = fromsRGB8LUT16[grn] & 0xffff;
1330+ blu = fromsRGB8LUT16[blu] & 0xffff;
1331+ fdata[0] = ((0.2125f * red) +
1332+ (0.7154f * grn) +
1333+ (0.0721f * blu)) / 65535.0f;
1334+ if (supportsAlpha) {
1335+ alp = (rgb>>24) & 0xff;
1336+ fdata[1] = alp * (1.0f / 255.0f);
1337+ if (isAlphaPremultiplied) {
1338+ fdata[0] *= fdata[1];
1339+ }
1340+ }
1341+ } else if (is_ICCGray_stdScale) {
1342+ red = fromsRGB8LUT16[red] & 0xffff;
1343+ grn = fromsRGB8LUT16[grn] & 0xffff;
1344+ blu = fromsRGB8LUT16[blu] & 0xffff;
1345+ int gray = (int) ((0.2125f * red) +
1346+ (0.7154f * grn) +
1347+ (0.0721f * blu) + 0.5f);
1348+ fdata[0] = (fromLinearGray16ToOtherGray16LUT[gray] &
1349+ 0xffff) / 65535.0f;
1350+ if (supportsAlpha) {
1351+ alp = (rgb>>24) & 0xff;
1352+ fdata[1] = alp * (1.0f / 255.0f);
1353+ if (isAlphaPremultiplied) {
1354+ fdata[0] *= fdata[1];
1355+ }
1356+ }
1357+ } else {
1358+ float norm[] = new float[3];
1359+ factor = 1.0f / 255.0f;
1360+ norm[0] = red * factor;
1361+ norm[1] = grn * factor;
1362+ norm[2] = blu * factor;
1363+ norm = colorSpace.fromRGB(norm);
1364+ if (supportsAlpha) {
1365+ alp = (rgb>>24) & 0xff;
1366+ fdata[numColorComponents] = alp * factor;
1367+ if (isAlphaPremultiplied) {
1368+ factor *= alp;
1369+ for (int i = 0; i < numColorComponents; i++) {
1370+ norm[i] *= factor;
1371+ }
1372+ }
1373+ }
1374+ for (int i = 0; i < numColorComponents; i++) {
1375+ fdata[i] = norm[i];
1376+ }
1377+ }
1378+ return fdata;
1379+ }
1380+ case DataBuffer.TYPE_DOUBLE:
1381+ {
1382+ double ddata[];
1383+ if (pixel == null) {
1384+ ddata = new double[numComponents];
1385+ } else {
1386+ ddata = (double[])pixel;
1387+ }
1388+ if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1389+ double factor;
1390+ if (is_LinearRGB_stdScale) {
1391+ red = fromsRGB8LUT16[red] & 0xffff;
1392+ grn = fromsRGB8LUT16[grn] & 0xffff;
1393+ blu = fromsRGB8LUT16[blu] & 0xffff;
1394+ factor = 1.0 / 65535.0;
1395+ } else {
1396+ factor = 1.0 / 255.0;
1397+ }
1398+ if (supportsAlpha) {
1399+ alp = (rgb>>24) & 0xff;
1400+ ddata[3] = alp * (1.0 / 255.0);
1401+ if (isAlphaPremultiplied) {
1402+ factor *= ddata[3];
1403+ }
1404+ }
1405+ ddata[0] = red * factor;
1406+ ddata[1] = grn * factor;
1407+ ddata[2] = blu * factor;
1408+ } else if (is_LinearGray_stdScale) {
1409+ red = fromsRGB8LUT16[red] & 0xffff;
1410+ grn = fromsRGB8LUT16[grn] & 0xffff;
1411+ blu = fromsRGB8LUT16[blu] & 0xffff;
1412+ ddata[0] = ((0.2125 * red) +
1413+ (0.7154 * grn) +
1414+ (0.0721 * blu)) / 65535.0;
1415+ if (supportsAlpha) {
1416+ alp = (rgb>>24) & 0xff;
1417+ ddata[1] = alp * (1.0 / 255.0);
1418+ if (isAlphaPremultiplied) {
1419+ ddata[0] *= ddata[1];
1420+ }
1421+ }
1422+ } else if (is_ICCGray_stdScale) {
1423+ red = fromsRGB8LUT16[red] & 0xffff;
1424+ grn = fromsRGB8LUT16[grn] & 0xffff;
1425+ blu = fromsRGB8LUT16[blu] & 0xffff;
1426+ int gray = (int) ((0.2125f * red) +
1427+ (0.7154f * grn) +
1428+ (0.0721f * blu) + 0.5f);
1429+ ddata[0] = (fromLinearGray16ToOtherGray16LUT[gray] &
1430+ 0xffff) / 65535.0;
1431+ if (supportsAlpha) {
1432+ alp = (rgb>>24) & 0xff;
1433+ ddata[1] = alp * (1.0 / 255.0);
1434+ if (isAlphaPremultiplied) {
1435+ ddata[0] *= ddata[1];
1436+ }
1437+ }
1438+ } else {
1439+ float factor = 1.0f / 255.0f;
1440+ float norm[] = new float[3];
1441+ norm[0] = red * factor;
1442+ norm[1] = grn * factor;
1443+ norm[2] = blu * factor;
1444+ norm = colorSpace.fromRGB(norm);
1445+ if (supportsAlpha) {
1446+ alp = (rgb>>24) & 0xff;
1447+ ddata[numColorComponents] = alp * (1.0 / 255.0);
1448+ if (isAlphaPremultiplied) {
1449+ factor *= alp;
1450+ for (int i = 0; i < numColorComponents; i++) {
1451+ norm[i] *= factor;
1452+ }
1453+ }
1454+ }
1455+ for (int i = 0; i < numColorComponents; i++) {
1456+ ddata[i] = norm[i];
1457+ }
1458+ }
1459+ return ddata;
1460+ }
1461+ }
1462+ }
1463+
1464+ // Handle BYTE, USHORT, & INT here
1465+ //REMIND: maybe more efficient not to use int array for
1466+ //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
1467+ int intpixel[];
1468+ if (transferType == DataBuffer.TYPE_INT &&
1469+ pixel != null) {
1470+ intpixel = (int[])pixel;
1471+ } else {
1472+ intpixel = new int[numComponents];
1473+ }
1474+
1475+ if (is_sRGB_stdScale || is_LinearRGB_stdScale) {
1476+ int precision;
1477+ float factor;
1478+ if (is_LinearRGB_stdScale) {
1479+ if (transferType == DataBuffer.TYPE_BYTE) {
1480+ red = fromsRGB8LUT8[red] & 0xff;
1481+ grn = fromsRGB8LUT8[grn] & 0xff;
1482+ blu = fromsRGB8LUT8[blu] & 0xff;
1483+ precision = 8;
1484+ factor = 1.0f / 255.0f;
1485+ } else {
1486+ red = fromsRGB8LUT16[red] & 0xffff;
1487+ grn = fromsRGB8LUT16[grn] & 0xffff;
1488+ blu = fromsRGB8LUT16[blu] & 0xffff;
1489+ precision = 16;
1490+ factor = 1.0f / 65535.0f;
1491+ }
1492+ } else {
1493+ precision = 8;
1494+ factor = 1.0f / 255.0f;
1495+ }
1496+ if (supportsAlpha) {
1497+ alp = (rgb>>24)&0xff;
1498+ if (nBits[3] == 8) {
1499+ intpixel[3] = alp;
1500+ }
1501+ else {
1502+ intpixel[3] = (int)
1503+ (alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1) + 0.5f);
1504+ }
1505+ if (isAlphaPremultiplied) {
1506+ factor *= (alp * (1.0f / 255.0f));
1507+ precision = -1; // force component calculations below
1508+ }
1509+ }
1510+ if (nBits[0] == precision) {
1511+ intpixel[0] = red;
1512+ }
1513+ else {
1514+ intpixel[0] = (int) (red * factor * ((1<<nBits[0]) - 1) + 0.5f);
1515+ }
1516+ if (nBits[1] == precision) {
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+
36+package java.awt.image;
37+
38+import 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+
76+public 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+
26+package java.awt.image;
27+
28+import java.awt.color.ICC_Profile;
29+import java.awt.geom.Rectangle2D;
30+import java.awt.Rectangle;
31+import java.awt.RenderingHints;
32+import java.awt.geom.Point2D;
33+import 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+ */
68+public 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+
26+package java.awt.image;
27+
28+import java.awt.image.ImageConsumer;
29+import java.awt.image.ColorModel;
30+import java.util.Hashtable;
31+import 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+ */
46+public 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+
36+package java.awt.image;
37+
38+import sun.java2d.StateTrackable.State;
39+import static sun.java2d.StateTrackable.State.*;
40+import sun.java2d.StateTrackableDelegate;
41+
42+import 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+ */
68+public 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+
36+package java.awt.image;
37+
38+import 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+ */
60+public 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+
26+package java.awt.image;
27+
28+import 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+
52+public 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+
26+package java.awt.image;
27+
28+import 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+
52+public 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+
36+package java.awt.image;
37+
38+import 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+ */
59+public 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+
36+package java.awt.image;
37+
38+import 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+ */
58+public 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+
36+package java.awt.image;
37+
38+import 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+ */
60+public 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+
26+package java.awt.image;
27+
28+import java.awt.color.ColorSpace;
29+import 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+ */
109+public 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+
26+package java.awt.image;
27+
28+import java.awt.Image;
29+import java.awt.image.ImageFilter;
30+import java.awt.image.ImageConsumer;
31+import java.awt.image.ImageProducer;
32+import java.util.Hashtable;
33+import 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+ */
54+public 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+
26+package java.awt.image;
27+
28+import 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+ */
40+public 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+
26+package java.awt.image;
27+
28+import 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+ */
45+public 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+
26+package java.awt.image;
27+
28+import 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+ */
36+public 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+
26+package 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+ */
39+public 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+
26+package 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+ */
34+public 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+
26+package java.awt.image;
27+
28+import java.awt.Transparency;
29+import java.awt.color.ColorSpace;
30+import 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+ */
124+public 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+
26+package 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+ */
39+public 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+
27+package java.awt.image;
28+
29+import java.awt.color.ColorSpace;
30+import java.awt.geom.Rectangle2D;
31+import java.awt.Rectangle;
32+import java.awt.RenderingHints;
33+import java.awt.geom.Point2D;
34+import 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+
77+public 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+
26+package 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+ */
46+public 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+
26+package java.awt.image;
27+
28+import java.awt.image.ImageConsumer;
29+import java.awt.image.ImageProducer;
30+import java.awt.image.ColorModel;
31+import java.util.Hashtable;
32+import java.util.Vector;
33+import 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+ */
107+public 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.