http://hi.youkuaiyun.com/space-289256-do-album-id-85553.html
要使用jpeg图片如上
想必大家对BMP文件的操作并不陌生,只是最近存在的一个问题让我百思不得其解,图片显示的颜色不对,而且出现了明显的倾斜现象,将该JPEG图片转为BMP图片,然后对其进行操作。在VC环境下使用的显示方式是调用DC的SetPixel方法。
如今已经得出了原因,是biSizeImage与图片的大小不一致产生的。现将代码分享如下,得出正确显示。
首先定义了数据结构
typedef struct BITMAP_FILE_TAG
{
BITMAPFILEHEADER bitmapfileheader; // this contains the bitmapfile header
BITMAPINFOHEADER bitmapinfoheader; // this is all the info including the palette
PALETTEENTRY palette[256]; // we will store the palette here
UCHAR *buffer; // this is a pointer to the data
} BITMAP_FILE, *BITMAP_FILE_PTR;
读取位图的程序如下:
CString StrFilter = "位图文件(*.bmp)|*.bmp|所有文件(*.*)|*.*||"; //filter file
CFileDialog Dlg(TRUE, //opendialog
NULL, //
NULL, //
NULL, //
StrFilter, //
this); //
if (!Dlg.DoModal() == IDOK) //
{
return;
}
CString StrFileName;
StrFileName = Dlg.GetFileName();
//BITMAPINFO
BITMAPINFO *pBmpInfo;
//DIB
BYTE* pBmpData;
CFile MyFile;
if (!MyFile.Open(StrFileName,CFile::modeRead|CFile::typeBinary))
{
return;
}
BITMAPFILEHEADER BmpHeader; //fileheader
if (MyFile.Read(&BmpHeader, sizeof(BmpHeader)) != sizeof(BmpHeader))
{
AfxMessageBox("read bimap file header failed");
return;
}
if (BmpHeader.bfType != 0x4D42) //'BM'
{
AfxMessageBox("not bitmap");
return;
}
BITMAPINFOHEADER BmpInfo; //infoheader
if (MyFile.Read(&BmpInfo, sizeof(BmpInfo)) != sizeof(BmpInfo))
{
AfxMessageBox("read bimap info failed");
return;
}
if (BmpInfo.biBitCount != 24) //judge 24bit map
{
AfxMessageBox("not 24bit bitmap,ignored");
return;
}
pBmpInfo = (BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER)]; //only use the bitmapinfoheader
//palette not used,
//cast bitmapinfoheader to bitmapinfo
if (!pBmpInfo)
{
AfxMessageBox("memory allocate failed");
return;
}
memcpy(pBmpInfo, &BmpInfo, sizeof(BITMAPINFOHEADER)); //cpy bmpinfo to the point pbmpinfo
DWORD dataBytes = BmpHeader.bfSize - BmpHeader.bfOffBits; //bfsize:size of bimap file
DWORD delta = (dataBytes/BmpInfo.biHeight - BmpInfo.biWidth*3); //databytes:the pixels size
pBmpData = (BYTE*)new char[dataBytes];
if (!pBmpData)
{
AfxMessageBox("memory allocate failed");
delete pBmpInfo;
return;
}
if (MyFile.Read(pBmpData, dataBytes) != dataBytes)
{
AfxMessageBox("read bitmap data failed");
delete pBmpInfo;
delete pBmpData;
return;
RGBTRIPLE *rgb;
rgb = new RGBTRIPLE[BmpInfo.biWidth*BmpInfo.biHeight];
MyFile.SeekToBegin();
MyFile.Seek(BmpHeader.bfOffBits, CFile::begin);
if (delta == 0)
{
MyFile.Read(rgb,BmpInfo.biWidth*BmpInfo.biHeight*3);//read pixels from dataregion
}
else
{
for (WORD count=0;count<BmpInfo.biHeight;count++)
{
MyFile.Read(&rgb[count*BmpInfo.biWidth],BmpInfo.biWidth*3);
MyFile.Seek(delta,CFile::current);
}
}
MyFile.Close();
CDC *pDC = GetDC();
CRect rect;
CBrush brush(RGB(255,255,255));
GetClientRect(&rect);
pDC->FillRect(&rect, &brush);
if (BmpInfo.biCompression != BI_RGB)
{
AfxMessageBox("compressed bmp,no process");
return;
}
}
for (int i=0;i<BmpInfo.biHeight;i++)
for (int j=0;j<BmpInfo.biWidth;j++)
{
pDC->SetPixel(j, BmpInfo.biHeight-1-i,
RGB(rgb[i*BmpInfo.biWidth+j].rgbtRed,
rgb[i*BmpInfo.biWidth+j].rgbtGreen,
rgb[i*BmpInfo.biWidth+j].rgbtBlue));
for (int k=0; k<1000; k++) ; //延时
}
delete pBmpInfo;
delete pBmpData;
delete rgb;
}
当然简单的方法也是有的,那就是调用StretchDIBits