我的批处理JPG大小调整适用于彩色图像,但灰度的人成为淘汰 [英] My batch jpg resizer works with color images, but grayscale ones become washed out

查看:179
本文介绍了我的批处理JPG大小调整适用于彩色图像,但灰度的人成为淘汰的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经与我的Java程序有问题。这对调整图像大小。您拖放到一个文件夹,运行它,它会创建与调整图像的新文件夹。它适用于颜色伟大的,但它与灰度的一个问题。该图像转换,但它们变得更轻,更冲了出去,仿佛有人用曲线或水平搞砸。所有输入文件和输出文件是sRGB色彩空间的JPEG文件,保存在RGB色彩模式。我有成千上万的50万像素的胶片扫描我想下转换为15百万像素或更低。任何帮助或想法的人可以提供将是最AP preciated。该计划的全部code是下面,它是关于130线。我有一种感觉问题可能出在toBufferedImage功能,但我失去了作为可能是什么。

 包jpegresize;进口java.awt中的*。
java.awt.image中导入*。
进口的java.util。*;
进口java.io. *;
进口javax.imageio中的*。
javax.imageio.stream中导入*。
进口的javax.swing *。公共类主要{公共静态无效的主要(字串[] args){    的System.out.println(JPEGResize运行。);    INT max_side = 4096;
    浮质量= 0.9F;    如果(args.length == 0)的System.out.println(没有最大边分辨率或COM pression质量参数给出,使用默认值\\ n用法:Java的罐子JPEGResize.jar<以像素为单位&GT最大边的分辨率。 ;&下;质量0%到100%>中);
    如果(args.length> = 1)max_side =的Integer.parseInt(参数[0]);
    如果(args.length> = 2)质量= Float.parseFloat(参数[1])/ 100.0f;    的System.out.println(最大方分辨率:+ max_side);
    的System.out.println(的COM pression质量:+(质量* 100)+%);    文件夹=新的文件(。);
    文件[] = listOfFiles folder.listFiles(新JPEGFilter());    的for(int i = 0; I< listOfFiles.length;我++){        的System.out.println(处理+ listOfFiles [I] .getName()+。);
        resizeFile(listOfFiles [I] .getName(),max_side,质量);
        的System.out.println(保存/调整/+ listOfFiles [I] .getName());
    }    的System.out.println(操作完成。);
}公共静态无效resizeFile(字符串文件名,INT max_side,浮动质量){    尝试
    {
        BufferedImage的input_img = ImageIO.read(新文件(文件名));        双ASPECT_RATIO =((双)input_img.getWidth())/((双)input_img.getHeight());
        INT宽度,高度;        如果(input_img.getWidth()&GT = input_img.getHeight()){            宽度= max_side;
            身高=(INT)(((双)max_side)/ ASPECT_RATIO);
        }
        其他{            宽度=(INT)(((双)max_side)* ASPECT_RATIO);
            高度= max_side;
        }        图像scaled_img = input_img.getScaledInstance(宽度,高度,Image.SCALE_SMOOTH);
        BufferedImage的output_img = toBufferedImage(scaled_img);        ITER的Iterator = ImageIO.getImageWritersByFormatName(JPEG);
        ImageWriter的作家=(ImageWriter的)iter.next();
        的ImageWriteParam IWP = writer.getDefaultWriteParam();
        iwp.setCom pressionMode(ImageWriteParam.MODE_EXPLICIT);
        iwp.setCom pressionQuality(质量);        文件doesDirExist =新的文件(调整大小/);
        如果(!doesDirExist.exists())
            新的文件(调整大小)的mkdir()。        档案文件=新的文件(调整大小/+文件名);
        FileImageOutputStream输出=新FileImageOutputStream(文件);
        writer.setOutput(输出);
        IIOImage中形象=新方法IIOImage(output_img,NULL,NULL);
        writer.write(NULL,图像,IWP);
        writer.dispose();
    }
    赶上(IOException异常E)
    {
        e.printStackTrace();
    }
}//该方法返回与图像的内容的缓冲的图像
公共静态的BufferedImage toBufferedImage(形象画像){
    如果(的instanceof BufferedImage的图像){
        回报(BufferedImage的)图像;
    }    //这code确保在图像中的所有像素为加载
    图像=新的ImageIcon(图).getImage();    //使用的格式,是与屏幕兼容创建一个缓冲图像
    BufferedImage的bimage = NULL;
    GraphicsEnvironment中GE = GraphicsEnvironment.getLocalGraphicsEnvironment();
    尝试{
        //确定的新的缓冲图像的透明性的类型
        诠释透明度=为Transparency.OPAQUE;        //创建缓冲图像
        GraphicsDevice的GS = ge.getDefaultScreenDevice();
        的GraphicsConfiguration GC = gs.getDefaultConfiguration();
        bimage = gc.createCompatibleImage(
            image.getWidth(空),image.getHeight(空),透明度);
    }赶上(HeadlessException的E){
        //系统不会有一个屏幕
    }    如果(bimage == NULL){
        //使用默认的颜色模型缓冲图像
        整型= BufferedImage.TYPE_INT_RGB;
        bimage =新的BufferedImage(image.getWidth(空),image.getHeight(空),类型);
    }    //将图片复制到缓冲图像
    图形G = bimage.createGraphics();    //图像绘制到缓冲图像
    g.drawImage(图像,0,0,NULL);
    g.dispose();    返回bimage;
}
}类JPEGFilter实现了FilenameFilter {
公共布尔接受(文件目录,字符串名称){
    回报(name.toLowerCase()的endsWith(JPG))|| (name.toLowerCase()的endsWith(JPEG)。);
    }
}


解决方案

如果JDK的类和方法是马车,报告错误到Oracle(哦!我希望我能一直在说要SUN ..)。

和,而下一个版本将修正的bug),尝试一些变通,自己喜欢的这里建议。

问候,
 斯特凡

I've been having a problem with my Java program. It's for resizing images. You drop it into a folder and run it, and it creates a new folder with the resized images. It works great on color, but it has a problem with grayscale. The images are converted, but they become lighter and more washed out, as if someone has messed with the curves or levels. All the input files and output files are sRGB color space jpegs, saved in RGB color mode. I have thousands of 50 megapixel film scans I'm trying to convert down to 15 megapixels or less. Any help or ideas anyone could offer would be most appreciated. The programs full code is below, it's about 130 lines. I have a feeling the problem may be in the toBufferedImage function but I'm lost as to what it could be.

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"));
    }
}

解决方案

If jdk's classes and methods are buggy, report the bug to oracle (oh! I wish I could go on saying to SUN..).

And, while the next release will correct the bug ;), try some work arounds, scaling image by yourself like proposed here.

Regards, Stéphane

这篇关于我的批处理JPG大小调整适用于彩色图像,但灰度的人成为淘汰的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