24位真彩色图像转换为16位高彩色图像的实现方法及效果改进

本篇博文来自博主Imageshop,打赏或想要查阅更多内容可以移步至Imageshop。

转载自:https://www.cnblogs.com/Imageshop/p/3453569.html   侵删

一、前言     

     高彩色位图像即我们常说16位图像,每个像素占用两个字节,相比于24位真彩色来说,在保持一定的图像质量的前提下可以节省1 /3的内存空间,在游戏编程中以及一些移动设备上常使用这种格式,一般PC机上似乎很少涉及,因此这方面的资料也不是特别多。

     真彩色转换为高彩色是一个信息量降低的过程,如果使得整个信息量的损失降低到最少(特别是对人眼来说),基本上没有引起什么人的注意,包括一些世界一流的图像软件的最新版本,也没有在这个方面下工夫,而更多的图像软件则是没有这个功能,比如PS CS6的转换效果就不尽人意:

     

     

              原图                                PS转换后的结果(博客园不支持BMP ,使用PNG上传的)

  请睁大眼睛仔细观察上面的右图,可以看到在天空等颜色比较单调的位置会有明显的纹理出现,原图可是没有的,而这种瑕疵的出现对于诸如游戏这类会有大量相似区域出现的图片来说是个致命的弱点。因此研究如何改进效果是有重要意义的。     

二、实现

     要实现真彩色转换为高彩色,比如常用R5G5B5格式,我们只需要取原先的各颜色分量的高5位充当新的颜色分量就可以了,但是,涉及到如何把这些数据保存到文件,则需要一番努力。

     首先,我们需要注意的是16位BMP也有多种格式,PS中为我们列举了X1R5G5B5、R5G6B5、A1R5G5B5、X4R4G4B4、A4R4G4B4等,这些只是一些常用的组合罢了。实际上我们也可以自创一些格式,比如A3R4G5B4,只要相互之间的掩码不相互重合就可以了。

     16位BMP在结构上与其他的几种位深的BMP有一定的不同,他是由以下几个部分组成的:

       BITMAPFILEHEADER

       BITMAPINFOHEADER

       BITMASK

       IMAGEDATA

     这里的BITMASK是24位或8位以下色所没有的,他表明了后面的数据部分各颜色分量所使用的蒙版。值得注意的是, X1R5G5B5是个特例,他没有BITMASK部分的数据,并且其位图信息结构中的biCompression为BI_RGB,而其他几种格式都为BI_bitfields。还有一点就是X1R5G5B5的文件头的biSize为40,其他的都为56。

     为了操作方便,在我们转换真彩色图像时,我们定义一个合适大小的integer数组(VB6下),按照不同的子格式把真彩色的3中颜色分量合成到一个integer中,这里我们简单的以R5G5B5为例说明一下。

      比如原始的R=45、G=129、B=234,我们分别取各颜色分量的高五位部分,在VB6中要实现这个过程可以用一下语句实现:

NewR=R And &HF8
NewG=G And &HF8
NewB=B And &HF8

  &HF8的二进制展开形式为11111000,和我们的原始颜色进行或操作则可以得到高五位分量。

     注意,由于VB的变量在内存中的位置存放的特殊性,我们需要把B5部分的数据放在integer变量的低5位,G5居中,R5为最高位。这里的变量合成可以用逻辑运算符OR实现,即:

Integer= (NewB \ 8)  Or  (NewG * 4)  Or  (NewR * 128)

  VB中没有移位运算符,因此左移只能用乘法代替,右移用右除来代替,开启高级优化这些会被优化为移位的。

     遍历彩色图像中的每一个像素,用上述算法计算对应的integer值,则得到R5G5B5格式所需要的图像数据。

     由于VB中除了byte类型外,没有其他无符号数据类型,因此对于R5G6B5这种利用了最高位的格式处理时,一定要小心。当我们计算出NewR的最高位的值为1时,如果直接把他用OR运算合成到integer中,则生成的integer在VB中表示的为负数了。因此要把这一位作为特殊情况予以处理。

     如果直接按照上述方式写入图像数据,对于颜色丰富的图像转换的图像在清晰度的降低上是不明显的。但是对于游戏编程中常见到的天空、大海之类的有着较为平滑过渡的渐变区域图像来说,结果可能惨不忍睹。弥补这个缺点的方法就是利用抖动,最常用的方式就是误差扩散以及顺序抖动,误差扩散算法通过将误差传递到周围像素而减轻其造成的视觉误差,这有利于提高图像的可视性。

     抖动在真彩色转换为索引色或者索引色转换为Bitmap模式时,最为常用,把他引入到真彩色转换为高彩色似乎就没有什么记录,这里就涉及到一个问题,如何确定这个误差的计算方式。

     在真彩色转换为索引色时,针对每一个像素点,所谓的误差是类似于以下的计算:

Entry = GetNearestPaletteIndex(Palette,RGB(ImageDataC(Speed+2),ImageDataC(Speed+1),ImageDataC(Speed))
ErrB = ImageDataC(Speed) + 0& - Palette(Entry).Blue
ErrG = ImageDataC(Speed + 1) + 0& - Palette(Entry).Green
ErrR = ImageDataC(Speed + 2) + 0& - Palette(Entry).Red
    GetNearestPaletteIndex是用于计算和原始颜色值最为相似的颜色在颜色表中索引的一个方法,ImageDataC(Speed)为原始像素的Blue值,Palette(Entry).Blue则是直接查找到的映射值,这两个值之间的差异,即误差,这个按照一定的规则向某一个方向传递到原始的颜色信息中,比如常用的传播方式有如下一些(*的位置表示当前像素,一般都是向右下角传播的):
   *2           *3             *7
1  1  0  /4      0  3  2   /8       3  5  1  /16

  以第三组为例,则对应的Blue值的传播的相关参考代码如下所示:

复制代码

NewB = ImageDataC(Speed) + 7 * ErrB \ 16                        ' 当前位置
ImageDataC(Speed) = (NewB And (NewB >= 0) Or (NewB >= 256)) And &HFF
NewB = ImageDataC(Speed + Stride - 3) + 3 * ErrB \ 16           ' 下一行左侧
ImageDataC(Speed + Stride - 3) = (NewB And (NewB >= 0) Or (NewB >= 256)) And &HFF
NewB = ImageDataC(Speed + Stride) + 5 * ErrB \ 16               ' 下一行正中
ImageDataC(Speed + Stride) = (NewB And (NewB >= 0) Or (NewB >= 256)) And &HFF
NewB = ImageDataC(Speed + Stride + 3) + ErrB \ 16               ' 下一行右侧
ImageDataC(Speed + Stride + 3) = (NewB And (NewB >= 0) Or (NewB >= 256)) And &HFF

复制代码

  其中的(NewB And (NewB >= 0) Or (NewB >= 256)) And &HFF代码是用将值现在在0到255之间的快速方法。

     这样将误差就传递到了ImageDataC中,在求下一个像素的Entry时就会受到前面的误差的影响。

     在真彩色转换为高彩色的过程,其基本的过程和上述其实是完全一样的,只是这个误差的描述会有所区别,很直观的,我们将在此情况下的误差定义为:

复制代码

Blue = ImageDataC(Speed) And &HF8
Green = ImageDataC(Speed + 1) And &HF8
Red = ImageDataC(Speed + 2) And &HF8
ErrB = ImageDataC(Speed) - Blue
ErrG = ImageDataC(Speed + 1) - Green
ErrR = ImageDataC(Speed + 2) - Red

复制代码

  OK,其他的过程请模仿常规的操作了吧,就这么简单。

三、效果

  就是经过这么简单的设计和处理,效果会有很大的改善,同样的对于上面的图像,依旧采用X1R5G5B5格式,和PS的处理的相比效果如下:

      

      

  经过处理的图片和原始的相比基本看不出有什么大的差异了。

四、关于16位图像的其他说明

     看到有人在帖子说在读取16位格式的图像时也要进行抖动,这是一个很大的错误,对于图像,如果他的数据一定,那么应该说不管你什么读图软件去读他,显示的结果应该是一样的,如果在读的时候有抖动,那如果大家利用的抖动算法不一致,结果也就不一致,这是明显的矛盾。其实在读的时候,就是一个量化的过程,比如我读取的某点的红色分量的2进制 表示为10110,对应十进制为22,则在显示器上输出的颜色即为22*8*255/248,解释下:这里成8表示左移三位,246的由来是因为11111000表示的十进制数。*255表示量化到0到255之间。

     如果要显示不同格式的16位的图像数据,其实也很简单,有两中方法,第一,是修改CreateDIBSection函数的一个参数类型pBitmapInfo ,把这个默认参数BITMAPINFO修改为BITMAPV4HEADER,这个结构是比较新的BMP信息头,我们稍微修改他的一些成员结构,即修改为如下形式:

复制代码

Private Type BITMAPV4HEADER
    Size                As Long
    Width               As Long
    Height              As Long
    Planes              As Integer
    BitCount            As Integer
    Compression         As Long
    SizeImage           As Long
    XPelsPerMeter       As Long
    YPelsPerMeter       As Long
    ClrUsed             As Long
    ClrImportant        As Long
    RedMask             As Long
    GreenMask           As Long
    BlueMask            As Long
    AlphaMask           As Long
End Type

复制代码

     和BITMAPINFO结构相比,他只是多了几个蒙版成员,如果我们实现知道了我们要创建的16位图像的格式,则填充入对应的mask数据,然后在创建DIBSection,显示的时候直接调用Bitblt函数就可以。

     第二种方法依旧是在创建DIBSection时,使用修改后的结构体参数,但不填充mask内容,在显示的时候在修改mask,然后调用SetDIBitsToDevice 函数来显示他,当然也要修改SetDIBitsToDevice 的对应的那个参数声明,这种方法实用于先创建一个空白的16位图像,然后由其他高彩色图像向这个空白图像填充数据的情况。

     另外一个现象就是:16位的R5G6B5X4R4G4B4格式XP自带的图片和传真查看器打不开,windows自带的画图板确可以打开,windows也不知道是如何考虑的。

五、参考资料

  http://blog.csdn.net/yangdelong/archive/2008/04/26/2330748.aspx

  http://www.pscode.com/vb/scripts/ShowCode.asp?txtCodeId=42376&lngWId=1  

      http://www.vbaccelerator.com/home/vb/code/vbMedia/Image_Processing/Floyd-Stucci_Colour_Reduction_Methods_and_Gray_Scaling/article.asp

 六、转换用工具

      这么好的效果,当然得给大家一个转换工具了: 真彩色转高彩色

   

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在现有省、市港口信息化系统进行有效整合基础上,借鉴新 一代的感知-传输-应用技术体系,实现对码头、船舶、货物、重 大危险源、危险货物装卸过程、航管航运等管理要素的全面感知、 有效传输和按需定制服务,为行政管理人员和相关单位及人员提 供高效的管理辅助,并为公众提供便捷、实时的水运信息服务。 建立信息整合、交换和共享机制,建立健全信息化管理支撑 体系,以及相关标准规范和安全保障体系;按照“绿色循环低碳” 交通的要求,搭建高效、弹性、高可扩展性的基于虚拟技术的信 息基础设施,支撑信息平台低成本运行,实现电子政务建设和服务模式的转变。 实现以感知港口、感知船舶、感知货物为手段,以港航智能 分析、科学决策、高效服务为目的和核心理念,构建“智慧港口”的发展体系。 结合“智慧港口”相关业务工作特点及信息化现状的实际情况,本项目具体建设目标为: 一张图(即GIS 地理信息服务平台) 在建设岸线、港口、港区、码头、泊位等港口主要基础资源图层上,建设GIS 地理信息服务平台,在此基础上依次接入和叠加规划建设、经营、安全、航管等相关业务应用专题数据,并叠 加动态数据,如 AIS/GPS/移动平台数据,逐步建成航运管理处 "一张图"。系统支持扩展框架,方便未来更多应用资源的逐步整合。 现场执法监管系统 基于港口(航管)执法基地建设规划,依托统一的执法区域 管理和数字化监控平台,通过加强对辖区内的监控,结合移动平 台,形成完整的多维路径和信息追踪,真正做到问题能发现、事态能控制、突发问题能解决。 运行监测和辅助决策系统 对区域港口与航运业务日常所需填报及监测的数据经过科 学归纳及分析,采用统一平台,消除重复的填报数据,进行企业 输入和自动录入,并进行系统智能判断,避免填入错误的数据, 输入的数据经过智能组合,自动生成各业务部门所需的数据报 表,包括字段、格式,都可以根据需要进行定制,同时满足扩展 性需要,当有新的业务监测数据表需要产生时,系统将分析新的 需求,将所需字段融合进入日常监测和决策辅助平台的统一平台中,并生成新的所需业务数据监测及决策表。 综合指挥调度系统 建设以港航应急指挥中心为枢纽,以各级管理部门和经营港 口企业为节点,快速调度、信息共享的通信网络,满足应急处置中所需要的信息采集、指挥调度和过程监控等通信保障任务。 设计思路 根据项目的建设目标和“智慧港口”信息化平台的总体框架、 设计思路、建设内容及保障措施,围绕业务协同、信息共享,充 分考虑各航运(港政)管理处内部管理的需求,平台采用“全面 整合、重点补充、突出共享、逐步完善”策略,加强重点区域或 运输通道交通基础设施、运载装备、运行环境的监测监控,完善 运行协调、应急处置通信手段,促进跨区域、跨部门信息共享和业务协同。 以“统筹协调、综合监管”为目标,以提供综合、动态、实 时、准确、实用的安全畅通和应急数据共享为核心,围绕“保畅通、抓安全、促应急"等实际需求来建设智慧港口信息化平台。 系统充分整合和利用航运管理处现有相关信息资源,以地理 信息技术、网络视频技术、互联网技术、移动通信技术、云计算 技术为支撑,结合航运管理处专网与行业数据交换平台,构建航 运管理处与各部门之间智慧、畅通、安全、高效、绿色低碳的智 慧港口信息化平台。 系统充分考虑航运管理处安全法规及安全职责今后的变化 与发展趋势,应用目前主流的、成熟的应用技术,内联外引,优势互补,使系统建设具备良好的开放性、扩展性、可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值