www.gusucode.com > eMule电驴下载VC++源代码-源码程序 > eMule电驴下载VC++源代码-源码程序\code\srchybrid\CxImage\ximabmp.cpp
//Download by http://www.NewXing.com /* * File: ximabmp.cpp * Purpose: Platform Independent BMP Image Class Loader and Writer * 07/Aug/2001 <ing.davide.pizzolato@libero.it> * CxImage version 5.71 25/Apr/2003 */ #include "ximabmp.h" #if CXIMAGE_SUPPORT_BMP #include "ximaiter.h" const int RLE_COMMAND = 0; const int RLE_ENDOFLINE = 0; const int RLE_ENDOFBITMAP = 1; const int RLE_DELTA = 2; #if !defined(BI_RLE8) #define BI_RLE8 1L #endif #if !defined(BI_RLE4) #define BI_RLE4 2L #endif //////////////////////////////////////////////////////////////////////////////// #if CXIMAGE_SUPPORT_ENCODE //////////////////////////////////////////////////////////////////////////////// bool CxImageBMP::Encode(CxFile * hFile) { if (hFile==NULL) return false; BITMAPFILEHEADER hdr; hdr.bfType = 0x4d42; // 'BM' WINDOWS_BITMAP_SIGNATURE hdr.bfSize = GetSize() + sizeof(BITMAPFILEHEADER); hdr.bfReserved1 = hdr.bfReserved2 = 0; hdr.bfOffBits = (DWORD) sizeof(hdr) + head.biSize + GetPaletteSize(); //copy attributes memcpy(pDib,&head,sizeof(BITMAPINFOHEADER)); // Write the file header hFile->Write(&hdr,sizeof(BITMAPFILEHEADER),1); // Write the DIB header and the pixels hFile->Write(pDib,GetSize(),1); return true; } //////////////////////////////////////////////////////////////////////////////// #endif //CXIMAGE_SUPPORT_ENCODE //////////////////////////////////////////////////////////////////////////////// #if CXIMAGE_SUPPORT_DECODE //////////////////////////////////////////////////////////////////////////////// bool CxImageBMP::Decode(CxFile * hFile) { if (hFile == NULL) return false; BITMAPFILEHEADER bf; DWORD off = hFile->Tell(); //<CSC> try { if (hFile->Read(&bf,sizeof(bf),1)==0) throw "Not a BMP"; if (bf.bfType != BFT_BITMAP) { //do we have a RC HEADER? bf.bfOffBits = 0L; hFile->Seek(off,SEEK_SET); } if (!DibReadBitmapInfo(hFile,&head)) throw "Error reading BMP info"; DWORD dwCompression=head.biCompression; DWORD dwBitCount=head.biBitCount; //preserve for BI_BITFIELDS compression <Thomas Ernst> bool bIsOS2 = head.biSize != sizeof(BITMAPINFOHEADER); head.biSize = sizeof(BITMAPINFOHEADER); bool bTopDownDib = head.biHeight<0; //<Flanders> check if it's a top-down bitmap if (bTopDownDib) head.biHeight=-head.biHeight; if (!Create(head.biWidth,head.biHeight,head.biBitCount,CXIMAGE_FORMAT_BMP)) throw "Can't allocate memory"; info.xDPI = (long) floor(head.biXPelsPerMeter * 254.0 / 10000.0 + 0.5); info.yDPI = (long) floor(head.biYPelsPerMeter * 254.0 / 10000.0 + 0.5); if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding RGBQUAD *pRgb = GetPalette(); if (pRgb){ if (bIsOS2){ // convert a old color table (3 byte entries) to a new // color table (4 byte entries) hFile->Read((void*)pRgb,DibNumColors(&head) * sizeof(RGBTRIPLE),1); for (int i=DibNumColors(&head)-1; i>=0; i--){ pRgb[i].rgbRed = ((RGBTRIPLE *)pRgb)[i].rgbtRed; pRgb[i].rgbBlue = ((RGBTRIPLE *)pRgb)[i].rgbtBlue; pRgb[i].rgbGreen = ((RGBTRIPLE *)pRgb)[i].rgbtGreen; pRgb[i].rgbReserved = (BYTE)0; } } else { hFile->Read((void*)pRgb,DibNumColors(&head) * sizeof(RGBQUAD),1); } } if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding switch (dwBitCount) { case 32 : if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB){ long imagesize=4*head.biHeight*head.biWidth; BYTE* buff32=(BYTE*)malloc(imagesize); if (buff32){ hFile->Read(buff32, imagesize,1); // read in the pixels Bitfield2RGB(buff32,0,0,0,32); free(buff32); } else throw "can't allocate memory"; } else throw "unknown compression"; break; case 24 : if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); if (dwCompression == BI_RGB){ hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels } else throw "unknown compression"; 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 hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1); // transform into RGB Bitfield2RGB(info.pImage,(WORD)bfmask[0],(WORD)bfmask[1],(WORD)bfmask[2],16); break; } case 8 : case 4 : case 1 : if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET); switch (dwCompression) { case BI_RGB : hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels break; case BI_RLE4 : { BYTE status_byte = 0; BYTE second_byte = 0; int scanline = 0; int bits = 0; BOOL low_nibble = FALSE; CImageIterator iter(this); for (BOOL bContinue = TRUE; bContinue;) { hFile->Read(&status_byte, sizeof(BYTE), 1); switch (status_byte) { case RLE_COMMAND : hFile->Read(&status_byte, sizeof(BYTE), 1); switch (status_byte) { case RLE_ENDOFLINE : bits = 0; scanline++; low_nibble = FALSE; break; case RLE_ENDOFBITMAP : bContinue=FALSE; break; case RLE_DELTA : { // read the delta values BYTE delta_x; BYTE delta_y; hFile->Read(&delta_x, sizeof(BYTE), 1); hFile->Read(&delta_y, sizeof(BYTE), 1); // apply them bits += delta_x / 2; scanline += delta_y; break; } default : hFile->Read(&second_byte, sizeof(BYTE), 1); BYTE *sline = iter.GetRow(scanline); for (int i = 0; i < status_byte; i++) { if (low_nibble) { if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ *(sline + bits) |= second_byte & 0x0F; } if (i != status_byte - 1) hFile->Read(&second_byte, sizeof(BYTE), 1); bits++; } else { if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ *(sline + bits) = (BYTE)(second_byte & 0xF0); } } low_nibble = !low_nibble; } if (((status_byte / 2) & 1 )== 1) hFile->Read(&second_byte, sizeof(BYTE), 1); break; }; break; default : { BYTE *sline = iter.GetRow(scanline); hFile->Read(&second_byte, sizeof(BYTE), 1); for (unsigned i = 0; i < status_byte; i++) { if (low_nibble) { if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ *(sline + bits) |= second_byte & 0x0F; } bits++; } else { if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){ *(sline + bits) = (BYTE)(second_byte & 0xF0); } } low_nibble = !low_nibble; } } break; }; } break; } case BI_RLE8 : { BYTE status_byte = 0; BYTE second_byte = 0; int scanline = 0; int bits = 0; CImageIterator iter(this); for (BOOL bContinue = TRUE; bContinue; ) { hFile->Read(&status_byte, sizeof(BYTE), 1); switch (status_byte) { case RLE_COMMAND : hFile->Read(&status_byte, sizeof(BYTE), 1); switch (status_byte) { case RLE_ENDOFLINE : bits = 0; scanline++; break; case RLE_ENDOFBITMAP : bContinue=FALSE; break; case RLE_DELTA : { // read the delta values BYTE delta_x; BYTE delta_y; hFile->Read(&delta_x, sizeof(BYTE), 1); hFile->Read(&delta_y, sizeof(BYTE), 1); // apply them bits += delta_x; scanline += delta_y; break; } default : hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(BYTE) * status_byte, 1); // align run length to even number of bytes if ((status_byte & 1) == 1) hFile->Read(&second_byte, sizeof(BYTE), 1); bits += status_byte; break; }; break; default : BYTE *sline = iter.GetRow(scanline); hFile->Read(&second_byte, sizeof(BYTE), 1); for (unsigned i = 0; i < status_byte; i++) { *(sline + bits) = second_byte; bits++; } break; }; } break; } default : throw "compression type not supported"; } } if (bTopDownDib) Flip(); //<Flanders> } catch (char *message) { strncpy(info.szLastError,message,255); return false; } return true; } //////////////////////////////////////////////////////////////////////////////// /* 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 CxImageBMP::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(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: return false; } FixBitmapInfo(pdib); return true; } //////////////////////////////////////////////////////////////////////////////// #endif //CXIMAGE_SUPPORT_DECODE //////////////////////////////////////////////////////////////////////////////// #endif // CXIMAGE_SUPPORT_BMP ////////////////////////////////////////////////////////////////////////////////