/* =========================================================================== Doom 3 GPL Source Code Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). Doom 3 Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Doom 3 Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Doom 3 Source Code. If not, see . In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ #include "../../idlib/precompiled.h" #pragma hdrstop #ifdef ID_DEBUG_MEMORY #undef new #endif #include "math.h" #include "CDIB.h" // Original ColorPicker/DIB source by Rajiv Ramachandran // included with Permission from the author #define BIG_DISTANCE 10000000L #define DIST(r1,g1,b1,r2,g2,b2) \ (long) (3L*(long)((r1)-(r2))*(long)((r1)-(r2)) + \ 4L*(long)((g1)-(g2))*(long)((g1)-(g2)) + \ 2L*(long)((b1)-(b2))*(long)((b1)-(b2))) static unsigned char masktable[] = { 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 }; CDIB::CDIB(HANDLE hDib,int nBits) { m_pVoid = NULL; m_pLinePtr = NULL; m_bUseGamma=FALSE; width=height=0; if(hDib) { CreateFromHandle(hDib,nBits); } } CDIB::~CDIB() { DestroyDIB(); } void CDIB::DestroyDIB() { if(m_pVoid) free(m_pVoid); m_pVoid = NULL; if(m_pLinePtr) free(m_pLinePtr); m_pLinePtr = NULL; } BOOL CDIB::Create(int width,int height,int bits) { /* Free existing image */ DestroyDIB(); // ASSERT(bits == 24 || bits == 8); BITMAPINFOHEADER bmInfo; memset(&bmInfo,0,sizeof(BITMAPINFOHEADER)); bmInfo.biSize = sizeof(BITMAPINFOHEADER); bmInfo.biWidth = width; bmInfo.biHeight = height; bmInfo.biPlanes = 1; bmInfo.biBitCount = bits; bmInfo.biCompression = BI_RGB; return Create(bmInfo); } BOOL CDIB::Create(BITMAPINFOHEADER& bmInfo) { bytes = (bmInfo.biBitCount*bmInfo.biWidth)>>3; height = bmInfo.biHeight; width = bmInfo.biWidth; // bmInfo.biHeight *= -1; while(bytes%4) bytes++; int size; size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize(bmInfo) + bytes*height; m_pVoid = (void *)malloc(size); if(!m_pVoid) return FALSE; m_pInfo = (PBITMAPINFO )m_pVoid; memcpy((void *)&m_pInfo->bmiHeader,(void *)&bmInfo,sizeof(BITMAPINFOHEADER)); m_pRGB = (RGBQUAD *)((unsigned char *)m_pVoid + sizeof(BITMAPINFOHEADER)) ; m_pBits = (unsigned char *)(m_pVoid) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize(); int i; BYTE **ptr; m_pLinePtr = (BYTE **)malloc(sizeof(BYTE *)*height); if(!m_pLinePtr) return FALSE; for(i=0,ptr=m_pLinePtr; i < height; i++,ptr++) { //*ptr = (int)(m_pBits)+(i*bytes); //*ptr = (int)GetLinePtr(i); *ptr = m_pBits + (height-i-1)*bytes; } m_nFlags = 0; return TRUE; } void CDIB::SetPalette(unsigned char *palette) { int i,size; RGBQUAD *rgb; if(!palette) return; size = GetPaletteSize(); for(i=0,rgb = m_pRGB; i < size; i++,rgb++,palette+=3) { if(m_bUseGamma) { rgb->rgbRed = Gamma[palette[0]]; rgb->rgbGreen = Gamma[palette[1]]; rgb->rgbBlue = Gamma[palette[2]]; } else { rgb->rgbRed = palette[0]; rgb->rgbGreen = palette[1]; rgb->rgbBlue = palette[2]; } rgb->rgbReserved = (BYTE)0; } } void CDIB::SetPalette(RGBQUAD *pRGB) { int size; if(!pRGB) return; size = GetPaletteSize(); memcpy(m_pRGB,pRGB,size*sizeof(RGBQUAD)); } int CDIB::GetPaletteSize() { return GetPaletteSize(m_pInfo->bmiHeader); } int CDIB::GetPaletteSize(BITMAPINFOHEADER& bmInfo) { switch(bmInfo.biBitCount) { case 1: return 2; case 4: return 16; case 8: return 256; default: return 0; } } void CDIB::SetPixel(int x,int y,COLORREF color) { unsigned char *ptr; ASSERT(x >= 0 && y >=0); ASSERT(x < width && y < height); // ptr = m_pBits + (y*bytes) + x * 3; ptr = (unsigned char *)m_pLinePtr[y]; ptr += x*3; *ptr++ = (unsigned char)GetBValue(color); *ptr++ = (unsigned char)GetGValue(color); *ptr++ = (unsigned char)GetRValue(color); } void CDIB::SetPixel8(int x,int y,unsigned char color) { unsigned char *ptr,*aptr; ASSERT(x >= 0 && y >=0); ASSERT(x < width && y < height); // ptr = m_pBits + (y*bytes) + x ; // ptr = (unsigned char *)m_pLinePtr[y] ; ptr = GetLinePtr(y); aptr = ptr; ptr += x; *ptr = color; } COLORREF CDIB::GetPixel(int x,int y) { unsigned char *ptr; COLORREF color; ASSERT(x >= 0 && y >=0); ASSERT(x < width && y < height); // ptr = m_pBits + (y*bytes) + x * 3; ptr = GetLinePtr(y); ptr += (x*3); color = RGB(*(ptr+2),*(ptr+1),*ptr); return color; } CBitmap *CDIB::GetTempBitmap(CDC& dc) { HBITMAP hBitmap; CBitmap *temp; ASSERT(m_pVoid != NULL); hBitmap = CreateDIBitmap(dc.m_hDC, (PBITMAPINFOHEADER)m_pInfo, CBM_INIT, (const void *)m_pBits, m_pInfo, DIB_RGB_COLORS); if(hBitmap == NULL) return NULL; temp = CBitmap::FromHandle(hBitmap); return temp; } CBitmap *CDIB::GetBitmap(CDC& dc) { HBITMAP hBitmap; CBitmap *temp; ASSERT(m_pVoid != NULL); hBitmap = CreateDIBitmap(dc.m_hDC, (PBITMAPINFOHEADER)m_pInfo, CBM_INIT, (const void *)m_pBits, m_pInfo, DIB_RGB_COLORS); if(hBitmap == NULL) return NULL; temp = CBitmap::FromHandle(hBitmap); if(temp) { BITMAP bmp; LPVOID lpVoid; temp->GetBitmap(&bmp); lpVoid = malloc(bmp.bmWidthBytes*bmp.bmHeight); if(!lpVoid) return NULL; temp->GetBitmapBits(bmp.bmWidthBytes*bmp.bmHeight,lpVoid); CBitmap *newBmp = new CBitmap; newBmp->CreateBitmapIndirect(&bmp); newBmp->SetBitmapBits(bmp.bmWidthBytes*bmp.bmHeight,lpVoid); free(lpVoid); return newBmp; } else return NULL; } void CDIB::CopyLine(int source,int dest) { unsigned char *src,*dst; ASSERT(source <= height && source >= 0); ASSERT(dest <= height && dest >= 0); if(source == dest) return; src = GetLinePtr(source); dst = GetLinePtr(dest); memcpy(dst,src,bytes); } void CDIB::InitDIB(COLORREF color) { int i,j; unsigned char *ptr; if(m_pInfo->bmiHeader.biBitCount == 24) { unsigned char col[3]; col[0]=GetBValue(color); col[1]=GetGValue(color); col[2]=GetRValue(color); for(i=0,ptr = m_pBits; i < height; i++) { ptr = m_pBits + i*bytes; for(j=0; j < width ; j++,ptr+=3) { memcpy(ptr,col,3); } } } else { for(i=0,ptr = m_pBits; i < height; i++,ptr+=bytes) { memset(ptr,(BYTE)color,bytes); } } } void CDIB::BitBlt(HDC hDest,int nXDest,int nYDest,int nWidth,int nHeight,int xSrc,int ySrc) { SetDIBitsToDevice(hDest,nXDest,nYDest,nWidth,nHeight,xSrc,Height()-ySrc-nHeight,0,Height(),m_pBits,m_pInfo,DIB_RGB_COLORS); } void CDIB::StretchBlt(HDC hDest,int nXDest,int nYDest,int nDWidth,int nDHeight,int xSrc,int ySrc,int nSWidth,int nSHeight) { int err; err = StretchDIBits(hDest,nXDest,nYDest,nDWidth,nDHeight,xSrc,ySrc,nSWidth,nSHeight,m_pBits,(CONST BITMAPINFO * )&m_pInfo->bmiHeader,DIB_RGB_COLORS,SRCCOPY); } void CDIB::ExpandBlt(int nXDest,int nYDest,int xRatio,int yRatio,CDIB& dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight) { SetPalette(dibSrc.m_pRGB); nSWidth = xSrc+nSWidth > dibSrc.width ? dibSrc.width-xSrc : nSWidth; nSHeight = ySrc+nSHeight > dibSrc.height? dibSrc.height-ySrc : nSHeight; Expand(nXDest,nYDest,xRatio,yRatio,dibSrc,xSrc,ySrc,nSWidth,nSHeight); } void CDIB::Expand(int nXDest,int nYDest,int xRatio,int yRatio,CDIB& dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight) { int xNum,yNum,xErr,yErr; int nDWidth,nDHeight; nDWidth = nSWidth*xRatio; nDHeight = nSHeight*yRatio; nDWidth = nXDest+nDWidth > width ? width-nXDest : nDWidth ; nDHeight = nYDest+nDHeight > height ? height-nYDest : nDHeight; xNum = nDWidth/xRatio; yNum = nDHeight/yRatio; xErr = nDWidth%xRatio; yErr = nDHeight%yRatio; unsigned char *buffer,*srcPtr,*destPtr,*ptr; int i,j,k; buffer = (unsigned char *)malloc(nDWidth+20); if(!buffer) return; for(i=0; i < yNum; i++,ySrc++) { srcPtr = dibSrc.GetLinePtr(ySrc) + xSrc; ptr = buffer; for(j=0; j < xNum; j++,ptr+=xRatio) { memset(ptr,*(srcPtr+j),xRatio); k=*(srcPtr+j); } memset(ptr,(unsigned char)k,xErr); for(j=0; j < yRatio ; j++,nYDest++) { destPtr = GetLinePtr(nYDest) + nXDest; memcpy(destPtr,buffer,nDWidth); } } for(j=0; j < yErr; j++,nYDest++) { destPtr = GetLinePtr(nYDest) + nXDest; memcpy(destPtr,buffer,nDWidth); } free(buffer); } void CDIB::StretchBlt(int nXDest,int nYDest,int nDWidth,int nDHeight,CDIB& dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight) { SetPalette(dibSrc.m_pRGB); nDWidth = nXDest+nDWidth > width ? width-nXDest : nDWidth ; nDHeight = nYDest+nDHeight > height ? height-nYDest : nDHeight; nSWidth = xSrc+nSWidth > dibSrc.width ? dibSrc.width-xSrc : nSWidth; nSHeight = ySrc+nSHeight > dibSrc.height? dibSrc.height-ySrc : nSHeight; int xDiv,yDiv; int xMod,yMod; xDiv = nDWidth/nSWidth; xMod = nDWidth%nSWidth; yDiv = nDHeight/nSHeight; yMod = nDHeight%nSHeight; if(!xMod && !yMod && xDiv > 0 && yDiv > 0) { ExpandBlt(nXDest,nYDest,xDiv,yDiv,dibSrc,xSrc,ySrc,nSWidth,nSHeight); return; } unsigned char *tempPtr,*srcPix,*destPix,*q; tempPtr = (unsigned char *)malloc(nDWidth+20); int i,j,k,l,x,y,m; int xErr,yErr; for(i=yErr=m=0; i < nSHeight; i++) { srcPix = dibSrc.GetLinePtr(i+ySrc) + xSrc; q = tempPtr; for(j=l=xErr=0; j < nSWidth; j++,srcPix++) { k = xDiv; xErr += xMod; if(xErr >= nSWidth) { k++; xErr%=nSWidth; } x=0; while(l < nDWidth && x < k) { *q++ = *srcPix; l++; x++; } } while(l < nDWidth) { *q++=*srcPix; l++; } k= yDiv; yErr += yMod; if(yErr >= nSHeight) { k++; yErr%=nSHeight; } y=0; while(m < nDHeight && y < k) { destPix = GetLinePtr(m+nYDest) + nXDest; memcpy(destPix,tempPtr,nDWidth); m++; y++; } } while(m < nDHeight ) { destPix = GetLinePtr(m+nYDest) + nXDest; memcpy(destPix,tempPtr,nDWidth); m++; } free(tempPtr); } void CDIB::BitBlt(int nXDest,int nYDest,int nWidth,int nHeight,CDIB& dibSrc,int nSrcX,int nSrcY,BYTE *colors) { SetPalette(dibSrc.m_pRGB); if(nXDest < 0) { nSrcX -= nXDest; nWidth += nXDest; nXDest=0; } if(nYDest < 0) { nSrcY -= nYDest; nHeight += nYDest; nYDest=0; } if(nSrcX < 0) { nXDest -= nSrcX; nWidth += nSrcX; nSrcX=0; } if(nSrcY < 0) { nYDest -= nSrcY; nHeight += nSrcY; nSrcY=0; } nWidth = nXDest+nWidth > width ? width-nXDest : nWidth ; nHeight = nYDest+nHeight > height ? height-nYDest : nHeight; nWidth = nSrcX+nWidth > dibSrc.width ? dibSrc.width-nSrcX : nWidth; nHeight = nSrcY+nHeight > dibSrc.height? dibSrc.height-nSrcY : nHeight; nWidth = __max(0,nWidth); nHeight = __max(0,nHeight); int i,k,l,j; unsigned char *srcPtr,*destPtr; if(!colors) { for(i=0,k=nSrcY,l=nYDest; i < nHeight; i++,k++,l++) { if(k < 0 || l < 0) { continue; } else { srcPtr = dibSrc.GetLinePtr(k); destPtr = GetLinePtr(l); memcpy(destPtr+nXDest,srcPtr+nSrcX,nWidth); } } } else { for(i=0,k=nSrcY,l=nYDest; i < nHeight; i++,k++,l++) { if(k < 0 || l < 0) { continue; } else { srcPtr = dibSrc.GetLinePtr(k)+nXDest; destPtr = GetLinePtr(l)+nSrcX; for(j=0; j < nWidth; j++,srcPtr++,destPtr++) { if(colors[*srcPtr]) *destPtr=*srcPtr; } } } } } unsigned char *CDIB::GetLinePtr(int line) { /*unsigned char *ptr; ptr = m_pBits + (height-line-1)*bytes; return ptr;*/ return m_pLinePtr[line]; } BOOL CDIB::CopyDIB(CDIB& dib) { if(Create(dib.m_pInfo->bmiHeader)) { SetPalette(dib.m_pRGB); memcpy(m_pBits,dib.m_pBits,height*bytes); return TRUE; } return FALSE; } void CDIB::ReplaceColor(unsigned char oldColor,unsigned char newColor) { int i,j; unsigned char *ptr; for(i=0; i < height; i++) { ptr = GetLinePtr(i); for(j=0; j < width; j++) { if(ptr[j] == oldColor) ptr[j] = newColor; } } } CDIB& CDIB::operator=(CDIB& dib) { CopyDIB(dib); return *this; } HANDLE CDIB::GetDIBits(int nStartX,int nStartY,int nCx,int nCy) { if(nStartX == -1) { nStartX = nStartY=0; nCx = width; nCy = height; CDIB dib; dib.Create(nCx,nCy,8); dib.BitBlt(0,0,nCx,nCy,*this,0,0); dib.SetPalette(m_pRGB); return dib.DIBHandle(); } return DIBHandle(); } DWORD CDIB::GetDIBSize() { return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize() + bytes*height; } HANDLE CDIB::DIBHandle() { int nSize; HANDLE hMem; nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize() + bytes*height; hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE,nSize); if(hMem == NULL) return NULL; UCHAR *lpVoid,*pBits; LPBITMAPINFOHEADER pHead; RGBQUAD *pRgb; lpVoid = (UCHAR *)GlobalLock(hMem); pHead = (LPBITMAPINFOHEADER )lpVoid; memcpy(pHead,&m_pInfo->bmiHeader,sizeof(BITMAPINFOHEADER)); pRgb = (RGBQUAD *)(lpVoid + sizeof(BITMAPINFOHEADER) ); memcpy(pRgb,m_pRGB,sizeof(RGBQUAD)*GetPaletteSize()); pBits = lpVoid + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize(); memcpy(pBits,m_pBits,height*bytes); GlobalUnlock(lpVoid); return hMem; } BOOL CDIB::CreateFromHandle(HANDLE hMem,int bits) { DestroyDIB(); UCHAR *lpVoid,*pBits; LPBITMAPINFOHEADER pHead; RGBQUAD *pRgb; lpVoid = (UCHAR *)GlobalLock(hMem); pHead = (LPBITMAPINFOHEADER )lpVoid; width = pHead->biWidth; height = pHead->biHeight; m_nBits = pHead->biBitCount; if(pHead->biCompression != BI_RGB) { GlobalUnlock(lpVoid); return FALSE; } if(pHead->biBitCount >= 15) { if(pHead->biBitCount != 24) { GlobalUnlock(lpVoid); return FALSE; } } if(!Create(*pHead)) { GlobalUnlock(lpVoid); return FALSE; } pRgb = (RGBQUAD *)(lpVoid + sizeof(BITMAPINFOHEADER) ); memcpy(m_pRGB,pRgb,sizeof(RGBQUAD)*GetPaletteSize()); pBits = lpVoid + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize(); memcpy(m_pBits,pBits,height*bytes); GlobalUnlock(lpVoid); return TRUE; } void CDIB::UseGamma(float fg,BOOL bUse) { m_bUseGamma = bUse; m_fOldGamma = m_fGamma; m_fGamma = fg; CreateGammaCurve(); } void CDIB::CreateGammaCurve() { int i; for(i=0;i<256;++i) { Gamma[i]=(int)(255 * powf((double)i/255,m_fGamma) + (double)0.5); } } void CDIB::GetPixel(UINT x,UINT y,int& pixel) { ASSERT(x < (UINT)Width()); ASSERT(y < (UINT)Height()); if(x >= (UINT)Width()) return; if(y >= (UINT)Height()) return; pixel=(GetLinePtr(y))[x]; } BOOL CDIB::Make8Bit(CDIB& dib) { int nBits; ASSERT(Width() == dib.Width()); ASSERT(Height() == dib.Height()); nBits = dib.GetBitCount(); switch(nBits) { case 1: return SwitchFromOne(dib); break; case 4: return SwitchFromFour(dib); break; case 8: return SwitchPalette(dib); break; case 24: return SwitchFrom24(dib); break; default: return FALSE; } return FALSE; } /* BOOL CDIB::SwitchFrom24(CDIB& dib) { int i,j,w,h; unsigned char *sPtr,*dPtr; w = Width(); h = Height(); memset(CachePtr,0,sizeof(CachePtr)); for(i=0; i < h; i++) { dPtr = GetLinePtr(i); sPtr = dib.GetLinePtr(i); for(j=0 ; j < w; j++,dPtr++,sPtr+=3) { *dPtr = ClosestColor((RGBQUAD *)sPtr); } } return TRUE; } */ BOOL CDIB::SwitchFromOne(CDIB& dib) { int i,j,w,h; unsigned char *sPtr,*dPtr; unsigned char cols[2]; w = Width(); h = Height(); memset(CachePtr,0,sizeof(CachePtr)); cols[0]=ClosestColor(dib.m_pRGB); cols[1]=ClosestColor(dib.m_pRGB+1); for(i=0; i < h; i++) { dPtr = GetLinePtr(i); sPtr = dib.GetLinePtr(i); for(j=0 ; j < w; j++,dPtr++) { if(!(sPtr[j>>3] & masktable[j&7])) *dPtr = cols[0]; else *dPtr = cols[1]; } } return TRUE; } BOOL CDIB::SwitchFromFour(CDIB& dib) { int i,n,j,w,h; unsigned char *sPtr,*dPtr; unsigned char cols[16]; w = Width(); h = Height(); memset(CachePtr,0,sizeof(CachePtr)); for(i=0; i < 16; i++) { cols[i]=ClosestColor(dib.m_pRGB+i); } for(i=0; i < h; i++) { dPtr = GetLinePtr(i); sPtr = dib.GetLinePtr(i); for(j=0 ; j < w; j++,dPtr++) { if(!(j&1)) n = (*sPtr & 0xf0)>>4; else { n = *sPtr & 0x0f; sPtr++; } *dPtr = cols[n]; } } return TRUE; } BOOL CDIB::SwitchPalette(CDIB& dib) { int i,j,w,h; unsigned char *sPtr,*dPtr; unsigned char cols[256]; w = Width(); h = Height(); memset(CachePtr,0,sizeof(CachePtr)); for(i=0; i < 256; i++) { cols[i]=ClosestColor(dib.m_pRGB+i); } for(i=0; i < h; i++) { dPtr = GetLinePtr(i); sPtr = dib.GetLinePtr(i); for(j=0 ; j < w; j++,sPtr++,dPtr++) { *dPtr = cols[*sPtr]; } } return TRUE; } int CDIB::ClosestColor(RGBQUAD *pRgb) { unsigned int dist=BIG_DISTANCE,i,d,c; RGBQUAD *pQuad=m_pRGB; unsigned int pSize=GetPaletteSize(); for(i=0; i < pSize;i++) { if(CachePtr[i]) { if(!memcmp((void *)&CacheQuad[i],(void *)pRgb,3)) { return i; } } } for(i=0; i < pSize; i++,pQuad++) { d = Distance(*pRgb,*pQuad); if(!d) { CacheQuad[i]=*pRgb; CachePtr[i]=1; return i; } if(dist > d) { c = i; dist = d; } } CacheQuad[c]=*pRgb; CachePtr[c]=1; return c; } unsigned int CDIB::Distance(RGBQUAD& rgb1,RGBQUAD& rgb2) { unsigned int d; d = 3*(unsigned)((rgb1.rgbRed)-(rgb2.rgbRed))*(unsigned)((rgb1.rgbRed)-(rgb2.rgbRed)); d += 4*(unsigned)((rgb1.rgbGreen)-(rgb2.rgbGreen))*(unsigned)((rgb1.rgbGreen)-(rgb2.rgbGreen)) ; d += 2*(unsigned)((rgb1.rgbBlue)-(rgb2.rgbBlue))*(unsigned)((rgb1.rgbBlue)-(rgb2.rgbBlue)); return d; } BOOL CDIB::OpenDIB(CString& csFileName) { CFile file; if(!file.Open(csFileName,CFile::modeRead | CFile::typeBinary)) { return FALSE; } file.Close(); if(OpenBMP(csFileName)) return TRUE; return FALSE; } BOOL CDIB::SaveDIB(CString& csFileName,BitmapType type) { CFile file; if(!file.Open(csFileName,CFile::modeCreate | CFile::typeBinary)) { return FALSE; } file.Close(); switch(type) { case BMP: return SaveBMP(csFileName); default: return FALSE; } return FALSE; } BOOL CDIB::SaveBMP(CString& csFileName) { BITMAPFILEHEADER bFile; CFile file; if(!file.Open(csFileName,CFile::modeWrite | CFile::typeBinary)) { return FALSE; } ::ZeroMemory(&bFile,sizeof(bFile)); memcpy((void *)&bFile.bfType,"BM",2); bFile.bfSize = GetDIBSize() + sizeof(bFile); bFile.bfOffBits = sizeof(BITMAPINFOHEADER) + GetPaletteSize()*sizeof(RGBQUAD) + sizeof(BITMAPFILEHEADER); file.Write(&bFile,sizeof(bFile)); file.Write(m_pVoid,GetDIBSize()); file.Close(); return TRUE; } BOOL CDIB::OpenBMP(CString& csFileName) { BITMAPFILEHEADER bFile; BITMAPINFOHEADER head; CFile file; if(!file.Open(csFileName,CFile::modeRead | CFile::typeBinary)) { return FALSE; } file.Read(&bFile,sizeof(bFile)); if(memcmp((void *)&bFile.bfType,"BM",2)) { file.Close(); return FALSE; } file.Read(&head,sizeof(head)); if(!Create(head)) { file.Close(); return FALSE; } file.Read(m_pRGB,sizeof(RGBQUAD)*GetPaletteSize()); file.Seek(bFile.bfOffBits,CFile::begin); file.Read(m_pBits,height*bytes); file.Close(); return TRUE; } int CDIB::CountColors() { ASSERT(GetBitCount()==8); BYTE colors[256],*ptr; int nNum=0,i,j,w,d; w = Width(); d = Height(); memset(colors,0,256); for(i=0; i < d; i++) { ptr = GetLinePtr(i); for(j=0; j < w; j++,ptr++) { if(!colors[*ptr]) { colors[*ptr]=1; nNum++; } } } return nNum; } int CDIB::EnumColors(BYTE *array) { ASSERT(GetBitCount()==8); BYTE *ptr; int nNum=0,i,j,w,d; w = Width(); d = Height(); memset(array,0,256); for(i=0; i < d; i++) { ptr = GetLinePtr(i); for(j=0; j < w; j++,ptr++) { if(!array[*ptr]) { array[*ptr]=1; nNum++; } } } return nNum; } COLORREF CDIB::PaletteColor(int nIndex) { ASSERT(nIndex < 256); RGBQUAD *pRGB= m_pRGB+nIndex; return RGB(pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue); } BOOL CDIB::SwitchFrom24(CDIB& dib) { int i,j,w,h,c; unsigned char *sPtr,*dPtr; BYTE *index_ptr=NULL; RGBQUAD rgb; w = Width(); h = Height(); index_ptr = (BYTE *)malloc(0x7FFF+1); if(!index_ptr) return FALSE; memset(CachePtr,0,sizeof(CachePtr)); for(i=0; i <= 0x7FFF; i++) { rgb.rgbRed = (((i & 0x7C00)>>10) << 3) | 0x07; rgb.rgbGreen = (((i & 0x3e0)>>5) << 3) | 0x07; rgb.rgbBlue = ((i & 0x1F)<<3) | 0x07; index_ptr[i] = ClosestColor(&rgb); } for(i=0; i < h; i++) { dPtr = GetLinePtr(i); sPtr = dib.GetLinePtr(i); for(j=0 ; j < w; j++,dPtr++,sPtr+=3) { c = (*sPtr >> 3) | ((*(sPtr+1) >> 3) << 5) | ((*(sPtr+2) >> 3) << 10); *dPtr = index_ptr[c]; } } free(index_ptr); return TRUE; }