feexon / thumbnailator

Automatically exported from code.google.com/p/thumbnailator
Other
0 stars 0 forks source link

Thumbnail distortion #5

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
my english is much poor,sorry -_-

but I really need your help

my runtime environments:
windows 7
JDK 1.6
thumbnailator 0.32

my code:

Thumbnails.of(temp)
.size(maxW, 3000)
.outputQuality(0.8)
.rendering(Rendering.SPEED)
.outputFormat("jpg")
.toFile(new File(f,img.getName().toLowerCase()));

I tried various options, but still did not get the expected results.
so I can only ask for your help.
this is a video shot,attached is the original image and thumbnails.

thumbnailator is a great open source software, thanks.

Original issue reported on code.google.com by im.tao...@gmail.com on 25 Mar 2011 at 3:59

Attachments:

GoogleCodeExporter commented 9 years ago
Please refer to changes "Thumbnailator 0.2.5 (October 27, 2010) item 1":This 
change was made to address an issue where color distortions occurred in the 
resulting thumbnail when the original image was a JPEG. This occurred due to 
the original behavior to create a thumbnail image with an alpha channel. The 
default JPEG encoder implementation which ships with the JRE appears to cause 
color distortions for images which contain an alpha channel.

Original comment by lamusico...@gmail.com on 29 Mar 2011 at 7:26

GoogleCodeExporter commented 9 years ago
Hello!

Thank you for taking your time to file a bug report.

I tried to resize the `original.jpg` with Thumbnailator 0.3.2, and I was not 
able to reproduce the issue.

* Environment
 * Windows XP
 * Sun JDK 6 Update 21
 * Thumbnailator 0.3.2

* Code

Thumbnails.of("/path/to/original.jpg")
  .size(600, 400)
  .outputQuality(0.8)
  .rendering(Rendering.SPEED)
  .outputFormat("jpg")
  .toFile("/path/to/thumbnail.jpg");

For reference, I would like to know the data type of the following variables in 
the code you've provided:
  * temp
    * Is this a `File`? `String`? `BufferedImage`?
  * f
    * Is this a `File`? `String`?
  * img.getName().toLowerCase()
    * I'm assuming this a `File`. What is the file extension of the file name?

-----------

Commenter 1:

Thank you for posting the relevant information.

It's possible that the workaround for the color distortion issue isn't covering 
all cases, and is causing it to fail under some circumstances.

I hope to get some follow-up from the original submitter to find out what is 
happening here.

Original comment by coobird...@gmail.com on 29 Mar 2011 at 3:45

GoogleCodeExporter commented 9 years ago
Thank you for your reply ^^

I downloaded the attachment, and use 'original.jpg ' for testing,I was not able 
to reproduce the issue.I think it might be the relationship in file.
So I uploaded the file to FTP,please download from 
http://www.icili.com/original.jpg,
this file can reproduce the issue.

code:

File img = new File("G:/uploadfile/original.jpg");
File temp = new File("G:/uploadfile/temp");
img.renameTo(temp);
System.out.println(img.getPath());
//System.out.println(img.length());
Thumbnails.of(temp)
.size(720, 3000)
.outputQuality(0.8)
.outputFormat("jpg")
.toFile(new File(new File("G:/uploadfile"),img.getName().toLowerCase()));
temp.delete();

rename to a temp file because if the original files to be overwritten, the file 
size will not change.i hope the file will be smaller

Thanks again!

Original comment by im.tao...@gmail.com on 31 Mar 2011 at 4:24

GoogleCodeExporter commented 9 years ago
Maybe this can serve as a complement.
I guess the original image was a snapshot of some film. So I just opened a 
movie and made two snapshots, one made by the player itself, one by windows 
SnippingTool.exe.
After
* code
Thumbnails.of("/path/to/movieNo.jpg")
  .size(600, 400)
  .outputQuality(0.8)
  .rendering(Rendering.SPEED)
  .outputFormat("jpg")
  .toFile("/path/to/thumbnail.jpg");

The problem has occurred on the image made by player itself but not on the 
other one. I checked their types, histograms, extensions and other infos. They 
are almost alike. This really confuses me. I'm working on it hoping to find a 
way out.

Original comment by lamusico...@gmail.com on 2 Apr 2011 at 4:07

GoogleCodeExporter commented 9 years ago
I forgot to upload these images. Sorry.

Original comment by lamusico...@gmail.com on 2 Apr 2011 at 4:11

Attachments:

GoogleCodeExporter commented 9 years ago
OK, I was able to reproduce the issue with the new file.

This issue does not seem like it is an issue with Thumbnailator itself, but it 
appears that either

  1. the JPEG reader (decoder) which ships with Java is not correctly reading the file, or 
  2. the file itself has some kind of non-standard data that the JPEG reader cannot recognize.

This thought can be illustrated with a simple example code.
For example, reading/writing the given file using the following code will lead 
to the same distortion in color:

    BufferedImage img = ImageIO.read(new File("original.jpg"));
    ImageIO.write(img, "jpg", new File("thumbnail.jpg"));

Therefore, at this point, I am not able to provide a fix for this issue.

Perhaps one could make a workaround by reading the JPEG file with another 
library that can properly handle the
given file, then handing that image to Thumbnailator.

At the present time, I will not take action on this issue, as there isn't much 
that can be done to Thumbnailator
to resolve an issue with the library provided by the Java runtime itself.

Notes
==========

Exiftool
----------

I used `exiftool` on `original.jpg` and it returned the following:

ExifTool Version Number         : 7.89
File Name                       : original.jpg
Directory                       : .
File Size                       : 87 kB
File Modification Date/Time     : xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
File Type                       : JPEG
MIME Type                       : image/jpeg
Image Width                     : 1024
Image Height                    : 768
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:4:4 (1 1)
Image Size                      : 1024x768

BufferedImage.toString
------------------------------

After loading `original.jpg`, the resulting `BufferedImage` object was the 
following:

    BufferedImage@1d6096: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@7d8483 \
      transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 533 height = 400 #numDataElements 3 dataOff[0] = 2

As a reference, another JPEG created by Thumbnailator was the following:

    BufferedImage@7fdcde: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@7d8483 \ 
      transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 1024 height = 768 #numDataElements 3 dataOff[0] = 2

The description fo the `BufferedImage` is identical other than the dimensions.
Therefore, it could be that the JPEG reader included in the Java ImageIO API is 
not able correctly read the file.

Possible bug references
------------------------------

* ImageIO does not correctly read some standard JPG files
  * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4881314
  * I tried running `MistyMorn-334229207.jpg` through Thumbnailator, and it did not cause color distortion,
    so the issue for this particular image has been resolved.
    However, there have been addition reports in the same ticket about color distortions in 2009.

Original comment by coobird...@gmail.com on 2 Apr 2011 at 4:14

GoogleCodeExporter commented 9 years ago
Thank you for what you have done! 
I tried to use JDK7, OPEN JDK, and another library —— mysema thumbs.
the result is the same - -
i can only give up now..

Original comment by im.tao...@gmail.com on 6 Apr 2011 at 7:18

GoogleCodeExporter commented 9 years ago
Hi there,

I've spent the last couple of weekends spending some time looking at this issue.

It does appear that the JPEG reader class which comes with Image I/O isn't able 
to read the
image in question.

I'd like to thank:
 * lamusico...@gmail.com for trying different applications, and 
 * im.tao...@gmail.com for trying JDK 7 and OpenJDK to see if the issue is present
   in those runtime environments as well.

At this point, all I can suggest is the following:

  1. Find a ImageIO plugin for the JPEG reader that can handle the image.
  2. Use some workaround code to read the JPEG file (more on that later.)

The Image I/O API (which is used for the reading and writing of image in 
Thumbnailator) is
a plugin architecture which allows different plugins to be used.

Therefore, if one can get a replacement plugin for reading JPEG files, it may 
be possible that
the replacement plugin can read the image correctly.

Further reading:
  * Image I/O
    * http://download.oracle.com/javase/6/docs/technotes/guides/imageio/index.html
  * Package javax.imageio -- some explanation about the Image I/O API
    * http://download.oracle.com/javase/6/docs/api/javax/imageio/package-summary.html
  * Standard JPEG plugin bundled with the JRE
    * http://download.oracle.com/javase/6/docs/api/javax/imageio/plugins/jpeg/package-summary.html

Workaround
----------

There appears to be a workaround with the JPEG loading issue, and has been 
verified to work
under Windows.

The workaround is to use the `java.awt.Toolkit` class' `createImage` method to 
open the
JPEG image.

At least on Windows, the `Toolkit` class seems to be able to open the image 
without causing
color distortions.

