gpt4 book ai didi

java - ImageIO read() 和 write() 操作后 GIF 图像变得错误

转载 作者:行者123 更新时间:2023-12-02 20:01:57 26 4
gpt4 key购买 nike

我有这个代码。它只是读取 GIF 文件,用背景重新绘制它,然后输出到新的 GIF 文件。

问题是结果文件变得奇怪。我不知道为什么它的质量变得很差。 JPG 文件不会出现此问题。如何解决?

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class ImageTest {

public static void main(String[] args) {
f();
}

private static final String EXTENSION = "gif";
private static final String FILENAME = "pinkHeart";
private static final String PATH = "/Users/hieugioi/Downloads/";

public static void f() {
File file = new File(PATH + FILENAME + "." + EXTENSION);

try {
final BufferedImage originalImage = ImageIO.read(file);

int imageType = getImageType(originalImage);
final BufferedImage buff = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), imageType);
final Graphics2D g = buff.createGraphics();

Color backgroundColor = Color.GRAY;
g.setColor(backgroundColor);
g.fill(new Rectangle(0, 0, buff.getWidth(), buff.getHeight()));
g.drawImage(originalImage, null, 0, 0);

File out = new File(PATH + FILENAME + "Out." + EXTENSION);
ImageIO.write(buff, EXTENSION, out);
} catch (IOException e) {
e.printStackTrace();
}
}

public static int getImageType(BufferedImage img) {
int imageType = img.getType();
if (imageType == BufferedImage.TYPE_CUSTOM) {
if (img.getAlphaRaster() != null) {
imageType = BufferedImage.TYPE_INT_ARGB_PRE;
} else {
imageType = BufferedImage.TYPE_INT_RGB;
}
} else if (imageType == BufferedImage.TYPE_BYTE_INDEXED && img.getColorModel().hasAlpha()) {
imageType = BufferedImage.TYPE_INT_ARGB_PRE;
}
return imageType;
}
}

输入图像(pinkHeart.gif):

enter image description here

输出图像(pinkHeartOut.gif):

enter image description here

更新案例2

输入图像(example.gif):

enter image description here

输出图像(exampleOut.gif):输出的黄色完全消失!

enter image description here

最佳答案

这里有两个不同的问题。

第一个假设是您的输入图像具有透明度。据我所知,他们没有。因此,在这两种情况下,背景都不会变为灰色,而是保持纯白色。这没有什么问题,但也许不是您想要/期望的。

另一个(“真正的”问题)是 getImageType(..) 的代码没有针对没有 alpha 的 BufferedImage.TYPE_BYTE_INDEXED 的特殊分支。因此,图像类型将按原样返回。当使用 BufferedImage.TYPE_BYTE_INDEXED 类型创建 BufferedImage 时,它​​将拥有一个带有固定默认调色板的颜色模型(事实上,这是老式的 256 色“网络安全”调色板)。原件中的粉色与此调色板中的粉色不完全匹配,因此使用粉色和白色进行抖动。

第二个输入图像的“问题”在于它根本不是TYPE_BYTE_INDEXED,而是TYPE_BYTE_BINARY。此类型用于每像素 1-4 位的图像,并且多个像素“打包”到一个字节中。如上所述,当使用 BufferedImage.TYPE_BYTE_BINARY 类型创建 BufferedImage 时,它​​将拥有一个带有固定的默认 2 色黑白调色板的颜色模型 (这就是黄色消失的原因)。

通过在返回 TYPE_INT_RGBgetImageType(..) 方法中添加上述类型的分支,我得到了与原始输出相同的输出(这就是我的输出)期望,只要您的图像没有透明背景):

public static int getImageType(BufferedImage img) {
int imageType = img.getType();
switch (imageType) {
case BufferedImage.TYPE_CUSTOM:
if (img.getAlphaRaster() != null) {
imageType = BufferedImage.TYPE_INT_ARGB_PRE;
}
else {
imageType = BufferedImage.TYPE_INT_RGB;
}
break;
case BufferedImage.TYPE_BYTE_BINARY:
// Handle both BYTE_BINARY (1-4 bit/pixel) and BYTE_INDEXED (8 bit/pixel)
case BufferedImage.TYPE_BYTE_INDEXED:
if (img.getColorModel().hasAlpha()) {
imageType = BufferedImage.TYPE_INT_ARGB_PRE;
}
else {
// Handle non-alpha variant
imageType = BufferedImage.TYPE_INT_RGB;
}
break;
}

return imageType;
}
<小时/>

PS:这是一种替代方法,可以完全避免创建原始图像副本的问题,而且速度更快,而且还可以节省内存。它应该与上面的代码的意图完全相同:

public class ImageTest2 {

public static void main(String[] args) throws IOException {
f(new File(args[0]));
}

static void f(File file) throws IOException {
BufferedImage image = ImageIO.read(file);

// TODO: Test if image has transparency before doing anything else,
// otherwise just copy the original as-is, for even better performance

Graphics2D g = image.createGraphics();

try {
// Here's the trick, with DstOver we'll paint "behind" the original image
g.setComposite(AlphaComposite.DstOver);
g.setColor(Color.GRAY);
g.fill(new Rectangle(0, 0, image.getWidth(), image.getHeight()));
}
finally {
g.dispose();
}

File out = new File(file.getParent() + File.separator + file.getName().replace('.', '_') + "_out.gif");
ImageIO.write(image, "GIF", out);
}
}

关于java - ImageIO read() 和 write() 操作后 GIF 图像变得错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35839279/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com