百度搜索CDib.zip
http://www.axu.cn/tech_doc/index.htm阿须数码http://www.axu.cn/tech_doc/pcbook/imageprocess/
CDibData is a utility class for: loading, saving, and manipulating bitmaps. http://www.codeproject.com/bitmap/jscdibdata.asp
CExBitmap : a CBitmap extension class with undo/redo
http://www.codeproject.com/bitmap/JrsCExBitmap.asp
面试问题: Rotate a bitmap by 90 degrees 8/18/2004
http://blog.joycode.com/fyuan/articles/30945.aspx
求助: 调试了2个小时,旋转还是有问题。下面是个简单的测试--
// dib.h
#ifndef _DIB_H_
#define _DIB_H_
#include
#pragma pack(push,1)
typedef struct {BYTE a; BYTE b; BYTE c; } triple;
#pragma pack(pop)
class CDib
{
public:
CDib();
~CDib();
bool Load(LPCTSTR strFileName);
bool Save(LPCTSTR strFileName);
void Show(HDC hdc, POINT pt);
// closewise rotate 90 degree. and reset the bitmap file also.
CDib* Rotate90() const;
public:
long m_nBpl; // BYTES per line
long m_szRGBQuad;
BITMAPINFOHEADER m_bmHeader;
RGBQUAD* m_pRGBQuad;
BYTE* m_pData;
};
#endif
// dib.cpp
#include "dib.h"
#include
#include
template
void g_Rotate90(const CDib* pSrc, CDib* pDes)
{
long desWidth = pDes->m_bmHeader.biWidth;
long desHeight = pDes->m_bmHeader.biHeight;
long desHeightDec = pDes->m_bmHeader.biHeight - 1;
long srcHeightDec = pSrc->m_bmHeader.biHeight - 1;
long srcBpl = pSrc->m_nBpl;
long desBpl = pDes->m_nBpl;
BYTE* pSrcData = pSrc->m_pData;
BYTE* pDesData = pDes->m_pData;
int i,j;
for(i = 0; i < desHeight; ++i) {
const pixel* pS = (pixel*)((BYTE*)pSrcData + srcBpl * srcHeightDec) + i ;
pixel* pD = (pixel*)((BYTE*)pDesData + desBpl * (desHeightDec - i));
for(j = 0; j < desWidth; ++j) {
*pD++ = *pS;
pS = (pixel*)((BYTE*)pS - srcBpl);
}
}
}
CDib::CDib()
{
m_pRGBQuad = NULL;
m_pData = NULL;
m_szRGBQuad = 0;
m_nBpl = 0;
}
CDib::~CDib()
{
m_szRGBQuad = 0;
m_nBpl = 0;
if(m_pData != NULL)
{
delete m_pData;
m_pData = NULL;
}
if(m_pRGBQuad != NULL)
{
delete m_pRGBQuad;
m_pRGBQuad = NULL;
}
}
bool CDib::Load(LPCTSTR strFileName)
{
std::ifstream inFile(strFileName,std::ios::binary | std::ios::in);
if(!inFile.is_open())
return false;
// get the file size.
inFile.seekg(0,std::ios::end);
const long szFile = inFile.tellg();
if(szFile <= 0)
{
inFile.close();
return false;
}
WORD bmFlag[7];
inFile.seekg(std::ios::beg);
inFile.read((char*)bmFlag, sizeof(WORD)*7);
if(bmFlag[0] != ((WORD)'B' | 'M'<<8)) // it's not a bitmap file.
{
inFile.close();
return false;
}
inFile.read((char*)&m_bmHeader, sizeof(BITMAPINFOHEADER));
long width = m_bmHeader.biWidth;
long height = m_bmHeader.biHeight;
long bpp = m_bmHeader.biBitCount;
if(bpp < 1)
{
inFile.close();
return false;
}
// BYTES per line = (bits + 31) / 32 * 4.
m_nBpl = ((width * bpp + 31) >> 5) << 2;
long clrUsed = m_bmHeader.biClrUsed;
if(clrUsed == 0)
{
switch(bpp) {
case 1:
m_szRGBQuad = 2; break;
case 4:
m_szRGBQuad = 16;
break;
case 8:
m_szRGBQuad = 256;
break;
case 16:
// NO color table,the case : m_bmHeader.biCompression == BI_RGB
m_szRGBQuad = 0;
break;
default:
m_szRGBQuad = 0;
}
}
else
{
m_szRGBQuad = clrUsed;
}
// match the color table.
if(m_szRGBQuad != 0)
{
m_pRGBQuad = new RGBQUAD[m_szRGBQuad];
inFile.read((char*)m_pRGBQuad, sizeof(RGBQUAD)*m_szRGBQuad);
}
long nData = height * m_nBpl;
m_pData = new BYTE[nData]; // allocate a buffer for bm data.
inFile.read((char*)m_pData, sizeof(BYTE) * nData);
inFile.close();
return true;
}
bool CDib::Save(LPCTSTR strFileName)
{
std::ofstream outFile(strFileName,std::ios::binary | std::ios::out | std::ios::trunc);
if(!outFile.is_open())
return false;
WORD bmFlag[7]; // for BitmapFileHeader with 1 alignment.
bmFlag[0] = (WORD('B') | 'M'<<8);
long nData = m_bmHeader.biHeight * m_nBpl;
DWORD szFile = (sizeof(WORD) * 7) + sizeof(BITMAPINFOHEADER) +
(sizeof(RGBQUAD) * m_szRGBQuad) + (sizeof(BYTE) * nData);
bmFlag[1] = LOWORD(szFile) ;
bmFlag[2] = HIWORD(szFile);
DWORD szOffData = (sizeof(WORD) * 7) + sizeof(BITMAPINFOHEADER) +
(sizeof(RGBQUAD) * m_szRGBQuad);
bmFlag[5] = LOWORD(szOffData);
bmFlag[6] = HIWORD(szOffData);
outFile.write((char*)bmFlag, sizeof(WORD) * 7);
outFile.write((char*)&m_bmHeader, sizeof(BITMAPINFOHEADER));
if(m_szRGBQuad != 0)
outFile.write((char*)m_pRGBQuad, sizeof(RGBQUAD) * m_szRGBQuad);
outFile.write((char*)m_pData, sizeof(BYTE) * nData);
outFile.close();
return true;
}
void CDib::Show(HDC hdc, POINT pt)
{
assert(hdc);
HBITMAP hBmp = CreateDIBitmap(hdc, &m_bmHeader, CBM_INIT, m_pData,
(BITMAPINFO*)&m_bmHeader, DIB_RGB_COLORS);
HDC hMemDC = CreateCompatibleDC(hdc);
HBITMAP hOld = (HBITMAP)SelectObject(hMemDC, hBmp);
BitBlt(hdc, pt.x, pt.y, m_bmHeader.biWidth, m_bmHeader.biHeight,
hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC,hOld);
DeleteObject(hBmp);
DeleteDC(hMemDC);
return;
}
CDib* CDib::Rotate90() const
{
// first, check!
int bitCount = m_bmHeader.biBitCount;
if(!m_pData || bitCount % 8)
return NULL;
long newWidth = m_bmHeader.biHeight;
long newHeight = m_bmHeader.biWidth;
// second, create a new instance of CDib.
CDib* pRet = new CDib();
pRet->m_bmHeader = m_bmHeader;
pRet->m_bmHeader.biHeight = newHeight;
pRet->m_bmHeader.biWidth = newWidth;
pRet->m_nBpl = ((newWidth * bitCount + 31) >> 5) << 2;
pRet->m_szRGBQuad = m_szRGBQuad;
if( m_szRGBQuad != 0)
memcpy( pRet->m_pRGBQuad, m_pRGBQuad, sizeof(RGBQUAD) * m_szRGBQuad);
pRet->m_pData = new BYTE[pRet->m_nBpl * newHeight];
if(!pRet->m_pData) return NULL;
// third, copy the data.
switch(bitCount) {
case 8:
g_Rotate90 (this, pRet);
break;
case 15:
case 16:
g_Rotate90 (this, pRet);
break;
case 24:
g_Rotate90 (this, pRet);
break;
case 32:
g_Rotate90 (this, pRet);
break;
case 64:
g_Rotate90 (this, pRet);
break;
default:
assert(false);
delete pRet;
pRet = NULL;
}
return pRet;
}
// dib.h
#ifndef _DIB_H_
#define _DIB_H_
#include
#pragma pack(push,1)
typedef struct {BYTE a; BYTE b; BYTE c; } triple;
#pragma pack(pop)
class CDib
{
public:
CDib();
~CDib();
bool Load(LPCTSTR strFileName);
bool Save(LPCTSTR strFileName);
void Show(HDC hdc, POINT pt);
// closewise rotate 90 degree. and reset the bitmap file also.
CDib* Rotate90() const;
public:
long m_nBpl; // BYTES per line
long m_szRGBQuad;
BITMAPINFOHEADER m_bmHeader;
RGBQUAD* m_pRGBQuad;
BYTE* m_pData;
};
#endif
// dib.cpp
#include "dib.h"
#include
#include
template
void g_Rotate90(const CDib* pSrc, CDib* pDes)
{
long desWidth = pDes->m_bmHeader.biWidth;
long desHeight = pDes->m_bmHeader.biHeight;
long desHeightDec = pDes->m_bmHeader.biHeight - 1;
long srcHeightDec = pSrc->m_bmHeader.biHeight - 1;
long srcBpl = pSrc->m_nBpl;
long desBpl = pDes->m_nBpl;
BYTE* pSrcData = pSrc->m_pData;
BYTE* pDesData = pDes->m_pData;
int i,j;
for(i = 0; i < desHeight; ++i) {
const pixel* pS = (pixel*)((BYTE*)pSrcData + srcBpl * srcHeightDec) + i ;
pixel* pD = (pixel*)((BYTE*)pDesData + desBpl * (desHeightDec - i));
for(j = 0; j < desWidth; ++j) {
*pD++ = *pS;
pS = (pixel*)((BYTE*)pS - srcBpl);
}
}
}
CDib::CDib()
{
m_pRGBQuad = NULL;
m_pData = NULL;
m_szRGBQuad = 0;
m_nBpl = 0;
}
CDib::~CDib()
{
m_szRGBQuad = 0;
m_nBpl = 0;
if(m_pData != NULL)
{
delete m_pData;
m_pData = NULL;
}
if(m_pRGBQuad != NULL)
{
delete m_pRGBQuad;
m_pRGBQuad = NULL;
}
}
bool CDib::Load(LPCTSTR strFileName)
{
std::ifstream inFile(strFileName,std::ios::binary | std::ios::in);
if(!inFile.is_open())
return false;
// get the file size.
inFile.seekg(0,std::ios::end);
const long szFile = inFile.tellg();
if(szFile <= 0)
{
inFile.close();
return false;
}
WORD bmFlag[7];
inFile.seekg(std::ios::beg);
inFile.read((char*)bmFlag, sizeof(WORD)*7);
if(bmFlag[0] != ((WORD)'B' | 'M'<<8)) // it's not a bitmap file.
{
inFile.close();
return false;
}
inFile.read((char*)&m_bmHeader, sizeof(BITMAPINFOHEADER));
long width = m_bmHeader.biWidth;
long height = m_bmHeader.biHeight;
long bpp = m_bmHeader.biBitCount;
if(bpp < 1)
{
inFile.close();
return false;
}
// BYTES per line = (bits + 31) / 32 * 4.
m_nBpl = ((width * bpp + 31) >> 5) << 2;
long clrUsed = m_bmHeader.biClrUsed;
if(clrUsed == 0)
{
switch(bpp) {
case 1:
m_szRGBQuad = 2; break;
case 4:
m_szRGBQuad = 16;
break;
case 8:
m_szRGBQuad = 256;
break;
case 16:
// NO color table,the case : m_bmHeader.biCompression == BI_RGB
m_szRGBQuad = 0;
break;
default:
m_szRGBQuad = 0;
}
}
else
{
m_szRGBQuad = clrUsed;
}
// match the color table.
if(m_szRGBQuad != 0)
{
m_pRGBQuad = new RGBQUAD[m_szRGBQuad];
inFile.read((char*)m_pRGBQuad, sizeof(RGBQUAD)*m_szRGBQuad);
}
long nData = height * m_nBpl;
m_pData = new BYTE[nData]; // allocate a buffer for bm data.
inFile.read((char*)m_pData, sizeof(BYTE) * nData);
inFile.close();
return true;
}
bool CDib::Save(LPCTSTR strFileName)
{
std::ofstream outFile(strFileName,std::ios::binary | std::ios::out | std::ios::trunc);
if(!outFile.is_open())
return false;
WORD bmFlag[7]; // for BitmapFileHeader with 1 alignment.
bmFlag[0] = (WORD('B') | 'M'<<8);
long nData = m_bmHeader.biHeight * m_nBpl;
DWORD szFile = (sizeof(WORD) * 7) + sizeof(BITMAPINFOHEADER) +
(sizeof(RGBQUAD) * m_szRGBQuad) + (sizeof(BYTE) * nData);
bmFlag[1] = LOWORD(szFile) ;
bmFlag[2] = HIWORD(szFile);
DWORD szOffData = (sizeof(WORD) * 7) + sizeof(BITMAPINFOHEADER) +
(sizeof(RGBQUAD) * m_szRGBQuad);
bmFlag[5] = LOWORD(szOffData);
bmFlag[6] = HIWORD(szOffData);
outFile.write((char*)bmFlag, sizeof(WORD) * 7);
outFile.write((char*)&m_bmHeader, sizeof(BITMAPINFOHEADER));
if(m_szRGBQuad != 0)
outFile.write((char*)m_pRGBQuad, sizeof(RGBQUAD) * m_szRGBQuad);
outFile.write((char*)m_pData, sizeof(BYTE) * nData);
outFile.close();
return true;
}
void CDib::Show(HDC hdc, POINT pt)
{
assert(hdc);
HBITMAP hBmp = CreateDIBitmap(hdc, &m_bmHeader, CBM_INIT, m_pData,
(BITMAPINFO*)&m_bmHeader, DIB_RGB_COLORS);
HDC hMemDC = CreateCompatibleDC(hdc);
HBITMAP hOld = (HBITMAP)SelectObject(hMemDC, hBmp);
BitBlt(hdc, pt.x, pt.y, m_bmHeader.biWidth, m_bmHeader.biHeight,
hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC,hOld);
DeleteObject(hBmp);
DeleteDC(hMemDC);
return;
}
CDib* CDib::Rotate90() const
{
// first, check!
int bitCount = m_bmHeader.biBitCount;
if(!m_pData || bitCount % 8)
return NULL;
long newWidth = m_bmHeader.biHeight;
long newHeight = m_bmHeader.biWidth;
// second, create a new instance of CDib.
CDib* pRet = new CDib();
pRet->m_bmHeader = m_bmHeader;
pRet->m_bmHeader.biHeight = newHeight;
pRet->m_bmHeader.biWidth = newWidth;
pRet->m_nBpl = ((newWidth * bitCount + 31) >> 5) << 2;
pRet->m_szRGBQuad = m_szRGBQuad;
if( m_szRGBQuad != 0)
memcpy( pRet->m_pRGBQuad, m_pRGBQuad, sizeof(RGBQUAD) * m_szRGBQuad);
pRet->m_pData = new BYTE[pRet->m_nBpl * newHeight];
if(!pRet->m_pData) return NULL;
// third, copy the data.
switch(bitCount) {
case 8:
g_Rotate90 (this, pRet);
break;
case 15:
case 16:
g_Rotate90 (this, pRet);
break;
case 24:
g_Rotate90 (this, pRet);
break;
case 32:
g_Rotate90 (this, pRet);
break;
case 64:
g_Rotate90 (this, pRet);
break;
default:
assert(false);
delete pRet;
pRet = NULL;
}
return pRet;
}
测试代码(win32 helloworld project.):
// ...(略)
case ID_SAVE: // 保存
g_pdib->Save("abc.bmp");
break;
case ID_ROTATE: // 旋转
pDib = g_pdib->Rotate90();
delete g_pdib;
g_pdib = pDib;
GetClientRect(hWnd, &rect);
InvalidateRect(hWnd, &rect, FALSE);
break;
// ...(略)
case WM_PAINT: // 显示
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
RECT rt;
GetClientRect(hWnd, &rt);
// DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
pt.x = pt.y = 0;
g_pdib->Show(hdc, pt);
EndPaint(hWnd, &ps);
break;
----- 问题如下 ---
当代码执行到:
for(i = 0; i < desHeight; ++i) {
const pixel* pS = (pixel*)((BYTE*)pSrcData + srcBpl * srcHeightDec) + i ;
pixel* pD = (pixel*)((BYTE*)pDesData + desBpl * (desHeightDec - i));
for(j = 0; j < desWidth; ++j) {
*pD++ = *pS;
pS = (pixel*)((BYTE*)pS - srcBpl);
}
}
当 i = 888 时,程序出错,pS指针超出。调试了2个小时,实在没有结果。
谢谢大家的关注。
// ...(略)
case ID_SAVE: // 保存
g_pdib->Save("abc.bmp");
break;
case ID_ROTATE: // 旋转
pDib = g_pdib->Rotate90();
delete g_pdib;
g_pdib = pDib;
GetClientRect(hWnd, &rect);
InvalidateRect(hWnd, &rect, FALSE);
break;
// ...(略)
case WM_PAINT: // 显示
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
RECT rt;
GetClientRect(hWnd, &rt);
// DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
pt.x = pt.y = 0;
g_pdib->Show(hdc, pt);
EndPaint(hWnd, &ps);
break;
----- 问题如下 ---
当代码执行到:
for(i = 0; i < desHeight; ++i) {
const pixel* pS = (pixel*)((BYTE*)pSrcData + srcBpl * srcHeightDec) + i ;
pixel* pD = (pixel*)((BYTE*)pDesData + desBpl * (desHeightDec - i));
for(j = 0; j < desWidth; ++j) {
*pD++ = *pS;
pS = (pixel*)((BYTE*)pS - srcBpl);
}
}
当 i = 888 时,程序出错,pS指针超出。调试了2个小时,实在没有结果。
谢谢大家的关注。