BMP图片格式详细解析--以256色为例还原256色BMP图像数据

news/2024/12/27 16:05:17/

256色bmp图像还原记录:

通过分析bmp图片的格式,可以完成BMP图片的打开和保存

一、bmp格式:

典型的 BMP 图像文件由四部分组成:

1 . 位图文件头数据结构 ,它包含 BMP 图像文件的类型、显示内容等信息;

2 . 位图信息数据结构 ,它包含有 BMP 图像的宽、高、压缩方法,以及定义颜色等信息;

   3. 调色板 ,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图( 24 位的 BMP )就不需要调色板;

4 . 位图数据 ,这部分的内容根据 BMP 位图使用的位数不同而不同,在 24 位图中直接使用 RGB ,而其他的小于 24 位的使用调色板中颜色索引值。

① BMP 文件头 (14 字节 )

BMP 文件头数据结构含有 BMP 文件的类型、文件大小和位图起始位置等信息 。 其结构定义如下 :

int bfType ; // 位图文件的类型,必须为 ' B '' M ' 两个字母 (0-1 字节 )

int bfSize ; // 位图文件的大小,以字节为单位 (2-5 字节 )

int bfReserved1 ; // 位图文件保留字,必须为 0(6-7 字节 )

int bfReserved2 ; // 位图文件保留字,必须为 0(8-9 字节 )

int bfOffBits ; // 位图数据的起始位置,以相对于位图 (10-13 字节 )

② 位图信息头 (40 字节 )

BMP 位图信息头数据用于说明位图的尺寸等信息。

int Size ; // 本结构所占用字节数 (14-17 字节 )

int image_width ; // 位图的宽度,以像素为单位 (18-21 字节 )

int image_heigh ; // 位图的高度,以像素为单位 (22-25 字节 )

int Planes ; // 目标设备的级别,必须为 1(26-27 字节 )

int biBitCount ; // 每个像素所需的位数,必须是或 1,4,8 24(// 真彩色 ) 之一 (28-29字节 )

int biCompression ; // 位图压缩类型,必须是 0( 不压缩 ), 1(BI_RLE8 压缩类型 ) 或// 2(BI_RLE4 压缩类型 ) 之一 (30-33 字节 )

int SizeImage ; // 位图 数据 的大小,以字节为单位 (34-37 字节 )

int biXPelsPerMeter ; // 位图水平分辨率,每米像素数 (38-41 字节 )

int biYPelsPerMeter ; // 位图垂直分辨率,每米像素数 (42-45 字节 )

int biClrUsed ; // 位图实际使用的颜色表中的颜色数 (46-49 字节 )

int biClrImportant ; // 位图显示过程中重要的颜色数 (50-53 字节 )

③ 颜色表

颜色表中 的个数有 biBitCount 来确定 。 当 biBitCount=1,4,8 时,分别有 2,16,256个颜色 ; 当 biBitCount=24 时,没有颜色表项。

在windows中每个颜色是 b g r a 四个字节保存,a代表透明度,如果是1位位图,那么颜色表一共站八个字节,如果是4位位图,颜色表站84个字节,如果是8位位图,需要表示256中颜色,每种颜色站四个字节,所以颜色表一共站1024个字节。

256色的时候,windows中,位图数据的大小就是0-255,代表着调色板中的数据,每次读八个为就是一个像素信息,其他位图类似。

④ 位图数据

位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右 , 扫描行之间是从下到上。位图的一个像素值所占的字节数 :

当 biBitCount=1 时, 8 个像素占 1 个字节 ;

当 biBitCount=4 时, 2 个像素占 1 个字节 ;

当 biBitCount=8 时, 1 个像素占 1 个字节 ;

当 biBitCount=24 时, 1 个像素占 3 个字节 ;

Windows 规定一个扫描行所占的字节数必须是 4 的倍数 ( 即以 long 为单位 ), 不足的以 0 填充,具体数据举例:

也就是说,写入图片一行的像素信息的时候,每一行的字节数都必须是4的倍数,不足的在后面补0,然后才又开始写入下一行的像素信息。

位图数据,其实就是在描述图片上每一个点的颜色,在windos中,是先写入该图片的最有一排像素点,从下往上,从左往右,没写完一排,如果写入的字节数不是4的倍数,就会补0,比如写入了3个字节,就不要再补一个字节的0,然后开始写下一排的数据。

对于单色位图,只需要一个位就可以表示其所有的颜色可能,黑白,对于16色位图,也就是有16中颜色的可能,那么需要四个位就可以表示16中可能,对于256色位图,那么需要8个位才能表示256中情况,对于真彩色,也就是表示所有的颜色,那么需要三个字节才可以表示所有情况(透明度不算),对于单色,16色,256色位图来说,位图数据读到的是调色板上的索引,通过这个索引在调试版中找到对应的颜色,然后显示在屏幕上。所以对于单色位图,他的调色板只有黑白两种颜色,16色位图,他的调色板有16种颜色,256色的调色板有256中颜色,如果是24位位图,他的位图信息,就是保存的真实颜色,每读三个字节就表示了一个像素点的颜色,不需要再进行调色板查找对应的颜色。

*******在还原的例子程序中我并没有还原成RGBA 还是按照BGRA的方式还原的 其它只有调整一下tt的位置就可以了

*******windows在保存的时候是先保存的最后一排的数据,从下往上从左往右保存的,还原时已经还原成正常的了.

*******先取图像中的一点(y*width+x)[y是高变量 x是宽变量]数据, 得到数据[永远都在0-255之间]来找调色板中的真实颜色数据.

用到这张256色的图片

#include<stdio.h>
#include<stdlib.h>
#include<GLUT/GLUT.h>
#include <string.h>
GLint imagewidth,imageheight;
unsigned char* PixelData;void decodeimages(const char* filename,GLint *w,GLint *h){FILE *fp;fp = fopen(filename, "r");if (fp == NULL) exit(EXIT_FAILURE);int width,height;fseek(fp, 0x12, SEEK_SET);fread(&width, sizeof(int), 1, fp);fread(&height, sizeof(int), 1, fp);*w = width;*h = height;fseek(fp, 0x36, SEEK_SET);//1024字节调色板unsigned char color[256][4];for (int i=0; i<256; i++) {fread(&color[i], 4, 1, fp);}fseek(fp, 0x436, SEEK_SET);unsigned char data[width*height];fread(&data, width*height, 1, fp);fclose(fp);PixelData = (unsigned char*)malloc(width*height*4);memset(PixelData, 0, width*height*4);unsigned char tt[4];int count = 0;if (height>0){//高度大于0图片是正的 小于0是从下到上从左到右还原for(int i = 0;i<height;i++){for (int j=0; j<width; j++) {//数据索引int index = i*width+j;//调色板索引int cindex = data[index];//图像存储是BRG模式 还原为RGBAtt[0] = color[cindex][2];tt[1] = color[cindex][1];tt[2] = color[cindex][0];tt[3] = color[cindex][3];memcpy(PixelData+count, tt, 4);count +=4;}}}else{for (int i=height-1; i>=0; i--) {for (int j=0; j<width; j++) {//数据索引int index = i*width+j;//调色板索引int cindex = data[index];//图像存储是BRG模式 还原为RGBAtt[0] = color[cindex][2];tt[1] = color[cindex][1];tt[2] = color[cindex][0];tt[3] = color[cindex][3];memcpy(PixelData+count, tt, 4);count +=4;}}}
}void disPlay(){glDrawPixels(imagewidth,imageheight, GL_RGBA, GL_UNSIGNED_BYTE, PixelData);glutSwapBuffers();
}int main(int argc, char* argv[]){char *filename = "003140.bmp";decodeimages(filename,&imagewidth,&imageheight);glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);glutPositionWindow(200, 200);glutInitWindowSize(imagewidth, imageheight);glutCreateWindow("还原BMP");glutDisplayFunc(&disPlay);glutMainLoop();free(PixelData);return EXIT_SUCCESS;
}

运行效果:



http://www.ppmy.cn/news/556360.html

相关文章

Python实现数字图像处理经典算法之256色转灰度图

算法介绍 256色转灰度图是数字图像处理经典算法中最简单的算法之一 1、彩色数字图像中的颜色有红、绿、蓝三种颜色混合而成&#xff0c;对应的像素颜色通道就是RGB&#xff08;R&#xff0c;G&#xff0c;B&#xff09;&#xff0c;R、G、B数值共有256个数值&#xff0c;也称…

计算机论文图片大小,对一副大小为256*256的bmp格式256色的灰度图象进行霍夫曼和字典编码压缩处理...

内容简介: 课程设计 对一副大小为256*256的bmp格式256色的灰度图象进行霍夫曼和字典编码压缩处理,共31页,6992字 目录 绪论1 1原理分析2 1.1数字图象2 1.1.1灰度图象2 1.1.2灰度直方图3 1.2霍夫曼(Huffman)编码5 1.2.1截断霍夫曼编码5 1.2.2自适应霍夫曼编码7 1.3LZW编码原理…

用PS制作256色的BMP图片

1.打开PS&#xff0c;新建文件&#xff0c;颜色模式为RGB&#xff0c;位数为8位&#xff0c;大小为640X480像素&#xff0c;其它默认 2.文件->打开&#xff0c;选中素材图片 3.将素材图片放到新建的图层上 4.打开文件菜单&#xff0c;存储为WEB和设备所用格式&#xff0c;设…

真彩色转256色算法

位图常用的一种压缩方法。从位图图片中选择最有代表性的若干种颜色&#xff08;通常不超过256种&#xff09;编制成颜色表&#xff0c;然后将图片中原有颜色用颜色表的索引来表示。 这样原图片可以被大幅度有损压缩。适合于压缩网页图形等颜色数较少的图形&#xff0c;不适合压…

计算机颜色格式(真彩、256色等)

原文链接&#xff1a;https://www.cnblogs.com/jackStudy/archive/2012/06/26/2563261.html 常见的颜色有 8位 16位 24位 32位色&#xff0c;其中24位及以上称为真彩&#xff0c;是PC上最常用的颜色&#xff0c;其他基本用于嵌入式系统或一些工控领域&#xff0c;详情可查阅一…

RGB转8色16色256色

RGB色的图片有255*255*25516581375种颜色&#xff0c;如果再加上透明度ARGB就要再乘以255&#xff0c;这么多的颜色在图形处理中有时不需要使用那么多的颜色&#xff0c;只需要转化成8色、16色或者256色就可以了&#xff0c;而透明度则作特殊处理&#xff0c;比如在阀值80以下的…

matlab 256灰度图像,MATLAB实现256色灰度图像的Arnold置乱

MATLAB实现256色灰度图像的Arnold置乱 下面的程序实现256色灰度图像的Arnold置乱。以前用VC做很麻烦&#xff0c;但在matlab中却显得非常简洁。matlab不愧是一款很受欢迎的辅助研究工具。 &#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0…

用C++实现RGB转256色

前言 RGB图片转256色&#xff0c;我知道的有两种方法&#xff1a; ①用Windows系统自带的画图工具打开图片&#xff0c;再另存为256色bmp图片 ②用Photoshop打开图片&#xff0c;然后图像→模式→索引颜色&#xff0c;选择局部&#xff08;可感知&#xff09;→确定→存储为…