11

I am trying to write a method that takes an image, and saves a 100 by 100 thumbnail of that image. However, when I save the file, it comes out as an unreadable 0 byte image (with the error "Error interpreting JPEG image file (Improper call to JPEG library in state 200)") in Ubuntu's ImageViewer. My code is as follows:

public boolean scale(){

    String file = filename.substring(filename.lastIndexOf(File.separator)+1);
    File out = new File("data"+File.separator+"thumbnails"+File.separator+file);

    if( out.exists() ) return false;

    BufferedImage bi;
    try{
        bi = ImageIO.read(new File(filename));
    }
    catch(IOException e){
        return false;
    }

    Dimension imgSize = new Dimension(bi.getWidth(), bi.getHeight());
    Dimension bounds = new Dimension(100, 100);
    int newHeight = imgSize.height;
    int newWidth = imgSize.width;

    if( imgSize.width > bounds.width ){
        newWidth = bounds.width;
        newHeight = (newWidth*imgSize.height)/imgSize.width;
    }

    if( imgSize.height > bounds.width ){
        newHeight = bounds.height;
        newWidth = (newHeight*imgSize.width)/imgSize.height;
    }

    Image img = bi.getScaledInstance(newWidth, newHeight, BufferedImage.SCALE_SMOOTH);
    BufferedImage thumb = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_4BYTE_ABGR);
    Graphics2D g2d = thumb.createGraphics();
    g2d.drawImage(img, 0, 0, null);
    g2d.dispose();

    try{
        ImageIO.write(thumb, "jpg", out);
    }
    catch(IOException e){
        return false;
    }

    return true;
}

Where "filename" is a global variable for the class housing this method, representing the path to the original image. My main issue is that I do not see why I'm creating a 0 byte image.

Thomas Preston
  • 697
  • 1
  • 7
  • 19
  • AFAIK you need to close the IO buffer for anything to actually be written. That's generally how IO works in Java - could be wrong though. –  Apr 14 '13 at 17:42
  • 3
    Check that you have permission to write to disk & that you have disk space available – Reimeus Apr 14 '13 at 17:45
  • @Reimeus - I have permission to write, and I have available disk space; at least I believe I do as I'm able to successfully create other files (specifically, .txt files), and unless I'm misunderstanding your meaning of "disk space" I have plenty. – Thomas Preston Apr 14 '13 at 18:09
  • @Telthien - Unless I'm missing something ImageIO doesn't seem to have a method for closing its buffer. I assume that it is then handled by ImageIO without my needing to invoke anything. – Thomas Preston Apr 14 '13 at 18:11
  • @ThomasPreston Hm. That does seem to be the case. Well, I've never used this before, so I'll leave this to those more skilled with ImageIO :P –  Apr 14 '13 at 18:18
  • For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Apr 14 '13 at 23:17
  • Why `BufferedImage.TYPE_4BYTE_ABGR`? Try `BufferedImage.TYPE_INT_ARGB` instead. – Andrew Thompson Apr 14 '13 at 23:18

3 Answers3

13

So, the issue was this. I'm working in OpenJDK. OpenJDK doesn't have a JPEG encoder, apparently, so while the file was being created by

ImageIO.write(thumb, "jpg", out);

it wasn't actually creating anything for the file to save; hence the empty 0 byte unreadable file. Changing the ImageIO argument to "png" (and adjusting the new File() extension, appropriately) successfully created the desired image with the above code.

Thomas Preston
  • 697
  • 1
  • 7
  • 19
3

I experienced the same issue even though the JVM had a JPG encoder and it was caused by using an unsupported type of BufferImage underneath. I had used BufferedImage.TYPE_USHORT_GRAY which is evidently not supported and gave no error messages but produced a 0 byte file. When I switched to BufferedImage.TYPE_BYTE_GRAY it worked perfectly.

kmader
  • 1,319
  • 1
  • 10
  • 13
2

JPG have no alpha channel, ImageIO.write() will fail silently (just return false) one way is to copy your image into another one

BufferedImage newBufferedImage = new BufferedImage(bufferedImage.getWidth(),
  bufferedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
newBufferedImage.getGraphics().drawImage(bufferedImage, 0, 0, null);

boolean write = ImageIO.write(newBufferedImage, extension, outputfile);
if (!write) {
  // do something
}
cedric.walter
  • 731
  • 6
  • 7