views:

833

answers:

3

My instructor sent me this code, which is supposed to be an integral part of an ongoing project. Thing is, it doesn't work.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.Kernel;
import java.awt.image.ConvolveOp;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import javax.swing.*;


public class ImageUtil {

    public static void resize(File originalFile, File resizedFile, int newWidth, float quality) throws IOException{

        if(quality <0||quality>1){
            throw new IllegalArgumentException ("quality has to be between 0 and 1");

        }

        ImageIcon ii = new ImageIcon(originalFile.getCanonicalPath());
        Image i = ii.getImage();
        Image resizedImage = null;

        int iWidth = i.getWidth (null);
        int iHeight = i.getHeight(null);

        if (iWidth > iHeight){
            resizedImage = i.getScaledInstance(newWidth,(newWidth*iHeight)/iWidth, Image.SCALE_SMOOTH);
        } else {
            resizedImage = i.getScaledInstance((newWidth*iWidth)/iHeight,newWidth, Image.SCALE_SMOOTH);
        }

        Image temp = new ImageIcon (resizedImage).getImage();

        BufferedImage bufferedImage = new BufferedImage (temp.getWidth(null), temp.getHeight(null),
                                                         BufferedImage.TYPE_INT_RGB);

        // copy to a buffered image
        Graphics g = bufferedImage.createGraphics();

        g.setColor(Color.white);
        g.fillRect(0,0,temp.getWidth(null), temp.getHeight(null)); // causea el error de ejecución?
        g.drawImage(temp,0,0,null);
        g.dispose();

        float softenFactor = 0.05f;
        float [] softenArray = {0, softenFactor,0, softenFactor, 1-(softenFactor*4), softenFactor,0, softenFactor,0};
        Kernel kernel = new Kernel (3,3,softenArray);
        ConvolveOp cOp = new ConvolveOp (kernel, ConvolveOp.EDGE_NO_OP,null);
        bufferedImage = cOp.filter (bufferedImage,null);

        FileOutputStream out = new FileOutputStream(resizedFile);

        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);

        JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufferedImage);

        param.setQuality(quality,true);

        encoder.setJPEGEncodeParam(param);
        encoder.encode(bufferedImage);



    }

    public static void main(String args[]) throws IOException {
       File originalImage= new File ("/images/goya.jpg");
       resize(originalImage,new File("/images/goyanuevotamanio.jpg"),350, 0.2f);
       resize(originalImage, new File("/images/goyanuevotamanio.jpg"), 350, 1f);

    }

}

He says the code should be able to resize both height and width yet his resize method:

public static void resize(File originalFile, File resizedFile, int newWidth, float quality)

lacks a newHeight parameter.

The RuntimeException that's thrown says:

Exception in thread "main" java.lang.IllegalArgumentException: **Width (-1) and height (-1) cannot be <= 0**
        at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:999)
        at java.awt.image.BufferedImage.<init>(BufferedImage.java:312)
        at ImageUtil.resize(ImageUtil.java:38)
        at ImageUtil.main(ImageUtil.java:72)
Java Result: 1

How can I change this?

+1  A: 

Without analyzing the code to see what the problem might be, I can say that if the intention is to keep the images aspect ratio, a new height parameter is not needed. It will always be a fixed ratio of the width.

UPDATE:

I've run the code against my own test image and it does indeed work as expected. The error you are getting is most likely caused when the program cannot find the source image you specify. I get the same error when I specify a source image that doesn't exist.

Try using an absolute path (including drive letter etc.) for your source image.

UPDATE 2

Add the following code after the line..

ImageIcon ii = new ImageIcon(originalFile.getCanonicalPath());

if(ii.getImageLoadStatus() == MediaTracker.COMPLETE)
{
    System.out.print("Load image ok\n");
}
else
{
    System.out.print("Load image failed\n");
}

This will tell you if the program is failing to load the source image.

Arnold Spence
Why is the exception complaining about the height value passed then?
omgzor
That's what we need to find out. An image has a height, but a resize function doesn't need to specify a height parameter if the aspect ratio is to be maintained and a new width is provided.
Arnold Spence
The height parameter mentioned in the exception, I think, is temp.getHeight(null) which is being passed to new BufferedImage.
Arnold Spence
I ran it on windows using resize(originalImage,new File("C:/Documents and Settings/Administrator/My Documents/NetBeansProjects/Galeria/src/imagesgoyanuevotamanio.jpg"),350, 0.2f);and the code gave the same Exception, what I'm I missing?
omgzor
The long path there is the output file. The problem is with the input file.. File originalImage= new File ("/images/goya.jpg");This is the one you need to specify a full path for or correct the relative path. I'll add an edit above with some code to verify the problem.
Arnold Spence
You are welcome.
Arnold Spence
A: 

Judging by the stack trace the exception is thrown by this line:

BufferedImage bufferedImage = new BufferedImage (temp.getWidth(null), temp.getHeight(null), BufferedImage.TYPE_INT_RGB);

I would think this is probably because temp.getWidth and temp.getHeight are returning -1 because the image has not finished loading.

There are tutorials and examples for working with images in Java available on the web. One sample is here http://snippets.dzone.com/posts/show/92. Look for the code using ImageObserver.

Skip Head
A: 

You have to give the program a starting parameter between 0 and 1. I did it and it work perfectly.