我的批处理jpg调整大小器适用于彩色图像,但灰度图像会被冲洗掉



我的Java程序一直有问题。它用于调整图像大小。你把它放进一个文件夹并运行它,它就会创建一个带有调整大小的图像的新文件夹。它在颜色上效果很好,但在灰度方面有问题。图像被转换,但它们变得更轻、更褪色,就好像有人弄乱了曲线或标高。所有的输入文件和输出文件都是sRGB颜色空间jpegs,保存在RGB颜色模式下。我有数千个5000万像素的胶片扫描,我正试图将其转换为1500万像素或更低。任何人能提供的帮助或想法都将不胜感激。程序的完整代码如下,大约有130行。我有一种感觉,问题可能在toBufferedImage函数中,但我不知道它可能是什么。

package jpegresize;
import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.io.*;
import javax.imageio.*;
import javax.imageio.stream.*;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
    System.out.println("JPEGResize running . . .");
    int max_side = 4096;
    float quality = 0.9f;
    if(args.length == 0) System.out.println("No maximum side resolution or compression quality arguments given, using default values.nUsage: java -jar JPEGResize.jar <maximum side resolution in pixels> <quality 0 to 100 percent>");
    if(args.length >= 1) max_side = Integer.parseInt(args[0]);
    if(args.length >= 2) quality = Float.parseFloat(args[1]) / 100.0f;
    System.out.println("Maximum side resolution: " + max_side);
    System.out.println("Compression quality: " + (quality * 100) + "%");
    File folder = new File(".");
    File[] listOfFiles = folder.listFiles(new JPEGFilter());
    for(int i = 0; i < listOfFiles.length; i++) {
        System.out.println("Processing " + listOfFiles[i].getName() + " . . .");
        resizeFile(listOfFiles[i].getName(), max_side, quality);
        System.out.println("Saved /resized/" + listOfFiles[i].getName());
    }
    System.out.println("Operations complete.");
}
public static void resizeFile(String filename, int max_side, float quality) {
    try
    {
        BufferedImage input_img = ImageIO.read(new File(filename));
        double aspect_ratio = ((double)input_img.getWidth()) / ((double)input_img.getHeight());
        int width, height;
        if(input_img.getWidth() >= input_img.getHeight()) {
            width = max_side;
            height = (int)(((double)max_side) / aspect_ratio);
        }
        else {
            width = (int)(((double)max_side) * aspect_ratio);
            height = max_side;
        }
        Image scaled_img = input_img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        BufferedImage output_img = toBufferedImage(scaled_img);
        Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
        ImageWriter writer = (ImageWriter)iter.next();
        ImageWriteParam iwp = writer.getDefaultWriteParam();
        iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        iwp.setCompressionQuality(quality);
        File doesDirExist = new File("resized/");
        if(!doesDirExist.exists())
            new File("resized").mkdir();
        File file = new File("resized/" + filename);
        FileImageOutputStream output = new FileImageOutputStream(file);
        writer.setOutput(output);
        IIOImage image = new IIOImage(output_img, null, null);
        writer.write(null, image, iwp);
        writer.dispose();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}
// This method returns a buffered image with the contents of an image
public static BufferedImage toBufferedImage(Image image) {
    if (image instanceof BufferedImage) {
        return (BufferedImage)image;
    }
    // This code ensures that all the pixels in the image are loaded
    image = new ImageIcon(image).getImage();
    // Create a buffered image with a format that's compatible with the screen
    BufferedImage bimage = null;
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    try {
        // Determine the type of transparency of the new buffered image
        int transparency = Transparency.OPAQUE;
        // Create the buffered image
        GraphicsDevice gs = ge.getDefaultScreenDevice();
        GraphicsConfiguration gc = gs.getDefaultConfiguration();
        bimage = gc.createCompatibleImage(
            image.getWidth(null), image.getHeight(null), transparency);
    } catch (HeadlessException e) {
        // The system does not have a screen
    }
    if (bimage == null) {
        // Create a buffered image using the default color model
        int type = BufferedImage.TYPE_INT_RGB;
        bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
    }
    // Copy image to buffered image
    Graphics g = bimage.createGraphics();
    // Paint the image onto the buffered image
    g.drawImage(image, 0, 0, null);
    g.dispose();
    return bimage;
}
}
class JPEGFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
    return (name.toLowerCase().endsWith(".jpg")) || (name.toLowerCase().endsWith(".jpeg"));
    }
}

如果jdk的类和方法有错误,请向oracle报告错误(哦!我希望我能继续对SUN..说)。

而且,虽然下一个版本将纠正错误;),尝试一些变通办法,像这里建议的那样自己缩放图像。

谨致问候,Stéphane

在您的代码中,您假设jpeg是用RGB编码的,但事实并非总是如此。还可以对8位灰度级jpeg进行编码。所以我建议你在构建BufferedImage时尝试一下,替换:

BufferedImage.TYPE_INT_RGB;

通过

BufferedImage.TYPE_BYTE_GRAY;

看看它是否适用于这些图像。

如果是这样的话,那么你仍然需要找到一种方法来确定编码类型,以自动更改要使用的BufferedImage颜色编码的类型,但你会更近一步。

谨致问候,Stéphane

最新更新