bitmap详解bitmaps
大家好,今天小编来为大家解答以下的问题,关于bitmap详解,bitmaps这个很多人还不知道,现在让我们一起来看看吧!
本文目录
如何制作Bitmap(bmp)文件iOS图形学(二):bitmap位图详解Android Bitmap理解Bitmap使用详解如何制作Bitmap(bmp)文件注:本文参考了林福宗老师的有关BMP文件格式的文章,在此声明。
简介
BMP(Bitmap-File)图形文件是Windows采用的图形文件格式,在Windows环境下运行的所有图象处理软件都支持BMP图象文件格式。Windows系统内部各图像绘制操作都是以BMP为基础的。Windows3.0以前的BMP图文件格式与显示设备有关,因此把这种BMP图象文件格式称为设备相关位图DDB(device-dependentbitmap)文件格式。Windows3.0以后的BMP图象文件与显示设备无关,因此把这种BMP图象文件格式称为设备无关位图DIB(device-independentbitmap)格式(注:Windows3.0以后,在系统中仍然存在DDB位图,象BitBlt()这种函
数就是基于DDB位图的,只不过如果你想将图像以BMP格式保存到磁盘文件中时,微软极力推荐你以DIB格式保存),目的是为了让Windows能够在任何类型的显示设备上显示所存储的图象。BMP位图文件默认的文件扩展名是BMP或者bmp(有时它也会以.DIB或.RLE作扩展名)。6.1.2文件结构
位图文件可看成由4个部分组成:位图文件头(bitmap-fileheader)、位图信息头(bitmap-informationheader)、彩色表(colortable)和定义位图的字节阵列,它具有如下所示的形式。
位图文件的组成结构名称符号
位图文件头(bitmap-fileheader)BITMAPFILEHEADERbmfh
位图信息头(bitmap-informationheader)BITMAPINFOHEADERbmih
彩色表(colortable)RGBQUADaColo
rs[]图象数据阵列字节BYTEaBitmapBits[]
位图文件结构可综合在表6-01中。
表01位图文件结构内容摘要
偏移量域的名称大小内容
图象文件
头0000h文件标识2bytes两字节的内容用来识别位图的类型:
‘BM’:Windows3.1x,95,NT,…
‘BA’:OS/2BitmapArray
‘CI’:OS/2ColorIcon
‘CP’:OS/2ColorPointer
‘IC’:OS/2Icon
‘PT’:OS/2Pointer
注:因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识“BM”就行。
0002hFileSize1dword用字节表示的整个文件的大小
0006hReserved1dword保留,必须设置为0
000AhBitmapDataOffset1dword从文件开始到位图数据开始之间的数据(bitmapdata)之间的偏移量
000EhBitmapHeaderSize1dword位图信息头(BitmapInfoHeader)的长度,用来描述位图的颜色、压缩方法等。下面的长度表示:
28h-Windows3.1x,95,NT,…
0Ch-OS/21.x
F0h-OS/22.x
注:在Windows95、98、2000等操作系统中,位图信息头的长度并不一定是28h,因为微软已经制定出了新的BMP文件格式,其中的信息头结构变化比较大,长度加长。所以最好不要直接使用常数28h,而是应该从具体的文件中读取这个值。这样才能确保程序的兼容性。
0012hWidth1dword位图的宽度,以象素为单位
0016hHeight1dword位图的高度,以象素为单位
001AhPlanes1word位图的位面数(注:该值将总是1)
图象
信息
头
001ChBitsPerPixel1word每个象素的位数
1-单色位图(实际上可有两种颜色,缺省情况下是黑色和白色。你可以自己定义这两种颜色)
4-16色位图
8-256色位图
16-16bit高彩色位图
24-24bit真彩色位图
32-32bit增强型真彩色位图
001EhCompression1dword压缩说明:
0-不压缩(使用BI_RGB表示)
1-RLE8-使用8位RLE压缩方式(用BI_RLE8表示)
2-RLE4-使用4位RLE压缩方式(用BI_RLE4表示)
3-Bitfields-位域存放方式(用BI_BITFIELDS表示)
0022hBitmapDataSize1dword用字节数表示的位图数据的大小。该数必须是4的倍数
0026hHResolution1dword用象素/米表示的水平分辨率
002AhVResolution1dword用象素/米表示的垂直分辨率
002EhColors1dword位图使用的颜色数。如8-比特/象素表示为100h或者256.
0032hImportantColors1dword指定重要的颜色数。当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要
调色板数据根据BMP版本的不同而不同PaletteN*4byte调色板规范。对于调色板中的每个表项,这4个字节用下述方法来描述RGB的值:1字节用于蓝色分量
1字节用于绿色分量
1字节用于红色分量
1字节用于填充符(设置为0)
图象数据根据BMP版本及调色板尺寸的不同而不同BitmapDataxxxbytes该域的大小取决于压缩方法及图像的尺寸和图像的位深度,它包含所有的位图数据字节,这些数据可能是彩色调色板的索引号,也可能是实际的RGB值,这将根据图像信息头中的位深度值来决定。
构件详解
1.位图文件头
位图文件头包含有关于文件类型、文件大小、存放位置等信息,在Windows3.0以上版本的位图文件中用BITMAPFILEHEADER结构来定义:
typedefstructtagBITMAPFILEHEADER{/*bmfh*/
UINTbfType;
DWORDbfSize;
UINTbfReserved1;
UINTbfReserved2;
DWORDbfOffBits;
}BITMAPFILEHEADER;
其中:
bfType说明文件的类型.(该值必需是0x4D42,也就是字符'BM'。我们不需要判断OS/2的位图标识,这么做现在来看似乎已经没有什么意义了,而且如果要支持OS/2的位图,程序将变得很繁琐。所以,在此只建议你检察'BM'标识)
bfSize说明文件的大小,用字节为单位
bfReserved1保留,必须设置为0
bfReserved2保留,必须设置为0
bfOffBits说明从文件头开始到实际的图象数据之间的字节的偏移量。这个参数是非常有用的,因为位图信息头和调色板的长度会根据不同情况而变化,所以你可以用这个偏移值迅速的从文件中读取到位数据。
2.位图信息头
位图信息用BITMAPINFO结构来定义,它由位图信息头(bitmap-informationheader)和彩色表(colortable)组成,前者用BITMAPINFOHEADER结构定义,后者用RGBQUAD结构定义。BITMAPINFO结构具有如下形式:
typedefstructtagBITMAPINFO{/*bmi*/
BITMAPINFOHEADERbmiHeader;
RGBQUADbmiColors[1];
}BITMAPINFO;
其中:
bmiHeader说明BITMAPINFOHEADER结构,其中包含了有关位图的尺寸及位格式等信息
bmiColors说明彩色表RGBQUAD结构的阵列,其中包含索引图像的真实RGB值。
BITMAPINFOHEADER结构包含有位图文件的大小、压缩类型和颜色格式,其结构定义为:
typedefstructtagBITMAPINFOHEADER{/*bmih*/
DWORDbiSize;
LONGbiWidth;
LONGbiHeight;
WORDbiPlanes;
WORDbiBitCount;
DWORDbiCompression;
DWORDbiSizeImage;
LONGbiXPelsPerMeter;
LONGbiYPelsPerMeter;
DWORDbiClrUsed;
DWORDbiClrImportant;
}BITMAPINFOHEADER;
其中:
biSize说明BITMAPINFOHEADER结构所需要的字数。注:这个值并不一定是BITMAPINFOHEADER结构的尺寸,它也可能是sizeof(BITMAPV4HEADER)的值,或是sizeof(BITMAPV5HEADER)的值。这要根据该位图文件的格式版本来决定,不过,就现在的情况来看,绝大多数的BMP图像都是BITMAPINFOHEADER结构的(可能是后两者太新的缘故吧:-)。
biWidth说明图象的宽度,以象素为单位
biHeight说明图象的高度,以象素为单位。注:这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位图,还是正向的位图。如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,也就是时,高度值是一个正数。(注:当高度值是一个负数时(正向图像),图像将不能被压缩(也就是说biCompression成员将不能是BI_RLE8或BI_RLE4)。
biPlanes为目标设备说明位面数,其值将总是被设为1
biBitCount说明比特数/象素,其值为1、4、8、16、24、或32
biCompression说明图象数据压缩的类型。
iOS图形学(二):bitmap位图详解概念:所谓的BitMap算法就是用一个bit位来标记某个元素所对应的value;
举例:
现有40亿个整数,当给定一个新的整数时,判断新的整数在这40亿个数字中是否存在,假设该架构下整形为4个字节;
其实这个问题的性能点有两方面:
假设40E个整数存储在磁盘中,也就是40亿*4字节,约等于16GB。
假设系统运行内存为2GB,每次新来一个数字就循环加载16GB进入系统,和新的整数进行对比。
这种方法每次来一个新的数字进行判断时,因为内存不够用,每次都需要8次i/O操作,且数据量巨大(2GB),时间上会达到小时级别;
最久时间消耗:8次I/O+40E次对比运算;
改进方法1,使用8个2GB运行内存的电脑加载16GB的数据,这样只需要并行加载,相当于只加载一次的时间,然后8台计算机对比新的整数,最后对结果进行汇总;
此时,因为40E个整数都已经被加载进入了内存,每来一个新的数字进行对比时,不需要再进行I/O操作,只需要在8台机器中并行对比即可;
最久时间消耗:1次I/O(一次性)+40E/8次对比运算;
上述两种方法的计算消耗比较高,接下来可以使用位图算法来针对计算消耗进行优化。
int为4个字节,范围为:-2147483648~2147483647,也就是4294967296个数字。使用一个bit也就是一个二进制位来代表一个数字,那么需要4294967296/8/1024/1024/1024约等于0.5GB(bit->byte->kb->m->gb)。
也就是说,如果使用内存中一个二进制位来代表一个数字,那么只需要开辟0.5G的内存就可以表示所有的整数,此时将int类型的内存消耗转化成了BOOL类型的内存消耗,所以内存消耗缩小了32倍。
I/O消耗仍然无法避免,但是一个整数在内存中的占用小了32倍,只需要一台机器,且不用循环I/O了。在内存中开辟0.5G内存之后,只需要循环读取40亿个数字,然后再内存中对应的bit位进行标记,也就是标记为1,最后根据指定的整数,取出内存中偏移地址的比特位的值,如果为1则表示存在,否则反之。此时,计算消耗为1次;
最久耗时:1次I/O(一次性)+1次位运算;
用特定大小的内存空间来表示单个像素的色值,以逐行扫描的方式来来表示整张图片中所有的像素的色值;
在《计算机图形学基础第四版》中对bitmap的描述如下:
总结一下其观点,针对帧缓存(FrameBuffer)而言:
个人理解:其实,位图的概念已经没有那么拘泥于是否一定要使用1个比特位了。bitmap的概念就是使用矩阵的方式来表示整体数据,以此来减少数据大小(算法)或则是实现某一目的(raster)。当然,严谨一点更好,所以FrameBuffer最好描述为pixmap(像素图);
从纯数学的角度,任何一个面都由无数个点组成。但从生理角度而言,人类的肉眼无法区分很小的点。所以在实际应用中,我们没有必要用无数个点来表示一张图片,甚至都没有必要使用足够多的点,只需要让点的个数和大小在人眼能区分的极限之上一点点就好了,如此就能在清晰度和节约内存之间达到平衡。
其一,是因为太多点,人眼也看不出来差别,这就是很多人觉得2k、4k好像和1024*76
8并没有太大差别的原因。其二,使用无数点来表示一张图片是不可能的,使用很大数量的点是极其耗费资源的,性价比很低。
最终决定使用一定数量的点来表示一张图片,而这个点就是像素。而视频本质上时无数图片的连贯播放,因此像素成了图形科学的基础单位;
显示器成像基本上是逐行扫描,如图所示:
再根据上述的位图原理,位图算法可以极大节省空间或者是减少运算量。而像素的数量较多,假设有1024*768个像素点,像素点使用我们最常用的16进制RGB来表示颜色,一个像素点有256*256*256种可能。假设一个Int类型占4字节,也就是32bit,那么一个像素点占用的内存空间就是:32bit。而采用位图之后单个像素占用的存储空间为:8bit*3=24bit,节省的空间就是24bit*像素个数。
上述计算看上去节省的空间不大,甚至如果是ARGB的颜色,那么同样也是32bit,相比于使用4字节的int来存储,好像并没有太大优化,但是这里涉及到几个问题:
综上,所以最终采用位图的方式来表示像素点。
压缩会在后文中讨论,这里从色深就可以很直观的知道,8bit的图片必定没有32bit的图片颜色丰富。
还需要补充一个概念:通道
一般ARGB颜色就是4个通道,分别是透明度、R、G、B,每个通道都使用一定的位数来表示,比如ARGB_8888就是4通道,每条通道8bit。比如8bit的灰度颜色,只有黑白,属于单通道。
安卓中,使用Config表示每个像素点对ARGB通道值的存储方案:
ARGB_8888:每个通道值采8bit来表示,每个像素点需要4字节的内存空间来存储数据。该方案图片质量是最高的,但是占用的内存也是最大的;
ARGB_4444:每个通道都是4位,每
个像素占用2个字节,图片的失真比较严重。一般不用这种方案。RGB_565:这种方案RGB通道值分别占5、6、5位,但是没有存储A通道值,所以不支持透明度。每个像素点占用2字节,是ARGB_8888方案的一半。
ALPHA_8:这种方案不支持颜色值,只存储透明度A通道值,使用场景特殊,比如设置遮盖效果等。
比较分析:一般我们在ARGB_8888方式和RGB_565方式中进行选取:不需要设置透明度时,比如拍摄的照片等,RGB_565是个节省内存空间的不错的选择;既要设置透明度,对图片质量要求又高,就用ARGB_8888;
iOS中常见的颜色为三种:
上述三种颜色,在设置bitmapcontext中的颜色时,又分为不同参数设置:
cs:colorspace
bpp:bitperpixel
bpc:bitpercomponent
常量的含义:
颜色布局:
图片的存储一般有两种形式:未加载进内存和加载进内存后;内存中都是以bitmap方式表达,非内存中,可以是bitmap,也可以是各种压缩格式。其中,在内存中的bitmap格式称为实际大小;
特点:
特点:
图片格式一般有几种:
bitmap的大小为:
size=width*height*bpp(bitperpixel)
平常我们见到的图片都是被压缩过后的图片,所以其大小会比bitmap格式的图片大小小很多;但是PNG格式的图片被加载进内存之后会被还原成全量bitmap,所以这也是很多重度使用图片的app的一个优化方向;
图元文件并不是矢量图,因为它存储的并不是矢量信息。
它存储的是你在绘图的时候调用了哪些操作。
如果是位图文件记录了你的画布上每一点的颜色的话,
图元文件就是纪录的你如何下笔的。
bitmap最终数据,被加载到framebuffer(显存)后,直接由显示器加载数据并最终显示到屏幕上;
Android Bitmap理解参考:
AndroidBitmap详解:关于Bitamp你所要知道的一切
AndroidBitmap(位图)详解
图片是由大量且有限个数的像素点组成。把一张图片通过bitmap的方式创建到内存中,实际上就是在内存中创建了一个叫做Bitmap的对象,然后把图片所有像素解码后的数据存放在Bitmap对象里面,Bitmap就拥有了图片的宽高,透明度,颜色值等数据。所以Bitmap的创建是通过BitmapFactory.decodeXxx()。
Config是Bitmap类中的枚举类。像素由ARGB四个颜色通道组成。Config描述位图中像素的存储方式。这里的存储方式,无非就是对颜色通道和用多大的容器(bit)来存储的排列组合。所以config会影响图片透明度,占用内存大小,保存成文件的大小,图片质量。
Config的字母表示该配置存储的像素的颜色通道,数字表示对应通道的数据用多少位来存储。
ALPHA_8:表示只存储alpha通道,使用8bit(1字节)的内存(容器)来存储一个像素。
RGB_565:表示存储RGB三个通道,分别使用5bit,6bit,5bit的内存(容器)来存储一个像素。
ARGB_4444:表示存储ARGB四个通道,每个通道都是以4bit的内存(容器)来存储一个像素。
ARGB_8888:表示存储ARGB四个通道,每个通道都是以8bit的内存(容器)来存储一个像素。
所以,ARGB_8888配置占用内存最大,图片质量最高。
图片压缩的一个思路就是降低图片的配置。
总内存=宽的像素数×高的像素数×每个像素点占用的大小
注:
1byte=8bit
1KB=1024byte
Bitmap使用详解用到的图片不仅仅包括.png、.gif、.9.png、.jpg和各种Drawable系对象,还包括位图Bitmap
图片的处理也经常是影响着一个程序的高效性和健壮性。
为什么不直接用Bitmap传输?
位图文件虽好,但是非压缩格式,占用较大存储空间。
Bitmap主要方法有:获取图像宽高、释放,判断是否已释放和是否可修改,压缩、创建制定位图等功能
用于从不同的数据源(如文件、输入流、资源文件、字节数组、文件描述符等)解析、创建Bitmap对象
允许我们定义图片以何种方式如何读到内存。
推荐阅读:Android-Bitmap-内存分析
注意事项:
decodeFileDescriptor比decodeFile高效
查看源码可以知道
替换成
建议采用decodeStream代替decodeResource。
因为BitmapFactory.decodeResource加载的图片可能会经过缩放,该缩放目前是放在java层做的,效率比较低,而且需要消耗java层的内存。因此,如果大量使用该接口加载图片,容易导致OOM错误,BitmapFactory.decodeStream不会对所加载的图片进行缩放,相比之下占用内存少,效率更高。
这两个接口各有用处,如果对性能要求较高,则应该使用decodeStream;如果对性能要求不高,且需要Android自带的图片自适应缩放功能,则可以使用decodeResource。
推荐阅读:[BitmapFactory.decodeResource加载图片缩小的原因及解决方法
canvas和Matrix可对Bitmap进行旋转、放缩、平移、切错等操作
可以用Bitmap.onCreateBitmap、Canvas的clipRect和clipPath等等方式
推荐阅读:android自定义View学习4--图像剪切与变换
对初始化Bitmap对象过程中可能发生的OutOfMemory异常进行了捕获。如果发生了OutOfMemory异常,应用不会崩溃,而是得到了一个默认的Bitmap图。
如果不进行缓存,尽管看到的是同一张图片文件,但是使用BitmapFactory类的方法来实例化出来的Bitmap,是不同的Bitmap对象。缓存可以避免新建多个Bitmap对象,避免内存的浪费。
如果图片像素过大,使用BitmapFactory类的方法实例化Bitmap的过程中,需要大于8M的内存空间,就必定会发生OutOfMemory异常。
可以将图片缩小,以减少载入图片过程中的内存的使用,避免异常发生。
推荐阅读:
Bitmap详解与Bitmap的内存优化
OK,本文到此结束,希望对大家有所帮助。