文档章节

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

abcijkxyz
 abcijkxyz
发布于 2016/11/22 16:41
字数 2646
阅读 10
收藏 0
点赞 0
评论 0

     本文是对多年前作者的一篇博文的重新整理和书写。

一、前言     

     高彩色位图像即我们常说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

 六、转换用工具

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

   

 

 

*********************************作者: laviewpbt   时间: 2013.12.2   联系QQ:  33184777  转载请保留本行信息*************************

   

本文转载自:http://www.cnblogs.com/Imageshop/p/3453569.html

共有 人打赏支持
abcijkxyz
粉丝 60
博文 6195
码字总数 1876
作品 0
深圳
项目经理
bitmap图像介绍

典型的BMP图像文件由四部分组成:   1:位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息;   2:位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信...

技术小胖子 ⋅ 2017/11/14 ⋅ 0

PNG格式说明

2009年4月3日 PNG格式说明 PNG是20世纪90年代中期开始开发的图像文件存储格式,其目的是企图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。 流式网络图形格式(Portable N...

付翔 ⋅ 2009/05/23 ⋅ 0

PNG格式到底是什么?

PNG是20世纪90年代中期开始开发的图像文件存储格式,其目的是企图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。流式网络图形格式(Portable Network Graphic Format,PNG...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

图标编辑工具--IcoFX

IcoFX 是一款免费的图标编辑工具,让您轻松创建 Windows XP 和 Windows Vista 图标。 在编辑区您可以轻松的预览、保存、更改您的图标。您可以将您喜欢的图像转换为图标或图标转换为图像。内置...

匿名 ⋅ 2009/11/01 ⋅ 0

VC怎样把一副自己画的图存成BMP格式和在VC++下实现高彩色工具条

VC怎样把一副自己画的图存成BMP格式 原文链接:http://blog.csdn.net/sunboy_2050/article/details/4991265

长平狐 ⋅ 2013/01/06 ⋅ 0

数据压缩原理与应用 图像文件的读写和转换(BMP2YUV)实验报告

一、实验原理 1.BMP文件的组成结构 BMP(全称 Bitmap )是Windows操作系统中的标准图像文件格式 ,可以分成两类:设备相关位图(DDB )和设备无关位图( DIB),使用非常广。它采用位映射存...

zgyggy ⋅ 2017/03/22 ⋅ 0

FRAMEBUFFER 显示原理及RGB显示

framebuffer / 像素深度 / 颜色深度 / RGB565 1, framebuffer相关的. framebuffer的可变的信息就是指Framebuffer的长度、宽度以及颜色深度等信息。这两个命令字相关的结构体有两个:struct ...

czg13548930186 ⋅ 03/26 ⋅ 0

PNG图片文件结构分析

PNG,JPEG,GIF,BMP作为数据压缩文件,有许多重要的信息我们需要区深度解析。 一.PNG的文件结构 1.1数据块构成结构 PNG文件结构很简单,主要有数据块(Chunk Block)组成,最少包含4个数据块。...

IamOkay ⋅ 2016/12/07 ⋅ 0

GIF/PNG/JPG和WEBP/base64/apng图片优点和缺点整理

 GIF/PNG/JPG/WEBP/APNG都是属于位图(位图 ,务必区别于矢量图);  GIF/PNG和JPG这三种格式的图片被广泛应用在现今的互联网中,gif曾在过去互联网初期慢速的情况下几乎是做到了大一统的地位...

凡尘里的一根葱 ⋅ 2015/10/01 ⋅ 0

Landsat7 ETM+数据使用ENVI进行融合(超详细傻瓜教程)

一、前言 前段时间由于项目的原因,需要15m的遥感数据,因此想到将landsat7的30m的数据通过融合得到15m的。本以为按照网上ENVI的融合教程就可以达到目的,但哪想,融合的数据彩色合成失真、呈...

fengwen2011 ⋅ 2017/03/12 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 32分钟前 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 40分钟前 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 46分钟前 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 56分钟前 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

容器之查看minikue的environment——minikube的环境信息

执行如下命令 mjduan@mjduandeMacBook-Pro:~/Docker % minikube docker-envexport DOCKER_TLS_VERIFY="1"export DOCKER_HOST="tcp://192.168.99.100:2376"export DOCKER_CERT_PATH="/U......

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

mysql远程连接不上

设置了root所有hosts远程登录,可是远程登录还是失败,原因可能如下: 登录本地数据库 mysql -uroot -p123456 查询用户表 mysql> select user,host,password from mysql.user; 删除密码为空的...

冰公子 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部