如何使用java将PNG图像转换为灰度?
我在将PNG图像更改为灰度时遇到问题。我想创建一个方法,该方法将接受byte[]image作为参数,并作为新修改的灰度图像返回byte[]
我发现一些链接,使图像灰度与JPEG图像使用下面的片段
private byte[] makeItGray(byte[] img, String contentType) throws IOException, Exception{
InputStream in = new ByteArrayInputStream(img);
BufferedImage bimg = ImageIO.read(in);
for(int y=0; y < bimg.getHeight(); y++){
for(int x=0; x < bimg.getWidth(); x++){
Color color = new Color(bimg.getRGB(x,y));
int graylevel = (color.getRed() + color.getGreen() + color.getBlue()) / 3;
int r = graylevel;
int g = graylevel;
int b = graylevel;
int rgb = ( r<<16 ) | ( g<<8 ) | b;
bimg.setRGB(x, y, rgb);
}
}
in.close();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if(contentType.equals(MediaType.IMAGE_PNG_VALUE)){
ImageIO.write(bimg, "png", baos);
System.out.println("PNG!!!");
}
else if(contentType.equals(MediaType.IMAGE_JPEG_VALUE)){
ImageIO.write(bimg, "jpg", baos);
}
else
throw new Exception();
baos.flush();
byte[] grayImage = baos.toByteArray();
baos.close();
return grayImage;
}
我的推荐信如下: How can I use ImageJ as a library for a separate Java application? https://www.mkyong.com/java/how-to-convert-byte-to-bufferedimage-in-java/
它适用于JPEG图像,但在PNG上,它会给我发送一个透明图像
// converting orig image to grayscale in byte[]
imageBytes = makeItGray(imageBytes, file.getContentType());
Path path = Paths.get("some path here that would overwrite existing image");
Files.write(path, imageBytes);
当我试图手动打开图像以检查它是否为灰度时,它会给我提供透明图像或没有显示图像,但不会为空,因为它返回字节[]数据。我想知道上述方法是否适用于PNG格式
如果有任何问题,请告诉我。谢谢
# 1 楼答案
实际上,
getRGB
和setRGB
方法,不管它们的名称如何,实际上返回并接受32位压缩ARGB格式的像素。这意味着,如果BufferedImage
的颜色模型实际上包含一个alpha通道,那么像您这样将像素的alpha值留空(0x00
),将产生一个全透明的图像PNG格式支持alpha,而JPEG通常不使用它,这就是为什么你会看到你所做的结果,以及为什么它对不同格式的工作方式不同
不过修复方法很简单,只需在像素值前加上所有不透明的alpha:
如果你想保留原版的alpha,你也可以这样做(我简化了代码):
注:请注意,通过平均值计算灰度值的方法并不是将RGB转换为灰度的推荐方法,因此与其他工具相比,您的图像可能看起来不太好。参见示例Converting color to grayscale
# 2 楼答案