1 18 package org.apache.batik.ext.awt.image; 19 20 import java.awt.Composite ; 21 import java.awt.Graphics2D ; 22 import java.awt.GraphicsConfiguration ; 23 import java.awt.GraphicsDevice ; 24 import java.awt.Point ; 25 import java.awt.Rectangle ; 26 import java.awt.RenderingHints ; 27 import java.awt.Shape ; 28 import java.awt.color.ColorSpace ; 29 import java.awt.geom.AffineTransform ; 30 import java.awt.geom.Rectangle2D ; 31 import java.awt.image.BufferedImage ; 32 import java.awt.image.ColorModel ; 33 import java.awt.image.ComponentSampleModel ; 34 import java.awt.image.DataBuffer ; 35 import java.awt.image.DataBufferByte ; 36 import java.awt.image.DataBufferInt ; 37 import java.awt.image.DataBufferShort ; 38 import java.awt.image.DataBufferUShort ; 39 import java.awt.image.DirectColorModel ; 40 import java.awt.image.Raster ; 41 import java.awt.image.RenderedImage ; 42 import java.awt.image.SampleModel ; 43 import java.awt.image.SinglePixelPackedSampleModel ; 44 import java.awt.image.WritableRaster ; 45 import java.awt.image.renderable.RenderContext ; 46 import java.awt.image.renderable.RenderableImage ; 47 import java.lang.ref.Reference ; 48 import java.lang.ref.WeakReference ; 49 50 import org.apache.batik.ext.awt.RenderingHintsKeyExt; 51 import org.apache.batik.ext.awt.image.renderable.PaintRable; 52 import org.apache.batik.ext.awt.image.rendered.AffineRed; 53 import org.apache.batik.ext.awt.image.rendered.Any2LsRGBRed; 54 import org.apache.batik.ext.awt.image.rendered.Any2sRGBRed; 55 import org.apache.batik.ext.awt.image.rendered.BufferedImageCachableRed; 56 import org.apache.batik.ext.awt.image.rendered.CachableRed; 57 import org.apache.batik.ext.awt.image.rendered.FormatRed; 58 import org.apache.batik.ext.awt.image.rendered.RenderedImageCachableRed; 59 import org.apache.batik.ext.awt.image.rendered.TranslateRed; 60 61 62 70 public class GraphicsUtil { 71 72 public static AffineTransform IDENTITY = new AffineTransform (); 73 74 82 public static void drawImage(Graphics2D g2d, 83 RenderedImage ri) { 84 drawImage(g2d, wrap(ri)); 85 } 86 87 95 public static void drawImage(Graphics2D g2d, 96 CachableRed cr) { 97 98 100 AffineTransform at = null; 101 while (true) { 102 if (cr instanceof AffineRed) { 103 AffineRed ar = (AffineRed)cr; 104 if (at == null) 105 at = ar.getTransform(); 106 else 107 at.concatenate(ar.getTransform()); 108 cr = ar.getSource(); 109 continue; 110 } else if (cr instanceof TranslateRed) { 111 TranslateRed tr = (TranslateRed)cr; 112 int dx = tr.getDeltaX(); 114 int dy = tr.getDeltaY(); 115 if (at == null) 116 at = AffineTransform.getTranslateInstance(dx, dy); 117 else 118 at.translate(dx, dy); 119 cr = tr.getSource(); 120 continue; 121 } 122 break; 123 } 124 AffineTransform g2dAt = g2d.getTransform(); 125 if ((at == null) || (at.isIdentity())) 126 at = g2dAt; 127 else 128 at.preConcatenate(g2dAt); 129 130 ColorModel srcCM = cr.getColorModel(); 131 ColorSpace g2dCS = getDestinationColorSpace(g2d); 132 ColorModel g2dCM = getDestinationColorModel(g2d); 133 if (g2dCS == null) 134 g2dCS = ColorSpace.getInstance(ColorSpace.CS_sRGB); 136 ColorModel drawCM = g2dCM; 137 if ((g2dCM == null) || !g2dCM.hasAlpha()) { 138 drawCM = sRGB_Unpre; 142 } 143 144 if (cr instanceof BufferedImageCachableRed) { 145 if (g2dCS.equals(srcCM.getColorSpace()) && 149 drawCM.equals(srcCM)) { 150 g2d.setTransform(at); 152 BufferedImageCachableRed bicr; 153 bicr = (BufferedImageCachableRed)cr; 154 g2d.drawImage(bicr.getBufferedImage(), 155 bicr.getMinX(), bicr.getMinY(), null); 156 g2d.setTransform(g2dAt); 157 return; 158 } 159 } 160 161 double determinant = at.getDeterminant(); 163 if (!at.isIdentity() && (determinant <= 1.0)) { 164 if (at.getType() != AffineTransform.TYPE_TRANSLATION) 165 cr = new AffineRed(cr, at, g2d.getRenderingHints()); 166 else { 167 int xloc = cr.getMinX() + (int)at.getTranslateX(); 168 int yloc = cr.getMinY() + (int)at.getTranslateY(); 169 cr = new TranslateRed(cr, xloc, yloc); 170 } 171 } 172 173 if (g2dCS != srcCM.getColorSpace()) { 174 if (g2dCS == ColorSpace.getInstance(ColorSpace.CS_sRGB)) 182 cr = convertTosRGB(cr); 183 else if (g2dCS == ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB)) 184 cr = convertToLsRGB(cr); 185 } 186 srcCM = cr.getColorModel(); 187 if (!drawCM.equals(srcCM)) 188 cr = FormatRed.construct(cr, drawCM); 189 190 if (!at.isIdentity() && (determinant > 1.0)) 192 cr = new AffineRed(cr, at, g2d.getRenderingHints()); 193 194 g2d.setTransform(IDENTITY); 196 197 Composite g2dComposite = g2d.getComposite(); 202 if (g2d.getRenderingHint(RenderingHintsKeyExt.KEY_TRANSCODING) == 203 RenderingHintsKeyExt.VALUE_TRANSCODING_PRINTING) { 204 if (SVGComposite.OVER.equals(g2dComposite)) { 205 g2d.setComposite(SVGComposite.OVER); 206 } 207 } 208 Rectangle crR = cr.getBounds(); 209 Shape clip = g2d.getClip(); 210 211 try { 212 Rectangle clipR; 213 if (clip == null) { 214 clip = crR; 215 clipR = crR; 216 } else { 217 clipR = clip.getBounds(); 218 219 if (clipR.intersects(crR) == false) 220 return; clipR = clipR.intersection(crR); 222 } 223 224 Rectangle gcR = getDestinationBounds(g2d); 225 if (gcR != null) { 227 if (clipR.intersects(gcR) == false) 228 return; clipR = clipR.intersection(gcR); 230 } 231 232 235 boolean useDrawRenderedImage = false; 236 237 srcCM = cr.getColorModel(); 238 SampleModel srcSM = cr.getSampleModel(); 239 if ((srcSM.getWidth()*srcSM.getHeight()) >= 240 (clipR.width*clipR.height)) 241 useDrawRenderedImage = true; 244 245 Object atpHint = g2d.getRenderingHint 246 (RenderingHintsKeyExt.KEY_AVOID_TILE_PAINTING); 247 248 if (atpHint == RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_ON) 249 useDrawRenderedImage = true; 251 if (atpHint == RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_OFF) 252 useDrawRenderedImage = false; 253 254 255 WritableRaster wr; 256 if (useDrawRenderedImage) { 257 Raster r = cr.getData(clipR); 261 wr = ((WritableRaster )r).createWritableChild 262 (clipR.x, clipR.y, clipR.width, clipR.height, 263 0, 0, null); 264 265 BufferedImage bi = new BufferedImage 266 (srcCM, wr, srcCM.isAlphaPremultiplied(), null); 267 268 g2d.drawImage(bi, clipR.x, clipR.y, null); 273 } else { 274 wr = Raster.createWritableRaster(srcSM, new Point (0,0)); 276 BufferedImage bi = new BufferedImage 277 (srcCM, wr, srcCM.isAlphaPremultiplied(), null); 278 279 int xt0 = cr.getMinTileX(); 280 int xt1 = xt0+cr.getNumXTiles(); 281 int yt0 = cr.getMinTileY(); 282 int yt1 = yt0+cr.getNumYTiles(); 283 int tw = srcSM.getWidth(); 284 int th = srcSM.getHeight(); 285 286 Rectangle tR = new Rectangle (0,0,tw,th); 287 Rectangle iR = new Rectangle (0,0,0,0); 288 289 if (false) { 290 System.err.println("SrcCM: " + srcCM); 291 System.err.println("CR: " + cr); 292 System.err.println("CRR: " + crR + " TG: [" + 293 xt0 +"," + 294 yt0 +"," + 295 xt1 +"," + 296 yt1 +"] Off: " + 297 cr.getTileGridXOffset() +"," + 298 cr.getTileGridYOffset()); 299 } 300 301 int yloc = yt0*th+cr.getTileGridYOffset(); 302 int skip = (clipR.y-yloc)/th; 303 if (skip <0) skip = 0; 304 yt0+=skip; 305 306 int xloc = xt0*tw+cr.getTileGridXOffset(); 307 skip = (clipR.x-xloc)/tw; 308 if (skip <0) skip = 0; 309 xt0+=skip; 310 311 int endX = clipR.x+clipR.width-1; 312 int endY = clipR.y+clipR.height-1; 313 314 if (false) { 315 System.out.println("clipR: " + clipR + " TG: [" + 316 xt0 +"," + 317 yt0 +"," + 318 xt1 +"," + 319 yt1 +"] Off: " + 320 cr.getTileGridXOffset() +"," + 321 cr.getTileGridYOffset()); 322 } 323 324 325 yloc = yt0*th+cr.getTileGridYOffset(); 326 int minX = xt0*tw+cr.getTileGridXOffset(); 327 int xStep = tw; 328 xloc = minX; 329 for (int y=yt0; y<yt1; y++, yloc += th) { 330 if (yloc > endY) break; 331 for (int x=xt0; x<xt1; x++, xloc+=xStep) { 332 if ((xloc<minX) || (xloc > endX)) break; 333 tR.x = xloc; 334 tR.y = yloc; 335 Rectangle2D.intersect(crR, tR, iR); 336 337 WritableRaster twr; 338 twr = wr.createWritableChild(0, 0, 339 iR.width, iR.height, 340 iR.x, iR.y, null); 341 342 cr.copyData(twr); 344 345 BufferedImage subBI; 347 subBI = bi.getSubimage(0, 0, iR.width, iR.height); 348 349 if (false) { 350 System.out.println("Drawing: " + tR); 351 System.out.println("IR: " + iR); 352 } 353 354 g2d.drawImage(subBI, iR.x, iR.y, null); 358 362 } 366 xStep = -xStep; xloc += xStep; } 369 } 370 373 374 } finally { 375 g2d.setTransform(g2dAt); 376 g2d.setComposite(g2dComposite); 377 } 378 379 } 381 382 383 398 public static void drawImage(Graphics2D g2d, 399 RenderableImage filter, 400 RenderContext rc) { 401 402 AffineTransform origDev = g2d.getTransform(); 403 Shape origClip = g2d.getClip(); 404 RenderingHints origRH = g2d.getRenderingHints(); 405 406 Shape clip = rc.getAreaOfInterest(); 407 if (clip != null) 408 g2d.clip(clip); 409 g2d.transform(rc.getTransform()); 410 g2d.setRenderingHints(rc.getRenderingHints()); 411 412 drawImage(g2d, filter); 413 414 g2d.setTransform(origDev); 415 g2d.setClip(origClip); 416 g2d.setRenderingHints(origRH); 417 } 418 419 432 public static void drawImage(Graphics2D g2d, 433 RenderableImage filter) { 434 if (filter instanceof PaintRable) { 435 PaintRable pr = (PaintRable)filter; 436 if (pr.paintRable(g2d)) 437 return; 439 } 440 441 AffineTransform at = g2d.getTransform(); 444 RenderedImage ri = filter.createRendering 445 (new RenderContext (at, g2d.getClip(), g2d.getRenderingHints())); 446 447 if (ri == null) 448 return; 449 450 g2d.setTransform(IDENTITY); 451 drawImage(g2d, GraphicsUtil.wrap(ri)); 452 g2d.setTransform(at); 453 } 454 455 467 public static Graphics2D createGraphics(BufferedImage bi, 468 RenderingHints hints) { 469 Graphics2D g2d = bi.createGraphics(); 470 if (hints != null) 471 g2d.addRenderingHints(hints); 472 g2d.setRenderingHint(RenderingHintsKeyExt.KEY_BUFFERED_IMAGE, 473 new WeakReference (bi)); 474 g2d.clip(new Rectangle (0, 0, bi.getWidth(), bi.getHeight())); 475 return g2d; 476 } 477 478 479 public static Graphics2D createGraphics(BufferedImage bi) { 480 Graphics2D g2d = bi.createGraphics(); 481 g2d.setRenderingHint(RenderingHintsKeyExt.KEY_BUFFERED_IMAGE, 482 new WeakReference (bi)); 483 g2d.clip(new Rectangle (0, 0, bi.getWidth(), bi.getHeight())); 484 return g2d; 485 } 486 487 488 public final static boolean WARN_DESTINATION = true; 489 490 public static BufferedImage getDestination(Graphics2D g2d) { 491 Object o = g2d.getRenderingHint 492 (RenderingHintsKeyExt.KEY_BUFFERED_IMAGE); 493 if (o != null) 494 return (BufferedImage )(((Reference )o).get()); 495 496 GraphicsConfiguration gc = g2d.getDeviceConfiguration(); 498 GraphicsDevice gd = gc.getDevice(); 499 if (WARN_DESTINATION && 500 (gd.getType() == GraphicsDevice.TYPE_IMAGE_BUFFER) && 501 (g2d.getRenderingHint(RenderingHintsKeyExt.KEY_TRANSCODING) != 502 RenderingHintsKeyExt.VALUE_TRANSCODING_PRINTING)) 503 System.out.println 505 ("Graphics2D from BufferedImage lacks BUFFERED_IMAGE hint"); 506 507 return null; 508 } 509 510 public static ColorModel getDestinationColorModel(Graphics2D g2d) { 511 BufferedImage bi = getDestination(g2d); 512 if (bi != null) 513 return bi.getColorModel(); 514 515 GraphicsConfiguration gc = g2d.getDeviceConfiguration(); 516 517 if (gc.getDevice().getType() == GraphicsDevice.TYPE_IMAGE_BUFFER) { 520 if (g2d.getRenderingHint(RenderingHintsKeyExt.KEY_TRANSCODING) == 521 RenderingHintsKeyExt.VALUE_TRANSCODING_PRINTING) 522 return sRGB_Unpre; 523 524 return null; 527 } 528 529 return gc.getColorModel(); 530 } 531 532 public static ColorSpace getDestinationColorSpace(Graphics2D g2d) { 533 ColorModel cm = getDestinationColorModel(g2d); 534 if (cm != null) return cm.getColorSpace(); 535 536 return null; 537 } 538 539 public static Rectangle getDestinationBounds(Graphics2D g2d) { 540 BufferedImage bi = getDestination(g2d); 541 if (bi != null) 542 return new Rectangle (0, 0, bi.getWidth(), bi.getHeight()); 543 544 GraphicsConfiguration gc = g2d.getDeviceConfiguration(); 545 546 if (gc.getDevice().getType() == GraphicsDevice.TYPE_IMAGE_BUFFER) 549 return null; 550 551 return null; 554 } 555 556 557 559 public final static ColorModel Linear_sRGB = 560 new DirectColorModel (ColorSpace.getInstance 561 (ColorSpace.CS_LINEAR_RGB), 24, 562 0x00FF0000, 0x0000FF00, 563 0x000000FF, 0x0, false, 564 DataBuffer.TYPE_INT); 565 568 public final static ColorModel Linear_sRGB_Pre = 569 new DirectColorModel (ColorSpace.getInstance 570 (ColorSpace.CS_LINEAR_RGB), 32, 571 0x00FF0000, 0x0000FF00, 572 0x000000FF, 0xFF000000, true, 573 DataBuffer.TYPE_INT); 574 577 public final static ColorModel Linear_sRGB_Unpre = 578 new DirectColorModel (ColorSpace.getInstance 579 (ColorSpace.CS_LINEAR_RGB), 32, 580 0x00FF0000, 0x0000FF00, 581 0x000000FF, 0xFF000000, false, 582 DataBuffer.TYPE_INT); 583 584 587 public final static ColorModel sRGB = 588 new DirectColorModel (ColorSpace.getInstance 589 (ColorSpace.CS_sRGB), 24, 590 0x00FF0000, 0x0000FF00, 591 0x000000FF, 0x0, false, 592 DataBuffer.TYPE_INT); 593 596 public final static ColorModel sRGB_Pre = 597 new DirectColorModel (ColorSpace.getInstance 598 (ColorSpace.CS_sRGB), 32, 599 0x00FF0000, 0x0000FF00, 600 0x000000FF, 0xFF000000, true, 601 DataBuffer.TYPE_INT); 602 605 public final static ColorModel sRGB_Unpre = 606 new DirectColorModel (ColorSpace.getInstance 607 (ColorSpace.CS_sRGB), 32, 608 0x00FF0000, 0x0000FF00, 609 0x000000FF, 0xFF000000, false, 610 DataBuffer.TYPE_INT); 611 612 620 public static ColorModel makeLinear_sRGBCM(boolean premult) { 621 if (premult) 622 return Linear_sRGB_Pre; 623 return Linear_sRGB_Unpre; 624 } 625 626 633 public static BufferedImage makeLinearBufferedImage(int width, 634 int height, 635 boolean premult) { 636 ColorModel cm = makeLinear_sRGBCM(premult); 637 WritableRaster wr = cm.createCompatibleWritableRaster(width, height); 638 return new BufferedImage (cm, wr, premult, null); 639 } 640 641 652 public static CachableRed convertToLsRGB(CachableRed src) { 653 ColorModel cm = src.getColorModel(); 654 ColorSpace cs = cm.getColorSpace(); 655 if (cs == ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB)) 656 return src; 657 658 return new Any2LsRGBRed(src); 659 } 660 661 671 public static CachableRed convertTosRGB(CachableRed src) { 672 ColorModel cm = src.getColorModel(); 673 ColorSpace cs = cm.getColorSpace(); 674 if (cs == ColorSpace.getInstance(ColorSpace.CS_sRGB)) 675 return src; 676 677 return new Any2sRGBRed(src); 678 } 679 680 693 public static CachableRed wrap(RenderedImage ri) { 694 if (ri instanceof CachableRed) 695 return (CachableRed) ri; 696 if (ri instanceof BufferedImage ) 697 return new BufferedImageCachableRed((BufferedImage )ri); 698 return new RenderedImageCachableRed(ri); 699 } 700 701 712 public static void copyData_INT_PACK(Raster src, WritableRaster dst) { 713 int x0 = dst.getMinX(); 715 if (x0 < src.getMinX()) x0 = src.getMinX(); 716 717 int y0 = dst.getMinY(); 718 if (y0 < src.getMinY()) y0 = src.getMinY(); 719 720 int x1 = dst.getMinX()+dst.getWidth()-1; 721 if (x1 > src.getMinX()+src.getWidth()-1) 722 x1 = src.getMinX()+src.getWidth()-1; 723 724 int y1 = dst.getMinY()+dst.getHeight()-1; 725 if (y1 > src.getMinY()+src.getHeight()-1) 726 y1 = src.getMinY()+src.getHeight()-1; 727 728 int width = x1-x0+1; 729 int height = y1-y0+1; 730 731 SinglePixelPackedSampleModel srcSPPSM; 732 srcSPPSM = (SinglePixelPackedSampleModel )src.getSampleModel(); 733 734 final int srcScanStride = srcSPPSM.getScanlineStride(); 735 DataBufferInt srcDB = (DataBufferInt )src.getDataBuffer(); 736 final int [] srcPixels = srcDB.getBankData()[0]; 737 final int srcBase = 738 (srcDB.getOffset() + 739 srcSPPSM.getOffset(x0-src.getSampleModelTranslateX(), 740 y0-src.getSampleModelTranslateY())); 741 742 743 SinglePixelPackedSampleModel dstSPPSM; 744 dstSPPSM = (SinglePixelPackedSampleModel )dst.getSampleModel(); 745 746 final int dstScanStride = dstSPPSM.getScanlineStride(); 747 DataBufferInt dstDB = (DataBufferInt )dst.getDataBuffer(); 748 final int [] dstPixels = dstDB.getBankData()[0]; 749 final int dstBase = 750 (dstDB.getOffset() + 751 dstSPPSM.getOffset(x0-dst.getSampleModelTranslateX(), 752 y0-dst.getSampleModelTranslateY())); 753 754 if ((srcScanStride == dstScanStride) && 755 (srcScanStride == width)) { 756 758 System.arraycopy(srcPixels, srcBase, dstPixels, dstBase, 759 width*height); 760 } else if (width > 128) { 761 int srcSP = srcBase; 762 int dstSP = dstBase; 763 for (int y=0; y<height; y++) { 764 System.arraycopy(srcPixels, srcSP, dstPixels, dstSP, width); 765 srcSP += srcScanStride; 766 dstSP += dstScanStride; 767 } 768 } else { 769 for (int y=0; y<height; y++) { 770 int srcSP = srcBase+y*srcScanStride; 771 int dstSP = dstBase+y*dstScanStride; 772 for (int x=0; x<width; x++) 773 dstPixels[dstSP++] = srcPixels[srcSP++]; 774 } 775 } 776 } 777 778 public static void copyData_FALLBACK(Raster src, WritableRaster dst) { 779 781 int x0 = dst.getMinX(); 782 if (x0 < src.getMinX()) x0 = src.getMinX(); 783 784 int y0 = dst.getMinY(); 785 if (y0 < src.getMinY()) y0 = src.getMinY(); 786 787 int x1 = dst.getMinX()+dst.getWidth()-1; 788 if (x1 > src.getMinX()+src.getWidth()-1) 789 x1 = src.getMinX()+src.getWidth()-1; 790 791 int y1 = dst.getMinY()+dst.getHeight()-1; 792 if (y1 > src.getMinY()+src.getHeight()-1) 793 y1 = src.getMinY()+src.getHeight()-1; 794 795 int width = x1-x0+1; 796 int [] data = null; 797 798 for (int y = y0; y <= y1 ; y++) { 799 data = src.getPixels(x0,y,width,1,data); 800 dst.setPixels (x0,y,width,1,data); 801 } 802 } 803 804 812 public static void copyData(Raster src, WritableRaster dst) { 813 if (is_INT_PACK_Data(src.getSampleModel(), false) && 814 is_INT_PACK_Data(dst.getSampleModel(), false)) { 815 copyData_INT_PACK(src, dst); 816 return; 817 } 818 819 copyData_FALLBACK(src, dst); 820 } 821 822 833 public static WritableRaster copyRaster(Raster ras) { 834 return copyRaster(ras, ras.getMinX(), ras.getMinY()); 835 } 836 837 838 858 public static WritableRaster copyRaster(Raster ras, int minX, int minY) { 859 WritableRaster ret = Raster.createWritableRaster 860 (ras.getSampleModel(), 861 new Point (0,0)); 862 ret = ret.createWritableChild 863 (ras.getMinX()-ras.getSampleModelTranslateX(), 864 ras.getMinY()-ras.getSampleModelTranslateY(), 865 ras.getWidth(), ras.getHeight(), 866 minX, minY, null); 867 868 DataBuffer srcDB = ras.getDataBuffer(); 870 DataBuffer retDB = ret.getDataBuffer(); 871 if (srcDB.getDataType() != retDB.getDataType()) { 872 throw new IllegalArgumentException 873 ("New DataBuffer doesn't match original"); 874 } 875 int len = srcDB.getSize(); 876 int banks = srcDB.getNumBanks(); 877 int [] offsets = srcDB.getOffsets(); 878 for (int b=0; b< banks; b++) { 879 switch (srcDB.getDataType()) { 880 case DataBuffer.TYPE_BYTE: { 881 DataBufferByte srcDBT = (DataBufferByte )srcDB; 882 DataBufferByte retDBT = (DataBufferByte )retDB; 883 System.arraycopy(srcDBT.getData(b), offsets[b], 884 retDBT.getData(b), offsets[b], len); 885 } 886 case DataBuffer.TYPE_INT: { 887 DataBufferInt srcDBT = (DataBufferInt )srcDB; 888 DataBufferInt retDBT = (DataBufferInt )retDB; 889 System.arraycopy(srcDBT.getData(b), offsets[b], 890 retDBT.getData(b), offsets[b], len); 891 } 892 case DataBuffer.TYPE_SHORT: { 893 DataBufferShort srcDBT = (DataBufferShort )srcDB; 894 DataBufferShort retDBT = (DataBufferShort )retDB; 895 System.arraycopy(srcDBT.getData(b), offsets[b], 896 retDBT.getData(b), offsets[b], len); 897 } 898 case DataBuffer.TYPE_USHORT: { 899 DataBufferUShort srcDBT = (DataBufferUShort )srcDB; 900 DataBufferUShort retDBT = (DataBufferUShort )retDB; 901 System.arraycopy(srcDBT.getData(b), offsets[b], 902 retDBT.getData(b), offsets[b], len); 903 } 904 } 905 } 906 907 return ret; 908 } 909 910 924 public static WritableRaster makeRasterWritable(Raster ras) { 925 return makeRasterWritable(ras, ras.getMinX(), ras.getMinY()); 926 } 927 928 955 public static WritableRaster makeRasterWritable(Raster ras, 956 int minX, int minY) { 957 WritableRaster ret = Raster.createWritableRaster 958 (ras.getSampleModel(), 959 ras.getDataBuffer(), 960 new Point (0,0)); 961 ret = ret.createWritableChild 962 (ras.getMinX()-ras.getSampleModelTranslateX(), 963 ras.getMinY()-ras.getSampleModelTranslateY(), 964 ras.getWidth(), ras.getHeight(), 965 minX, minY, null); 966 return ret; 967 } 968 969 977 public static ColorModel 978 coerceColorModel(ColorModel cm, boolean newAlphaPreMult) { 979 if (cm.isAlphaPremultiplied() == newAlphaPreMult) 980 return cm; 981 982 WritableRaster wr = cm.createCompatibleWritableRaster(1,1); 986 return cm.coerceData(wr, newAlphaPreMult); 987 } 988 989 998 public static ColorModel 999 coerceData(WritableRaster wr, ColorModel cm, boolean newAlphaPreMult) { 1000 1001 if (cm.hasAlpha()== false) 1004 return cm; 1006 1007 if (cm.isAlphaPremultiplied() == newAlphaPreMult) 1008 return cm; 1010 1011 1013 if (newAlphaPreMult) { 1014 multiplyAlpha(wr); 1015 } else { 1016 divideAlpha(wr); 1017 } 1018 1019 return coerceColorModel(cm, newAlphaPreMult); 1020 } 1021 1022 public static void multiplyAlpha(WritableRaster wr) { 1023 if (is_BYTE_COMP_Data(wr.getSampleModel())) 1024 mult_BYTE_COMP_Data(wr); 1025 else if (is_INT_PACK_Data(wr.getSampleModel(), true)) 1026 mult_INT_PACK_Data(wr); 1027 else { 1028 int [] pixel = null; 1029 int bands = wr.getNumBands(); 1030 float norm = 1f/255f; 1031 int x0, x1, y0, y1, a, b; 1032 float alpha; 1033 x0 = wr.getMinX(); 1034 x1 = x0+wr.getWidth(); 1035 y0 = wr.getMinY(); 1036 y1 = y0+wr.getHeight(); 1037 for (int y=y0; y<y1; y++) 1038 for (int x=x0; x<x1; x++) { 1039 pixel = wr.getPixel(x,y,pixel); 1040 a = pixel[bands-1]; 1041 if ((a >= 0) && (a < 255)) { 1042 alpha = a*norm; 1043 for (b=0; b<bands-1; b++) 1044 pixel[b] = (int)(pixel[b]*alpha+0.5f); 1045 wr.setPixel(x,y,pixel); 1046 } 1047 } 1048 } 1049 } 1050 1051 public static void divideAlpha(WritableRaster wr) { 1052 if (is_BYTE_COMP_Data(wr.getSampleModel())) 1053 divide_BYTE_COMP_Data(wr); 1054 else if (is_INT_PACK_Data(wr.getSampleModel(), true)) 1055 divide_INT_PACK_Data(wr); 1056 else { 1057 int x0, x1, y0, y1, a, b; 1058 float ialpha; 1059 int bands = wr.getNumBands(); 1060 int [] pixel = null; 1061 1062 x0 = wr.getMinX(); 1063 x1 = x0+wr.getWidth(); 1064 y0 = wr.getMinY(); 1065 y1 = y0+wr.getHeight(); 1066 for (int y=y0; y<y1; y++) 1067 for (int x=x0; x<x1; x++) { 1068 pixel = wr.getPixel(x,y,pixel); 1069 a = pixel[bands-1]; 1070 if ((a > 0) && (a < 255)) { 1071 ialpha = 255/(float)a; 1072 for (b=0; b<bands-1; b++) 1073 pixel[b] = (int)(pixel[b]*ialpha+0.5f); 1074 wr.setPixel(x,y,pixel); 1075 } 1076 } 1077 } 1078 } 1079 1080 1087 public static void 1088 copyData(BufferedImage src, BufferedImage dst) { 1089 Rectangle srcRect = new Rectangle (0, 0, 1090 src.getWidth(), src.getHeight()); 1091 copyData(src, srcRect, dst, new Point (0,0)); 1092 } 1093 1094 1095 1104 public static void 1105 copyData(BufferedImage src, Rectangle srcRect, 1106 BufferedImage dst, Point destP) { 1107 1108 1114 boolean srcAlpha = src.getColorModel().hasAlpha(); 1115 boolean dstAlpha = dst.getColorModel().hasAlpha(); 1116 1117 1123 if (srcAlpha == dstAlpha) 1124 if ((srcAlpha == false) || 1125 (src.isAlphaPremultiplied() == dst.isAlphaPremultiplied())) { 1126 copyData(src.getRaster(), dst.getRaster()); 1128 return; 1129 } 1130 1131 1133 int [] pixel = null; 1134 Raster srcR = src.getRaster(); 1135 WritableRaster dstR = dst.getRaster(); 1136 int bands = dstR.getNumBands(); 1137 1138 int dx = destP.x-srcRect.x; 1139 int dy = destP.y-srcRect.y; 1140 1141 int w = srcRect.width; 1142 int x0 = srcRect.x; 1143 int y0 = srcRect.y; 1144 int y1 = y0+srcRect.height-1; 1145 1146 if (!srcAlpha) { 1147 int [] oPix = new int[bands*w]; 1150 int out = (w*bands)-1; while(out >= 0) { 1152 oPix[out] = 255; 1154 out -= bands; 1155 } 1156 1157 int b, in; 1158 for (int y=y0; y<=y1; y++) { 1159 pixel = srcR.getPixels(x0,y,w,1,pixel); 1160 in = w*(bands-1)-1; 1161 out = (w*bands)-2; switch (bands) { 1163 case 4: 1164 while(in >= 0) { 1165 oPix[out--] = pixel[in--]; 1166 oPix[out--] = pixel[in--]; 1167 oPix[out--] = pixel[in--]; 1168 out--; 1169 } 1170 break; 1171 default: 1172 while(in >= 0) { 1173 for (b=0; b<bands-1; b++) 1174 oPix[out--] = pixel[in--]; 1175 out--; 1176 } 1177 } 1178 dstR.setPixels(x0+dx, y+dy, w, 1, oPix); 1179 } 1180 } else if (dstAlpha && dst.isAlphaPremultiplied()) { 1181 int a, b, alpha, in, fpNorm = (1<<24)/255, pt5 = 1<<23; 1184 for (int y=y0; y<=y1; y++) { 1185 pixel = srcR.getPixels(x0,y,w,1,pixel); 1186 in=bands*w-1; 1187 switch (bands) { 1188 case 4: 1189 while(in >= 0) { 1190 a = pixel[in]; 1191 if (a == 255) 1192 in -= 4; 1193 else { 1194 in--; 1195 alpha = fpNorm*a; 1196 pixel[in] = (pixel[in]*alpha+pt5)>>>24; in--; 1197 pixel[in] = (pixel[in]*alpha+pt5)>>>24; in--; 1198 pixel[in] = (pixel[in]*alpha+pt5)>>>24; in--; 1199 } 1200 } 1201 break; 1202 default: 1203 while(in >= 0) { 1204 a = pixel[in]; 1205 if (a == 255) 1206 in -= bands; 1207 else { 1208 in--; 1209 alpha = fpNorm*a; 1210 for (b=0; b<bands-1; b++) { 1211 pixel[in] = (pixel[in]*alpha+pt5)>>>24; 1212 in--; 1213 } 1214 } 1215 } 1216 } 1217 dstR.setPixels(x0+dx, y+dy, w, 1, pixel); 1218 } 1219 } else if (dstAlpha && !dst.isAlphaPremultiplied()) { 1220 int a, b, ialpha, in, fpNorm = 0x00FF0000, pt5 = 1<<15; 1223 for (int y=y0; y<=y1; y++) { 1224 pixel = srcR.getPixels(x0,y,w,1,pixel); 1225 in=(bands*w)-1; 1226 switch(bands) { 1227 case 4: 1228 while(in >= 0) { 1229 a = pixel[in]; 1230 if ((a <= 0) || (a >= 255)) 1231 in -= 4; 1232 else { 1233 in--; 1234 ialpha = fpNorm/a; 1235 pixel[in] = (pixel[in]*ialpha+pt5)>>>16; in--; 1236 pixel[in] = (pixel[in]*ialpha+pt5)>>>16; in--; 1237 pixel[in] = (pixel[in]*ialpha+pt5)>>>16; in--; 1238 } 1239 } 1240 break; 1241 default: 1242 while(in >= 0) { 1243 a = pixel[in]; 1244 if ((a <= 0) || (a >= 255)) 1245 in -= bands; 1246 else { 1247 in--; 1248 ialpha = fpNorm/a; 1249 for (b=0; b<bands-1; b++) { 1250 pixel[in] = (pixel[in]*ialpha+pt5)>>>16; 1251 in--; 1252 } 1253 } 1254 } 1255 } 1256 dstR.setPixels(x0+dx, y+dy, w, 1, pixel); 1257 } 1258 } else if (src.isAlphaPremultiplied()) { 1259 int [] oPix = new int[bands*w]; 1260 int a, b, ialpha, in, out, fpNorm = 0x00FF0000, pt5 = 1<<15; 1263 for (int y=y0; y<=y1; y++) { 1264 pixel = srcR.getPixels(x0,y,w,1,pixel); 1265 in = (bands+1)*w -1; 1266 out = (bands*w)-1; 1267 while(in >= 0) { 1268 a = pixel[in]; in--; 1269 if (a > 0) { 1270 if (a < 255) { 1271 ialpha = fpNorm/a; 1272 for (b=0; b<bands; b++) 1273 oPix[out--] = (pixel[in--]*ialpha+pt5)>>>16; 1274 } else 1275 for (b=0; b<bands; b++) 1276 oPix[out--] = pixel[in--]; 1277 } else { 1278 in -= bands; 1279 for (b=0; b<bands; b++) 1280 oPix[out--] = 255; 1281 } 1282 } 1283 dstR.setPixels(x0+dx, y+dy, w, 1, oPix); 1284 } 1285 } else { 1286 Rectangle dstRect = new Rectangle (destP.x, destP.y, 1289 srcRect.width, srcRect.height); 1290 for (int b=0; b<bands; b++) 1291 copyBand(srcR, srcRect, b, 1292 dstR, dstRect, b); 1293 } 1294 } 1295 1296 public static void copyBand(Raster src, int srcBand, 1297 WritableRaster dst, int dstBand) { 1298 1299 Rectangle sR = src.getBounds(); 1300 Rectangle dR = dst.getBounds(); 1301 Rectangle cpR = sR.intersection(dR); 1302 1303 copyBand(src, cpR, srcBand, dst, cpR, dstBand); 1304 } 1305 1306 public static void copyBand(Raster src, Rectangle sR, int sBand, 1307 WritableRaster dst, Rectangle dR, int dBand) { 1308 int dy = dR.y -sR.y; 1309 int dx = dR.x -sR.x; 1310 sR = sR.intersection(src.getBounds()); 1311 dR = dR.intersection(dst.getBounds()); 1312 int width, height; 1313 if (dR.width < sR.width) width = dR.width; 1314 else width = sR.width; 1315 if (dR.height < sR.height) height = dR.height; 1316 else height = sR.height; 1317 1318 int x = sR.x+dx; 1319 int [] samples = null; 1320 for (int y=sR.y; y< sR.y+height; y++) { 1321 samples = src.getSamples(sR.x, y, width, 1, sBand, samples); 1322 dst.setSamples(x, y+dy, width, 1, dBand, samples); 1323 } 1324 } 1325 1326 public static boolean is_INT_PACK_Data(SampleModel sm, 1327 boolean requireAlpha) { 1328 if(!(sm instanceof SinglePixelPackedSampleModel )) return false; 1330 1331 if(sm.getDataType() != DataBuffer.TYPE_INT) return false; 1333 1334 SinglePixelPackedSampleModel sppsm; 1335 sppsm = (SinglePixelPackedSampleModel )sm; 1336 1337 int [] masks = sppsm.getBitMasks(); 1338 if (masks.length == 3) { 1339 if (requireAlpha) return false; 1340 } else if (masks.length != 4) 1341 return false; 1342 1343 if(masks[0] != 0x00ff0000) return false; 1344 if(masks[1] != 0x0000ff00) return false; 1345 if(masks[2] != 0x000000ff) return false; 1346 if ((masks.length == 4) && 1347 (masks[3] != 0xff000000)) return false; 1348 1349 return true; 1350 } 1351 1352 public static boolean is_BYTE_COMP_Data(SampleModel sm) { 1353 if(!(sm instanceof ComponentSampleModel )) return false; 1355 1356 if(sm.getDataType() != DataBuffer.TYPE_BYTE) return false; 1358 1359 return true; 1360 } 1361 1362 protected static void divide_INT_PACK_Data(WritableRaster wr) { 1363 1365 SinglePixelPackedSampleModel sppsm; 1366 sppsm = (SinglePixelPackedSampleModel )wr.getSampleModel(); 1367 1368 final int width = wr.getWidth(); 1369 1370 final int scanStride = sppsm.getScanlineStride(); 1371 DataBufferInt db = (DataBufferInt )wr.getDataBuffer(); 1372 final int base 1373 = (db.getOffset() + 1374 sppsm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(), 1375 wr.getMinY()-wr.getSampleModelTranslateY())); 1376 int pixel, a, aFP; 1377 final int pixels[] = db.getBankData()[0]; 1379 for (int y=0; y<wr.getHeight(); y++) { 1380 int sp = base + y*scanStride; 1381 final int end = sp + width; 1382 while (sp < end) { 1383 pixel = pixels[sp]; 1384 a = pixel>>>24; 1385 if (a<=0) { 1386 pixels[sp] = 0x00FFFFFF; 1387 } 1388 else if (a<255) { 1389 aFP = (0x00FF0000/a); 1390 pixels[sp] = 1391 ((a << 24) | 1392 (((((pixel&0xFF0000)>>16)*aFP)&0xFF0000) ) | 1393 (((((pixel&0x00FF00)>>8) *aFP)&0xFF0000)>>8 ) | 1394 (((((pixel&0x0000FF)) *aFP)&0xFF0000)>>16)); 1395 } 1396 sp++; 1397 } 1398 } 1399 } 1400 1401 protected static void mult_INT_PACK_Data(WritableRaster wr) { 1402 1404 SinglePixelPackedSampleModel sppsm; 1405 sppsm = (SinglePixelPackedSampleModel )wr.getSampleModel(); 1406 1407 final int width = wr.getWidth(); 1408 1409 final int scanStride = sppsm.getScanlineStride(); 1410 DataBufferInt db = (DataBufferInt )wr.getDataBuffer(); 1411 final int base 1412 = (db.getOffset() + 1413 sppsm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(), 1414 wr.getMinY()-wr.getSampleModelTranslateY())); 1415 final int pixels[] = db.getBankData()[0]; 1417 for (int y=0; y<wr.getHeight(); y++) { 1418 int sp = base + y*scanStride; 1419 final int end = sp + width; 1420 while (sp < end) { 1421 int pixel = pixels[sp]; 1422 int a = pixel>>>24; 1423 if ((a>=0) && (a<255)) { 1424 pixels[sp] = ((a << 24) | 1425 ((((pixel&0xFF0000)*a)>>8)&0xFF0000) | 1426 ((((pixel&0x00FF00)*a)>>8)&0x00FF00) | 1427 ((((pixel&0x0000FF)*a)>>8)&0x0000FF)); 1428 } 1429 sp++; 1430 } 1431 } 1432 } 1433 1434 1435 protected static void divide_BYTE_COMP_Data(WritableRaster wr) { 1436 1438 ComponentSampleModel csm; 1439 csm = (ComponentSampleModel )wr.getSampleModel(); 1440 1441 final int width = wr.getWidth(); 1442 1443 final int scanStride = csm.getScanlineStride(); 1444 final int pixStride = csm.getPixelStride(); 1445 final int [] bandOff = csm.getBandOffsets(); 1446 1447 DataBufferByte db = (DataBufferByte )wr.getDataBuffer(); 1448 final int base 1449 = (db.getOffset() + 1450 csm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(), 1451 wr.getMinY()-wr.getSampleModelTranslateY())); 1452 1453 1454 int a=0; 1455 int aOff = bandOff[bandOff.length-1]; 1456 int bands = bandOff.length-1; 1457 int b, i; 1458 final byte pixels[] = db.getBankData()[0]; 1460 for (int y=0; y<wr.getHeight(); y++) { 1461 int sp = base + y*scanStride; 1462 final int end = sp + width*pixStride; 1463 while (sp < end) { 1464 a = pixels[sp+aOff]&0xFF; 1465 if (a==0) { 1466 for (b=0; b<bands; b++) 1467 pixels[sp+bandOff[b]] = (byte)0xFF; 1468 } else if (a<255) { 1469 int aFP = (0x00FF0000/a); 1470 for (b=0; b<bands; b++) { 1471 i = sp+bandOff[b]; 1472 pixels[i] = (byte)(((pixels[i]&0xFF)*aFP)>>>16); 1473 } 1474 } 1475 sp+=pixStride; 1476 } 1477 } 1478 } 1479 1480 protected static void mult_BYTE_COMP_Data(WritableRaster wr) { 1481 1483 ComponentSampleModel csm; 1484 csm = (ComponentSampleModel )wr.getSampleModel(); 1485 1486 final int width = wr.getWidth(); 1487 1488 final int scanStride = csm.getScanlineStride(); 1489 final int pixStride = csm.getPixelStride(); 1490 final int [] bandOff = csm.getBandOffsets(); 1491 1492 DataBufferByte db = (DataBufferByte )wr.getDataBuffer(); 1493 final int base 1494 = (db.getOffset() + 1495 csm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(), 1496 wr.getMinY()-wr.getSampleModelTranslateY())); 1497 1498 1499 int a=0; 1500 int aOff = bandOff[bandOff.length-1]; 1501 int bands = bandOff.length-1; 1502 int b, i; 1503 1504 final byte pixels[] = db.getBankData()[0]; 1506 for (int y=0; y<wr.getHeight(); y++) { 1507 int sp = base + y*scanStride; 1508 final int end = sp + width*pixStride; 1509 while (sp < end) { 1510 a = pixels[sp+aOff]&0xFF; 1511 if (a!=0xFF) 1512 for (b=0; b<bands; b++) { 1513 i = sp+bandOff[b]; 1514 pixels[i] = (byte)(((pixels[i]&0xFF)*a)>>8); 1515 } 1516 sp+=pixStride; 1517 } 1518 } 1519 } 1520 1521 1587 1588} 1589 | Popular Tags |