问题描述
||
我的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颜色编码的类型,但是您将一站式地接近。
问候,
斯特凡