blob: c9d58d97f2635f638c14737f30a3d418dfb6e7e2 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17/**
18 * @author Igor V. Stolyarov
19 * @version $Revision$
20 */
21
22package java.awt.image;
23
24import com.android.internal.awt.AndroidGraphics2D;
25
26import java.awt.Graphics;
27import java.awt.Graphics2D;
28import java.awt.GraphicsEnvironment;
29import java.awt.Image;
30import java.awt.Point;
31import java.awt.Rectangle;
32import java.awt.Transparency;
33import java.awt.color.ColorSpace;
34import java.util.Enumeration;
35import java.util.Hashtable;
36import java.util.Vector;
37
38import org.apache.harmony.awt.gl.ImageSurface;
39import org.apache.harmony.awt.gl.Surface;
40import org.apache.harmony.awt.gl.image.BufferedImageSource;
41import org.apache.harmony.awt.internal.nls.Messages;
42
43/**
44 * The BufferedImage class describes an Image which contains a buffer of image
45 * data and includes a ColorModel and a Raster for this data. This class
46 * provides methods for obtaining and setting the Raster and for manipulating
47 * the ColorModel parameters.
48 *
49 * @since Android 1.0
50 */
51public class BufferedImage extends Image implements WritableRenderedImage, Transparency {
52
53 /**
54 * The Constant TYPE_CUSTOM indicates that Image type is unknown.
55 */
56 public static final int TYPE_CUSTOM = 0;
57
58 /**
59 * The Constant TYPE_INT_RGB indicates an image with 8 bit RGB color
60 * components, it has a DirectColorModel without alpha.
61 */
62 public static final int TYPE_INT_RGB = 1;
63
64 /**
65 * The Constant TYPE_INT_ARGB indicates an image with 8 bit RGBA color
66 * components, it has a DirectColorModel with alpha.
67 */
68 public static final int TYPE_INT_ARGB = 2;
69
70 /**
71 * The Constant TYPE_INT_ARGB_PRE indicates an image with 8 bit RGBA color
72 * components, it has a DirectColorModel with alpha, and image data is
73 * pre-multiplied by alpha.
74 */
75 public static final int TYPE_INT_ARGB_PRE = 3;
76
77 /**
78 * The Constant TYPE_INT_BGR indicates an image with 8 bit RGB color
79 * components, BGR color model (with the colors Blue, Green, and Red). There
80 * is no alpha. The image has a DirectColorModel.
81 */
82 public static final int TYPE_INT_BGR = 4;
83
84 /**
85 * The Constant TYPE_3BYTE_BGR indicates an image with 8 bit RGB color
86 * components, BGR color model (with the colors Blue, Green, and Red stored
87 * in 3 bytes). There is no alpha. The image has a ComponentColorModel.
88 */
89 public static final int TYPE_3BYTE_BGR = 5;
90
91 /**
92 * The Constant TYPE_4BYTE_ABGR indicates an image with 8 bit RGBA color
93 * components stored in 3 bytes and 1 byte of alpha. It has a
94 * ComponentColorModel with alpha.
95 */
96 public static final int TYPE_4BYTE_ABGR = 6;
97
98 /**
99 * The Constant TYPE_4BYTE_ABGR_PRE indicates an image with 8 bit RGBA color
100 * components stored in 3 bytes and 1 byte for alpha. The image has a
101 * ComponentColorModel with alpha. The color data is pre-multiplied with
102 * alpha.
103 */
104 public static final int TYPE_4BYTE_ABGR_PRE = 7;
105
106 /**
107 * The Constant TYPE_USHORT_565_RGB indicates an image with 565 RGB color
108 * components (5-bits red, 6-bits green, 5-bits blue) with no alpha. This
109 * image has a DirectColorModel.
110 */
111 public static final int TYPE_USHORT_565_RGB = 8;
112
113 /**
114 * The Constant TYPE_USHORT_555_RGB indicates an image with 555 RGB color
115 * components (5-bits red, 5-bits green, 5-bits blue) with no alpha. This
116 * image has a DirectColorModel.
117 */
118 public static final int TYPE_USHORT_555_RGB = 9;
119
120 /**
121 * The Constant TYPE_BYTE_GRAY indicates a unsigned byte image. This image
122 * has a ComponentColorModel with a CS_GRAY ColorSpace.
123 */
124 public static final int TYPE_BYTE_GRAY = 10;
125
126 /**
127 * The Constant TYPE_USHORT_GRAY indicates an unsigned short image. This
128 * image has a ComponentColorModel with a CS_GRAY ColorSpace.
129 */
130 public static final int TYPE_USHORT_GRAY = 11;
131
132 /**
133 * The Constant TYPE_BYTE_BINARY indicates an opaque byte-packed 1, 2 or 4
134 * bit image. The image has an IndexColorModel without alpha.
135 */
136 public static final int TYPE_BYTE_BINARY = 12;
137
138 /**
139 * The Constant TYPE_BYTE_INDEXED indicates an indexed byte image.
140 */
141 public static final int TYPE_BYTE_INDEXED = 13;
142
143 /**
144 * The Constant ALPHA_MASK.
145 */
146 private static final int ALPHA_MASK = 0xff000000;
147
148 /**
149 * The Constant RED_MASK.
150 */
151 private static final int RED_MASK = 0x00ff0000;
152
153 /**
154 * The Constant GREEN_MASK.
155 */
156 private static final int GREEN_MASK = 0x0000ff00;
157
158 /**
159 * The Constant BLUE_MASK.
160 */
161 private static final int BLUE_MASK = 0x000000ff;
162
163 /**
164 * The Constant RED_BGR_MASK.
165 */
166 private static final int RED_BGR_MASK = 0x000000ff;
167
168 /**
169 * The Constant GREEN_BGR_MASK.
170 */
171 private static final int GREEN_BGR_MASK = 0x0000ff00;
172
173 /**
174 * The Constant BLUE_BGR_MASK.
175 */
176 private static final int BLUE_BGR_MASK = 0x00ff0000;
177
178 /**
179 * The Constant RED_565_MASK.
180 */
181 private static final int RED_565_MASK = 0xf800;
182
183 /**
184 * The Constant GREEN_565_MASK.
185 */
186 private static final int GREEN_565_MASK = 0x07e0;
187
188 /**
189 * The Constant BLUE_565_MASK.
190 */
191 private static final int BLUE_565_MASK = 0x001f;
192
193 /**
194 * The Constant RED_555_MASK.
195 */
196 private static final int RED_555_MASK = 0x7c00;
197
198 /**
199 * The Constant GREEN_555_MASK.
200 */
201 private static final int GREEN_555_MASK = 0x03e0;
202
203 /**
204 * The Constant BLUE_555_MASK.
205 */
206 private static final int BLUE_555_MASK = 0x001f;
207
208 /**
209 * The cm.
210 */
211 private ColorModel cm;
212
213 /**
214 * The raster.
215 */
216 private final WritableRaster raster;
217
218 /**
219 * The image type.
220 */
221 private final int imageType;
222
223 /**
224 * The properties.
225 */
226 private Hashtable<?, ?> properties;
227
228 // Surface of the Buffered Image - used for blitting one Buffered Image
229 // on the other one or on the Component
230 /**
231 * The image surf.
232 */
233 private final ImageSurface imageSurf;
234
235 /**
236 * Instantiates a new BufferedImage with the specified ColorModel, and
237 * WritableRaster objects. The Raster data can be be divided or multiplied
238 * by alpha. It depends on the alphaPremultiplied state in the ColorModel.
239 *
240 * @param cm
241 * the ColorModel of the new image.
242 * @param raster
243 * the WritableRaster of the new image.
244 * @param isRasterPremultiplied
245 * if true the data of the specified Raster is pre-multiplied by
246 * alpha.
247 * @param properties
248 * the properties of new Image.
249 */
250 public BufferedImage(ColorModel cm, WritableRaster raster, boolean isRasterPremultiplied,
251 Hashtable<?, ?> properties) {
252 if (!cm.isCompatibleRaster(raster)) {
253 // awt.4D=The raster is incompatible with this ColorModel
254 throw new IllegalArgumentException(Messages.getString("awt.4D")); //$NON-NLS-1$
255 }
256
257 if (raster.getMinX() != 0 || raster.getMinY() != 0) {
258 // awt.228=minX or minY of this raster not equal to zero
259 throw new IllegalArgumentException(Messages.getString("awt.228")); //$NON-NLS-1$
260 }
261
262 this.cm = cm;
263 this.raster = raster;
264 this.properties = properties;
265
266 coerceData(isRasterPremultiplied);
267
268 imageType = Surface.getType(cm, raster);
269
270 imageSurf = createImageSurface(imageType);
271 }
272
273 /**
274 * Instantiates a new BufferedImage with the specified width, height
275 * predefined image type (TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED) and the
276 * specified IndexColorModel.
277 *
278 * @param width
279 * the width of new image.
280 * @param height
281 * the height of new image.
282 * @param imageType
283 * the predefined image type.
284 * @param cm
285 * the specified IndexColorModel.
286 */
287 public BufferedImage(int width, int height, int imageType, IndexColorModel cm) {
288 switch (imageType) {
289 case TYPE_BYTE_BINARY:
290 if (cm.hasAlpha()) {
291 // awt.227=This image type can't have alpha
292 throw new IllegalArgumentException(Messages.getString("awt.227")); //$NON-NLS-1$
293 }
294 int pixel_bits = 0;
295 int mapSize = cm.getMapSize();
296 if (mapSize <= 2) {
297 pixel_bits = 1;
298 } else if (mapSize <= 4) {
299 pixel_bits = 2;
300 } else if (mapSize <= 16) {
301 pixel_bits = 4;
302 } else {
303 // awt.221=The imageType is TYPE_BYTE_BINARY and the color
304 // map has more than 16 entries
305 throw new IllegalArgumentException(Messages.getString("awt.221")); //$NON-NLS-1$
306 }
307
308 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, width, height, 1,
309 pixel_bits, null);
310 break;
311
312 case TYPE_BYTE_INDEXED:
313 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, 1,
314 null);
315 break;
316
317 default:
318 // awt.222=The imageType is not TYPE_BYTE_BINARY or
319 // TYPE_BYTE_INDEXED
320 throw new IllegalArgumentException(Messages.getString("awt.222")); //$NON-NLS-1$
321
322 }
323
324 if (!cm.isCompatibleRaster(raster)) {
325 // awt.223=The imageType is not compatible with ColorModel
326 throw new IllegalArgumentException(Messages.getString("awt.223")); //$NON-NLS-1$
327 }
328
329 this.cm = cm;
330 this.imageType = imageType;
331 imageSurf = createImageSurface(imageType);
332
333 }
334
335 /**
336 * Instantiates a new BufferedImage with the specified width, height and
337 * predefined image type.
338 *
339 * @param width
340 * the width of new image.
341 * @param height
342 * the height of new image.
343 * @param imageType
344 * the predefined image type.
345 */
346 public BufferedImage(int width, int height, int imageType) {
347
348 switch (imageType) {
349 case TYPE_INT_RGB:
350 cm = new DirectColorModel(24, RED_MASK, GREEN_MASK, BLUE_MASK);
351 raster = cm.createCompatibleWritableRaster(width, height);
352 break;
353
354 case TYPE_INT_ARGB:
355 cm = ColorModel.getRGBdefault();
356 raster = cm.createCompatibleWritableRaster(width, height);
357 break;
358
359 case TYPE_INT_ARGB_PRE:
360 cm = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 32, RED_MASK,
361 GREEN_MASK, BLUE_MASK, ALPHA_MASK, true, DataBuffer.TYPE_INT);
362
363 raster = cm.createCompatibleWritableRaster(width, height);
364 break;
365
366 case TYPE_INT_BGR:
367 cm = new DirectColorModel(24, RED_BGR_MASK, GREEN_BGR_MASK, BLUE_BGR_MASK);
368
369 raster = cm.createCompatibleWritableRaster(width, height);
370 break;
371
372 case TYPE_3BYTE_BGR: {
373 int bits[] = {
374 8, 8, 8
375 };
376 int bandOffsets[] = {
377 2, 1, 0
378 };
379 cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), bits,
380 false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
381
382 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height,
383 width * 3, 3, bandOffsets, null);
384 }
385 break;
386
387 case TYPE_4BYTE_ABGR: {
388 int bits[] = {
389 8, 8, 8, 8
390 };
391 int bandOffsets[] = {
392 3, 2, 1, 0
393 };
394 cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), bits,
395 true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
396
397 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height,
398 width * 4, 4, bandOffsets, null);
399 }
400 break;
401
402 case TYPE_4BYTE_ABGR_PRE: {
403 int bits[] = {
404 8, 8, 8, 8
405 };
406 int bandOffsets[] = {
407 3, 2, 1, 0
408 };
409 cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), bits,
410 true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
411
412 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height,
413 width * 4, 4, bandOffsets, null);
414 }
415 break;
416
417 case TYPE_USHORT_565_RGB:
418 cm = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 16,
419 RED_565_MASK, GREEN_565_MASK, BLUE_565_MASK, 0, false,
420 DataBuffer.TYPE_USHORT);
421
422 raster = cm.createCompatibleWritableRaster(width, height);
423 break;
424
425 case TYPE_USHORT_555_RGB:
426 cm = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 15,
427 RED_555_MASK, GREEN_555_MASK, BLUE_555_MASK, 0, false,
428 DataBuffer.TYPE_USHORT);
429
430 raster = cm.createCompatibleWritableRaster(width, height);
431 break;
432
433 case TYPE_BYTE_GRAY: {
434 int bits[] = {
435 8
436 };
437 cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), bits,
438 false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
439
440 raster = cm.createCompatibleWritableRaster(width, height);
441 }
442 break;
443
444 case TYPE_USHORT_GRAY: {
445 int bits[] = {
446 16
447 };
448 cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), bits,
449 false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
450 raster = cm.createCompatibleWritableRaster(width, height);
451 }
452 break;
453
454 case TYPE_BYTE_BINARY: {
455 int colorMap[] = {
456 0, 0xffffff
457 };
458 cm = new IndexColorModel(1, 2, colorMap, 0, false, -1, DataBuffer.TYPE_BYTE);
459
460 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, width, height, 1, 1, null);
461 }
462 break;
463
464 case TYPE_BYTE_INDEXED: {
465 int colorMap[] = new int[256];
466 int i = 0;
467 for (int r = 0; r < 256; r += 51) {
468 for (int g = 0; g < 256; g += 51) {
469 for (int b = 0; b < 256; b += 51) {
470 colorMap[i] = (r << 16) | (g << 8) | b;
471 i++;
472 }
473 }
474 }
475
476 int gray = 0x12;
477 for (; i < 256; i++, gray += 6) {
478 colorMap[i] = (gray << 16) | (gray << 8) | gray;
479 }
480 cm = new IndexColorModel(8, 256, colorMap, 0, false, -1, DataBuffer.TYPE_BYTE);
481 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, 1,
482 null);
483
484 }
485 break;
486 default:
487 // awt.224=Unknown image type
488 throw new IllegalArgumentException(Messages.getString("awt.224")); //$NON-NLS-1$
489 }
490 this.imageType = imageType;
491 imageSurf = createImageSurface(imageType);
492 }
493
494 @Override
495 public Object getProperty(String name, ImageObserver observer) {
496 return getProperty(name);
497 }
498
499 public Object getProperty(String name) {
500 if (name == null) {
501 // awt.225=Property name is null
502 throw new NullPointerException(Messages.getString("awt.225")); //$NON-NLS-1$
503 }
504 if (properties == null) {
505 return Image.UndefinedProperty;
506 }
507 Object property = properties.get(name);
508 if (property == null) {
509 property = Image.UndefinedProperty;
510 }
511 return property;
512 }
513
514 public WritableRaster copyData(WritableRaster outRaster) {
515 if (outRaster == null) {
516 outRaster = Raster.createWritableRaster(raster.getSampleModel(), new Point(raster
517 .getSampleModelTranslateX(), raster.getSampleModelTranslateY()));
518 }
519
520 int w = outRaster.getWidth();
521 int h = outRaster.getHeight();
522 int minX = outRaster.getMinX();
523 int minY = outRaster.getMinY();
524
525 Object data = null;
526
527 data = raster.getDataElements(minX, minY, w, h, data);
528 outRaster.setDataElements(minX, minY, w, h, data);
529
530 return outRaster;
531 }
532
533 public Raster getData(Rectangle rect) {
534 int minX = rect.x;
535 int minY = rect.y;
536 int w = rect.width;
537 int h = rect.height;
538
539 SampleModel sm = raster.getSampleModel();
540 SampleModel nsm = sm.createCompatibleSampleModel(w, h);
541 WritableRaster outr = Raster.createWritableRaster(nsm, rect.getLocation());
542 Object data = null;
543
544 data = raster.getDataElements(minX, minY, w, h, data);
545 outr.setDataElements(minX, minY, w, h, data);
546 return outr;
547 }
548
549 public Vector<RenderedImage> getSources() {
550 return null;
551 }
552
553 public String[] getPropertyNames() {
554 if (properties == null) {
555 return null;
556 }
557 Vector<String> v = new Vector<String>();
558 for (Enumeration<?> e = properties.keys(); e.hasMoreElements();) {
559 try {
560 v.add((String)e.nextElement());
561 } catch (ClassCastException ex) {
562 }
563 }
564 int size = v.size();
565 if (size > 0) {
566 String names[] = new String[size];
567 for (int i = 0; i < size; i++) {
568 names[i] = v.elementAt(i);
569 }
570 return names;
571 }
572 return null;
573 }
574
575 /**
576 * Returns the string representation of this BufferedImage object.
577 *
578 * @return the string representation of this BufferedImage object.
579 */
580 @Override
581 public String toString() {
582 return "BufferedImage@" + Integer.toHexString(hashCode()) + //$NON-NLS-1$
583 ": type = " + imageType + " " + cm + " " + raster; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
584 }
585
586 public WritableRaster getWritableTile(int tileX, int tileY) {
587 return raster;
588 }
589
590 /**
591 * Gets the WritableRaster of this BufferedImage.
592 *
593 * @return the WritableRaster of this BufferedImage.
594 */
595 public WritableRaster getRaster() {
596 return raster;
597 }
598
599 /**
600 * Gets a WritableRaster object which contains the alpha channel of
601 * BufferedImage object with ColorModel objects that supports a separate
602 * alpha channel such as ComponentColorModel or DirectColorModel.
603 *
604 * @return the WritableRaster object which contains the alpha channel of
605 * this BufferedImage.
606 */
607 public WritableRaster getAlphaRaster() {
608 return cm.getAlphaRaster(raster);
609 }
610
611 public void removeTileObserver(TileObserver to) {
612 }
613
614 public void addTileObserver(TileObserver to) {
615 }
616
617 public SampleModel getSampleModel() {
618 return raster.getSampleModel();
619 }
620
621 public void setData(Raster r) {
622
623 Rectangle from = r.getBounds();
624 Rectangle to = raster.getBounds();
625 Rectangle intersection = to.intersection(from);
626
627 int minX = intersection.x;
628 int minY = intersection.y;
629 int w = intersection.width;
630 int h = intersection.height;
631
632 Object data = null;
633
634 data = r.getDataElements(minX, minY, w, h, data);
635 raster.setDataElements(minX, minY, w, h, data);
636 }
637
638 public Raster getTile(int tileX, int tileY) {
639 if (tileX == 0 && tileY == 0) {
640 return raster;
641 }
642 // awt.226=Both tileX and tileY are not equal to 0
643 throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.226")); //$NON-NLS-1$
644 }
645
646 public Raster getData() {
647 int w = raster.getWidth();
648 int h = raster.getHeight();
649 int minX = raster.getMinX();
650 int minY = raster.getMinY();
651
652 WritableRaster outr = Raster.createWritableRaster(raster.getSampleModel(), new Point(raster
653 .getSampleModelTranslateX(), raster.getSampleModelTranslateY()));
654
655 Object data = null;
656
657 data = raster.getDataElements(minX, minY, w, h, data);
658 outr.setDataElements(minX, minY, w, h, data);
659
660 return outr;
661 }
662
663 @Override
664 public ImageProducer getSource() {
665 return new BufferedImageSource(this, properties);
666 }
667
668 @Override
669 public int getWidth(ImageObserver observer) {
670 return raster.getWidth();
671 }
672
673 @Override
674 public int getHeight(ImageObserver observer) {
675 return raster.getHeight();
676 }
677
678 public ColorModel getColorModel() {
679 return cm;
680 }
681
682 /**
683 * Gets the rectangular area of this BufferedImage as a subimage.
684 *
685 * @param x
686 * the x coordinate.
687 * @param y
688 * the y coordinate.
689 * @param w
690 * the width of the subimage.
691 * @param h
692 * the height of the subimage.
693 * @return the BufferedImage.
694 */
695 public BufferedImage getSubimage(int x, int y, int w, int h) {
696 WritableRaster wr = raster.createWritableChild(x, y, w, h, 0, 0, null);
697 return new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), properties);
698 }
699
700 public Point[] getWritableTileIndices() {
701 Point points[] = new Point[1];
702 points[0] = new Point(0, 0);
703 return points;
704 }
705
706 /**
707 * Creates the Graphics2D object which allows to draw into this
708 * BufferedImage.
709 *
710 * @return the graphics2D object.
711 */
712 public Graphics2D createGraphics() {
713 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
714 // return ge.createGraphics(this);
715 // ???AWT hack, FIXME
716 // return AndroidGraphics2D.getInstance();
717 // throw new RuntimeException("Not implemented!");
718 return null;
719 }
720
721 @Override
722 public Graphics getGraphics() {
723 return createGraphics();
724 }
725
726 /**
727 * Coerces the data to achieve the state which is specified by the
728 * isAlphaPremultiplied variable.
729 *
730 * @param isAlphaPremultiplied
731 * the is alpha pre-multiplied state.
732 */
733 public void coerceData(boolean isAlphaPremultiplied) {
734 if (cm.hasAlpha() && cm.isAlphaPremultiplied() != isAlphaPremultiplied) {
735 cm = cm.coerceData(raster, isAlphaPremultiplied);
736 }
737 }
738
739 /**
740 * Gets an array of colors in the TYPE_INT_ARGB color model and default sRGB
741 * color space of the specified area of this BufferedImage. The result array
742 * is composed by the following algorithm:
743 * <p>
744 * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)]
745 * </p>
746 *
747 * @param startX
748 * the start X area coordinate.
749 * @param startY
750 * the start Y area coordinate.
751 * @param w
752 * the width of the area.
753 * @param h
754 * the height of the area.
755 * @param rgbArray
756 * the result array will be stored to this array.
757 * @param offset
758 * the offset of the rgbArray array.
759 * @param scansize
760 * the scanline stride for the rgbArray.
761 * @return an array of colors for the specified area.
762 */
763 public int[] getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset,
764 int scansize) {
765 if (rgbArray == null) {
766 rgbArray = new int[offset + h * scansize];
767 }
768
769 int off = offset;
770 for (int y = startY; y < startY + h; y++, off += scansize) {
771 int i = off;
772 for (int x = startX; x < startX + w; x++, i++) {
773 rgbArray[i] = cm.getRGB(raster.getDataElements(x, y, null));
774 }
775 }
776 return rgbArray;
777 }
778
779 /**
780 * Sets RGB values from the specified array to the specified BufferedImage
781 * area. The pixels are in the default RGB color model (TYPE_INT_ARGB) and
782 * default sRGB color space.
783 *
784 * @param startX
785 * the start X coordinate.
786 * @param startY
787 * the start Y coordinate.
788 * @param w
789 * the width of the BufferedImage area.
790 * @param h
791 * the height of the BufferedImage area.
792 * @param rgbArray
793 * the array of RGB values.
794 * @param offset
795 * the offset of the rgbArray array.
796 * @param scansize
797 * the scanline stride for the rgbArray.
798 */
799 public void setRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset,
800 int scansize) {
801 int off = offset;
802 for (int y = startY; y < startY + h; y++, off += scansize) {
803 int i = off;
804 for (int x = startX; x < startX + w; x++, i++) {
805 raster.setDataElements(x, y, cm.getDataElements(rgbArray[i], null));
806 }
807 }
808 }
809
810 /**
811 * Sets a the specified RGB value to the specified pixel of this
812 * BufferedImage. The pixel should be in the default RGB color model
813 * (TYPE_INT_ARGB) and default sRGB color space.
814 *
815 * @param x
816 * the X coordinate of the pixel.
817 * @param y
818 * the Y coordinate of the pixel.
819 * @param rgb
820 * the RGB value to be set.
821 */
822 public synchronized void setRGB(int x, int y, int rgb) {
823 raster.setDataElements(x, y, cm.getDataElements(rgb, null));
824 }
825
826 public boolean isTileWritable(int tileX, int tileY) {
827 if (tileX == 0 && tileY == 0) {
828 return true;
829 }
830 // awt.226=Both tileX and tileY are not equal to 0
831 throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.226")); //$NON-NLS-1$
832 }
833
834 public void releaseWritableTile(int tileX, int tileY) {
835 }
836
837 /**
838 * Gets a color in the TYPE_INT_ARGB color model and default sRGB color
839 * space of the specified pixel.
840 *
841 * @param x
842 * the X coordinate of the pixel.
843 * @param y
844 * the Y coordinate of the pixel.
845 * @return the color of the specified pixel in the TYPE_INT_ARGB color model
846 * and default sRGB color space.
847 */
848 public int getRGB(int x, int y) {
849 return cm.getRGB(raster.getDataElements(x, y, null));
850 }
851
852 /**
853 * Returns true if alpha is pre-multiplied, false if alpha is not
854 * pre-multiplied or there is no alpha.
855 *
856 * @return true if alpha is pre-multiplied, false if alpha is not
857 * pre-multiplied or there is no alpha.
858 */
859 public boolean isAlphaPremultiplied() {
860 return cm.isAlphaPremultiplied();
861 }
862
863 public boolean hasTileWriters() {
864 return true;
865 }
866
867 @Override
868 public void flush() {
869 imageSurf.dispose();
870 }
871
872 public int getWidth() {
873 return raster.getWidth();
874 }
875
876 /**
877 * Gets the image type.
878 *
879 * @return the image type.
880 */
881 public int getType() {
882 return imageType;
883 }
884
885 public int getTileWidth() {
886 return raster.getWidth();
887 }
888
889 public int getTileHeight() {
890 return raster.getHeight();
891 }
892
893 public int getTileGridYOffset() {
894 return raster.getSampleModelTranslateY();
895 }
896
897 public int getTileGridXOffset() {
898 return raster.getSampleModelTranslateX();
899 }
900
901 public int getNumYTiles() {
902 return 1;
903 }
904
905 public int getNumXTiles() {
906 return 1;
907 }
908
909 public int getMinY() {
910 return raster.getMinY();
911 }
912
913 public int getMinX() {
914 return raster.getMinX();
915 }
916
917 public int getMinTileY() {
918 return 0;
919 }
920
921 public int getMinTileX() {
922 return 0;
923 }
924
925 public int getHeight() {
926 return raster.getHeight();
927 }
928
929 /**
930 * Creates the image surface.
931 *
932 * @param type
933 * the type.
934 * @return the image surface.
935 */
936 private ImageSurface createImageSurface(int type) {
937 return new ImageSurface(getColorModel(), getRaster(), type);
938 }
939
940 /**
941 * Gets the image surface.
942 *
943 * @return the image surface.
944 */
945 ImageSurface getImageSurface() {
946 return imageSurf;
947 }
948
949 public int getTransparency() {
950 return cm.getTransparency();
951 }
952}