However, one issue is that the `Toolkit.createImage` class returns an `Image` 
object that does not
contain the image data, and when one does try to retrieve the image data, it 
must first be loaded
*asynchronously* on a separate thread.

Therefore, in order to find out when the image has actually been read and is 
ready to be used,
one must call the `Toolkit.prepareImage` until we know that the `Image` 
contains the actual
image data and is ready to be used to create thumbnails.

I've posted some workaround code below, but keep in mind that this code 
includes some nasties:

  1. This code relies on a possibly platform-dependent image reading pathway which could exhitbit
     different behaviors on various platforms.

  2. In order to find out when the `Image` is available, we have a busy loop checking on the
     `Image.prepareImage` method.

WARNING! This is a nasty workaround that I wouldn't want to see in production 
code!
================================================================================
=====================

   // Uses the java.awt.Toolkit class to load the JPEG. 
   Toolkit toolkit = Toolkit.getDefaultToolkit();
   Image toolkitImg = toolkit.createImage("/path/to/original.jpg");

   /*
    * Wait until the image finishes loading.
    * 
    * The image loads on a separate thread, so we need a way to find out when the
    * image finishes loading, by ... unfortunately invoking the `prepareImage`
    * method a few times.
    * 
    * Here, `Thread.yield` is being called to make the loop not consume too much
    * CPU resources. Using `Thread.sleep` is another option.
    * (Neither are truly desirable methods, however.)
    */
   while (!toolkit.prepareImage(toolkitImg, toolkitImg.getWidth(null), toolkitImg.getHeight(null), null)) {
       Thread.yield();
   }

   int width = toolkitImg.getWidth(null);
   int height = toolkitImg.getHeight(null);

   // Copy the `Image` over to a `BufferedImage`
   BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
   Graphics g = img.getGraphics();
   g.drawImage(toolkitImg, 0, 0, null);
   g.dispose();

   Thumbnails.of(img)
      .size(600, 400)
      .outputQuality(0.8)
      .rendering(Rendering.SPEED)
      .outputFormat("jpg")
      .toFile("/path/to/thumbnail.jpg");

================================================================================
=====================

Please let me know if you have any other suggestions in order to resolve this 
issue.

Original comment by coobird...@gmail.com on 17 Apr 2011 at 9:52

GoogleCodeExporter commented 9 years ago
Any chance that this bug is related to bad color profile support in ImageIO?

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4799903
http://stackoverflow.com/questions/2408613/problem-reading-jpeg-image-using-imag
eio-readfile-file

Original comment by viper2...@gmail.com on 6 Nov 2011 at 3:09

GoogleCodeExporter commented 9 years ago
Hi viper,

Thank you for providing those links. 

It's definitely a possibility, as Thumbnailator more-or-less blindly accepts 
JPEGs decoded by the JPEG plugin of Image I/O.

I'll keep those links handy when revisiting this issue.

Original comment by coobird...@gmail.com on 13 Nov 2011 at 6:24

GoogleCodeExporter commented 9 years ago
Hi,

I use following java version:
java version "1.7.0_07"
Java(TM) SE Runtime Environment (build 1.7.0_07-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.3-b01, mixed mode)

and pro.jpg and clip.jpg can be read and written correctly by java ImageIO 
alone and by thumbnailator.

The file original.jpg can be correctly written by ImageIO if the image metadata 
retrieved when reading the image is used when the image is written. Imho in the 
java memory the imagecolors are distoreted but the jpg image metadata 
compensates for that.

But for this to work you have to use this code to generate all subsequent 
images:
new BufferedImage(bi.getColorModel(), 
bi.getRaster().createCompatibleWritableRaster(width, height), 
bi.getColorModel().isAlphaPremultiplied(), null);

And use public void write(IIOImage image) where image contains the new 
BufferedImage and the original metadata.

This doesn't work for gif images though.

Original comment by beagdok...@gmail.com on 29 Nov 2013 at 10:00

GoogleCodeExporter commented 9 years ago
Issue 61 has been merged into this issue.

Original comment by coobird...@gmail.com on 21 Dec 2013 at 12:10

GoogleCodeExporter commented 9 years ago
Note
------
Use of "TwelveMonkeys ImageIO" fixes this particular issue.
https://github.com/haraldk/TwelveMonkeys

Original comment by coobird...@gmail.com on 21 Sep 2014 at 10:38