当前位置: 首页 > 面试题库 >

调整BufferedImage的大小并将其存储到文件中会导致JPG图像的黑色背景

终安和
2023-03-14
问题内容

我有以下代码:

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()代码,而只是尝试bm1使用将原始文件重写到磁盘上ImageIO.write(bm1, "jpg", resized),则可以正常工作。仅当使用调整大小getScaledInstance()然后尝试将结果转换Image回时BufferedImage,我才会获得完全黑色的背景文件。

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


问题答案:

当我运行您的代码时,我没有得到黑色背景,但是图像的颜色看起来很奇怪(通道似乎被弄乱了)。

当我 改变图像类型toBufferedImage(..),以BufferedImage.TYPE_INT_RGB没有阿尔法
,因为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;
    }
}


 类似资料:
  • 我想在上传到Firebase存储之前调整图像的大小。 我的问题是:FireBase在其Uri上上传图像。我从图库意图中获取图像,并将其放在上,然后像这样调整其大小: firebase根据Uri像这样上传它(如果有其他上传文件的方法,它将非常有用!): 有没有办法获取

  • 我试图得到这样的结果:固定的盒子大小(133x100),图像应该调整大小,但不要拉伸以适应盒子内,空白的空间应该用黑色填充。 我实际上正在尝试使用以下命令: 然而,我不是在请求的框中拟合图像,而是获得了图像的裁剪。如何获得所要求的结果?我正在深入研究文档,但有很多选择,我仍然没有找到(我认为)我需要的一个。

  • 问题内容: 我正在从磁盘读取图像,并将其显示在一行中。图像文件大于行中需要显示的图像文件。由于我需要将RAM 缓存在内存中以加快访问速度,因此我希望它们的大小只能与s 一样大(85x85 dip) 现在我正在读文件 位图= BitmapFactory.decodeFile(file); 而ImageView负责缩放和裁剪它 android:scaleType =“ centerCrop” AFAI

  • 问题内容: 我正在尝试将调整大小的图像上传到S3: 但我得到一个错误: 问题答案: 您需要先将输出图像转换为一组字节,然后才能上载到s3。您可以将图像写入文件然后上传文件,也可以使用cStringIO对象来避免写入磁盘,就像我在这里所做的那样:

  • 问题内容: 我在这里使用Go调整大小包:https://github.com/nfnt/resize 我正在从S3中提取图像,如下所示: // this gives me data []byte 之后,我需要调整图像大小: // problem is that the original_image has to be of type image.Image 将图像上传到我的S3存储桶 // pro