From bc6c79fc128b462a1eea73a8cd1b9bf843d065cc Mon Sep 17 00:00:00 2001 From: luc Date: Fri, 20 Nov 2015 14:35:36 +0100 Subject: [PATCH] Corrected scaling function for non RGB images. --- htroot/ViewImage.java | 48 +++++++++++++------ .../net/yacy/peers/graphics/EncodedImage.java | 31 ++++++++++++ 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/htroot/ViewImage.java b/htroot/ViewImage.java index 690b7d590..07857af5d 100644 --- a/htroot/ViewImage.java +++ b/htroot/ViewImage.java @@ -232,7 +232,7 @@ public class ViewImage { ImageInputStream imageInStream) throws IOException { EncodedImage encodedImage = null; - Image image = ImageIO.read(imageInStream); + BufferedImage image = ImageIO.read(imageInStream); if (image == null) { try { /* When a null image is returned, we have to close the stream */ @@ -289,7 +289,7 @@ public class ViewImage { * An error can still occur when transcoding from buffered image to * target ext : in that case return null */ - encodedImage = new EncodedImage(image, ext, isStatic); + encodedImage = new EncodedImage((Image)image, ext, isStatic); if (encodedImage.getImage().length() == 0) { throw new IOException("Image could not be encoded to format : " + ext); } @@ -366,9 +366,9 @@ public class ViewImage { * image to scale. Must not be null. * @return a scaled image */ - protected static Image scale(final int width, final int height, Image image) { + protected static BufferedImage scale(final int width, final int height, final BufferedImage image) { // compute scaled image - final Image scaled = image.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING); + Image scaled = image.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING); final MediaTracker mediaTracker = new MediaTracker(new Container()); mediaTracker.addImage(scaled, 0); try { @@ -377,20 +377,40 @@ public class ViewImage { } // make a BufferedImage out of that - final BufferedImage i = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); try { - i.createGraphics().drawImage(scaled, 0, 0, width, height, null); - image = i; + result.createGraphics().drawImage(scaled, 0, 0, width, height, null); // check outcome - final Raster raster = i.getData(); - int[] pixel = new int[3]; + final Raster raster = result.getData(); + int[] pixel = new int[raster.getSampleModel().getNumBands()]; pixel = raster.getPixel(0, 0, pixel); - if (pixel[0] != 0 || pixel[1] != 0 || pixel[2] != 0) - image = i; } catch (final Exception e) { - // java.lang.ClassCastException: [I cannot be cast to [B + /* + * Exception may be caused by source image color model : try now to + * convert to RGB before scaling + */ + try { + BufferedImage converted = EncodedImage.convertToRGB(image); + scaled = converted.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING); + mediaTracker.addImage(scaled, 1); + try { + mediaTracker.waitForID(1); + } catch (final InterruptedException e2) { + } + result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + result.createGraphics().drawImage(scaled, 0, 0, width, height, null); + + // check outcome + final Raster raster = result.getData(); + int[] pixel = new int[result.getSampleModel().getNumBands()]; + pixel = raster.getPixel(0, 0, pixel); + } catch (Exception e2) { + result = image; + } + + ConcurrentLog.fine("ViewImage", "Image could not be scaled"); } - return image; + return result; } /** @@ -402,7 +422,7 @@ public class ViewImage { * @param w * @return */ - protected static Image makeSquare(Image image, final int h, final int w) { + protected static BufferedImage makeSquare(BufferedImage image, final int h, final int w) { if (w > h) { final BufferedImage dst = new BufferedImage(h, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g = dst.createGraphics(); diff --git a/source/net/yacy/peers/graphics/EncodedImage.java b/source/net/yacy/peers/graphics/EncodedImage.java index ac4afbf82..645705c97 100644 --- a/source/net/yacy/peers/graphics/EncodedImage.java +++ b/source/net/yacy/peers/graphics/EncodedImage.java @@ -22,6 +22,7 @@ package net.yacy.peers.graphics; import java.awt.Image; import java.awt.image.BufferedImage; +import java.awt.image.ColorConvertOp; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -56,6 +57,15 @@ public class EncodedImage { public EncodedImage(final BufferedImage bi, final String targetExt, final boolean isStatic) { this.extension = targetExt; this.image = RasterPlotter.exportImage(bi, targetExt); + if(this.image == null || this.image.length() == 0) { + /* + * Buffered image rendering to targetExt format might fail because + * no image writer support source image color model. Let's try + * converting source image to RGB before rendering + */ + BufferedImage converted = convertToRGB(bi); + this.image = RasterPlotter.exportImage(converted, targetExt); + } this.isStatic = isStatic; } @@ -124,4 +134,25 @@ public class EncodedImage { public boolean isStatic() { return this.isStatic; } + + /** + * If source source image colorspace is not RGB or ARGB, convert it to RGB or ARGB when alpha channel is present. + * @param image source image. Must not be null. + * @return converted image or source image when already RGB. + */ + public static BufferedImage convertToRGB(BufferedImage image) { + BufferedImage converted = image; + if(image.getType() != BufferedImage.TYPE_INT_RGB && image.getType() != BufferedImage.TYPE_INT_ARGB) { + int targetType; + if(image.getColorModel() != null && image.getColorModel().hasAlpha()) { + targetType = BufferedImage.TYPE_INT_ARGB; + } else { + targetType = BufferedImage.TYPE_INT_RGB; + } + BufferedImage target = new BufferedImage(image.getWidth(), image.getHeight(), targetType); + ColorConvertOp convertOP = new ColorConvertOp(null); + converted = convertOP.filter(image, target); + } + return converted; + } }