Java处理某些图片红色问题

本文探讨了Java中使用ImageIO.read()方法处理图片时出现的红色覆盖问题,并提供了使用Toolkit.getDefaultToolkit().getImage()和createImage()替代方案来解决此问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题现象:

Java上传图片时,对某些图片进行缩放、裁剪或者生成缩略图时会蒙上一层红色,经过检查只要经过ImageIO.read()方法读取后再保存,该图片便已经变成红图。因此,可以推测直接原因在于ImageIO.read()方法加载图片的过程存在问题。

  1. public static BufferedImage getImages(byte[] data) throws IOException {  
  2.         ByteArrayInputStream input = new ByteArrayInputStream(data);  
  3.         return ImageIO.read(input);  
  4.     }  

经过查阅得知ImageIO.read()方法读取图片时可能存在不正确处理图片ICC信息的问题,ICC为JPEG图片格式中的一种头部信息,导致渲染图片前景色时蒙上一层红色。
解决方案:

不再使用ImageIO.read()方法加载图片,而使用JDK中提供的Image src=Toolkit.getDefaultToolkit().getImage

  1. Image src=Toolkit.getDefaultToolkit().getImage(file.getPath());  
  2. BufferedImage image=BufferedImageBuilder.toBufferedImage(src);//Image to BufferedImage  

或者Toolkit.getDefaultToolkit().createImage
  1. Image imageTookit = Toolkit.getDefaultToolkit().createImage(bytes);  
  2. BufferedImage cutImage = BufferedImageBuilder.toBufferedImage(imageTookit);  

BufferedImageBuilder源码:
  1. public static BufferedImage toBufferedImage(Image image) {  
  2.         if (image instanceof BufferedImage) {  
  3.             return (BufferedImage) image;  
  4.         }  
  5.         // This code ensures that all the pixels in the image are loaded  
  6.         image = new ImageIcon(image).getImage();  
  7.         BufferedImage bimage = null;  
  8.         GraphicsEnvironment ge = GraphicsEnvironment  
  9.                 .getLocalGraphicsEnvironment();  
  10.         try {  
  11.             int transparency = Transparency.OPAQUE;  
  12.             GraphicsDevice gs = ge.getDefaultScreenDevice();  
  13.             GraphicsConfiguration gc = gs.getDefaultConfiguration();  
  14.             bimage = gc.createCompatibleImage(image.getWidth(null),  
  15.                     image.getHeight(null), transparency);  
  16.         } catch (HeadlessException e) {  
  17.             // The system does not have a screen  
  18.         }  
  19.         if (bimage == null) {  
  20.             // Create a buffered image using the default color model  
  21.             int type = BufferedImage.TYPE_INT_RGB;  
  22.             bimage = new BufferedImage(image.getWidth(null),  
  23.                     image.getHeight(null), type);  
  24.         }  
  25.         // Copy image to buffered image  
  26.         Graphics g = bimage.createGraphics();  
  27.         // Paint the image onto the buffered image  
  28.         g.drawImage(image, 00null);  
  29.         g.dispose();  
  30.         return bimage;  
  31.     } 
### 使用 Java 和 OpenCV 移除图像中的红色部分 为了实现这一目标,可以采用颜色阈值法来检测并替换特定范围内的红色像素。以下是具体操作: #### 导入必要的库 确保导入了所需的 OpenCV 库,并正确设置了开发环境。 ```java import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.Scalar; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; ``` #### 加载图像并转换色彩空间 加载原始图像并将BGR色彩空间转换为HSV色彩空间以便更好地分离颜色特征[^1]。 ```java // 动态链接OpenCV库 System.loadLibrary(Core.NATIVE_LIBRARY_NAME); Mat image = Imgcodecs.imread("path_to_image"); Mat hsvImage = new Mat(); Imgproc.cvtColor(image, hsvImage, Imgproc.COLOR_BGR2HSV); ``` #### 定义红色区域的上下限 定义 HSV 色彩模型下的红色区间,考虑到不同光照条件的影响,通常会设置较宽泛的界限[^2]。 ```java Scalar lowerRed = new Scalar(0, 70, 50); // 下界 Scalar upperRed = new Scalar(10, 255, 255); // 上界 ``` 注意:由于Hue(色调)是一个圆环形参数,实际应用中可能还需要考虑跨越零点的情况,即高饱和度红与低饱和度红之间的过渡区段。 #### 创建掩码并与原图相乘 创建二值化掩膜用于标记属于指定颜色范围内的像素位置;接着利用此掩模修改对应位置上的像素值为白色或其他背景色。 ```java Mat mask = new Mat(); Core.inRange(hsvImage, lowerRed, upperRed, mask); // 对于跨越hue=0的情形也需要额外处理... // 这里省略这部分逻辑... // 将mask应用于原图 Mat result = new Mat(); image.copyTo(result, mask.inv()); // 只保留非红色部分 Core.bitwise_not(mask, mask); // 取反得到只含红色的部分 Core.addWeighted(result, 1., mask, 255, 0, result); // 合成最终效果 ``` 以上代码片段展示了如何通过调整颜色阈值的方式有效地消除图片中的红色印记或元素。需要注意的是,在某些情况下,简单的颜色过滤可能会误伤其他相似色调的对象,因此建议根据实际情况微调参数直至获得满意的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值