1 /* 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 22 package java.awt.image; 23 24 import com.android.internal.awt.AndroidGraphics2D; 25 26 import java.awt.Graphics; 27 import java.awt.Graphics2D; 28 import java.awt.GraphicsEnvironment; 29 import java.awt.Image; 30 import java.awt.Point; 31 import java.awt.Rectangle; 32 import java.awt.Transparency; 33 import java.awt.color.ColorSpace; 34 import java.util.Enumeration; 35 import java.util.Hashtable; 36 import java.util.Vector; 37 38 import org.apache.harmony.awt.gl.ImageSurface; 39 import org.apache.harmony.awt.gl.Surface; 40 import org.apache.harmony.awt.gl.image.BufferedImageSource; 41 import 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 */ 51 public 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 } 953