]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/tools/comafx/CDIB.cpp
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / tools / comafx / CDIB.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 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.
23
24 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.
25
26 ===========================================================================
27 */
28
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #ifdef ID_DEBUG_MEMORY
33 #undef new
34 #endif
35
36 #include "math.h"
37 #include "CDIB.h"
38
39 // Original ColorPicker/DIB source by Rajiv Ramachandran <rrajivram@hotmail.com>
40 // included with Permission from the author
41
42 #define BIG_DISTANCE 10000000L
43
44 #define DIST(r1,g1,b1,r2,g2,b2) \
45             (long) (3L*(long)((r1)-(r2))*(long)((r1)-(r2)) + \
46                     4L*(long)((g1)-(g2))*(long)((g1)-(g2)) + \
47                     2L*(long)((b1)-(b2))*(long)((b1)-(b2)))
48
49
50 static unsigned char masktable[] = { 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 };
51
52
53
54 CDIB::CDIB(HANDLE hDib,int nBits)
55 {
56         m_pVoid = NULL;
57         m_pLinePtr = NULL;
58         m_bUseGamma=FALSE;
59         width=height=0;
60         if(hDib)
61         {
62                 CreateFromHandle(hDib,nBits);
63         }
64 }
65
66 CDIB::~CDIB()
67 {
68         DestroyDIB();
69 }
70
71 void CDIB::DestroyDIB()
72 {
73         if(m_pVoid) free(m_pVoid);
74         m_pVoid = NULL;
75         if(m_pLinePtr) free(m_pLinePtr);
76         m_pLinePtr = NULL;
77 }
78
79
80 BOOL CDIB::Create(int width,int height,int bits)
81 {
82         /*
83                 Free existing image
84         */
85         DestroyDIB();
86 //      ASSERT(bits == 24 || bits == 8);
87
88 BITMAPINFOHEADER bmInfo;
89         
90         memset(&bmInfo,0,sizeof(BITMAPINFOHEADER));
91         bmInfo.biSize = sizeof(BITMAPINFOHEADER);
92         bmInfo.biWidth = width;
93         bmInfo.biHeight = height;
94         bmInfo.biPlanes = 1;
95         bmInfo.biBitCount = bits;
96         bmInfo.biCompression = BI_RGB;
97         return Create(bmInfo);
98 }
99
100 BOOL CDIB::Create(BITMAPINFOHEADER& bmInfo)
101 {
102         bytes = (bmInfo.biBitCount*bmInfo.biWidth)>>3;
103         height = bmInfo.biHeight;
104         width = bmInfo.biWidth;
105 //      bmInfo.biHeight *= -1;
106         while(bytes%4) bytes++;
107
108         int size;
109         size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize(bmInfo) + bytes*height;
110         m_pVoid = (void *)malloc(size);
111         if(!m_pVoid) return FALSE;
112
113         m_pInfo = (PBITMAPINFO )m_pVoid;
114         memcpy((void *)&m_pInfo->bmiHeader,(void *)&bmInfo,sizeof(BITMAPINFOHEADER));
115         m_pRGB = (RGBQUAD *)((unsigned char *)m_pVoid + sizeof(BITMAPINFOHEADER)) ;
116         m_pBits = (unsigned char *)(m_pVoid) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize();
117
118 int i;
119 BYTE **ptr;
120         m_pLinePtr = (BYTE **)malloc(sizeof(BYTE *)*height);
121         if(!m_pLinePtr) return FALSE;
122         for(i=0,ptr=m_pLinePtr; i < height; i++,ptr++)
123         {
124                 //*ptr = (int)(m_pBits)+(i*bytes);
125                 //*ptr = (int)GetLinePtr(i);
126                 *ptr = m_pBits + (height-i-1)*bytes;
127         }
128         m_nFlags = 0;
129         return TRUE;
130 }
131
132 void CDIB::SetPalette(unsigned char *palette)
133 {
134 int i,size;
135 RGBQUAD *rgb;
136         if(!palette) return;
137         size = GetPaletteSize();
138         for(i=0,rgb = m_pRGB; i < size; i++,rgb++,palette+=3)
139         {
140                 if(m_bUseGamma)
141                 {
142                         rgb->rgbRed = Gamma[palette[0]];
143                         rgb->rgbGreen = Gamma[palette[1]];
144                         rgb->rgbBlue = Gamma[palette[2]];
145                 }
146                 else
147                 {
148                         rgb->rgbRed = palette[0];
149                         rgb->rgbGreen = palette[1];
150                         rgb->rgbBlue = palette[2];
151                 }
152                 rgb->rgbReserved = (BYTE)0;
153         }
154 }
155
156 void CDIB::SetPalette(RGBQUAD *pRGB)
157 {
158 int size;
159         if(!pRGB) return;
160         size = GetPaletteSize();
161         memcpy(m_pRGB,pRGB,size*sizeof(RGBQUAD));
162 }
163
164
165 int CDIB::GetPaletteSize()
166 {
167         return GetPaletteSize(m_pInfo->bmiHeader);
168 }
169
170
171 int CDIB::GetPaletteSize(BITMAPINFOHEADER& bmInfo)
172 {
173         switch(bmInfo.biBitCount)
174         {
175         case 1:
176                         return 2;
177         case 4:
178                         return 16;
179         case 8:
180                         return 256;
181         default:
182                         return 0;
183         }
184 }
185
186
187 void CDIB::SetPixel(int x,int y,COLORREF color)
188 {
189 unsigned char *ptr;
190         ASSERT(x >= 0 && y >=0);
191         ASSERT(x < width && y < height);
192
193 //      ptr = m_pBits + (y*bytes) + x * 3;
194         ptr = (unsigned char *)m_pLinePtr[y];
195         ptr += x*3;
196         *ptr++ = (unsigned char)GetBValue(color);
197         *ptr++ = (unsigned char)GetGValue(color);
198         *ptr++ = (unsigned char)GetRValue(color);
199 }
200
201 void CDIB::SetPixel8(int x,int y,unsigned char color)
202 {
203 unsigned char *ptr,*aptr;
204         ASSERT(x >= 0 && y >=0);
205         ASSERT(x < width && y < height);
206
207 //      ptr = m_pBits + (y*bytes) + x ;
208 //      ptr = (unsigned char *)m_pLinePtr[y] ;
209         ptr = GetLinePtr(y);
210         aptr = ptr;
211         ptr += x;
212         *ptr = color;
213 }
214
215
216 COLORREF CDIB::GetPixel(int x,int y)
217 {
218 unsigned char *ptr;
219 COLORREF color;
220         ASSERT(x >= 0 && y >=0);
221         ASSERT(x < width && y < height);
222
223 //      ptr = m_pBits + (y*bytes) + x * 3;
224         ptr = GetLinePtr(y);
225         ptr += (x*3);
226         color = RGB(*(ptr+2),*(ptr+1),*ptr);
227         return color;
228 }
229
230 CBitmap *CDIB::GetTempBitmap(CDC& dc)
231 {
232 HBITMAP hBitmap;
233 CBitmap *temp;
234         ASSERT(m_pVoid != NULL);
235         hBitmap = CreateDIBitmap(dc.m_hDC,
236                                 (PBITMAPINFOHEADER)m_pInfo,
237                                 CBM_INIT,
238                                 (const void *)m_pBits,
239                                 m_pInfo,
240                                 DIB_RGB_COLORS);
241
242         if(hBitmap == NULL) return NULL;
243         temp = CBitmap::FromHandle(hBitmap);
244         return temp;
245 }
246
247 CBitmap *CDIB::GetBitmap(CDC& dc)
248 {
249 HBITMAP hBitmap;
250 CBitmap *temp;
251         ASSERT(m_pVoid != NULL);
252         hBitmap = CreateDIBitmap(dc.m_hDC,
253                                 (PBITMAPINFOHEADER)m_pInfo,
254                                 CBM_INIT,
255                                 (const void *)m_pBits,
256                                 m_pInfo,
257                                 DIB_RGB_COLORS);
258
259         if(hBitmap == NULL) return NULL;
260         temp = CBitmap::FromHandle(hBitmap);
261         if(temp)
262         {
263                 BITMAP bmp;
264                 LPVOID lpVoid;
265                 temp->GetBitmap(&bmp);
266                 lpVoid = malloc(bmp.bmWidthBytes*bmp.bmHeight);
267                 if(!lpVoid) return NULL;
268                 temp->GetBitmapBits(bmp.bmWidthBytes*bmp.bmHeight,lpVoid);
269                 CBitmap *newBmp = new CBitmap;
270                 newBmp->CreateBitmapIndirect(&bmp);
271                 newBmp->SetBitmapBits(bmp.bmWidthBytes*bmp.bmHeight,lpVoid);
272                 free(lpVoid);
273                 return newBmp;
274         }
275         else return NULL;
276
277 }
278
279 void CDIB::CopyLine(int source,int dest)
280 {
281 unsigned char *src,*dst;
282         ASSERT(source <= height && source >= 0);
283         ASSERT(dest <= height && dest >= 0);
284         if(source == dest) return;
285         src = GetLinePtr(source);
286         dst = GetLinePtr(dest);
287         memcpy(dst,src,bytes);
288 }
289
290 void CDIB::InitDIB(COLORREF color)
291 {
292 int i,j;
293 unsigned char *ptr;
294         
295         if(m_pInfo->bmiHeader.biBitCount == 24)
296         {
297                 unsigned char col[3];
298                 col[0]=GetBValue(color);
299                 col[1]=GetGValue(color);
300                 col[2]=GetRValue(color);
301                 for(i=0,ptr = m_pBits; i < height; i++)
302                 {
303                         ptr = m_pBits + i*bytes;
304                         for(j=0; j < width ; j++,ptr+=3)
305                         {
306                                 memcpy(ptr,col,3);
307                         }
308                 }
309         }
310         else
311         {
312                 for(i=0,ptr = m_pBits; i < height; i++,ptr+=bytes)
313                 {
314                         memset(ptr,(BYTE)color,bytes);
315                 }
316         }
317 }
318
319
320 void CDIB::BitBlt(HDC hDest,int nXDest,int nYDest,int nWidth,int nHeight,int xSrc,int ySrc)
321 {
322         SetDIBitsToDevice(hDest,nXDest,nYDest,nWidth,nHeight,xSrc,Height()-ySrc-nHeight,0,Height(),m_pBits,m_pInfo,DIB_RGB_COLORS);
323 }
324
325 void CDIB::StretchBlt(HDC hDest,int nXDest,int nYDest,int nDWidth,int nDHeight,int xSrc,int ySrc,int  nSWidth,int nSHeight)
326 {
327         int err;
328         err = StretchDIBits(hDest,nXDest,nYDest,nDWidth,nDHeight,xSrc,ySrc,nSWidth,nSHeight,m_pBits,(CONST BITMAPINFO * )&m_pInfo->bmiHeader,DIB_RGB_COLORS,SRCCOPY);
329 }
330
331 void CDIB::ExpandBlt(int nXDest,int nYDest,int xRatio,int yRatio,CDIB& dibSrc,int xSrc,int ySrc,int  nSWidth,int nSHeight)
332 {
333         SetPalette(dibSrc.m_pRGB);
334
335         nSWidth = xSrc+nSWidth > dibSrc.width ? dibSrc.width-xSrc : nSWidth;
336         nSHeight = ySrc+nSHeight > dibSrc.height? dibSrc.height-ySrc : nSHeight;
337
338         Expand(nXDest,nYDest,xRatio,yRatio,dibSrc,xSrc,ySrc,nSWidth,nSHeight);
339 }
340
341 void CDIB::Expand(int nXDest,int nYDest,int xRatio,int yRatio,CDIB& dibSrc,int xSrc,int ySrc,int  nSWidth,int nSHeight)
342 {
343 int xNum,yNum,xErr,yErr;        
344 int nDWidth,nDHeight;
345         
346         nDWidth = nSWidth*xRatio;
347         nDHeight = nSHeight*yRatio;
348
349         nDWidth = nXDest+nDWidth > width ? width-nXDest : nDWidth ; 
350         nDHeight = nYDest+nDHeight > height ? height-nYDest : nDHeight;
351
352         xNum = nDWidth/xRatio;
353         yNum = nDHeight/yRatio;
354         xErr = nDWidth%xRatio;
355         yErr = nDHeight%yRatio;
356
357 unsigned char *buffer,*srcPtr,*destPtr,*ptr;
358 int i,j,k;
359         
360         buffer = (unsigned char *)malloc(nDWidth+20);
361         if(!buffer) return;
362
363         for(i=0; i < yNum; i++,ySrc++)
364         {
365                 srcPtr = dibSrc.GetLinePtr(ySrc) + xSrc;
366                 ptr = buffer;
367                 for(j=0; j < xNum; j++,ptr+=xRatio)
368                 {
369                         memset(ptr,*(srcPtr+j),xRatio);
370                         k=*(srcPtr+j);
371                 }
372                 memset(ptr,(unsigned char)k,xErr);
373                 for(j=0; j < yRatio ; j++,nYDest++)
374                 {
375                         destPtr = GetLinePtr(nYDest) + nXDest;
376                         memcpy(destPtr,buffer,nDWidth);         
377                 }
378         }
379         for(j=0; j < yErr; j++,nYDest++)
380         {
381                 destPtr = GetLinePtr(nYDest) + nXDest;
382                 memcpy(destPtr,buffer,nDWidth);         
383         }
384         free(buffer);
385 }
386
387 void CDIB::StretchBlt(int nXDest,int nYDest,int nDWidth,int nDHeight,CDIB& dibSrc,int xSrc,int ySrc,int  nSWidth,int nSHeight)
388 {
389         SetPalette(dibSrc.m_pRGB);
390         nDWidth = nXDest+nDWidth > width ? width-nXDest : nDWidth ; 
391         nDHeight = nYDest+nDHeight > height ? height-nYDest : nDHeight;
392
393         nSWidth = xSrc+nSWidth > dibSrc.width ? dibSrc.width-xSrc : nSWidth;
394         nSHeight = ySrc+nSHeight > dibSrc.height? dibSrc.height-ySrc : nSHeight;
395
396 int xDiv,yDiv;
397 int xMod,yMod;
398
399         xDiv = nDWidth/nSWidth;
400         xMod = nDWidth%nSWidth;
401
402         yDiv = nDHeight/nSHeight;
403         yMod = nDHeight%nSHeight;
404
405         if(!xMod && !yMod && xDiv > 0 && yDiv > 0)
406         {
407                 ExpandBlt(nXDest,nYDest,xDiv,yDiv,dibSrc,xSrc,ySrc,nSWidth,nSHeight);
408                 return;
409         }
410
411 unsigned char *tempPtr,*srcPix,*destPix,*q;
412         tempPtr = (unsigned char *)malloc(nDWidth+20);
413 int i,j,k,l,x,y,m;
414 int xErr,yErr;
415         for(i=yErr=m=0; i < nSHeight; i++)
416         {
417                 srcPix = dibSrc.GetLinePtr(i+ySrc) + xSrc;
418                 q = tempPtr;
419                 for(j=l=xErr=0; j < nSWidth; j++,srcPix++)
420                 {
421                         k = xDiv;
422                         xErr += xMod;
423                         if(xErr >= nSWidth)
424                         {
425                                 k++;
426                                 xErr%=nSWidth;
427                         }
428                         x=0;
429                         while(l < nDWidth &&  x < k)
430                         {
431                                 *q++ = *srcPix;
432                                 l++;
433                                 x++;
434                         }
435                 }
436                 while(l < nDWidth)
437                 {
438                         *q++=*srcPix;
439                         l++;
440                 }
441                 k= yDiv;
442                 yErr += yMod;
443                 if(yErr >= nSHeight)
444                 {
445                         k++;
446                         yErr%=nSHeight;
447                 }
448                 y=0;
449                 while(m < nDHeight && y < k)
450                 {
451                         destPix = GetLinePtr(m+nYDest) + nXDest;
452                         memcpy(destPix,tempPtr,nDWidth);
453                         m++;
454                         y++;
455                 }
456         }
457         while(m < nDHeight )
458         {
459                 destPix = GetLinePtr(m+nYDest) + nXDest;
460                 memcpy(destPix,tempPtr,nDWidth);
461                 m++;
462         }
463         free(tempPtr);
464 }
465
466 void CDIB::BitBlt(int nXDest,int nYDest,int nWidth,int nHeight,CDIB& dibSrc,int nSrcX,int nSrcY,BYTE *colors)
467 {
468         SetPalette(dibSrc.m_pRGB);
469         if(nXDest < 0)
470         {
471                 nSrcX -= nXDest;
472                 nWidth += nXDest;
473                 nXDest=0;
474         }
475         if(nYDest < 0)
476         {
477                 nSrcY -= nYDest;
478                 nHeight += nYDest;
479                 nYDest=0;
480         }
481         if(nSrcX < 0)
482         {
483                 nXDest -= nSrcX;
484                 nWidth += nSrcX;
485                 nSrcX=0;
486         }
487         if(nSrcY < 0)
488         {
489                 nYDest -= nSrcY;
490                 nHeight += nSrcY;
491                 nSrcY=0;
492         }
493         nWidth = nXDest+nWidth > width ? width-nXDest : nWidth ; 
494         nHeight = nYDest+nHeight > height ? height-nYDest : nHeight;
495
496         nWidth = nSrcX+nWidth > dibSrc.width ? dibSrc.width-nSrcX : nWidth;
497         nHeight = nSrcY+nHeight > dibSrc.height? dibSrc.height-nSrcY : nHeight;
498
499         nWidth = __max(0,nWidth);
500         nHeight = __max(0,nHeight);
501 int i,k,l,j;
502 unsigned char *srcPtr,*destPtr;
503         if(!colors)
504         {
505                 for(i=0,k=nSrcY,l=nYDest; i < nHeight; i++,k++,l++)
506                 {
507                         if(k < 0 || l < 0)
508                         {
509                                 continue;
510                         }
511                         else
512                         {
513                                 srcPtr = dibSrc.GetLinePtr(k);
514                                 destPtr = GetLinePtr(l);
515                                 memcpy(destPtr+nXDest,srcPtr+nSrcX,nWidth);
516                         }
517                 }
518         }
519         else
520         {
521                 for(i=0,k=nSrcY,l=nYDest; i < nHeight; i++,k++,l++)
522                 {
523                         if(k < 0 || l < 0)
524                         {
525                                 continue;
526                         }
527                         else
528                         {
529                                 srcPtr = dibSrc.GetLinePtr(k)+nXDest;
530                                 destPtr = GetLinePtr(l)+nSrcX;
531                                 for(j=0; j < nWidth; j++,srcPtr++,destPtr++)
532                                 {
533                                         if(colors[*srcPtr]) *destPtr=*srcPtr;
534                                 }
535                         }
536                 }
537         }
538 }
539
540 unsigned char *CDIB::GetLinePtr(int line)
541 {
542 /*unsigned char *ptr;
543         ptr = m_pBits + (height-line-1)*bytes;
544         return ptr;*/
545         return m_pLinePtr[line];
546 }
547         
548 BOOL CDIB::CopyDIB(CDIB& dib)
549 {
550         if(Create(dib.m_pInfo->bmiHeader))
551         {
552                 SetPalette(dib.m_pRGB);
553                 memcpy(m_pBits,dib.m_pBits,height*bytes);
554                 return TRUE;
555         }
556         return FALSE;
557 }
558
559 void CDIB::ReplaceColor(unsigned char oldColor,unsigned char newColor)
560 {
561 int i,j;
562 unsigned char *ptr;     
563         for(i=0; i < height; i++)
564         {
565                 ptr = GetLinePtr(i);
566                 for(j=0; j < width; j++)
567                 {
568                         if(ptr[j] == oldColor) ptr[j] = newColor;
569                 }
570         }
571 }
572
573
574 CDIB& CDIB::operator=(CDIB& dib)
575 {
576         CopyDIB(dib);
577         return *this;
578 }
579
580 HANDLE CDIB::GetDIBits(int nStartX,int nStartY,int nCx,int nCy)
581 {
582         if(nStartX == -1)
583         {
584                 nStartX = nStartY=0;
585                 nCx = width;
586                 nCy = height;
587                 CDIB dib;
588                 dib.Create(nCx,nCy,8);
589                 dib.BitBlt(0,0,nCx,nCy,*this,0,0);
590                 dib.SetPalette(m_pRGB);
591                 return dib.DIBHandle();
592         }
593         return DIBHandle();
594 }
595
596 DWORD CDIB::GetDIBSize()
597 {
598         return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize() + bytes*height;
599 }
600
601 HANDLE CDIB::DIBHandle()
602 {
603 int nSize;
604 HANDLE hMem;
605         nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize() + bytes*height;
606         hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE,nSize);
607         if(hMem  == NULL) return NULL;
608 UCHAR *lpVoid,*pBits;
609 LPBITMAPINFOHEADER pHead;
610 RGBQUAD *pRgb;
611         lpVoid = (UCHAR *)GlobalLock(hMem);
612         pHead = (LPBITMAPINFOHEADER )lpVoid;
613         memcpy(pHead,&m_pInfo->bmiHeader,sizeof(BITMAPINFOHEADER));
614         pRgb = (RGBQUAD *)(lpVoid + sizeof(BITMAPINFOHEADER) );
615         memcpy(pRgb,m_pRGB,sizeof(RGBQUAD)*GetPaletteSize());
616         pBits = lpVoid + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize();
617         memcpy(pBits,m_pBits,height*bytes);
618         GlobalUnlock(lpVoid);
619         return hMem;
620 }
621
622 BOOL CDIB::CreateFromHandle(HANDLE hMem,int bits)
623 {
624         DestroyDIB();
625 UCHAR *lpVoid,*pBits;
626 LPBITMAPINFOHEADER pHead;
627 RGBQUAD *pRgb;
628         lpVoid = (UCHAR *)GlobalLock(hMem);
629         pHead = (LPBITMAPINFOHEADER )lpVoid;
630         width = pHead->biWidth;
631         height = pHead->biHeight;
632         m_nBits = pHead->biBitCount;
633         if(pHead->biCompression != BI_RGB) 
634         {
635                 GlobalUnlock(lpVoid);
636                 return FALSE;
637         }
638         if(pHead->biBitCount >= 15)
639         {
640                 if(pHead->biBitCount != 24) 
641                 {
642                         GlobalUnlock(lpVoid);
643                         return FALSE;
644                 }
645         }
646         if(!Create(*pHead))
647         {
648                 GlobalUnlock(lpVoid);
649                 return FALSE;
650         }
651         pRgb = (RGBQUAD *)(lpVoid + sizeof(BITMAPINFOHEADER) );
652         memcpy(m_pRGB,pRgb,sizeof(RGBQUAD)*GetPaletteSize());
653         pBits = lpVoid + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize();
654         memcpy(m_pBits,pBits,height*bytes);
655         GlobalUnlock(lpVoid);
656         return TRUE;
657 }
658
659 void CDIB::UseGamma(float fg,BOOL bUse)
660 {
661         m_bUseGamma = bUse;
662         m_fOldGamma = m_fGamma;
663         m_fGamma = fg;
664         CreateGammaCurve();
665 }
666
667
668 void CDIB::CreateGammaCurve()
669 {
670 int i;
671         for(i=0;i<256;++i)
672         {
673             Gamma[i]=(int)(255 * powf((double)i/255,m_fGamma) + (double)0.5);
674         }
675 }
676
677
678
679 void CDIB::GetPixel(UINT x,UINT y,int& pixel)
680 {
681         ASSERT(x < (UINT)Width());
682         ASSERT(y < (UINT)Height());
683         if(x >= (UINT)Width()) return;
684         if(y >= (UINT)Height()) return;
685         pixel=(GetLinePtr(y))[x];
686 }
687
688 BOOL CDIB::Make8Bit(CDIB& dib)
689 {
690 int nBits;      
691         ASSERT(Width() == dib.Width());
692         ASSERT(Height() == dib.Height());
693         nBits = dib.GetBitCount();
694         switch(nBits)
695         {
696         case 1:
697                 return SwitchFromOne(dib);
698                 break;
699         case 4:
700                 return SwitchFromFour(dib);
701                 break;
702         case 8:
703                 return SwitchPalette(dib);
704                 break;
705         case 24:
706                 return SwitchFrom24(dib);
707                 break;
708         default:
709                 return FALSE;
710         }
711         return FALSE;
712 }
713
714 /*
715 BOOL CDIB::SwitchFrom24(CDIB& dib)
716 {
717 int i,j,w,h;
718 unsigned char *sPtr,*dPtr;
719         w = Width();
720         h = Height();
721         memset(CachePtr,0,sizeof(CachePtr));
722         for(i=0; i < h; i++)
723         {
724                 dPtr = GetLinePtr(i);
725                 sPtr = dib.GetLinePtr(i);
726                 for(j=0 ; j < w; j++,dPtr++,sPtr+=3)
727                 {
728                         *dPtr = ClosestColor((RGBQUAD *)sPtr);
729                 }
730         }
731         return TRUE;
732 }
733 */
734
735
736 BOOL CDIB::SwitchFromOne(CDIB& dib)
737 {
738 int i,j,w,h;
739 unsigned char *sPtr,*dPtr;
740 unsigned char cols[2];
741         w = Width();
742         h = Height();
743         memset(CachePtr,0,sizeof(CachePtr));
744         cols[0]=ClosestColor(dib.m_pRGB);
745         cols[1]=ClosestColor(dib.m_pRGB+1);
746         for(i=0; i < h; i++)
747         {
748                 dPtr = GetLinePtr(i);
749                 sPtr = dib.GetLinePtr(i);
750                 for(j=0 ; j < w; j++,dPtr++)
751                 {
752                         if(!(sPtr[j>>3] & masktable[j&7])) *dPtr = cols[0];
753                         else *dPtr = cols[1];
754                 }
755         }
756         return TRUE;
757 }
758
759 BOOL CDIB::SwitchFromFour(CDIB& dib)
760 {
761 int i,n,j,w,h;
762 unsigned char *sPtr,*dPtr;
763 unsigned char cols[16];
764         w = Width();
765         h = Height();
766         memset(CachePtr,0,sizeof(CachePtr));
767         for(i=0; i < 16; i++)
768         {
769                 cols[i]=ClosestColor(dib.m_pRGB+i);
770         }
771         for(i=0; i < h; i++)
772         {
773                 dPtr = GetLinePtr(i);
774                 sPtr = dib.GetLinePtr(i);
775                 for(j=0 ; j < w; j++,dPtr++)
776                 {
777                         if(!(j&1)) n = (*sPtr & 0xf0)>>4;
778                         else 
779                         {
780                                 n = *sPtr & 0x0f;
781                                 sPtr++;
782                         }
783                         *dPtr = cols[n];
784                 }
785         }
786         return TRUE;
787 }
788
789 BOOL CDIB::SwitchPalette(CDIB& dib)
790 {
791 int i,j,w,h;
792 unsigned char *sPtr,*dPtr;
793 unsigned char cols[256];
794         w = Width();
795         h = Height();
796         memset(CachePtr,0,sizeof(CachePtr));
797         for(i=0; i < 256; i++)
798         {
799                 cols[i]=ClosestColor(dib.m_pRGB+i);
800         }
801         for(i=0; i < h; i++)
802         {
803                 dPtr = GetLinePtr(i);
804                 sPtr = dib.GetLinePtr(i);
805                 for(j=0 ; j < w; j++,sPtr++,dPtr++)
806                 {
807                         *dPtr = cols[*sPtr];
808                 }
809         }
810         return TRUE;
811 }
812
813
814 int CDIB::ClosestColor(RGBQUAD *pRgb)
815 {
816 unsigned int dist=BIG_DISTANCE,i,d,c;
817 RGBQUAD *pQuad=m_pRGB;
818 unsigned int pSize=GetPaletteSize();
819         for(i=0; i < pSize;i++)
820         {
821                 if(CachePtr[i])
822                 {
823                         if(!memcmp((void *)&CacheQuad[i],(void *)pRgb,3)) 
824                         {
825                                 return i;
826                         }
827                 }
828         }
829         for(i=0; i < pSize; i++,pQuad++)
830         {
831                 d = Distance(*pRgb,*pQuad);
832                 if(!d) 
833                 {
834                         CacheQuad[i]=*pRgb;
835                         CachePtr[i]=1;
836                         return i;
837                 }               
838                 if(dist > d) 
839                 {
840                         c = i;
841                         dist = d;
842                 }
843         }
844         CacheQuad[c]=*pRgb;
845         CachePtr[c]=1;
846         return c;
847 }
848
849 unsigned int CDIB::Distance(RGBQUAD& rgb1,RGBQUAD& rgb2)
850 {
851 unsigned int d;
852         d =  3*(unsigned)((rgb1.rgbRed)-(rgb2.rgbRed))*(unsigned)((rgb1.rgbRed)-(rgb2.rgbRed));
853         d += 4*(unsigned)((rgb1.rgbGreen)-(rgb2.rgbGreen))*(unsigned)((rgb1.rgbGreen)-(rgb2.rgbGreen)) ;
854         d += 2*(unsigned)((rgb1.rgbBlue)-(rgb2.rgbBlue))*(unsigned)((rgb1.rgbBlue)-(rgb2.rgbBlue));
855         return d;
856 }
857
858 BOOL CDIB::OpenDIB(CString& csFileName)
859 {
860 CFile file;
861         if(!file.Open(csFileName,CFile::modeRead | CFile::typeBinary))
862         {
863                 return FALSE;
864         }
865         file.Close();
866         if(OpenBMP(csFileName)) return TRUE;
867         return FALSE;
868 }
869
870
871
872 BOOL CDIB::SaveDIB(CString& csFileName,BitmapType type)
873 {
874 CFile file;
875         if(!file.Open(csFileName,CFile::modeCreate | CFile::typeBinary))
876         {
877                 return FALSE;
878         }
879         file.Close();
880         switch(type)
881         {
882         case BMP:
883                         return SaveBMP(csFileName);
884         default:
885                         return FALSE;
886         }
887         return FALSE;
888 }
889
890 BOOL CDIB::SaveBMP(CString& csFileName)
891 {
892 BITMAPFILEHEADER bFile;
893 CFile file;
894         if(!file.Open(csFileName,CFile::modeWrite | CFile::typeBinary))
895         {
896                 return FALSE;
897         }
898         ::ZeroMemory(&bFile,sizeof(bFile));
899         memcpy((void *)&bFile.bfType,"BM",2);
900         bFile.bfSize = GetDIBSize() + sizeof(bFile);
901         bFile.bfOffBits = sizeof(BITMAPINFOHEADER) + GetPaletteSize()*sizeof(RGBQUAD) + sizeof(BITMAPFILEHEADER);
902         file.Write(&bFile,sizeof(bFile));
903         file.Write(m_pVoid,GetDIBSize());
904         file.Close();
905         return TRUE;
906
907 }
908
909 BOOL CDIB::OpenBMP(CString& csFileName)
910 {
911 BITMAPFILEHEADER bFile;
912 BITMAPINFOHEADER head;
913 CFile file;
914         if(!file.Open(csFileName,CFile::modeRead | CFile::typeBinary))
915         {
916                 return FALSE;
917         }
918         file.Read(&bFile,sizeof(bFile));
919         if(memcmp((void *)&bFile.bfType,"BM",2))
920         {
921                 file.Close();
922                 return FALSE;
923         }
924         file.Read(&head,sizeof(head));
925         if(!Create(head))
926         {
927                 file.Close();
928                 return FALSE;
929         }
930         file.Read(m_pRGB,sizeof(RGBQUAD)*GetPaletteSize());
931         file.Seek(bFile.bfOffBits,CFile::begin);
932         file.Read(m_pBits,height*bytes);
933         file.Close();
934         return TRUE;
935
936 }
937
938
939 int CDIB::CountColors()
940 {
941         ASSERT(GetBitCount()==8);
942 BYTE colors[256],*ptr;
943 int nNum=0,i,j,w,d;
944         w = Width();
945         d = Height();
946         memset(colors,0,256);
947         for(i=0; i < d; i++)
948         {
949                 ptr = GetLinePtr(i);
950                 for(j=0; j < w; j++,ptr++)
951                 {
952                         if(!colors[*ptr])
953                         {
954                                 colors[*ptr]=1;
955                                 nNum++;
956                         }
957                 }
958         }
959         return nNum;
960 }
961
962 int CDIB::EnumColors(BYTE *array)
963 {
964         ASSERT(GetBitCount()==8);
965 BYTE *ptr;
966 int nNum=0,i,j,w,d;
967         w = Width();
968         d = Height();
969         memset(array,0,256);
970         for(i=0; i < d; i++)
971         {
972                 ptr = GetLinePtr(i);
973                 for(j=0; j < w; j++,ptr++)
974                 {
975                         if(!array[*ptr])
976                         {
977                                 array[*ptr]=1;
978                                 nNum++;
979                         }
980                 }
981         }
982         return nNum;
983 }
984
985 COLORREF CDIB::PaletteColor(int nIndex)
986 {
987         ASSERT(nIndex < 256);
988 RGBQUAD *pRGB= m_pRGB+nIndex;
989         return RGB(pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue);
990 }
991
992 BOOL CDIB::SwitchFrom24(CDIB& dib)
993 {
994 int i,j,w,h,c;
995 unsigned char *sPtr,*dPtr;
996 BYTE *index_ptr=NULL;
997 RGBQUAD rgb;
998         w = Width();
999         h = Height();
1000         index_ptr = (BYTE *)malloc(0x7FFF+1);
1001         if(!index_ptr) return FALSE;
1002         memset(CachePtr,0,sizeof(CachePtr));
1003         for(i=0; i <= 0x7FFF; i++)
1004         {
1005                 rgb.rgbRed = (((i & 0x7C00)>>10) << 3) | 0x07;
1006                 rgb.rgbGreen = (((i & 0x3e0)>>5) << 3) | 0x07;
1007                 rgb.rgbBlue = ((i & 0x1F)<<3) | 0x07;
1008                 index_ptr[i] = ClosestColor(&rgb);
1009         }
1010         for(i=0; i < h; i++)
1011         {
1012                 dPtr = GetLinePtr(i);
1013                 sPtr = dib.GetLinePtr(i);
1014                 for(j=0 ; j < w; j++,dPtr++,sPtr+=3)
1015                 {
1016                         c = (*sPtr >> 3) | ((*(sPtr+1) >> 3) << 5) | ((*(sPtr+2) >> 3) << 10);
1017                         *dPtr = index_ptr[c];
1018                 }
1019         }
1020         free(index_ptr);
1021         return TRUE;
1022 }