如何设置 BufferedImage 中的 RGB 像素以显示 16 位深度的 PNG?

2024-04-08

我正在尝试读取并显示 PNG 文件。 我处理 8 位深度的图像没有问题。 我按如下方式进行:

BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

然后我读取每个像素的3*8=24位,将它们保存在字节数组中data并将它们放入图像中:

for (int y = 0; y < height; y++)
   for (int x = 0; x < width; x++)
     result.setRGB(x, y, ((data[x * 3 + 0] & 0xff) << 16)
                       + ((data[x * 3 + 1] & 0xff) << 8)
                       + ((data[x * 3 + 2] & 0xff)));

现在的问题是 16 位深度图像。当然data现在更大了,它包含 48 位,分为 6 个字节,每个 RGB 三元组:来自调试器data具有我期望的值。 如何设置RGB像素?我必须更改 BufferedImage 声明吗?也许与:

BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_565_RGB);

提前谢谢了!

P.S.:根据 PNG 标准,图像的颜色类型为 2(不含 alpha 的 RGB)。


也许我必须使用http://docs.oracle.com/javase/7/docs/api/java/awt/image/ColorModel.html http://docs.oracle.com/javase/7/docs/api/java/awt/image/ColorModel.html


@haraldK 指出了正确的方向。我提供了一些来自“PNGReader”的工作代码icafe https://github.com/dragon66/icafe“Java图像库。

if(bitsPerPixel == 16) {
    if(interlace_method==NON_INTERLACED)
       spixels = generate16BitRGBPixels(compr_data, false);
    else {
       spixels = generate16BitRGBInterlacedPixels(compr_data, false);
               }
    int[] off = {0, 1, 2}; //band offset, we have 3 bands
    int numOfBands = 3;
    boolean hasAlpha = false;
    int trans = Transparency.OPAQUE;
    int[] nBits = {16, 16, 16}; 
    if(alpha != null) { // Deal with single color transparency
       off = new int[] {0, 1, 2, 3}; //band offset, we have 4 bands
       numOfBands = 4;
       hasAlpha = true;
       trans = Transparency.TRANSLUCENT;
       nBits = new int[] {16, 16, 16, 16};                      
    }
    db = new DataBufferUShort(spixels, spixels.length);
    raster = Raster.createInterleavedRaster(db, width, height, width*numOfBands, numOfBands, off, null);
    cm = new ComponentColorModel(colorSpace, nBits, hasAlpha, false, trans, DataBuffer.TYPE_USHORT);
}
return new BufferedImage(cm, raster, false, null);

这是generate16BitRGBPixels()方法:

private short[] generate16BitRGBPixels(byte[] compr_data, boolean fullAlpha) throws Exception {
     //
     int bytesPerPixel = 0;
     byte[] pixBytes;

     if (fullAlpha)
         bytesPerPixel = 8;
     else 
         bytesPerPixel = 6;

     bytesPerScanLine = width*bytesPerPixel;         

     // Now inflate the data.
     pixBytes = new byte[height * bytesPerScanLine];

     // Wrap an InflaterInputStream with a bufferedInputStream to speed up reading
     BufferedInputStream bis = new BufferedInputStream(new InflaterInputStream(new ByteArrayInputStream(compr_data)));

     apply_defilter(bis, pixBytes, height, bytesPerPixel, bytesPerScanLine);

     short[] spixels = null;

     if(alpha != null) { // Deal with single color transparency
         spixels = new short[width*height*4];
         short redMask = (short)((alpha[1]&0xff)|(alpha[0]&0xff)<<8);
         short greenMask = (short)((alpha[3]&0xff)|(alpha[2]&0xff)<<8);;
         short blueMask = (short)((alpha[5]&0xff)|(alpha[4]&0xff)<<8);

         for(int i = 0, index = 0; i < pixBytes.length; index += 4) {
             short red = (short)((pixBytes[i++]&0xff)<<8|(pixBytes[i++]&0xff));
             short green = (short)((pixBytes[i++]&0xff)<<8|(pixBytes[i++]&0xff));
             short blue = (short)((pixBytes[i++]&0xff)<<8|(pixBytes[i++]&0xff));
             spixels[index] = red;
             spixels[index + 1] = green;
             spixels[index + 2] = blue;
             if(spixels[index] == redMask && spixels[index + 1] == greenMask && spixels[index + 2] == blueMask) {
                 spixels[index + 3] = (short)0x0000;                               
             } else {
                 spixels[index + 3] = (short)0xffff;
             }
         }
     } else
         spixels = ArrayUtils.toShortArray(pixBytes, true);

     return spixels;         
 }

