对bmp处理 注意宽度必须是4的倍数(字节)
将bmp内容读取到unsigned char格式的内存中,直接对该内存进行处理
MyBitmap.h
#pragma once
#include "stdafx.h"
#include <cmath>
class MyBitmap
{
public:
void GetBmpByFilePath(char *filepath);
void ShowArrayToDevice(CDC *dc, int xDes, int yDes, const unsigned char *desfile,WORD BitCount, tagRGBQUAD *pPal);
WORD GetBitCount();
bool HavePalette();
unsigned char *GetBmp();
LONG GetWidth();
LONG GetHeight();
private:
WORD biBitCount;
tagRGBQUAD *pPal;
unsigned char *bmp;
LONG width;
LONG height;
};
MyBitmap.cpp
#include "MyBitmap.h"
void MyBitmap::GetBmpByFilePath(char *filepath)
{
FILE *file = NULL;
file = fopen(filepath, "rb");
if (file == NULL) { AfxMessageBox("文件读取失败!"); return; }
//读取bmp头
BITMAPFILEHEADER bmpFileHead;
fread(&bmpFileHead, sizeof(BITMAPFILEHEADER), 1, file);
if (bmpFileHead.bfType != 0x4d42) { AfxMessageBox("图像不是bmp格式!"); return; }
DWORD sumNum = bmpFileHead.bfSize;//这个长度是数据长度
DWORD offNum = bmpFileHead.bfOffBits;//数据偏移头部长度
BITMAPINFOHEADER bmpInfoHead;
fread(&bmpInfoHead, sizeof(BITMAPINFOHEADER), 1, file);
if (bmpInfoHead.biCompression != 0){ AfxMessageBox("无法处理的bmp压缩格式!"); return; }
biBitCount = bmpInfoHead.biBitCount;
long nPlantNum;
if (bmpInfoHead.biBitCount < 24)//读取调色板
{
nPlantNum = long(pow(2, double(bmpInfoHead.biBitCount))); // Mix color Plant Number;
pPal = new tagRGBQUAD[nPlantNum*sizeof(tagRGBQUAD)];
memset(pPal, 0, nPlantNum*sizeof(tagRGBQUAD));
fread(pPal, 4, nPlantNum, file);
}
else pPal = NULL;
width = bmpInfoHead.biWidth;//宽度必须是4B的倍数
height = bmpInfoHead.biHeight;
if (bmpInfoHead.biBitCount < 24)//注意宽度的计算方式
{
width = (width % (32 / biBitCount) == 0) ? width : (width / (32 / biBitCount) + 1) * (32 / biBitCount);//宽度调整为4B 32的倍数
// width = (width+3)/4*4;
width = width*biBitCount / 8;
}
else
width = (width*biBitCount / 8 + 3) / 4 * 4;
height = abs(height);
bmp = new unsigned char[height*width];
fread(bmp, 1, height*width, file);
fclose(file);
}
WORD MyBitmap::GetBitCount()
{
return biBitCount;
}
bool MyBitmap::HavePalette()
{
if (pPal) return false;
return true;
}
unsigned char *MyBitmap::GetBmp()
{
return bmp;
}
LONG MyBitmap::GetHeight()
{
return height;
}
LONG MyBitmap::GetWidth()
{
return width;
}
void MyBitmap::ShowArrayToDevice(CDC *dc, int x, int y, const unsigned char *desfile,WORD BitCount, tagRGBQUAD *pPal)
{
CDC dcMemory;
dcMemory.CreateCompatibleDC(dc);
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(dc, width / 3, height);
dcMemory.SelectObject(&bitmap);
int k;
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)//宽度变长,比如2倍,图像会显示2副,第二幅为第一副的隔行
{
unsigned char r, g, b, gray;
COLORREF c;
BYTE w16;
switch (BitCount)
{
case 1://读取单色bmp
// fread(&gray, sizeof(BYTE), 1, file);
gray = bmp[(height - 1 - j)*width + i];
for (k = 0; k < 8; k++)
{
c = gray & 0x80;
if (c == 0x80) c = RGB(255, 255, 255);
else c = 0;
dcMemory.SetPixel(x + i * 8 + k, y + j, c);
// SetPixel(hdc, x + i++, y + height - j, c);
gray = gray << 1;
}
break;
case 4://读取4位16色
w16 = bmp[j*width + i];
dcMemory.SetPixel(x + i * 2, y + height - j, RGB(pPal[w16 >> 4].rgbRed, pPal[w16 >> 4].rgbGreen, pPal[w16 >> 4].rgbBlue));
dcMemory.SetPixel(x + i * 2 + 1, y + height - j, RGB(pPal[w16 & 0x0f].rgbRed, pPal[w16 & 0x0f].rgbGreen, pPal[w16 & 0x0f].rgbBlue));
break;
case 8://读取8位256色
gray = bmp[j*width + i];
dcMemory.SetPixel(x + i, y + height - j, RGB(pPal[gray].rgbRed, pPal[gray].rgbGreen, pPal[gray].rgbBlue));
break;
case 24:
b = bmp[j*width + i];
g = bmp[j*width + i + 1];
r = bmp[j*width + i + 2];
dcMemory.SetPixel(x + i / 3, y + height - j, RGB(r, g, b));
i += 2;
break;
}
}
dc->BitBlt(0, 0, width, height, &dcMemory, 0, 0, SRCCOPY);
}