📄 bmpprocessor.cpp
字号:
// BmpProcessor.cpp: implementation of the CBmpProcessor class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ResourceEditor.h"
#include "BmpProcessor.h"
#include "Converter.h"
//#include "dal_img.h"
//#include "Img_port.h"
#define IMG_SUCCESS 0
extern "C" void IMG_xFreeMem(void *ptr);
extern "C" uint32 IMG_CompressBmp(
const uint8 *bmpfile_stream,
uint8 **code_stream,
uint32 *codelen
);
extern "C" uint32 IMG_CompressMovie(
const char *dirname,
uint32 framenum,
uint8 **code_stream,
uint32 *codelen,
uint32 same_color888
);
extern "C" uint32 IMG_ExtractBmp(
const uint8* code_stream,
uint8 **bmpfile_stream,
uint32 *filelen
);
extern "C" uint32 IMG_ExtractMovie(
const uint8* code_stream,
char *dirname,
uint32 *framenum
);
extern "C" uint32 IMG_ExtractMovieByIdx(
const uint8* code_stream,
uint8 ** pBmp,
uint16 index
);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBmpProcessor::CBmpProcessor()
{
*m_szErrMsg = 0;
}
CBmpProcessor::~CBmpProcessor()
{
}
BOOL CBmpProcessor::LoadBmpFile( LPCTSTR pszFileName, LPBYTE * pBmpStream,
int * pSize /* = NULL */, BOOL b565 /* = TRUE */ )
{
_ASSERTE( pszFileName != NULL );
_ASSERTE( pBmpStream != NULL );
HANDLE hFile = ::CreateFile( pszFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
_stprintf(m_szErrMsg, _T("The file '%s' not exist!"), pszFileName);
return FALSE;
}
int nSize = (int)GetFileSize(hFile, NULL);
if( nSize < sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) )
{
::CloseHandle(hFile);
_stprintf(m_szErrMsg, _T("The file '%s' size is too little!"), pszFileName);
return FALSE;
}
LPBYTE pBmp = (LPBYTE)malloc(nSize);
//memset( pBmp,0xff,nSize );
if( NULL == pBmp )
{
::CloseHandle(hFile);
return FALSE;
}
DWORD dwRead = 0;
if( !ReadFile(hFile, pBmp, nSize, &dwRead, NULL) || nSize != (int)dwRead )
{
TRACE1("ReadFile %s error!\r\n", pszFileName);
_stprintf(m_szErrMsg, _T("ReadFile '%s' error!"), pszFileName);
::CloseHandle(hFile);
return FALSE;
}
::CloseHandle(hFile);
PBITMAPFILEHEADER pbfh = (PBITMAPFILEHEADER)pBmp;
if( pbfh->bfType != 0x4d42 )
{
free(pBmp);
_stprintf(m_szErrMsg, _T("The file '%s' is incorrect bitmap file!"), pszFileName);
return FALSE;
}
// @ Hongliang Xin 2006-8-11
if(pbfh->bfSize != (unsigned int)nSize)
{
pbfh->bfSize = (unsigned int)nSize;
}
PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER)(pbfh + 1);
BOOL bRet = TRUE;
if( !b565 )
{
if( pbih->biBitCount != 24 && pbih->biBitCount != 16 )
{
free(pBmp);
_tcscpy(m_szErrMsg, _T("Currently, we only support 24 or 16 bit") );
return FALSE;
}
*pBmpStream = pBmp;
}
else
{
if( pbih->biBitCount == 24 )
{
LPBYTE p565Bmp = NULL;
bRet = Convert24To565Stream(pBmp, p565Bmp, nSize);
if( bRet )
{
*pBmpStream = p565Bmp;
free(pBmp);
}
}
else if( pbih->biBitCount == 16 )
{
LPDWORD pRedMask = (LPDWORD)(pbih + 1);
if( *pRedMask == 0xF800 )
{
_ASSERTE( *(pRedMask+1) == 0x07E0 );
_ASSERTE( *(pRedMask+2) == 0x001F );
int nDelta = pbfh->bfOffBits - sizeof(BITMAPFILEHEADER) -
sizeof(BITMAPINFOHEADER) - 3 * sizeof(DWORD);
if( nDelta > 0 )
{
pbfh->bfSize -= nDelta;
LPBYTE pBmpData = (LPBYTE)(pBmp + pbfh->bfOffBits);
pbfh->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
3 * sizeof(DWORD);
pbih->biSize = sizeof(BITMAPINFOHEADER);
MoveMemory( pBmp + pbfh->bfOffBits, pBmpData, pbfh->bfSize - pbfh->bfOffBits );
LPBYTE pBmpFile = new BYTE[pbfh->bfSize];
if(pBmpFile == NULL)
{
free(pBmp);
return FALSE;
}
CopyMemory(pBmpFile,pBmp,pbfh->bfSize);
free(pBmp);
pBmp = pBmpFile;
}
else
{
pbih->biSizeImage = pbfh->bfSize - pbfh->bfOffBits;//
}
*pBmpStream = pBmp;
}
else
{
LPBYTE p565Bmp = NULL;
bRet = Convert555To565Stream(pBmp, p565Bmp, nSize);
if( bRet )
{
*pBmpStream = p565Bmp;
free(pBmp);
}
}
}
else
{
free(pBmp);
_tcscpy(m_szErrMsg, _T("Currently, we only support 24 or 16 bit") );
return FALSE;
}
}
if( pSize != NULL )
*pSize = nSize;
return bRet;
}
CSize CBmpProcessor::GetBmpSize( LPBYTE pBmp )
{
_ASSERTE( pBmp != NULL );
PBITMAPFILEHEADER pbfh = (PBITMAPFILEHEADER)pBmp;
_ASSERTE(pbfh->bfType == 0x4d42);
PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER)(pbfh + 1);
return CSize(pbih->biWidth, pbih->biHeight);
}
CSize CBmpProcessor::GetMovieSize( LPBYTE pMovie )
{
_ASSERTE( pMovie != NULL );
PBITMAPFILEHEADER pbfh = (PBITMAPFILEHEADER)pMovie;
_ASSERTE(pbfh->bfType == 0x4D56); // "MV"
PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER)(pbfh + 1);
return CSize(pbih->biWidth, pbih->biHeight);
}
HBITMAP CBmpProcessor::CreateBitmap( LPBYTE pBmpStream )
{
_ASSERTE( NULL != pBmpStream );
PBITMAPFILEHEADER pbfh = (PBITMAPFILEHEADER)pBmpStream;
PBITMAPINFO pbi = (PBITMAPINFO)(pbfh + 1);
pBmpStream += pbfh->bfOffBits;
LPBYTE pBits = NULL;
HBITMAP hBmp = ::CreateDIBSection(NULL, pbi, DIB_RGB_COLORS, (LPVOID *)&pBits, NULL, 0 );
// 注意文件中数据的内容长度可能大于实际数据的长度
int nSize = ((pbi->bmiHeader.biWidth * pbi->bmiHeader.biBitCount + 31) &~31) / 8;;
nSize *= pbi->bmiHeader.biHeight;
memcpy(pBits, pBmpStream, nSize);
return hBmp;
}
HBITMAP CBmpProcessor::CreateBitmap( LPCTSTR pszFileName )
{
_ASSERTE( pszFileName != NULL );
LPBYTE pBmp = NULL;
HBITMAP hBmp = NULL;
if( LoadBmpFile(pszFileName, &pBmp) )
{
hBmp = CreateBitmap(pBmp);
free(pBmp);
}
return hBmp;
}
void CBmpProcessor::DeleteBitmap( HBITMAP hBmp )
{
_ASSERTE( hBmp != NULL );
::DeleteObject(hBmp);
}
// 将原始位图数据流转换为16位565格式的数据流(这里的数据流指完整的位图文件内容)
// 如果pBmp就是16位565格式的,直接返回此指针,否则会产生新的内存块
BOOL CBmpProcessor::Convert24To565Stream( LPBYTE p24Bmp, LPBYTE &p16Bmp, int &nSize )
{
_ASSERTE( p24Bmp != NULL );
PBITMAPFILEHEADER p24bfh = (PBITMAPFILEHEADER)p24Bmp;
_ASSERTE(p24bfh->bfType == 0x4d42);
PBITMAPINFOHEADER p24bih = (PBITMAPINFOHEADER)(p24bfh + 1);
_ASSERTE( p24bih->biBitCount == 24 );
LPBYTE p24Data = p24Bmp + p24bfh->bfOffBits;
int nWidth = p24bih->biWidth;
int nHeight = p24bih->biHeight;
int n24RowSize = ( (nWidth * 24 + 31) & ~31 ) / 8;
int n16RowSize = ( (nWidth * 16 + 31) & ~31 ) / 8;
nSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
3 * sizeof(DWORD) + n16RowSize * nHeight;
p16Bmp = (LPBYTE)malloc(nSize);
if( NULL == p16Bmp )
{
nSize = 0;
return FALSE;
}
memset( p16Bmp, 0, nSize );
PBITMAPFILEHEADER p16bfh = (PBITMAPFILEHEADER)p16Bmp;
memcpy(p16bfh, p24bfh, sizeof(BITMAPFILEHEADER));
p16bfh->bfOffBits = nSize - n16RowSize * nHeight;
p16bfh->bfSize = nSize;
PBITMAPINFOHEADER p16bih = (PBITMAPINFOHEADER)(p16bfh + 1);
memcpy(p16bih, p24bih, sizeof(BITMAPINFOHEADER));
p16bih->biSize = sizeof(BITMAPINFOHEADER);
p16bih->biBitCount = 16;
p16bih->biCompression = BI_BITFIELDS;
p16bih->biSizeImage = 0;
p16bih->biClrUsed = 0;
LPDWORD pRedMask = (LPDWORD)(p16bih + 1);
*pRedMask = 0xF800;
LPDWORD pGreenMask = pRedMask + 1;
*pGreenMask = 0x07E0;
LPDWORD pBlueMask = pGreenMask + 1;
*pBlueMask = 0x001F;
LPBYTE p16Data = (LPBYTE)(pBlueMask + 1);
for( int i = 0; i < nHeight; ++i )
{
Bmp24To565(p24Data + i * n24RowSize, nWidth * 3, (LPWORD)p16Data, n16RowSize);
p16Data += n16RowSize;
}
// 调试用
//FILE * pfile = fopen("c:\\24to565.bmp", "wb");
//fwrite(p16Bmp, 1, nSize, pfile);
//fclose(pfile);
return TRUE;
}
void CBmpProcessor::Bmp24To565(LPBYTE p888, int n888Size, LPWORD p565, int n565Size)
{
_ASSERTE( p888 != NULL && p565 != NULL );
_ASSERTE( n888Size * 2 / 3 <= n565Size );
WORD wValue;
for(int i = 0; i < (int)n888Size; i += 3)
{
wValue = *p888 >> 3;
*p565 = wValue;
p888++;
wValue = *p888 >> 2;
wValue <<= 5;
*p565 |= wValue;
p888++;
wValue = *p888 >> 3;
wValue <<= 11;
*p565 |= wValue;
p888++;
p565++;
}
}
BOOL CBmpProcessor::Convert555To565Stream( LPBYTE p555Bmp, LPBYTE &p565Bmp, int &nSize )
{
_ASSERTE( p555Bmp != NULL );
PBITMAPFILEHEADER p555bfh = (PBITMAPFILEHEADER)p555Bmp;
_ASSERTE(p555bfh->bfType == 0x4d42);
PBITMAPINFOHEADER p555bih = (PBITMAPINFOHEADER)(p555bfh + 1);
_ASSERTE( p555bih->biBitCount == 16 );
LPWORD p555Data = (LPWORD)(p555Bmp + p555bfh->bfOffBits);
int nWidth = p555bih->biWidth;
int nHeight = p555bih->biHeight;
int n16RowSize = ( (nWidth * 16 + 31) & ~31 ) / 8;
nSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
3 * sizeof(DWORD) + n16RowSize * nHeight;
p565Bmp = (LPBYTE)malloc(nSize);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -