文档章节

简单而又快速的获取一副真彩色图像实际使用的颜色数。

abcijkxyz
 abcijkxyz
发布于 2016/11/22 16:40
字数 1466
阅读 1
收藏 0

  一副真彩色图像,最多可能使用的颜色数为256*256*256=16777216种,但是通常情况下绝对不会有如此之多,因为即使图像中每个像素颜色都不相同,也至少需要4096×4096大小的图,这么大小的图对目前的数码相机来说也不普遍。因此,在现实中一副颜色很丰富的彩色图像,其使用的不同颜色数一般都不会超过100万。本文介绍一种简单而又快速的统计这个数据的方法。

      一种最简单而又直接的方式就是定义一个含有16777216个元素的数组,然后循环整幅位图,对位图某处对应的颜色值,计算数组的索引,计算方式有很多种,比如:

      Index = Red + Green *  256 + Blue *  65536

      如果该位置的数组的值为0,则修改为1,同时计数器增加1;如果为1,说明图像中之前已经存在该颜色,不做任何处理,直接处理下一个像素。

      因为我们只需要记录0和1两种状态,因此布尔变量是比较合适的,不过有些语言,比如VB6,布尔类型是占用两个字节的。一般的编程语言中最小的数据类型都是Byte,即一个字节,因此,16777216个最少需要占用16MB的内存。简单示意代码如下:

 1      Dim Flag( 16777215As  Byte
 2      For Y =  0  To m_Height -  1
 3         Speed = Y * m_Stride             ' 移动到下一行首个像素
 4          For X =  0  To m_Width -  1
 5             Index = ImageData(Speed +  2) + ImageData(Speed +  1) *  256& + ImageData(Speed) *  65536    ' 计算索引
 6              If Flag(Index) =  0  Then      ' 如果之前没有出现过该颜色值
 7                 Flag(Index) =  1          ' 该颜色值已经出现
 8                 Count = Count +  1        ' 计数加1
 9              End  If
10             Speed = Speed +  3            ' 移动到下一个像素
11          Next
12      Next

      这个代码很简单,也很容易明白,不过令人不是很满意是16MB内存的占用,对于一副3000×4000的图像来说,也许没啥概念,可如果本身是一副300×400的图呢,这个内存比图本身占用的内存还大很多,因此,我们试图对这个方面进行适当的改良。

      改良的方式也是很简单,也许大家都能想得到:既然每种颜色只有0和1两种状态,那为何不用位来记录该颜色是否存在过呢。基于这个想法,我们的数组大小就可以修改成16777216/8=2097152字节,即2MB大小。
      这样做的好处内存占用量减少为原先的1/8,坏处就是访问位信息要比直接访问字节困难。不过有这么大的内存占用优势,困难是值得的。

      首先,我们要定位某个颜色值在我们新定义的数组中对应的索引BytePos,这个没有问题,直接除以8就可以了,8非常特殊,除以8可以优化为右移3位,右移是高效的运算符,很好。

      接着,我们要得到需要访问BytePos索引对应的字节的第几位。第几位,很简单,就是颜色值的原始索引(Index变量)对8进行取余运算而已,可惜,取余运算符是个耗时的运算符,但同样可幸,是对8取余,And运算符能帮我们解决。对8取余就是对7进行And运算: Index mod 8 == Index And 7 。 8我爱你。

      下一步,没啥好说的了,判断该位是否为0啊,这里我们还是借用And运算,用该位的位置对应的特殊数据进行按位和运算,如果运算后的结果为0,则表示该颜色没有存在过,改变状态,并且将其改为1,改为1的方式加上我们的特殊数据即可,同时计数器加1,;如果不为0(不用管他为多少),则不用做任何处理了。

      我们简单的看下实现的代码:

 1      Dim Flag( 2097151)    As  Byte
 2      Dim Pow2( 7)          As  Long
 3      Dim BitPos           As  Long
 4      Dim BytePos          As  Long
 5      For Y =  0  To  7
 6         Pow2(Y) =  2 ^ ( 7 - Y)
 7      Next
 8      For Y =  0  To m_Height -  1
 9         Speed = Y * m_Stride                                     ' 移动到下一行首个像素
10          For X =  0  To m_Width -  1
11             Index = ImageData(Speed +  2) + ImageData(Speed +  1) *  256& + ImageData(Speed) *  65536    ' 计算索引
12             BytePos = Index \  8                                  ' 计算索引对应的字节位置
13             BitPos = Index  And  7                                 ' 计算索引对应的位的位置
14              If (Flag(BytePos)  And Pow2(BitPos)) =  0  Then         ' 判断改位是否为1
15                 Flag(BytePos) = Flag(BytePos) + Pow2(BitPos)     ' 不为1,则修改为1
16                 Count = Count +  1                                ' 计数器增1
17              End  If
18             Speed = Speed +  3                                    ' 移动到下一个像素
19          Next
20      Next

 

   注意,这里的列出的是VB的代码,实际上 ImageData(Speed + 1) * 256&这种表达式在勾选上高级优化时编译器会自动编译为左移8位的,而 Index \ 8则会优化为Index>>3,因此,速度上不会和其他有这些运算符的语言有差别。当然,如果直接用类似VC的语言,请直接使用这些运算符。

      关于那个Pow2数组的使用,我感觉我自己表达能力有限,为什么有那种效果,其实明白人还是一看就知道的。在这就不多言了。

      两种方式,在我自己的本机上编译后,居然是后一种算法的速度快一些,这个除了是分配内存时使用的使用的时间稍微少些外,其他的实在是不明白,也许和内存的访问之类有关吧,我对这方面了解粗浅,还烦请有兴趣的高手指点。

 

 

 

 

 

本文转载自:http://www.cnblogs.com/Imageshop/archive/2011/12/07/2279883.html

共有 人打赏支持
abcijkxyz
粉丝 60
博文 6196
码字总数 1876
作品 0
深圳
项目经理
[非原创] 用于将真彩色图像降级为索引图像的八叉树算法

    本文介绍的内容,是用八叉树法降级一个真彩色图像(BPP=16以上)。这也是某公司在今年校园招聘中的笔试中的最后一道题目。我参考了 Jeff Prosise 所写的这篇文章(见参考资料),然后...

hoodlum1980
2010/10/27
0
0
bitmap图像介绍

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

技术小胖子
2017/11/14
0
0
CreateDIBSection和位图结构

理解分辨率 我们常说的屏幕分辨率为640×480,刷新频率为70Hz,意思是说每行要扫描640个象素,一共有480行,每秒重复扫描屏幕70次。 理解调色板 有一个长宽各为200个象素,颜色数为16色的彩色...

姿势喵
02/06
0
0
PNG图片文件结构分析

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

IamOkay
2016/12/07
1K
0
PNG格式说明

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

付翔
2009/05/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

谷歌 Fuchsia 上手体验,将取代Android/win10

在手机市场领域,Google表现很抢眼,毫无疑问,Android 至今在移动操作系统的市场份额占据绝对领先地位,但是 Android 仍然存在不少问题,碎片化问题严重,在平板以及大屏幕设备上表现糟糕,...

linux-tao
24分钟前
1
0
List、Array与ArrayList

数组在内存中是连续存储的,所以它的索引速度很快,而且赋值和修改元素也非常快,比如: string[] s=new string[3];//赋值 s[0]="a"; s[1]="b"; s[2]="c";//修改 s[1]="b1"; 但是数组...

shimmerkaiye
26分钟前
0
0
Linux 的Lnmp环境下为mysql添加环境变量

一.问题 在Linux 安装完Lnmp 环境后 , 连接Mysql 告诉没有这条命令 mysql -uroot -p 命令失效 因为是源码安装的,所以会出现这样的的原因 。集成环境是不会出现的。 其实很简单,只需要给m...

15834278076
28分钟前
3
0
apolloxlua include函数

include函数不是单独使用的函数, 他并不是标准库的一部分, 你可以使用include函数将某个后缀为 .aop的文档包含到你的文档流中。 因为include是单独处理流, 所以不会在主处理流程中有所表示...

钟元OSS
32分钟前
0
0
【转载分享】做一名较真的工程师

近些年与我共事过的同事,一定知道我至今仍有一个较真的性格。我会:指出同事所写代码的不当命名问题(并帮助改进);指出同事所写文档中的逻辑混乱问题(并辅以修订);指出同事所写PPT中乱...

HellerZhang
34分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部