和 ArrayUtils.toShortArray() 方法:

public static short[] toShortArray(byte[] data, int offset, int len, boolean bigEndian) {

    ByteBuffer byteBuffer = ByteBuffer.wrap(data, offset, len);

    if (bigEndian) {
        byteBuffer.order(ByteOrder.BIG_ENDIAN);
    } else {
        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
    }

    ShortBuffer shortBuf = byteBuffer.asShortBuffer();
    short[] array = new short[shortBuf.remaining()];
    shortBuf.get(array);

    return array;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何设置 BufferedImage 中的 RGB 像素以显示 16 位深度的 PNG? 的相关文章

  • Java 迭代器获取下一个而不递增

    我正在用 Java 编写以下循环 对于每个循环 我想访问链表 r 的当前元素和下一个元素 List
  • 将 CSV 文件读入 Java 作为数据库表

    我发现了很多关于使用 Java 读取 CSV 的帖子 并且他们所指向的 API 在读取 CSV 文件时都采用了面向行的方法 就像 当你得到一行时 获取每一列的值 我希望有一个更高级别的 API 比如在 Perl 中 DBI 允许您在 CSV
  • GSON:自定义对象反序列化

    好吧 我编辑了这个问题 因为它不够清楚 Edit 2 更新了 JSON 文件 我在 Android 应用程序中使用 GSON 我需要解析来自服务器的 JSON 文件 而且有点太复杂了 我不想让我的对象结构太重 所以我想简化内容 所以我的对象
  • 可以向 @ManyToMany Hibernate 额外表添加额外字段吗?

    我有这两类 表 Entity Table name course public class Course Id Column name courseid private String courseId Column name coursen
  • 从继承的受保护 Java 字段创建公共访问器

    我怎样才能完成以下工作 class Foo extends javax swing undo UndoManager increase visibility works for method override def editToBeUnd
  • Java 将字节转换为二进制安全字符串

    我有一些以字节为单位的数据 我想将它们放入Redis中 但是Redis只接受二进制安全字符串 而我的数据有一些二进制非安全字节 那么如何将这些字节转换为二进制安全字符串以便将它们保存到 Redis 中呢 Base64 对我有用 但它使数据更
  • 可以混合使用 JVM 语言吗?即:Groovy 和 Clojure

    我知道你可以轻松地混合groovy java clojure java 无论什么JvmLang java 这是否也意味着我也可以让 clojure 和 groovy 代码进行交互 如果我使用 Grails 或 jRoR 我也可以在该环境中使
  • Keycloak 社交登录 REST API

    我已经为我的 keycloak 实例启用了谷歌社交登录 但我需要将其用作休息服务 是否有可用于执行此操作的端点 Keycloak 中没有 Google 身份验证 API 但您可以使用以下方法解决它代币交换 https www keycloa
  • 为什么 Java 中的 hashCode() 可以对不同对象返回相同的值?

    引用我正在读的书中的一段话首先Java http www amazon co uk Head First Java Kathy Sierra dp 0596009208 关键是 哈希码可以相同 但不一定保证对象相等 因为使用的 哈希算法 h
  • 比较和删除列表和数组java中不存在的元素

    我有一个String数组和一List
  • kafka Avro 多个主题的消息反序列化器

    我正在尝试以 avro 格式反序列化 kafka 消息 我使用以下代码 https github com ivangfr springboot kafka debezium ksql blob master kafka research c
  • 在 Java 中打开现有文件并关闭它。

    是否可以在java中打开一个文件附加数据并关闭多次 例如 psuedocode class variable declaration FileWriter writer1 new FileWriter filename fn1 writer
  • 如何在 Spring Boot 中创建 Apache POI Excel 视图配置

    当我想使用 Spring Boot Web 将数据导出到 Excel 时遇到问题 我使用 Thymeleaf 作为模板引擎 由 Spring Boot 自动配置 但是当我在附加配置中添加 XmlViewResolver 时 由 XmlVie
  • JSP 作为电子邮件模板

    有没有办法发送 MIME 电子邮件 其中电子邮件正文源自 JSP 我需要使用 Javamail 发送一封电子邮件 其中包含一个表格 我认为如果我可以使用 JSP 来完成所有格式设置和布局 将会很方便 在这个线程中 Java 电子邮件模板的建
  • 获取证书链

    我正在 Java 中使用 X509 证书 给定一个证书 是否可以在签名层次结构中找到所有其他证书 直到找到根证书 我有一个证书文件 带有 cer扩展名 我想提取父签名证书 我想继续查找该证书的父证书 直到获得最终的自签名根证书 我已经检查了
  • Maven `help: effective-pom` 只为单个项目生成,而不是所有项目

    我想为多模块构建中的所有子项目生成有效的 pom The help effective pom文档here http maven apache org plugins maven help plugin usage html The hel
  • 在 Java 服务器中验证 Windows 用户

    我正在开发一个用 Java 编写的服务器和一个在同一网络上的 Windows 计算机上运行的客户端 用 Net 编写的桌面应用程序 我希望进行一些基本身份验证 以便服务器可以确定运行客户端的用户的用户名 而不需要用户在客户端中重新输入其 W
  • 如果所有类不在同一个包中,Spring @autowired 不起作用

    我有四个包裹 com spring org Files HomeController java com spring org dao Files SubscriberDao java SubscriberDaoImpl java com s
  • RecyclerView 适配器的 Kotlin 泛型

    我正在尝试编写一个通用的 recyclerview 适配器 我找到了几个例子 然而 仍然无法弄清楚如何实现通用适配器 我写的代码是 open abstract class BaseAdapter
  • 对 Java 协议缓冲区对象进行一些小更改

    我想在 Java 协议缓冲区对象树的深处进行一个小更改 我可以使用 getBuilder 方法来创建一个新对象 该新对象是旧对象的克隆并进行一些更改 当深入完成此操作时 代码会变得丑陋 Quux Builder quuxBuilder fo

随机推荐

  • 应用程序图标创建叠加信息(数字)?

    如何在 Android 应用程序上克隆此行为 iOS 从技术上讲 这绝对是可能的 因为我在 Android 手机上有一个自己的应用程序 它是一个电子邮件应用程序 图标上有一个非常相似的指示器 显示未读邮件数量 是的 你可以像 ios 一样实
  • 用户输入-DOS批处理文件

    我得到一个bat文件 如下所示 ECHO Executing scripts PAUSE for X in SQL do SQLCMD S localhost d CTL I i X gt gt ResultScript txt pause
  • 以编程方式更改滑动时的 ViewPager 动画持续时间

    我正在使用以下代码更改幻灯片 viewPager setCurrentItem index true 但变化太快了 有没有办法手动设置动画速度 I ve wanted to do myself and have achieved a sol
  • 我可以在全局范围内只安装 Gulp 吗?

    我一直致力于新的网络开发项目 这些项目在实践中并不需要他们的node modules部署时的文件夹 如果我能够创建一个小的 它会更适合我gulpfile js对于每个项目 而不是包含在 6000 多个文件node modules每个项目的文
  • 在 Restful Web 服务中下载文件

    我的要求是 我应该通过restful服务向客户端发送一个10MB的zip文件 我在论坛中找到了发送StreamingOutput对象是更好的方法 但是我如何创建一个StreamingOutput以下代码中的对象 Path PDF file
  • 使用“Object.create”而不是“new”

    Javascript 1 9 3 ECMAScript 5 介绍Object create 其中道格拉斯 克罗克福德 Douglas Crockford 等人提倡 http javascript crockford com prototyp
  • 如何从一组 N 个对象中选择 n 个对象,最大化它们之间的成对距离之和

    您有一组 N 400 个对象 每个对象在 19 维空间中都有自己的坐标 您计算 欧几里德 距离矩阵 所有成对距离 现在您想要选择 n 50 个对象 使得所选对象之间所有成对距离的总和最大 我设计了一种通过线性编程来解决这个问题的方法 下面的
  • 如何使用完成处理程序将图像放入 SwiftUI 视图中

    我已经尝试过这个 但我不知道如何在 SwiftUI 视图中使用结果 func getProfilePicture completion escaping UIImage gt Void Alamofire request GIDSignIn
  • 关于如何构建 HTML Diff 工具的建议?

    In 这个帖子 https stackoverflow com questions 48669 are there any tools out there to compare the structure of 2 web pages我问是
  • SQL Server 进程队列竞争条件

    我有一个订单队列 多个订单处理器通过存储过程访问该队列 每个处理器都会传递一个唯一的 ID 该 ID 用于锁定接下来的 20 个订单以供自己使用 然后 存储过程将这些记录返回给订单处理器以进行操作 有些情况下多个处理器能够检索相同的 Ord
  • MYSQL限制特定列值的出现次数

    从数据库中提取一些优惠券 每张优惠券都有一个merchantid包含优惠券所属商家 ID 的列 我正在尝试构建一个提取 5 张优惠券的查询 但我只想要每张 1 张优惠券merchantid 我不想要多张相同的优惠券merchantid 你可
  • strtol 重用参数

    该代码似乎按预期工作 使用单个指针填充数字数组 include
  • 您可以指定嵌入 IPython 后运行的命令吗?

    打电话时IPython embed 是否可以给它一个命令或魔术函数来在嵌入发生后运行 我想运行这样的东西 import IPython IPython embed command pylab qt4 我当前的解决方法是将命令字符串复制到剪贴
  • 在 boost::spirit 语法中翻转规则内的子规则顺序会导致段错误

    警告 虽然我试图将代码缩短到最少 我仍然需要包含相当多的内容 以确保提供所需的信息 该代码编译文件并运行 导致语法错误 name simple name qi val qi 1 qualified name qi val qi 1 虽然这
  • 将前导零填充到公共宽度[重复]

    这个问题在这里已经有答案了 我正在处理具有小时格式的数据库 例如 HOUR ID 1 2 10 4 5 6 20 6 我想在 1 个字符的值中放置一个零 并将它们存储在名为 NHOUR 的新列中 例如 NHOUR HOUR ID 01 1
  • 如何以角度从一个组件打开模态到另一个组件?

    我创建模态模态组件并在 modal component html 文件中编码我的模态 我想在标头组件的 header component html 文件中使用此模式 我的 header component html 的相关部分如下 div
  • 可以从 http(javascript 客户端)直接向 Amazon SQS 发送请求吗?

    是否可以直接从 JavaScript 向 Amazon 的 SQS 发送消息请求 我正在尝试创建一个日志系统 并且希望绕过将请求发送到中间人服务器 另外 有人知道我可以利用这个解决方案的任何替代方案吗 SQS 事实上所有 aws 服务 都公
  • SQL 内连接。 ON 条件与 WHERE 子句

    我正忙于将使用旧样式语法的查询转换为新的联接语法 我的查询的实质如下 原始查询 SELECT i FROM InterestRunDailySum i InterestRunDetail ird InterestPayments p WHE
  • 对动态大小的对象进行排序

    Problem 假设我有一个包含一些数据的大字节数组 最多 4GB 这些字节对应于不同的对象 使得每个s字节 认为 s 最多 32 将构成单个对象 一个重要的事实是这个尺寸s对于所有对象都是相同的 不存储在对象本身中 并且在编译时不知道 目
  • 如何设置 BufferedImage 中的 RGB 像素以显示 16 位深度的 PNG?

    我正在尝试读取并显示 PNG 文件 我处理 8 位深度的图像没有问题 我按如下方式进行 BufferedImage result new BufferedImage width height BufferedImage TYPE INT R