bmp图像大小biSizeImage算法公式由来

LPBITMAPINFOHEADER lpbmiHeader;

// ...

计算BMP方法

法一:lpbmiHeader->biSizeImage = (cx * biBitCount + 31)/32*4*cy;

法二:lpbmiHeader->biSizeImage = ((cx * biBitCount + 31) & ~31) / 8 * cy;

法三:lpbmiHeader->biSizeImage = ((cx * biBitCount + 31) & ~31) >> 3 * cy;


前提: 在BMP的文件格式中规定每行的字节数必须是4的整数倍,不是4的整数倍要补齐。

上面公式红色部分都是一样的结果,都是计算BMP图像中每行的字节数。

其中cx * biBitCount是实际一行占用的位数。暂且用dwRowBit表示吧。

情况1:dwRowBit小于32位(假设dwRowBit为31),那么dwRowBit/8 就小于4,但是我们需要补齐4个字节。办法就是(31 + 31)/32 * 4

情况2: dwRowBit正好32位,不需要考虑多少。 32/8 ,和32/32 * 4都是一样的

情况3: dwRowBit为34位,按理说最少需要4个字节带1位,但是因为必须是4的整数倍,所以应该以8个字节保存。

如何将34位转化为8个字节呢?就是要将dwRowBit中除以32的余数部分添加到满足32位的情况。

所以(dwRowBit + 31)/32 * 4;

其实我们也可以换个思维考虑:

如下dwRowBit分成2个部分: dwRowBit1为正好能被32整除的部分,dwRowBit2为不能被32整除的部分(则dwRowBit2肯定小于32,为什么?你们想想?)

那么上述公式划分为

(dwRowBit1 + dwRowBit2 + 31) / 32 * 4;

再简化一下就是dwRowBit1 / 32 * 4 + (dwRowBit2 + 31) / 32 * 4

再简化一下dwRowBit1 / 8 + (dwRowBit2 + 31) / 32 * 4

dwRowBit2从31位中取一定的位数使自己补齐为32,31剩余的部分除以32的话自动为0.


另外还要补充一点: 对单位的考虑

(dwRowBit1 + dwRowBit2 + 31) bit / 32 bit  * 4 Byte


//===============================================================================================//

// 参考资料1 

计算biSizeImage的两种方法:

1.最简单的方法是由BITMAPFILEHEADER结构的bfSize减去bfOffBits。

2.由图像的高度和宽度来计算图像数据的字节数。要注意的是并不是图像的高度乘以图像宽度乘以表示每象

素的字节数就行了,因为在BMP的文件格式中规定每行的字节数必须是4的整数倍,不是4的整数倍的要补

零。因此,正确的算法是:

biSizeImage=(biWidth*biBitCount+31)/32*4*biHeight

其中,biWidth*biBitCount是每一行图像占用的位数,除以8是每行图像占用的字节数,要为4的整数倍,所

以除以32再乘以4,整数除法自动取整。(不能直接除以8,想想为什么?加31有什么作用?)

不足的位数补充上如241存储为244.(..........如果可以位数舍去,241为240,这是不可能的,那不用加31)


// 参考资料2

csdn论坛搜索关键字:

biSizeImage

VC/MFC分区——图形处理/算法

主要链接:

http://topic.csdn.net/u/20070929/13/9ED13464-121E-401E-B827-91E3BF5F0036.html

http://topic.csdn.NET/u/20100114/21/0A67123E-1407-4FC0-B4E0-6D27FB8626C2.html

http://topic.csdn.net/u/20100116/17/4590fdf6-91c7-49a6-a76f-fa3effbae759.html

 

关键心得:

 

biSizeImage=(biWidth*biBitCount+31)/32*4*biHeight其中,biWidth*biBitCount是每一行图像占用的位数,除以8是每行图像占用的字节数,要为4的整数倍,所以除以32再乘以4
31是按整数除法自动取整的原则来的,其保证每行图像字节数必须是4的整倍数!
举一个例子,对于2色图,如果图象宽是31,则每一行需要31位存储,合3个字节加7位,因为字节数必须是4的整倍数,所以应该是4。所以补齐时需要加上4个字节数即32位

 

===================================

