📄 jzimagebmp.cpp
字号:
// JzImageBmp.cpp: implementation of the CJzImageBmp class.
//
//////////////////////////////////////////////////////////////////////
#include "JzImageBmp.h"
#include "JzImageInfo.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CJzImageBmp::CJzImageBmp()
{
}
CJzImageBmp::~CJzImageBmp()
{
}
bool CJzImageBmp::Decode(CxFile * mhFile)
{
hFile = mhFile;
if (hFile == NULL) return false;
dwCompression=bmpHeader.biCompression;
DWORD dwBitCount;
off = hFile->Tell(); //<CSC>
pRgb = NULL;
if (hFile->Read(&bf,min(14,sizeof(bf)),1)==0)
{
printf("Not a BMP!");
goto EXIT;
}
if (bf.bfType != BFT_BITMAP) { //do we have a RC HEADER?
bf.bfOffBits = 0L;
hFile->Seek(off,SEEK_SET);
}
if (!DibReadBitmapInfo(hFile,&bmpHeader))
{
printf("Error reading BMP info!\n");
goto EXIT;
}
bTopDownDib = bmpHeader.biHeight<0; //<Flanders> check if it's a top-down bitmap
dwCompression=bmpHeader.biCompression;
dwBitCount=bmpHeader.biBitCount; //preserve for BI_BITFIELDS compression <Thomas Ernst>
bIsOldBmp = bmpHeader.biSize == sizeof(BITMAPCOREHEADER);
if (info.nEscape == -1) {
// Return output dimensions only
info.dwWidth = bmpHeader.biWidth;
info.dwHeight = bmpHeader.biHeight;
printf("output dimensions returned");
goto EXIT;
}
if (bTopDownDib) bmpHeader.biHeight=-bmpHeader.biHeight;
printf(" ================= bmpHeader.biBitCount: %d ============\n", bmpHeader.biBitCount);
{
IVSETIMAGEINFO ivSetImageInfo = ivGetImageInfoCallback();
if( ivSetImageInfo )
{
IVIMAGEINFO ImageInfo;
ImageInfo.w = bmpHeader.biWidth;
ImageInfo.h = bmpHeader.biHeight;
ImageInfo.bpp = bmpHeader.biBitCount;
ivSetImageInfo( &ImageInfo );
info.dwimaWidth = ImageInfo.w;
info.dwimaHeight = ImageInfo.h;
info.pImage = ImageInfo.pImage;
ivscale = ImageInfo.ivscale;
if( info.pImage == NULL ) return FALSE;
}
}
if( bmpHeader.biBitCount < 16 ) return FALSE;
printf("bmpHeader.biWidth,bmpHeader.biHeight= %d, %d \n",bmpHeader.biWidth,bmpHeader.biHeight);
if (!CreateImageInfo(bmpHeader.biWidth,bmpHeader.biHeight,bmpHeader.biBitCount,CXIMAGE_FORMAT_BMP))
{
printf("Can't allocate memory!");
goto EXIT;
}
if (info.nEscape)
{
printf("Cancelled!\n"); // <vho> - cancel decoding
goto EXIT;
}
if(bmpHeader.biBitCount <= 8)
if(bIsOldBmp)
pRgb = new RGBQUAD[DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE)];
else
pRgb = new RGBQUAD[DibNumColors(&bmpHeader) * sizeof(RGBQUAD)];
if (pRgb){
if (bIsOldBmp){
// convert a old color table (3 byte entries) to a new
// color table (4 byte entries)
hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1);
} else {
hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1);
//force rgbReserved=0, to avoid problems with some WinXp bitmaps
}
}
if (info.nEscape){
printf("Cancelled\n"); // <vho> - cancel decoding
goto EXIT;
}
switch (dwBitCount) {
case 32 :
if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB){
if(!Read32BPPData(dwBitCount,0))
goto EXIT;
} else
{
printf("unknown compression\n");
goto EXIT;
}
break;
case 24 :
if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
if (dwCompression == BI_RGB){
if(!Read32BPPData(dwBitCount,0))
{
printf(" exit bmp\n");
goto EXIT;
}
} else
printf("unknown compression\n");
break;
case 16 :
{
DWORD bfmask[3];
if (dwCompression == BI_BITFIELDS)
{
hFile->Read(bfmask, 12, 1);
} else {
bfmask[0]=0x7C00; bfmask[1]=0x3E0; bfmask[2]=0x1F; //RGB555
}
// bf.bfOffBits required after the bitfield mask <Cui Ying Jie>
if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
// read in the pixels
if(!Read32BPPData(dwBitCount,(unsigned int *)bfmask))
goto EXIT;
break;
}
case 8 :
case 4 :
case 1 :
return false;
if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
switch (dwCompression) {
case BI_RGB :
if(!Read4BPPData(dwBitCount))
goto EXIT; // read in the pixels
break;
default :
{
printf("compression type not supported\n");
goto EXIT;
}
}
}
if(pRgb)
delete[] pRgb;
return true;
EXIT:
if (info.nEscape==-1) return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////
/* ReadDibBitmapInfo()
*
* Will read a file in DIB format and return a global HANDLE to its
* BITMAPINFO. This function will work with both "old" and "new"
* bitmap formats, but will always return a "new" BITMAPINFO.
*/
bool CJzImageBmp::DibReadBitmapInfo(CxFile* fh, BITMAPINFOHEADER *pdib)
{
if ((fh==NULL)||(pdib==NULL)) return false;
if (fh->Read(pdib,sizeof(BITMAPINFOHEADER),1)==0) return false;
BITMAPCOREHEADER bc;
switch (pdib->biSize) // what type of bitmap info is this?
{
case sizeof(BITMAPINFOHEADER):
break;
case 64: //sizeof(OS2_BMP_HEADER):
fh->Seek((long)(64 - sizeof(BITMAPINFOHEADER)),SEEK_CUR);
break;
case sizeof(BITMAPCOREHEADER):
bc = *(BITMAPCOREHEADER*)pdib;
pdib->biSize = bc.bcSize;
pdib->biWidth = (DWORD)bc.bcWidth;
pdib->biHeight = (DWORD)bc.bcHeight;
pdib->biPlanes = bc.bcPlanes;
pdib->biBitCount = bc.bcBitCount;
pdib->biCompression = BI_RGB;
pdib->biSizeImage = 0;
pdib->biXPelsPerMeter = 0;
pdib->biYPelsPerMeter = 0;
pdib->biClrUsed = 0;
pdib->biClrImportant = 0;
fh->Seek((long)(sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER)), SEEK_CUR);
break;
default:
//give a last chance
if (pdib->biSize > (sizeof(BITMAPINFOHEADER))&&
(pdib->biSizeImage==(unsigned long)(pdib->biHeight*((((pdib->biBitCount*pdib->biWidth)+31)/32)*4)))&&
(pdib->biPlanes==1)&&(pdib->biCompression==BI_RGB)&&(pdib->biClrUsed==0))
{
fh->Seek((long)(pdib->biSize - sizeof(BITMAPINFOHEADER)),SEEK_CUR);
break;
}
return false;
}
FixBitmapInfo(pdib);
return true;
}
#if 1
bool CJzImageBmp::Read32BPPData(unsigned int wBpp,unsigned int *mask)
{
DWORD i, j;
RGBQUAD c;
int dx, dy, direction = 0;
BYTE *src = NULL;
//info.dwEffWidth = pScr->w*4;
printf(" ======== wBpp: %d\n", wBpp );
unsigned int byte = wBpp / 8;
//long imagesize=info.dwEffWidth;
long imagesize=((((wBpp * bmpHeader.biWidth) + 31) / 32) * 4);
printf(" ========== imagesize: %d\n", imagesize );
BYTE* psrc= (BYTE*)malloc(imagesize);
info.dwEffWidth = info.dwimaWidth*4;
//ivscale = (int)( ((float)info.dwimaWidth/bmpHeader.biWidth)*128.0+1 );
//if( ivscale > 128 ) ivscale = 128;
BYTE *line = info.pImage+info.dwimaWidth*(info.dwimaHeight - 1)*4;
//unsigned int *ptar = pScr->buffer;//for test
//ptar += pScr->w * (info.dwimaHeight - 1);
printf("cpp ============info.dwimaWidth: %d, info.dwimaHeight: %d\n", info.dwimaWidth, info.dwimaHeight );
dy = 0;
for( j = 0; j < info.dwimaHeight; j++ )
{
memset( line, 0, info.dwEffWidth );
while( ivscale*dy/128 <= j )
{
if(!hFile->Read(psrc, imagesize, 1))
{
printf("11Read File Error!");
//return false;
}
dy++;
}
//////////// row
dx = 0;
for( i = 0; i < info.dwimaWidth; i++ )
{
while( ivscale*dx/128 < i ) dx++;
Bitfield2BPP(wBpp,mask,&psrc[dx * byte],&c);
line[i * 4 + 2] = (unsigned int) c.rgbBlue;
line[i * 4 + 1] = (unsigned int) c.rgbGreen;
line[i * 4 + 0] = (unsigned int) c.rgbRed;
}
///////////
//memcpy( (void *)ptar, line, info.dwEffWidth );
//ptar -= pScr->w;
//line = line + info.dwimaWidth*4;
line = line - info.dwimaWidth*4;
}
//test
free(psrc);
return true;
}
#endif
#if 0
bool CJzImageBmp::Read32BPPData(unsigned int wBpp,unsigned int *mask)
{
long imagesize=info.dwEffWidth;
BYTE* psrc= (BYTE*)malloc(imagesize);
DWORD *xtotal,ytotal;
xtotal = (DWORD *)malloc( sizeof(DWORD) *info.dwimaWidth);
unsigned int *line = (unsigned int *)malloc(info.dwimaWidth * 3 * sizeof(unsigned int));
int dx,dy;
unsigned int *ptar = pScr->buffer;
ptar += pScr->w * (info.dwimaHeight - 1);
dy = 0;
unsigned int byte = wBpp / 8;
for(DWORD i = 0;i < info.dwimaHeight ;i++)
{
ytotal = 0;
memset(line,0,sizeof(unsigned int) * info.dwimaWidth * 3);
while((DWORD)((float)dy * fyscale) == i)
{
if(!hFile->Read(psrc, imagesize, 1))
{
printf("Read File Error!");
return false;
}
dx = 0;
for(DWORD j = 0; j < info.dwimaWidth; j++)
{
xtotal[j] = 0;
while((DWORD)((float)dx * fxscale) == j)
{
RGBQUAD c;
Bitfield2BPP(wBpp,mask,&psrc[dx * byte],&c);
line[j * 3 + 0] += (unsigned int) c.rgbBlue;
line[j * 3 + 1] += (unsigned int) c.rgbGreen;
line[j * 3 + 2] += (unsigned int) c.rgbRed;
xtotal[j]++;
dx++;
}
}
dy++;
ytotal++;
}
for(DWORD j = 0;j < info.dwimaWidth;j++)
{
int av = xtotal[j] * ytotal;
if(av == 0) av = 1;
ptar[j] = SETRGB(line[j * 3 + 0] / av, line[j * 3 + 1] / av,line[j * 3 + 2] / av);
}
ptar -= pScr->w;
}
free(psrc);
free(xtotal);
free(line);
return true;
}
#endif
#if 1
bool CJzImageBmp::Read4BPPData(unsigned int wBpp)
{
long imagesize=info.dwEffWidth;
BYTE* psrc= (BYTE*)malloc(imagesize);
DWORD *xtotal,ytotal;
xtotal = (DWORD *)malloc( sizeof(DWORD) *info.dwimaWidth);
unsigned int *line = (unsigned int *)malloc(info.dwimaWidth * 3 * sizeof(unsigned int));
int dx,dy;
unsigned int *ptar = pScr->buffer;
ptar += pScr->w * (info.dwimaHeight - 1);
dy = 0;
unsigned char bi = 8 / wBpp;
for(DWORD i = 0;i < info.dwimaHeight ;i++)
{
ytotal = 0;
memset(line,0,sizeof(unsigned int) * info.dwimaWidth * 3);
while((DWORD)((float)dy * fyscale) == i)
{
if(!hFile->Read(psrc, imagesize, 1))
{
printf("Read File Error!");
return false;
}
dx = 0;
DWORD n = 0;
unsigned char d;
for(DWORD j = 0; j < info.dwimaWidth; j++)
{
xtotal[j] = 0;
while((DWORD)((float)dx * fxscale) == j)
{
if(dx % bi == 0)
d = psrc[dx / bi];
RGBQUAD c;
Bitfield2BPP(wBpp,0,&d,&c);
line[j * 3 + 0] += (unsigned int) c.rgbBlue;
line[j * 3 + 1] += (unsigned int) c.rgbGreen;
line[j * 3 + 2] += (unsigned int) c.rgbRed;
d = d >> wBpp;
xtotal[j]++;
dx++;
}
}
dy++;
ytotal++;
}
for(DWORD j = 0;j < info.dwimaWidth;j++)
{
int av = xtotal[j] * ytotal;
if(av == 0) av = 1;
ptar[j] = SETRGB(line[j * 3 + 0] / av, line[j * 3 + 1] / av,line[j * 3 + 2] / av);
}
ptar -= pScr->w;
}
free(psrc);
free(xtotal);
free(line);
return true;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -