java:图像(BufferedImage)色彩空间转换(灰度)暨获取图像矩阵数据byte[](sRGB/gray)

ColorConvertOp

java.awt.image包下面有个类java.awt.image.ColorConvertOp,类名直译就是”颜色转换操作”。
顾名思义,它的作用就是将一个色彩空间(color space)的图像转换为另一个色彩空间的图像。有了这个神器我们就能轻易的将一张彩色图你像转换成灰度(gray)或其他色彩空间图像。
代码非常简单,只要一行。

    public BufferedImage toGray(BufferedImage srcImg){      return new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(srcImg, null);}

依此类推,你可以参照ColorConvertOp的参数说明将图像转为其他格式。
java.awt.color.ColorSpace中列出了很多支持的色彩空间定义TYPE_RGB,TYPE_CMYK,TYPE_HSV,TYPE_YCbCr….

Raster.getDataElements

有时我们通过ImageIO得到解码后的图像数据对象(BufferedImage)以后,需要获取图像矩阵的裸数据(即一个存储图像数据的byte数组)。
BufferedImage中提供了一个getRGB()方法,它返回的是一个ARGB格式int[]数组(每个int型元素的4个字节分别代表一个像素的Alpha,Red,Green,Blue四个通道)
如果你要从这个方法获取RGB的数组,你还得自己写转换代码:

    /*** 返回图像的RGB格式字节数组* @param image* @return*/public static byte[] getMatrixRGB(BufferedImage image){int w = image.getWidth();int h = image.getHeight();int[] intArray = new int[w * h];byte[] matrixRGB = new byte[w * h * 3];image.getRGB(0, 0, w, h, intArray, 0, w);// ARGB->RGBfor(int i=0,b=0;i<intArray.length;++i){matrixRGB[b++]=(byte) (matrixRGB[i]&0x000000FF);matrixRGB[b++]=(byte) ((matrixRGB[i]&0x0000FF00)>>8);matrixRGB[b++]=(byte) ((matrixRGB[i]&0x00FF0000)>>16);}return matrixRGB;}

好烦呐,我以前就是这么干的,真的没有提供更好的方法吗?
不是没有更好的方法,而是我学艺不精没找到而已。
在仔细研究了BufferedImage的代码之后,才明白getRGB()只是BufferedImage为默认 RGB 颜色模型 (TYPE_INT_ARGB)提供的一个便利性封装。
通过getRGB()源码可以知道BufferedImage对象中真正的图像数据是由成员对象raster(java.awt.image.WritableRaster)管理。而WritableRasterjava.awt.image.Raster的子类。Raster中getDataElements方法可以我们所需要的字节数组。
还以前面图像转灰度举例,如果要从灰度图像中获取图像矩阵的字节数组,代码示例如下:

    /*** 获取灰度图像的字节数组* @param image* @return*/public static byte[] getMatrixGray(BufferedImage image) {// 转灰度图像BufferedImage grayImage = new BufferedImage(width, height,  BufferedImage.TYPE_BYTE_GRAY);      new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(image, grayImage);// getData方法返回BufferedImage的raster成员对象return (byte[]) grayImage.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null);       }

注意这里return语句使用了(byte[])强制类型转换,因为getDataElements返回的是打开声明 java.lang.Object对象。
也就是说getDataElements返回的未必是byte[]类型,为什么呢?看下面getDataElements方法的说明:
这里写图片描述
看不懂没关系,我们可以看到这里的返回的类型可能是:TYPE_BYTE,TYPE_USHORT,TYPE_INT,TYPE_SHORT,TYPE_FLOAT,TYPE_DOUBLE。并不一定是byte。
那么问题来了,如何控制返回的数组类型是byte[]呢?
同样,我们可以使用前面的ColorConvertOp对象进行转换。
比如我们需要得到图像的RGB数据:

    /*** 获取图像RGB格式数据* @param image* @return*/public static byte[] getMatrixRGB(BufferedImage image){if(image.getType()!=BufferedImage.TYPE_3BYTE_BGR){// 转sRGB格式BufferedImage rgbImage = new BufferedImage(image.getWidth(), image.getHeight(),  BufferedImage.TYPE_3BYTE_BGR);new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_sRGB), null).filter(image, rgbImage);// 从Raster对象中获取字节数组return (byte[]) rgbImage.getData().getDataElements(0, 0, rgbImage.getWidth(), rgbImage.getHeight(), null);}else{return (byte[]) image.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554761.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis-Plus updateById方法更新不了空字符串/null解决方法

最近遇到了Mybatis-Plus updateById()&#xff0c;更新某一个字段为null&#xff0c;却发现没有更新成功。记录一下 一、简介 因为最近在忙项目&#xff0c;好久都没有更新博客&#xff0c;最近在项目中刚好遇到一个问题&#xff0c;就是在使用MyBatis-Plus updateById&#…

Java 分割字符串的方法String.split()底层原理与使用

文章目录split()底层原理1.举例说明2.split源码分析3.API原解4.regex参数API原解5.limit参数介绍6.结果的验证7.此方法的使用split方法的使用split用法分析参数解释—regex参数解释—limit不同limit值的情况下的split结果验证扩展split()底层原理 1.举例说明 1.最普通的用法 …

MySQL中数据类型的长度问题解析

MySQL中数据类型的长度问题总结 1&#xff09;&#xff1a;int类型&#xff0c;对吧&#xff0c;经常像保存个时间戳啊、id啊、数量啊、排序啊都会用到 提问&#xff1a;INT&#xff08;11&#xff09;是什么意思&#xff1f;最大保存十一位数么&#xff1f; 回答&#xff1a;…

HttpComponents入门解析

1 简介 超文本传输协议(http)是目前互联网上极其普遍的传输协议&#xff0c;它为构建功能丰富&#xff0c;绚丽多彩的网页提供了强大的支持。构建一个网站&#xff0c;通常无需直接操作http协议&#xff0c;目前流行的WEB框架已经透明的将这些底层功能封装的很好了&#xff0c…

HttpClient使用和详解

文章目录一、关于HttpClient二、HttpClient使用步骤详解1、创建一个HttpClient对象A、HttpCLientConnectionManagerB、HttpRoutePlannerC、RequestConfig2、创建一个Request对象3、执行Request请求4、处理response1&#xff09;关闭和entity相关的content stream2&#xff09;关…

你还在 Docker 中跑 MySQL?

容器的定义&#xff1a;容器是为了解决“在切换运行环境时&#xff0c;如何保证软件能够正常运行”这一问题。 目前&#xff0c;容器和 Docker依旧是技术领域最热门的词语&#xff0c;无状态的服务容器化已经是大势所趋&#xff0c;同时也带来了一个热点问题被大家所争论不以&…

使用mybatis-plus来自定义排序

需求&#xff1a; 先时间升序排序&#xff0c;相同的时间在按状态排序&#xff0c;状态的顺序为1 在线 4 潜伏 2 隐身 3 离开&#xff0c;状态相同在按姓名升序排序对排序好的数据进行分页运用mybatis-plus中QueryWrapper 1.导入依赖 <dependencies><dependency>…

Postman实现接口测试(附项目实战)

文章目录Postman实现接口测试1.Postman介绍和安装2. Postman安装2.1 安装方式2.2 安装步骤3. Postman入门示例Postman基本用法Postman高级用法1. 管理用例2. Postman断言3. 全局变量与环境变量5. Postman关联6. 批量执行测试用例7. 读取外部文件实现参数化Postman测试报告目标项…

Postman 使用教程详解

Postman页面 2、新建一个项目 直接点击左边栏上面的添加目录图标来新增一个根目录&#xff0c;这样就等于新建了一个项目&#xff0c;我们可以把一个项目或一个模块的用例都存放在这个目录之下&#xff0c;并且在根目录之下我们还可以在建立子目录来进行功能用例的细分&#…

聊聊@Autowired注解注入,写接口名字还是实现类的名字

用Autowired注解注入,写接口名字还是实现类的名字 来自某程序员一个问答问题 有一点没明白&#xff0c;为什么注解repository注解的是接口UserDAO的实现类UserDAOImpl&#xff0c;而在UserServiceImpl中使用Autowired注解注入属性private UserDAO userDAO自动装配&#xff0c…

Spring注入接口还是实现类,同一接口有多个实现类,如何注入

1、接口&#xff1a;IUserService public interface IUserService {public void sayHello(); }2、实现类&#xff1a;UserServiceImpl&#xff0c;实现了UserService接口 Service("UserServiceImpl ") public class UserServiceImpl implements IUserService{// 添…

Spring只能注入接口,不能注入实现类

只能注入接口&#xff0c;不能注入实现类。 Controller public class Test {AutowiredprivateRoleDao rdi; }privateRoleDao是个接口 这样注入就没有问题&#xff0c; 而注入 Controller public class Test {AutowiredprivateRoleDaoImpl rdi; }会报错&#xff1a;No qua…

调用Dubbo报错: com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method 问题原因和解决办法

我们在使用Dubbo的过程中&#xff0c;时常会碰到这个异常。而有可能导致这个异常的原因是非常多的&#xff0c;排查起来比较困难。下面把如何排查该问题的思路整理了一下&#xff0c;目前我知道的会导致这个异常的原因分为以下几类&#xff1a; 1.需要进行序列化的POJO类没有进…

Springboot dubbo @Service @Transactional 无法提供服务或者无法提供事务的解决办法

问题场景&#xff1a; 今天在springboot中集成spring事务的时候&#xff0c;遇到了一个大坑。如果&#xff08;springbootdubbo&#xff09;中添加 Service、Transactional 两个注解的时候&#xff0c;就不能进行dubbo服务注册了。 解决历程&#xff1a; 1&#xff0c;先是在…

Dubbo序列化

Dubbo序列化 dubbo作为一个rpc框架支持丰富的序列化方式&#xff0c;本文简单介绍dubbo的序列化。本文结构&#xff1a; 对象序列化是什么意思&#xff1f;dubbo序列化几个问题 对象序列化是什意思&#xff1f; 先来思考两个问题&#xff1a; 普通的Java对象的生命周期是仅…

什么是 serialVersionUID ? 序列化对象时必须提供 serialVersionUID 吗?

什么是 serialVersionUID &#xff1f; 序列化对象时必须提供 serialVersionUID 吗&#xff1f; 1&#xff0c;什么是 serialVersionUID &#xff1f; 顾名思义&#xff0c;serialVersionUID是序列化版本号。所有可序列化的类&#xff0c;都有一个静态serialVersionUID属性&a…

【Dubbo学习系列】Dubbo消费端的代理生成详解(@DubboReference和@Reference)

文章目录Spring中Dubbo实现RPC如何加载Reference和DubboReference注解DubboComponentScanRegistrar概括发现Refrence和DubboReference注解&#xff0c;并编织RPC通信逻辑ReferenceAnnotationBeanPostProcessor&#xff08;核心&#xff09;ReferenceDubboReferenceReference和D…

【Java编程】之 List 与数组之间的相互转换Arrays.asList 和 ArrayList 的 subList

文章目录一、数组转换成 List 集合二、List 集合转数组浅谈 Arrays.asList1、不能往 Arrays.asList 生成的 List 集合中添加元素Arrays.asList 只是简单的充当转换接口二、浅谈 ArrayList 的 subList1、subList 索引的取值边界2、subList 不可强转成 ArrayList3、对 subList 的…

谈Java集合类的toArray()的小bug

谈Java集合类的toArray()的小bug toArray()方法 它的作用是将集合转换成数组。但是这个方法有一个弊端&#xff0c;当toArray()方法使用不当时会产生ClassCastException&#xff08;类转换异常&#xff09; public static void main(String[] args) {List<Integer> li…

Dubbo系统里面MultipartFile文件传输问题Dubbo文件上传/传输服务

今天遇到一个问题&#xff0c;在Controller 层里面&#xff0c;直接使用MultipartFile 来接收上传的图片&#xff0c;遇到几个坑。 一、在spring配置文件里面配置文件上传 <!--文件上传--><bean name"multipartResolver"class"org.springframework.web…