java - 调整 BufferedImages 的大小并将其存储到 JPG 图像黑色背景的文件结果中

标签 java image-manipulation bufferedimage

我有以下代码:

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;


public class JavaApplication
{
    public static void main(String[] args) throws Exception
    {
        File orig = new File ("/home/xxx/Pictures/xxx.jpg");
        BufferedImage bm1 = ImageIO.read(orig);

        Image scaled = bm1.getScaledInstance(100, 200, BufferedImage.SCALE_SMOOTH);
        BufferedImage bm2 = toBufferedImage(scaled);

        File resized = new File ("/home/xxx/Pictures/resized.jpg");
        ImageIO.write(bm2, "jpg", resized);
    }

    public static BufferedImage toBufferedImage(Image img)
    {
        if (img instanceof BufferedImage)
        {
            return (BufferedImage) img;
        }

        BufferedImage bimage = new BufferedImage(img.getWidth(null),       img.getHeight(null), BufferedImage.TYPE_INT_ARGB);

        bimage.getGraphics().drawImage(img, 0, 0 , null);
        return bimage;
      }
}

如果我在 .png 文件上使用此代码,它可以正常工作,并按预期调整文件大小。但是对于 jpg 文件,它会导致黑色背景。

如果我删除 getScaledInstance() 代码,并尝试使用 ImageIO.write(bm1, "jpg"将原始 bm1 重新写入磁盘“,调整大小),效果很好。仅当使用 getScaledInstance() 调整大小,然后尝试将生成的 Image 转换回 BufferedImage 时,我才会获得全黑的背景文件。

关于如何解决这个问题的任何想法,或者我做错了什么?

最佳答案

当我运行你的代码时,我没有得到黑色背景,但图像的颜色看起来很奇怪( channel 似乎很困惑)。

当我toBufferedImage(..)中的图像类型更改为BufferedImage.TYPE_INT_RGB(无alpha ,因为 JPEG 不支持透明度),一切正常。

仍然很奇怪,ImageIO 在写入 JPEG 图像时没有考虑到这一点...

顺便说一句,异步图像缩放(如 getScaledInstance(..) 所做的那样)不是问题,我确保在继续之前完成图像大小调整,这对结果没有影响。

要完全加载图像,请使用 MediaTracker:

public static void loadCompletely (Image img) {

    MediaTracker tracker = new MediaTracker(new JPanel());
    tracker.addImage(img, 0);
    try {
        tracker.waitForID(0);
    } catch (InterruptedException ex) {
        throw new RuntimeException(ex);
    }
}

编辑
这是我用来调整图像大小、保留比例的代码(不同的调整大小方法取决于您是放大还是缩小,以及更快的区域平均替代方案):

public static BufferedImage resizeImage (BufferedImage image, int areaWidth, int areaHeight) {
    float scaleX = (float) areaWidth / image.getWidth();
    float scaleY = (float) areaHeight / image.getHeight();
    float scale = Math.min(scaleX, scaleY);
    int w = Math.round(image.getWidth() * scale);
    int h = Math.round(image.getHeight() * scale);

    int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;

    boolean scaleDown = scale < 1;

    if (scaleDown) {
        // multi-pass bilinear div 2
        int currentW = image.getWidth();
        int currentH = image.getHeight();
        BufferedImage resized = image;
        while (currentW > w || currentH > h) {
            currentW = Math.max(w, currentW / 2);
            currentH = Math.max(h, currentH / 2);

            BufferedImage temp = new BufferedImage(currentW, currentH, type);
            Graphics2D g2 = temp.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2.drawImage(resized, 0, 0, currentW, currentH, null);
            g2.dispose();
            resized = temp;
        }
        return resized;
    } else {
        Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR;

        BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = resized.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
        g2.drawImage(image, 0, 0, w, h, null);
        g2.dispose();
        return resized;
    }
}

关于java - 调整 BufferedImages 的大小并将其存储到 JPG 图像黑色背景的文件结果中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19654017/

相关文章:

Java - 在接口(interface)中声明变量但不分配它们

java - 我们可以在测试服务本身的同时模拟服务中的方法吗?

python - 在 Python 中操作 WebP 图像

java - 在 Java 中打印 BufferedImage 的正确方法

java - 上传新文件时如何同时获取文件MD5和SHA1校验和?

java - 用于几种类型请求的 JMX Bean

python - 将像素从图像的裁剪部分转换为原始图像 OpenCV

php - 合并图像 PHP

java - 读取14位和16位图像

java - 如何从原始数据创建 BufferedImage