| 1 7 8 package java.awt.image; 9 10 import java.awt.Transparency ; 11 import java.awt.color.ColorSpace ; 12 import java.awt.Graphics2D ; 13 import java.awt.GraphicsConfiguration ; 14 import java.awt.GraphicsEnvironment ; 15 import java.awt.ImageCapabilities ; 16 import java.awt.geom.Rectangle2D ; 17 import java.awt.geom.Point2D ; 18 import java.awt.Point ; 19 import java.awt.Rectangle ; 20 import java.util.Hashtable ; 21 import java.util.Vector ; 22 23 import sun.awt.image.BytePackedRaster; 24 import sun.awt.image.ShortComponentRaster; 25 import sun.awt.image.ByteComponentRaster; 26 import sun.awt.image.IntegerComponentRaster; 27 import sun.awt.image.OffScreenImageSource; 28 29 52 53 public class BufferedImage extends java.awt.Image  54 implements WritableRenderedImage , Transparency  55 { 56 int imageType = TYPE_CUSTOM; 57 ColorModel colorModel; 58 WritableRaster raster; 59 OffScreenImageSource osis; 60 Hashtable properties; 61 62 boolean isAlphaPremultiplied; 65 sun.awt.image.SurfaceManager surfaceManager; 66 67 70 71 76 public static final int TYPE_CUSTOM = 0; 77 78 89 public static final int TYPE_INT_RGB = 1; 90 91 100 public static final int TYPE_INT_ARGB = 2; 101 102 108 public static final int TYPE_INT_ARGB_PRE = 3; 109 110 122 public static final int TYPE_INT_BGR = 4; 123 124 136 public static final int TYPE_3BYTE_BGR = 5; 137 138 147 public static final int TYPE_4BYTE_ABGR = 6; 148 149 157 public static final int TYPE_4BYTE_ABGR_PRE = 7; 158 159 170 public static final int TYPE_USHORT_565_RGB = 8; 171 172 183 public static final int TYPE_USHORT_555_RGB = 9; 184 185 196 public static final int TYPE_BYTE_GRAY = 10; 197 198 209 public static final int TYPE_USHORT_GRAY = 11; 210 211 238 public static final int TYPE_BYTE_BINARY = 12; 239 240 257 public static final int TYPE_BYTE_INDEXED = 13; 258 259 private static final int DCM_RED_MASK = 0x00ff0000; 260 private static final int DCM_GREEN_MASK = 0x0000ff00; 261 private static final int DCM_BLUE_MASK = 0x000000ff; 262 private static final int DCM_ALPHA_MASK = 0xff000000; 263 private static final int DCM_565_RED_MASK = 0xf800; 264 private static final int DCM_565_GRN_MASK = 0x07E0; 265 private static final int DCM_565_BLU_MASK = 0x001F; 266 private static final int DCM_555_RED_MASK = 0x7C00; 267 private static final int DCM_555_GRN_MASK = 0x03E0; 268 private static final int DCM_555_BLU_MASK = 0x001F; 269 private static final int DCM_BGR_RED_MASK = 0x0000ff; 270 private static final int DCM_BGR_GRN_MASK = 0x00ff00; 271 private static final int DCM_BGR_BLU_MASK = 0xff0000; 272 273 274 static private native void initIDs(); 275 static { 276 ColorModel.loadLibraries(); 277 initIDs(); 278 } 279 280 302 public BufferedImage(int width, 303 int height, 304 int imageType) { 305 switch (imageType) { 306 case TYPE_INT_RGB: 307 { 308 colorModel = new DirectColorModel (24, 309 0x00ff0000, 0x0000ff00, 0x000000ff, 0x0 ); 314 raster = colorModel.createCompatibleWritableRaster(width, 315 height); 316 } 317 break; 318 319 case TYPE_INT_ARGB: 320 { 321 colorModel = ColorModel.getRGBdefault(); 322 323 raster = colorModel.createCompatibleWritableRaster(width, 324 height); 325 } 326 break; 327 328 case TYPE_INT_ARGB_PRE: 329 { 330 colorModel = new 331 DirectColorModel ( 332 ColorSpace.getInstance(ColorSpace.CS_sRGB), 333 32, 334 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, true, DataBuffer.TYPE_INT 340 ); 341 342 raster = colorModel.createCompatibleWritableRaster(width, 343 height); 344 } 345 break; 346 347 case TYPE_INT_BGR: 348 { 349 colorModel = new DirectColorModel (24, 350 0x000000ff, 0x0000ff00, 0x00ff0000 ); 354 raster = colorModel.createCompatibleWritableRaster(width, 355 height); 356 } 357 break; 358 359 case TYPE_3BYTE_BGR: 360 { 361 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); 362 int[] nBits = {8, 8, 8}; 363 int[] bOffs = {2, 1, 0}; 364 colorModel = new ComponentColorModel (cs, nBits, false, false, 365 Transparency.OPAQUE, 366 DataBuffer.TYPE_BYTE); 367 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 368 width, height, 369 width*3, 3, 370 bOffs, null); 371 } 372 break; 373 374 case TYPE_4BYTE_ABGR: 375 { 376 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); 377 int[] nBits = {8, 8, 8, 8}; 378 int[] bOffs = {3, 2, 1, 0}; 379 colorModel = new ComponentColorModel (cs, nBits, true, false, 380 Transparency.TRANSLUCENT, 381 DataBuffer.TYPE_BYTE); 382 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 383 width, height, 384 width*4, 4, 385 bOffs, null); 386 } 387 break; 388 389 case TYPE_4BYTE_ABGR_PRE: 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, true, 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_BYTE_GRAY: 405 { 406 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); 407 int[] nBits = {8}; 408 colorModel = new ComponentColorModel (cs, nBits, false, true, 409 Transparency.OPAQUE, 410 DataBuffer.TYPE_BYTE); 411 raster = colorModel.createCompatibleWritableRaster(width, 412 height); 413 } 414 break; 415 416 case TYPE_USHORT_GRAY: 417 { 418 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); 419 int[] nBits = {16}; 420 colorModel = new ComponentColorModel (cs, nBits, false, true, 421 Transparency.OPAQUE, 422 DataBuffer.TYPE_USHORT); 423 raster = colorModel.createCompatibleWritableRaster(width, 424 height); 425 } 426 break; 427 428 case TYPE_BYTE_BINARY: 429 { 430 byte[] arr = {(byte)0, (byte)0xff}; 431 432 colorModel = new IndexColorModel (1, 2, arr, arr, arr); 433 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, 434 width, height, 1, 1, null); 435 } 436 break; 437 438 case TYPE_BYTE_INDEXED: 439 { 440 int[] cmap = new int[256]; 442 int i=0; 443 for (int r=0; r < 256; r += 51) { 444 for (int g=0; g < 256; g += 51) { 445 for (int b=0; b < 256; b += 51) { 446 cmap[i++] = (r<<16)|(g<<8)|b; 447 } 448 } 449 } 450 int grayIncr = 256/(256-i); 452 453 int gray = grayIncr*3; 455 for (; i < 256; i++) { 456 cmap[i] = (gray<<16)|(gray<<8)|gray; 457 gray += grayIncr; 458 } 459 460 colorModel = new IndexColorModel (8, 256, cmap, 0, false, -1, 461 DataBuffer.TYPE_BYTE); 462 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 463 width, height, 1, null); 464 } 465 break; 466 467 case TYPE_USHORT_565_RGB: 468 { 469 colorModel = new DirectColorModel (16, 470 DCM_565_RED_MASK, 471 DCM_565_GRN_MASK, 472 DCM_565_BLU_MASK 473 ); 474 raster = colorModel.createCompatibleWritableRaster(width, 475 height); 476 } 477 break; 478 479 case TYPE_USHORT_555_RGB: 480 { 481 colorModel = new DirectColorModel (15, 482 DCM_555_RED_MASK, 483 DCM_555_GRN_MASK, 484 DCM_555_BLU_MASK 485 ); 486 raster = colorModel.createCompatibleWritableRaster(width, 487 height); 488 } 489 break; 490 491 default: 492 throw new IllegalArgumentException ("Unknown image type " + 493 imageType); 494 } 495 496 this.imageType = imageType; 497 } 498 499 522 public BufferedImage (int width, 523 int height, 524 int imageType, 525 IndexColorModel cm) { 526 if (cm.hasAlpha() && cm.isAlphaPremultiplied()) { 527 throw new IllegalArgumentException ("This image types do not have "+ 528 "premultiplied alpha."); 529 } 530 531 switch(imageType) { 532 case TYPE_BYTE_BINARY: 533 int bits; int mapSize = cm.getMapSize(); 535 if (mapSize <= 2) { 536 bits = 1; 537 } else if (mapSize <= 4) { 538 bits = 2; 539 } else if (mapSize <= 16) { 540 bits = 4; 541 } else { 542 throw new IllegalArgumentException  543 ("Color map for TYPE_BYTE_BINARY " + 544 "must have no more than 16 entries"); 545 } 546 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, 547 width, height, 1, bits, null); 548 break; 549 550 case TYPE_BYTE_INDEXED: 551 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 552 width, height, 1, null); 553 break; 554 default: 555 throw new IllegalArgumentException ("Invalid image type (" + 556 imageType+"). Image type must"+ 557 " be either TYPE_BYTE_BINARY or "+ 558 " TYPE_BYTE_INDEXED"); 559 } 560 561 if (!cm.isCompatibleRaster(raster)) { 562 throw new IllegalArgumentException ("Incompatible image type and IndexColorModel"); 563 } 564 565 colorModel = cm; 566 this.imageType = imageType; 567 } 568 569 599 600 601 607 public BufferedImage (ColorModel cm, 608 WritableRaster raster, 609 boolean isRasterPremultiplied, 610 Hashtable <?,?> properties) { 611 612 if (!cm.isCompatibleRaster(raster)) { 613 throw new 614 IllegalArgumentException ("Raster "+raster+ 615 " is incompatible with ColorModel "+ 616 cm); 617 } 618 619 if ((raster.minX != 0) || (raster.minY != 0)) { 620 throw new 621 IllegalArgumentException ("Raster "+raster+ 622 " has minX or minY not equal to zero: " 623 + raster.minX + " " + raster.minY); 624 } 625 626 colorModel = cm; 627 this.raster = raster; 628 this.properties = properties; 629 int numBands = raster.getNumBands(); 630 boolean isAlphaPre = cm.isAlphaPremultiplied(); 631 ColorSpace cs; 632 633 coerceData(isRasterPremultiplied); 636 637 SampleModel sm = raster.getSampleModel(); 638 cs = cm.getColorSpace(); 639 int csType = cs.getType(); 640 if (csType != ColorSpace.TYPE_RGB) { 641 if (csType == ColorSpace.TYPE_GRAY 642 && cm instanceof ComponentColorModel ) { 643 if (sm instanceof ComponentSampleModel && 645 ((ComponentSampleModel )sm).getPixelStride() != numBands) { 646 imageType = TYPE_CUSTOM; 647 } else if (raster instanceof ByteComponentRaster && 648 raster.getNumBands() == 1 && 649 cm.getComponentSize(0) == 8 && 650 ((ByteComponentRaster)raster).getPixelStride() == 1) { 651 imageType = TYPE_BYTE_GRAY; 652 } else if (raster instanceof ShortComponentRaster && 653 raster.getNumBands() == 1 && 654 cm.getComponentSize(0) == 16 && 655 ((ShortComponentRaster)raster).getPixelStride() == 1) { 656 imageType = TYPE_USHORT_GRAY; 657 } 658 } else { 659 imageType = TYPE_CUSTOM; 660 } 661 return; 662 } 663 664 if ((raster instanceof IntegerComponentRaster) && 665 (numBands == 3 || numBands == 4)) { 666 IntegerComponentRaster iraster = 667 (IntegerComponentRaster) raster; 668 int pixSize = cm.getPixelSize(); 671 if (iraster.getPixelStride() == 1 && 672 cm instanceof DirectColorModel && 673 (pixSize == 32 || pixSize == 24)) 674 { 675 DirectColorModel dcm = (DirectColorModel ) cm; 677 int rmask = dcm.getRedMask(); 678 int gmask = dcm.getGreenMask(); 679 int bmask = dcm.getBlueMask(); 680 if (rmask == DCM_RED_MASK && gmask == DCM_GREEN_MASK && 681 bmask == DCM_BLUE_MASK) 682 { 683 if (dcm.getAlphaMask() == DCM_ALPHA_MASK) { 684 imageType = (isAlphaPre 685 ? TYPE_INT_ARGB_PRE 686 : TYPE_INT_ARGB); 687 } 688 else { 689 if (!dcm.hasAlpha()) { 691 imageType = TYPE_INT_RGB; 692 } 693 } 694 } else if (rmask == DCM_BGR_RED_MASK && gmask == DCM_BGR_GRN_MASK 696 && bmask == DCM_BGR_BLU_MASK) { 697 if (!dcm.hasAlpha()) { 698 imageType = TYPE_INT_BGR; 699 } 700 } } } else if ((cm instanceof IndexColorModel ) && (numBands == 1) && 704 (!cm.hasAlpha() || !isAlphaPre)) 705 { 706 IndexColorModel icm = (IndexColorModel ) cm; 707 int pixSize = icm.getPixelSize(); 708 709 if (raster instanceof BytePackedRaster) { 710 imageType = TYPE_BYTE_BINARY; 711 } else if (raster instanceof ByteComponentRaster) { 713 ByteComponentRaster braster = (ByteComponentRaster) raster; 714 if (braster.getPixelStride() == 1 && pixSize <= 8) { 715 imageType = TYPE_BYTE_INDEXED; 716 } 717 } 718 } else if ((raster instanceof ShortComponentRaster) 720 && (cm |