|
44 | 44 | import java.awt.image.ComponentColorModel; |
45 | 45 | import java.awt.image.ConvolveOp; |
46 | 46 | import java.awt.image.DataBuffer; |
| 47 | +import java.awt.image.DirectColorModel; |
47 | 48 | import java.awt.image.IndexColorModel; |
48 | 49 | import java.awt.image.Kernel; |
49 | 50 | import java.awt.image.LookupOp; |
@@ -134,7 +135,7 @@ protected static enum Hacks { |
134 | 135 | /** set destination type for blur operation */ |
135 | 136 | forceDestForBlur, |
136 | 137 | /** set destination type for scale operation */ |
137 | | - forceDestForScale, |
| 138 | + forceDestForScaleCustom, |
138 | 139 | /** JPEG writer can't deal with RGBA */ |
139 | 140 | needsJpegWriteRgb, |
140 | 141 | /** add ICC profile to PNG metadata manually */ |
@@ -214,8 +215,7 @@ protected static enum Hacks { |
214 | 215 | // this hopefully works for all |
215 | 216 | mapBgrByteTable = new ByteLookupTable(0, new byte[][] { mapR, mapG, mapB }); |
216 | 217 | imageHacks.put(Hacks.force16BitTo8, true); |
217 | | - imageHacks.put(Hacks.forceDestForScale, true); |
218 | | - imageHacks.put(Hacks.forceDestForBlur, true); |
| 218 | + imageHacks.put(Hacks.forceDestForScaleCustom, true); |
219 | 219 | imageHacks.put(Hacks.needsJpegWriteRgb, true); |
220 | 220 | imageHacks.put(Hacks.needsPngWriteProfile, true); |
221 | 221 | imageHacks.put(Hacks.needsPngLoadProfile, true); |
@@ -346,16 +346,33 @@ public Iterator<String> getSupportedFormats() { |
346 | 346 | /** |
347 | 347 | * Create an empty BufferedImage that is compatible and uses the same ColorModel as oldImg. |
348 | 348 | * |
349 | | - * @param width |
350 | | - * @param height |
351 | | - * @param oldImg |
352 | | - * @return |
353 | | - */ |
354 | | - protected BufferedImage createCompatibleImage(int width, int height, BufferedImage oldImg) { |
| 349 | + * @param width |
| 350 | + * @param height |
| 351 | + * @param hasAlpha |
| 352 | + * @param oldImg |
| 353 | + * @return |
| 354 | + */ |
| 355 | + protected BufferedImage createCompatibleImage(int width, int height, boolean hasAlpha, |
| 356 | + BufferedImage oldImg) { |
355 | 357 | ColorModel oldCM = oldImg.getColorModel(); |
356 | 358 | boolean isAlphaPre = oldCM.isAlphaPremultiplied(); |
357 | | - WritableRaster newRaster = oldCM.createCompatibleWritableRaster(width, height); |
358 | | - BufferedImage bi = new BufferedImage(oldCM, newRaster, isAlphaPre, null); |
| 359 | + int transferType = oldCM.getTransferType(); |
| 360 | + int transparency = oldCM.getTransparency(); |
| 361 | + ColorSpace newCS = oldCM.getColorSpace(); |
| 362 | + ColorModel newCM; |
| 363 | + if (oldCM instanceof ComponentColorModel) { |
| 364 | + newCM = new ComponentColorModel(newCS, hasAlpha, isAlphaPre, transparency, transferType); |
| 365 | + } else if (oldCM instanceof DirectColorModel) { |
| 366 | + final DirectColorModel oldDCM = (DirectColorModel) oldCM; |
| 367 | + newCM = new DirectColorModel(newCS, oldCM.getPixelSize(), |
| 368 | + oldDCM.getRedMask(), oldDCM.getGreenMask(), oldDCM.getBlueMask(), oldDCM.getAlphaMask(), |
| 369 | + isAlphaPre, transferType); |
| 370 | + } else { |
| 371 | + logger.warn("Unknown ColorModel in createCompatibleImage! Returning null."); |
| 372 | + return null; |
| 373 | + } |
| 374 | + WritableRaster outRaster = newCM.createCompatibleWritableRaster(width, height); |
| 375 | + BufferedImage bi = new BufferedImage(newCM, outRaster, false, null); |
359 | 376 | return bi; |
360 | 377 | } |
361 | 378 |
|
@@ -476,7 +493,9 @@ protected BufferedImage changeTo8BitNoAlpha(BufferedImage bi) { |
476 | 493 | ColorModel newCm = new ComponentColorModel(newCs, false, false, Transparency.OPAQUE, transferType); |
477 | 494 | WritableRaster newRaster = newCm.createCompatibleWritableRaster(bi.getWidth(), bi.getHeight()); |
478 | 495 | // use child Raster with only color components (bands 0,1,2) |
479 | | - WritableRaster colorRaster = img.getRaster().createWritableChild(0, 0, img.getWidth(), img.getHeight(), 0, 0, new int[] {0, 1, 2}); |
| 496 | + final int[] colorBands = new int[] { 0, 1, 2 }; |
| 497 | + WritableRaster colorRaster = bi.getRaster().createWritableChild(0, 0, bi.getWidth(), bi.getHeight(), 0, 0, |
| 498 | + colorBands); |
480 | 499 | BufferedImage newBi = new BufferedImage(newCm, newRaster, false, null); |
481 | 500 | newBi.setData(colorRaster); |
482 | 501 | return newBi; |
@@ -980,11 +999,13 @@ public void scale(double scaleX, double scaleY) throws ImageOpException { |
980 | 999 | logger.debug("scaled from {}x{} img={}", imgW, imgH, img); |
981 | 1000 | AffineTransformOp scaleOp = new AffineTransformOp(AffineTransform.getScaleInstance(scaleX, scaleY), renderHint); |
982 | 1001 | BufferedImage dest = null; |
983 | | - if (imageHacks.get(Hacks.forceDestForScale) && !(img.getColorModel() instanceof IndexColorModel)) { |
| 1002 | + final ColorModel cm = img.getColorModel(); |
| 1003 | + if (imageHacks.get(Hacks.forceDestForScaleCustom) && img.getType() == BufferedImage.TYPE_CUSTOM) { |
984 | 1004 | // set destination image |
985 | 1005 | int dw = (int) Math.round(imgW * scaleX); |
986 | 1006 | int dh = (int) Math.round(imgH * scaleY); |
987 | | - dest = createCompatibleImage(dw, dh, img); |
| 1007 | + boolean hasAlpha = cm.hasAlpha(); |
| 1008 | + dest = createCompatibleImage(dw, dh, hasAlpha, img); |
988 | 1009 | logger.debug("scale: setting destination image {}", dest); |
989 | 1010 | } |
990 | 1011 | img = scaleOp.filter(img, dest); |
@@ -1022,10 +1043,6 @@ public void blur(int radius) throws ImageOpException { |
1022 | 1043 | // blur with convolve operation |
1023 | 1044 | ConvolveOp blurOp = new ConvolveOp(blur, ConvolveOp.EDGE_NO_OP, renderHint); |
1024 | 1045 | BufferedImage dest = null; |
1025 | | - if (imageHacks.get(Hacks.forceDestForBlur) && !(img.getColorModel() instanceof IndexColorModel)) { |
1026 | | - dest = createCompatibleImage(img.getWidth(), img.getHeight(), img); |
1027 | | - logger.debug("blur: setting destination image {}", dest); |
1028 | | - } |
1029 | 1046 | img = blurOp.filter(img, dest); |
1030 | 1047 | logger.debug("blurred: {}", img); |
1031 | 1048 | //testPixels(img); |
|
0 commit comments