Question

This code attempts to resize images in a directory called "imgs". Unfortunately for some reason when I uncomment the listFiles(..) loop ImageIO.read(sourceImageFile) will return null. Yet processing the same file straightaway outside the loop (res("imgs/foto_3.jpg")) works. So apparently, this loop is preventing the files from being read. Solutions?

import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import static org.imgscalr.Scalr.*;

public class App {

    public static void main(String[] args) throws IOException {
//        for (File sourceImageFile : new File("imgs").listFiles()) {
//            res("imgs/"+sourceImageFile.getName());
//        }
        res("imgs/foto_3.jpg");

    }

    public static void res(String arg) throws IOException {

        File sourceImageFile = new File(arg);
        BufferedImage img = ImageIO.read(sourceImageFile);

        BufferedImage thumbnail = resize(img, 500);

        thumbnail.createGraphics().drawImage(thumbnail, 0, 0, null);
        ImageIO.write(thumbnail, "jpg", new File("resized/" + sourceImageFile.getName()));
    }
}

enter image description here

To reproduce the problem you can download the Maven project.

Was it helpful?

Solution 5

I've changed res method:

public static void res(File arg) throws IOException {
        if (arg.contains(".DS_Store")) {
            return;
        }

A mac-issue (or should filter non-image files, as was suggested)!

OTHER TIPS

Can you change res to accept a File object rather than a String? Then you could write the following, which is a lot nicer:

for (File sourceImageFile : new File("imgs").listFiles()) {
    res(sourceImageFile);
}

As to your original question, try adding some tracing statements or using a debugger to find what exactly gets passed to res.

I am not sure why the file listing iteration would mess with the thumbnail generation, but you mentioned privately to me that you were using imgscalr and were curious what the correct code to batch-process a directory would look like, so I wrote up this example code for you.

The code below will process any directory (imgs is hard-coded to stay consistent with your example code) and write it out to any other directory (resized is used to stay consistent -- feel free to change either directory)

import static org.imgscalr.Scalr.*;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ScaleDirExample {
    public static void main(String[] args) throws IOException {
        File[] images = new File("imgs").listFiles();

        for (File f : images) {
            System.out.println("Processing: " + f.getName() + "...");

            if (f.isDirectory()) {
                System.out.println("\tSkipping, file is a directory...");
                continue;
            } else
                process(f);
        }
    }

    private static void process(File file) throws IOException {
        // Load image.
        BufferedImage image = ImageIO.read(file);

        // Resize image.
        image = resize(image, 500);

        // Save the resized image as the thumbnail.
        saveThumbnail(file, image);
    }

    private static void saveThumbnail(File originalFile, BufferedImage thumbnail)
            throws IOException {
        String filename = originalFile.getName();

        // Determine file extension.
        String fileExt = filename.substring(filename.lastIndexOf('.') + 1);

        // Save the thumbnail to the resized dir.
        ImageIO.write(thumbnail, fileExt, new File("resized/" + filename));
    }
}

The call to resize(image, 500) can be modified to match any of the Scalr.resize methods - you can pass filters or improve quality if you want.

Example output from my test setup looks like:

Processing: flower-dog-gimp.jpg...
Processing: flower-dog.jpg...
Processing: logoOXdaComida.png...
Processing: mr-t-thumbnail.jpg...
Processing: mr-t.jpg...
Processing: problem-trans-peter-griffin.png...

Hope that helps!

OK, I figured it out. now it's working. You (or whoever created the downloadable project u pasted here) are using Mac OS, and it automatically creates a .DS_Store file. When you try to pass it to the res method, it doesn't know how to handle a non-image file and acts as null.

   public static void main(String[] args) throws IOException {
        for (File sourceImageFile : new File("imgs").listFiles()) {
            if (sourceImageFile.getName().endsWith(".jpg"))
                res(sourceImageFile.getAbsolutePath());
        }
    }

This is the modified void main method. it works, u can refine the if statement for more in depth filtering of wrong files. Also I changed the argument given to the res method. it looks better now, as getAbsoulutePath returns the name and the path. Let me know how it worked

One obvious way to debug this to output the specific sourceImageFile that ImageIO.read(..) is returning null on. I suspect its because listFiles will give you a list of all files and directories that are in the image directory. listFiles javadoc. You can prevent that by using a FileFilter that makes sure that listFiles only returns files and additionally files of the right type.

An example of a file filter that only returns file is below:

import java.io.FileFilter
class RegularFilesOnlyFileFilter implements FileFilter {
   public boolean accept(File pathName) {
       return pathName.isFile();
   }
}

The way to use this filter is this - new File("imgs").listFiles(new RegularFilesOnlyFilesFilter())

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top