我的批处理jpg尺寸调整器可用于彩色图像,但是灰度级图像会被冲洗掉

问题描述

|| 我的Java程序一直有问题。用于调整图像大小。您将其放到一个文件夹中并运行它,它会创建一个带有调整大小图像的新文件夹。它在颜色上效果很好,但是在灰度方面存在问题。图像被转换,但是它们变得更亮,更褪色,好像有人弄乱了曲线或水平。所有输入文件输出文件均为sRGB色彩空间jpeg,以RGB色彩模式保存。我有成千上万个50兆像素的胶片扫描,试图将其转换为15兆像素或更少。任何人都可以提供的任何帮助或想法,将不胜感激。该程序的完整代码在下面,大约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),type);
    }

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

    // Paint the image onto the buffered image
    g.drawImage(image,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说..)。 并且,尽管下一版本将纠正该错误;),请尝试一些变通方法,如此处所建议的那样自行缩放图像。 问候,  斯特凡     ,        在您的代码中,您假定jpeg是用RGB编码的,但并非总是如此。也可以对8位灰度jpeg进行编码。所以我建议您在构建BufferedImage时尝试一下,替换:
BufferedImage.TYPE_INT_RGB;
通过
BufferedImage.TYPE_BYTE_GRAY;
并查看它是否适用于这些图像。 如果是这样,那么您仍然必须找出一种确定编码类型的方法,以自动更改要使用的BufferedImage颜色编码的类型,但是您将一站式地接近。 问候,  斯特凡