失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 图解 bmp 文件(BITMAP windows位图文件)格式

图解 bmp 文件(BITMAP windows位图文件)格式

时间:2020-04-15 07:35:20

相关推荐

图解 bmp 文件(BITMAP windows位图文件)格式

既然是图解,此处省去介绍....直接上图

以下代码中SetPixel()为在屏幕中打点的函数,在单片机中由自己实现,

根据不同的位深来解析,都是根据以上图片方式,推导出来的算法.

并没有实现压缩算法,图像高度为负的情况,并且未优化,图像较大时速度慢

(pmybmp指向bmp文件的数组)

//windows下加入缓冲提高速度

HDC hdc=GetDC(hWnd);//second method

HDC hmdc = CreateCompatibleDC(hdc);

HBITMAP hbmp = CreateCompatibleBitmap(hdc, bminfohdr.biWidth, bminfohdr.biHeight);

SelectObject(hmdc, hbmp);

char *pmybmp = (char*)BMP_WAVE;BITMAPFILEHEADER bmfilehdr;BITMAPINFOHEADER bminfohdr; memcpy(&bmfilehdr, &pmybmp[0], sizeof(BITMAPFILEHEADER));//14memcpy(&bminfohdr, &pmybmp[14], sizeof(BITMAPINFOHEADER));//40printf("\n..............................\n");printf("\nsizeof(BITMAPFILEHEADER)=%d\n", sizeof(BITMAPFILEHEADER));printf("bmfilehdr.bfType=%#02x\n", bmfilehdr.bfType);printf("bmfilehdr.bfSize=%#04x,bmp文件大小:%d字节\n", bmfilehdr.bfSize, bmfilehdr.bfSize);printf("bmfilehdr.bfOffBits=%#04x (到RGBQUAD偏移字节)\n", bmfilehdr.bfOffBits);printf("sizeof(BITMAPINFOHEADER)=%d\n", sizeof(BITMAPINFOHEADER));printf("bminfohdr.biSize=%#04x ( 结构体BITMAPINFOHEADER大小,=sizeof(BITMAPINFOHEADER) )\n", bminfohdr.biSize);printf("bminfohdr.biWidth=%#04x (位图宽:%dpixels)\n", bminfohdr.biWidth, bminfohdr.biWidth);printf("bminfohdr.biHeight=%#04x (位图高:%dpixels)\n", bminfohdr.biHeight, bminfohdr.biHeight);printf("bminfohdr.biPlanes=%#02x (平面数)\n", bminfohdr.biPlanes);printf("bminfohdr.biBitCount=%#02x (%d位深,1:单色,4:16色,8:256色,16:高彩色,24:真彩色,32:增强真彩色)\n", bminfohdr.biBitCount, bminfohdr.biBitCount);printf("bminfohdr.biCompression=%d (压缩算法:0:BI_RGB,1:BI_RLE8,2:BI_RLE4,3:BI_BITFIELEDS,4:BI_JPEG,5:BI_PNG)\n", bminfohdr.biCompression);printf("bminfohdr.biSizeImage=%d (位图缓冲,BI_RGB常为0)\n", bminfohdr.biSizeImage);printf("bminfohdr.biXPelsPerMeter=%d (水平分辨率,pixels/meter)\n", bminfohdr.biXPelsPerMeter);printf("bminfohdr.biYPelsPerMeter=%d (垂直分辨率,pixels/meter)\n", bminfohdr.biYPelsPerMeter);printf("bminfohdr.biClrUsed=%d (位深为1~8时,用于指定调用板用到的颜色数,0表示全部都用到)\n", bminfohdr.biClrUsed);printf("bminfohdr.biClrImportant=%d (0表示所有色彩都重要)\n", bminfohdr.biClrImportant);switch (bminfohdr.biBitCount)//位深,bpp,bit per pixel{//色彩位数case 32://0x20,增强真彩色,RGBA///bminfohdr.biCompression == BI_RGB ||bminfohdr.biCompression ==BI_BITFIELDS{for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){unsigned long idxRGB = bmfilehdr.bfOffBits + w*bminfohdr.biBitCount / 8 + (bminfohdr.biWidth*bminfohdr.biBitCount / 8)*h;//由索引到调色板,0XBB,0XGG,0XGG //bmfilehdr.bfOffBits指向 调色板 的开头RGBQUAD *pixelclr = (RGBQUAD*)&pmybmp[idxRGB];SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr->rgbRed, pixelclr->rgbGreen, pixelclr->rgbBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}break;case 24://24bit/pixel,0x18,真彩色,16777216色{long pad0 = (4 - bminfohdr.biBitCount / 8 * bminfohdr.biWidth % 4) % 4;//补0字节数,bitcount 为位数要除以8!!!for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){unsigned long idxRGB = bmfilehdr.bfOffBits + w*bminfohdr.biBitCount / 8 + (bminfohdr.biWidth*bminfohdr.biBitCount / 8 + pad0)*h;//由索引到调色板,0XBB,0XGG,0XGG //bmfilehdr.bfOffBits指向 调色板 的开头RGBTRIPLE *pixelclr = (RGBTRIPLE*)&pmybmp[idxRGB];// printf("index:%d,RGB(%d,%d,%d)\n", idxRGB, pixelclr->rgbtRed, pixelclr->rgbtGreen, pixelclr->rgbtBlue);SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr->rgbtRed, pixelclr->rgbtGreen, pixelclr->rgbtBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}break;case 16://0x10,高彩色,65536色,RGB565,RGB444,RGB555switch (bminfohdr.biSize){case 0x28://X1RGB555,最高位空{int pad0 = 32 - bminfohdr.biBitCount*bminfohdr.biWidth % 32;for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){unsigned long idxRGB = bmfilehdr.bfOffBits + w*bminfohdr.biBitCount / 8 + (bminfohdr.biWidth*bminfohdr.biBitCount + pad0)*h / 8;//由索引到调色板,0XBB,0XGG,0XGG //bmfilehdr.bfOffBits指向 调色板 的开头USHORT color = *(USHORT*)&pmybmp[idxRGB];RGBTRIPLE pixelclr;pixelclr.rgbtRed = ((0x7c00 & color) >> 7);//RED:D6D5D4D3D2,即每个分量只有5位,靠MSB位置处放pixelclr.rgbtGreen = ((0x03e0 & color) >> 2);//GREEN:D6D5D4D3D2pixelclr.rgbtBlue = ((0x001f & color) << 3);//BLUE:D6D5D4D3D2SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr.rgbtRed, pixelclr.rgbtGreen, pixelclr.rgbtBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}break;case 0x38://根据掩膜来取RGB,X4RGB444,RGB565{if (bminfohdr.biCompression == BI_BITFIELDS){struct CLRMASK{DWORD RedMask, GreenMask, BlueMask, AlphaMask;};int rr = 0, rg = 0, rb = 0;CLRMASK *clr = (CLRMASK*)&pmybmp[icolor_table];//printf("icolor_table:%02X,RGBA_MASK:%04x,%04x,%04x,%04x\n", icolor_table, clr->RedMask, clr->GreenMask, clr->BlueMask, clr->AlphaMask);int pad0 = (32 - bminfohdr.biBitCount*bminfohdr.biWidth % 32) % 32;//cmd.puts("...............,.............\n");if (clr->RedMask == 0xf800 && clr->GreenMask == 0x07e0 && clr->BlueMask == 0x001f) { rr = 8; rg = 3; rb = 3; }else if (clr->RedMask == 0x0f00 && clr->GreenMask == 0x00f0 && clr->BlueMask == 0x000f) { rr = 4; rg = 0; rb = 4; }for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){unsigned long idxRGB = bmfilehdr.bfOffBits + w*bminfohdr.biBitCount / 8 + (bminfohdr.biWidth*bminfohdr.biBitCount + pad0)*h / 8;//由索引到调色板,0XBB,0XGG,0XGG //bmfilehdr.bfOffBits指向 调色板 的开头USHORT color = *(USHORT*)&pmybmp[idxRGB];RGBTRIPLE pixelclr;pixelclr.rgbtRed = (BYTE)((clr->RedMask & color) >> rr);//RED:D6D5D4D3D2,即每个分量只有5位,靠MSB位置处放pixelclr.rgbtGreen = (BYTE)((clr->GreenMask & color) >> rg);//GREEN:D6D5D4D3D2pixelclr.rgbtBlue = (BYTE)((clr->BlueMask & color) << rb);//BLUE:D6D5D4D3D2SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr.rgbtRed, pixelclr.rgbtGreen, pixelclr.rgbtBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}}break;}break;case 8://8bit/pixel,256色{long pad0 = (4 - bminfohdr.biBitCount * bminfohdr.biWidth / 8 % 4) % 4;//补0字节数//if (pad0 == 4) pad0 = 0;for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth + pad0; w++){//位图颜色数据索引unsigned longibmoffset = w + (bminfohdr.biWidth + pad0) * h;unsigned char iclrtbl = pmybmp[bmfilehdr.bfOffBits + ibmoffset];//由索引到调色板,0XBB,0XGG,0XGG,0XAA //icolor_table指向 调色板 的开头RGBQUAD *pixelclr = (RGBQUAD*)&pmybmp[icolor_table + iclrtbl * 4];SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr->rgbRed, pixelclr->rgbGreen, pixelclr->rgbBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}//printf("FINISHED\n");}break;case 4: //4bit/pixel,16色位图//bminfohdr.biCompression{int pad0 = (32 - bminfohdr.biBitCount*bminfohdr.biWidth % 32) % 32;for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){//索引,4位的索引,即半字节索引unsigned longibmoffset = bmfilehdr.bfOffBits + w / 2 + (bminfohdr.biBitCount*bminfohdr.biWidth + pad0) / 8 * h;unsigned char iclrtbl = (pmybmp[ibmoffset] >> ((1 - (w & 0x1)) * 4)) & 0x0f;//由索引到调色板,0XBB,0XGG,0XGG,0XAA //icolor_table指向 调色板 的开头RGBQUAD *pixelclr = (RGBQUAD*)&pmybmp[icolor_table + iclrtbl * 4];SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, RGB(pixelclr->rgbRed, pixelclr->rgbGreen, pixelclr->rgbBlue)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}break;case 1://单色,一般为黑白,1=白,0=黑,但其实两是两种可定义的颜色,即双色位图 {int pad0 = (32 - bminfohdr.biBitCount*bminfohdr.biWidth % 32) % 32;for (long h = 0; h < bminfohdr.biHeight; h++){for (long w = 0; w < bminfohdr.biWidth; w++){long idx = (w + h*(bminfohdr.biWidth + pad0)) / 8;unsigned char mask = (1 << (7 - w % 8));unsigned char dat = pmybmp[bmfilehdr.bfOffBits + idx];SetPixel(hmdc, w, bminfohdr.biHeight - h - 1, (dat & mask) ? RGB(255, 255, 255) : RGB(0, 0, 0)); // bminfohdr.biHeight>0,图像上下倒置,所以要bminfohdr.biHeight - h}}}break;}

//windows下加入缓冲提高速度

BitBlt(hdc,1,1,bminfohdr.biWidth,bminfohdr.biHeight, hmdc, 0, 0, SRCCOPY);

DeleteObject(hbmp);

DeleteDC(hmdc);

ReleaseDC(hWnd,hdc);

补充:在WINDOWS上可以用一条语句代替以上代码,速度非常之快,超乎想象,不知道WINDOWS内部是怎么实现的

SetDIBitsToDevice(hdc, 0, 0, bminfohdr.biWidth, bminfohdr.biHeight, 0, 0, 0, bminfohdr.biHeight, (pmybmp+ bmfilehdr.bfOffBits), (BITMAPINFO*)&pmybmp[14], DIB_RGB_COLORS);

//lpvBits :Pointer to DIB color data stored as an array of bytes.

//BITMAPFILEHEADER.bfOffBits:Specifies the offset, in bytes, from the BITMAPFILEHEADER structure to the bitmap bits

如果觉得《图解 bmp 文件(BITMAP windows位图文件)格式》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。