6

I am trying to convert an image (url below) using two libraries (thumbnailator and imgscalr. My code works on most of the images except a few which after conversion have a pink/reddish tint.

I am trying to understand the cause and would welcome any recommendation.

Note - Image type of this image is 5 i.e BufferedImage.TYPE_3BYTE_BGR and i am using Java 7

enter image description here enter image description here

Using Thumbnailator

  Thumbnails.of(fromDir.listFiles())                
                    .size(thumbnailWidth, thumbnailHeight)
                    .toFiles(Rename.SUFFIX_HYPHEN_THUMBNAIL);

Using imgscalr

    BufferedImage bufferedImage = ImageIO.read(file);
    final BufferedImage jpgImage;

    LOG.debug("image type is =[{}] ", bufferedImage.getType());

     BufferedImage scaledImg = Scalr.resize(bufferedImage, Method.ULTRA_QUALITY, thumbnailWidth, thumbnailHeight, Scalr.OP_ANTIALIAS);


    File thumbnailFile = new File(fromDirPath + "/" + getFileName(file.getName()) +THUMBNAIL_KEYWORD  + ".png");

    ImageIO.write(scaledImg, getFileExtension(file.getName()), thumbnailFile);

    bufferedImage.flush();
    scaledImg.flush();
rohtakdev
  • 956
  • 1
  • 13
  • 16
  • I think the problem is that the JPEGImageReader misinterprets the JPEG data, and assumes it to be RGB, rather than YCbCr (which is what it really is). What happens if you try to display, or write (as PNG, without scaling) `bufferedImage` from the imgscalr code above? Does it still look incorrect? Or does it happen only after scaling/storing as JPEG? – Harald K Sep 30 '14 at 12:54
  • @haraldK - Same tint. – rohtakdev Oct 01 '14 at 03:46
  • I suggest trying [JPEG plugin for ImageIO](https://github.com/haraldk/TwelveMonkeys#jpeg). It usually does a better job than the default `JPEGImageReader`, when determining the output color space. One of the libraries mentioned already comes pre-bundled with an older version of my plugin, make sure you get the latest version, as the bundled version had a bug regarding this. – Harald K Oct 01 '14 at 11:03
  • I wrote a more detailed reply here with some code examples if that helps - http://stackoverflow.com/questions/17755036/imgscalr-with-background-red – Riyad Kalla Dec 04 '14 at 17:31

2 Answers2

6

I get this question a lot (author of imgscalr) -- the problem is almost always that you are reading/writing out different file formats and the ALPHA channel is causing one of your color channels (R/G/B) to be culled from the resulting file.

For example, if you read in a file that was ARGB (4 channel) and wrote it out as a JPG (3 channel) - unless you purposefully manipulate the image types yourself and render the old image to the new one directly, you will get a file with a "ARG" channels... or more specifically, just Red and Green - no Blue.

PNG supports an alpha channel and JPG does not, so be aware of that.

The way to fix this is to purposefully create appropriate BufferedImage's of the right type (RGB, ARGB, etc.) and using the destImage.getGraphics() call to render one image to the other before writing it out to disk and re-encoding it.

Sun and Oracle have NEVER made the ImageIO libraries smart enough to detect the unsupported channels when writing to differing file types, so this behavior happens all the time :(

Hope that helps!

pbaris
  • 4,525
  • 5
  • 37
  • 61
Riyad Kalla
  • 10,604
  • 7
  • 53
  • 56
2

The following piece of code resolved my issue:

ByteArrayOutputStream baos = new ByteArrayOutputStream();

  Thumbnails.of(new ByteArrayInputStream(imageByteArray))
    .outputFormat("jpg")
    .size(200, 200)
    .toOutputStream(outputStream);

  return baos.toByteArray();

I am using Thumbnailator and the code was posted here: https://github.com/coobird/thumbnailator/issues/23

md. ariful ahsan
  • 606
  • 7
  • 19