我的Java程序一直存在问题。这是为了调整图像大小。您将其放入文件夹并运行它,它会创建一个包含已调整大小的图像的新文件夹。它在颜色方面效果很好,但它有灰度问题。图像被转换,但它们变得更轻,更褪色,好像有人弄乱了曲线或水平。所有输入文件和输出文件都是sRGB色彩空间jpeg,以RGB颜色模式保存。我有成千上万的50万像素胶片扫描,我试图将其转换为低至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"));
}
}
答案 0 :(得分:1)
在你的代码中,你假设jpeg是用RGB编码的,但情况并非总是如此。它也可以编码8位灰度缩放jpeg。所以我建议你在构建BufferedImage时尝试这个,替换:
BufferedImage.TYPE_INT_RGB;
通过
BufferedImage.TYPE_BYTE_GRAY;
并查看它是否适用于这些图像。
如果是这样,那么你仍然需要找到一种方法来确定编码类型以自动更改要使用的BufferedImage颜色编码的类型,但是你将会更近一步。
此致 斯特凡
答案 1 :(得分:1)
如果jdk的类和方法有问题,请将错误报告给oracle(哦!我希望我可以继续对SUN说..)。
并且,虽然下一个版本将纠正错误;),尝试一些解决方法,像proposed here一样自己缩放图像。
此致 Stéphane