1:biWidth = 241 是位图的宽度而不是字节数目
2:(bits)其实需要输入:(biWidth * biBitCount),
3:WIDTHBYTES()根据输入(biWidth*biBitCount)而得出行字节数,而扫描行字节数乘以扫描行总数(位图的高度biHeight),就得出位数据的实际字节数目,估计你是理解错误了.
4:那估计是乱写的,正确是不能把 (xx)/32*4写成(xx)/8的,在计算机那是不相等的,举例:
width = 2,bpp = 8那么行字节数应该是
(2*8+31)/32*4 得4个字节.
(2*8+31)/8 得5个字节.
有少少常识的都知道,上面那个是对的,下面那个是错的,原因那些家伙根本不理解"对齐"的意思,片面地把"/32*4"合成为"/8"来误人误已. hoho.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一些关于BMP图像直方图均衡算法的基本思路和C语言实现。 直方图均衡化是一种图像增强技术,它可以使图像的对比度增强,提高图像的质量。直方图均衡化的基本思路是将图像的像素值进行重新分配,使得图像的灰度级分布更加均匀。 下面是一种基于C语言实现的BMP图像直方图均衡算法的伪代码: 1. 读取BMP图像的像素矩阵 2. 统计图像像素矩阵的灰度级直方图 3. 计算直方图均衡化映射表 4. 对原始像素矩阵进行直方图均衡化 5. 将均衡化后的像素矩阵写回BMP图像 下面是一份可以实现直方图均衡化的C语言代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #pragma pack(1) //按字节对齐 typedef struct BMPFileHeader { char bfType[2]; int bfSize; short bfReserved1; short bfReserved2; int bfOffBits; } BMPFileHeader; typedef struct BMPInfoHeader { int biSize; int biWidth; int biHeight; short biPlanes; short biBitCount; int biCompression; int biSizeImage; int biXPelsPerMeter; int biYPelsPerMeter; int biClrUsed; int biClrImportant; } BMPInfoHeader; typedef struct RGB { unsigned char blue; unsigned char green; unsigned char red; } RGB; int main() { FILE* fp; BMPFileHeader bmpFileHeader; BMPInfoHeader bmpInfoHeader; RGB* image; RGB* image2; unsigned char* grayImage; unsigned char* grayImage2; int* hist; int* eqHist; int* map; int width, height, size, size2, i, j, k, max; char filename[100]; // 读取图像文件 printf("Enter the filename of the BMP image: "); scanf("%s", filename); fp = fopen(filename, "rb"); if (!fp) { printf("Error: Failed to open the file.\n"); return -1; } // 读取文件头 fread(&bmpFileHeader, sizeof(BMPFileHeader), 1, fp); if (bmpFileHeader.bfType[0] != 'B' || bmpFileHeader.bfType[1] != 'M') { printf("Error: Not a BMP file.\n"); return -1; } // 读取信息头 fread(&bmpInfoHeader, sizeof(BMPInfoHeader), 1, fp); if (bmpInfoHeader.biBitCount != 24) { printf("Error: Not a 24-bit BMP file.\n"); return -1; } // 计算图像大小 width = bmpInfoHeader.biWidth; height = bmpInfoHeader.biHeight; size = width * height; size2 = sizeof(unsigned char) * size; // 读取像素数据 image = (RGB*)malloc(sizeof(RGB) * size); fread(image, sizeof(RGB), size, fp); // 将RGB图像转换为灰度图像 grayImage = (unsigned char*)malloc(size2); for (i = 0; i < size; i++) { grayImage[i] = (unsigned char)(0.299 * image[i].red + 0.587 * image[i].green + 0.114 * image[i].blue); } // 计算灰度级直方图 hist = (int*)malloc(sizeof(int) * 256); memset(hist, 0, sizeof(int) * 256); for (i = 0; i < size; i++) { hist[grayImage[i]]++; } // 计算直方图均衡化映射表 eqHist = (int*)malloc(sizeof(int) * 256); map = (int*)malloc(sizeof(int) * 256); max = size / 256; for (i = 0; i < 256; i++) { eqHist[i] = 0; for (j = 0; j <= i; j++) { eqHist[i] += hist[j]; } map[i] = (int)(eqHist[i] * 255.0 / size + 0.5); if (eqHist[i] > max) { eqHist[i] = max; } } // 对灰度图像进行直方图均衡化 grayImage2 = (unsigned char*)malloc(size2); for (i = 0; i < size; i++) { grayImage2[i] = (unsigned char)map[grayImage[i]]; } // 将灰度图像转换为RGB图像 image2 = (RGB*)malloc(sizeof(RGB) * size); for (i = 0; i < size; i++) { image2[i].red = grayImage2[i]; image2[i].green = grayImage2[i]; image2[i].blue = grayImage2[i]; } // 写回图像文件 fseek(fp, sizeof(BMPFileHeader) + sizeof(BMPInfoHeader), SEEK_SET); fwrite(image2, sizeof(RGB), size, fp); fclose(fp); free(image); free(image2); free(grayImage); free(grayImage2); free(hist); free(eqHist); free(map); printf("Done.\n"); return 0; } ``` 这份代码可以读取一个BMP图像文件,将其转换为灰度图像,进行直方图均衡化,然后将均衡化后的图像写回文件中。注意,这份代码只支持24位的BMP图像文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值