如何使用 java 将 PNG 图像转换为灰度图像?
How to convert PNG image to grayscale using java?
我在将 PNG 图像更改为灰度时遇到问题。我想创建一个方法,接受 byte[] 图像作为参数,return 作为新修改的灰度图像作为 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);
当我尝试手动打开图像以检查它是否为灰度时,它给我透明图像或没有图像显示但不为空,因为它是 return 字节 [] 数据。我想知道上述方法是否适用于 PNG 格式?
如有任何问题,请告诉我。谢谢!
实际上,getRGB
和 setRGB
方法,尽管它们的名称,实际上 returns 并接受 32 位打包 ARGB 格式的像素。这意味着如果 BufferedImage
的颜色模型实际上包含一个 alpha 通道,像您一样将像素的 alpha 值留空 (0x00
),将导致全透明图像...
PNG 格式支持 alpha,而 JPEG 通常不使用它,这就是为什么您会看到您所做的结果,以及为什么它似乎对不同格式的工作方式不同。
虽然修复很简单,只需在像素值前加上所有不透明的 alpha:
int rgb = 0xff000000 | (r << 16) | (g << 8) | b;
bimg.setRGB(x, y, rgb);
如果你想保留原来的alpha,你也可以这样做(我稍微简化了代码):
int oldrgb = bimg.getRGB(x,y);
Color color = new Color(oldrgb);
int gray = (color.getRed() + color.getGreen() + color.getBlue()) / 3;
int rgb = (oldrgb & 0xff000000) | (gray << 16) | (gray << 8) | gray;
bimg.setRGB(x, y, rgb);
PS:请注意,您通过平均计算灰度值的方法不是将 RGB 转换为灰度的推荐方法,因此与其他工具相比,您的图像可能看起来不合适。例如参见 [=16=].
public class GrayScaleImage{
public static void main(String[]args)throws IOException{
BufferedImage img = null;
File f = null;
try{
f = new File("D:\Image\image.jpg");
img = ImageIO.read(f);
} catch(IOExeption e){
System.out.println(e);
}
int width = img.getWidth();
int height = img.getHeight();
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
int p = img.getRGB(x,y);
int a = (p>>24)&0ff;
int r = (p>>16)&0ff;
int g = (p>>8)&0ff;
int b = p&0ff;
int avg = (r + g + b)/3;
p = (a<<24) | (avg<<16) | (avg<<8) | avg;
img.setRGB(x, y, p);
}
}
try{
f = new File("D:\Image\output.jpg");
ImageIO.write(img, "jpg", f);
} catch(IOException e){
System.out.println(e);
}
我在将 PNG 图像更改为灰度时遇到问题。我想创建一个方法,接受 byte[] 图像作为参数,return 作为新修改的灰度图像作为 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);
当我尝试手动打开图像以检查它是否为灰度时,它给我透明图像或没有图像显示但不为空,因为它是 return 字节 [] 数据。我想知道上述方法是否适用于 PNG 格式?
如有任何问题,请告诉我。谢谢!
实际上,getRGB
和 setRGB
方法,尽管它们的名称,实际上 returns 并接受 32 位打包 ARGB 格式的像素。这意味着如果 BufferedImage
的颜色模型实际上包含一个 alpha 通道,像您一样将像素的 alpha 值留空 (0x00
),将导致全透明图像...
PNG 格式支持 alpha,而 JPEG 通常不使用它,这就是为什么您会看到您所做的结果,以及为什么它似乎对不同格式的工作方式不同。
虽然修复很简单,只需在像素值前加上所有不透明的 alpha:
int rgb = 0xff000000 | (r << 16) | (g << 8) | b;
bimg.setRGB(x, y, rgb);
如果你想保留原来的alpha,你也可以这样做(我稍微简化了代码):
int oldrgb = bimg.getRGB(x,y);
Color color = new Color(oldrgb);
int gray = (color.getRed() + color.getGreen() + color.getBlue()) / 3;
int rgb = (oldrgb & 0xff000000) | (gray << 16) | (gray << 8) | gray;
bimg.setRGB(x, y, rgb);
PS:请注意,您通过平均计算灰度值的方法不是将 RGB 转换为灰度的推荐方法,因此与其他工具相比,您的图像可能看起来不合适。例如参见 [=16=].
public class GrayScaleImage{
public static void main(String[]args)throws IOException{
BufferedImage img = null;
File f = null;
try{
f = new File("D:\Image\image.jpg");
img = ImageIO.read(f);
} catch(IOExeption e){
System.out.println(e);
}
int width = img.getWidth();
int height = img.getHeight();
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
int p = img.getRGB(x,y);
int a = (p>>24)&0ff;
int r = (p>>16)&0ff;
int g = (p>>8)&0ff;
int b = p&0ff;
int avg = (r + g + b)/3;
p = (a<<24) | (avg<<16) | (avg<<8) | avg;
img.setRGB(x, y, p);
}
}
try{
f = new File("D:\Image\output.jpg");
ImageIO.write(img, "jpg", f);
} catch(IOException e){
System.out.println(e);
}