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 "tools/edit_gui_common.h"
30
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
CDIB(HANDLE hDib,int nBits)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
~CDIB()66 CDIB::~CDIB()
67 {
68 DestroyDIB();
69 }
70
DestroyDIB()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
Create(int width,int height,int bits)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
Create(BITMAPINFOHEADER & bmInfo)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
SetPalette(unsigned char * palette)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
SetPalette(RGBQUAD * pRGB)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
GetPaletteSize()165 int CDIB::GetPaletteSize()
166 {
167 return GetPaletteSize(m_pInfo->bmiHeader);
168 }
169
170
GetPaletteSize(BITMAPINFOHEADER & bmInfo)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
SetPixel(int x,int y,COLORREF color)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
SetPixel8(int x,int y,unsigned char color)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
GetPixel(int x,int y)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
GetTempBitmap(CDC & dc)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
GetBitmap(CDC & dc)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
CopyLine(int source,int dest)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
InitDIB(COLORREF color)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
BitBlt(HDC hDest,int nXDest,int nYDest,int nWidth,int nHeight,int xSrc,int ySrc)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
StretchBlt(HDC hDest,int nXDest,int nYDest,int nDWidth,int nDHeight,int xSrc,int ySrc,int nSWidth,int nSHeight)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
ExpandBlt(int nXDest,int nYDest,int xRatio,int yRatio,CDIB & dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight)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
Expand(int nXDest,int nYDest,int xRatio,int yRatio,CDIB & dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight)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
StretchBlt(int nXDest,int nYDest,int nDWidth,int nDHeight,CDIB & dibSrc,int xSrc,int ySrc,int nSWidth,int nSHeight)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
BitBlt(int nXDest,int nYDest,int nWidth,int nHeight,CDIB & dibSrc,int nSrcX,int nSrcY,BYTE * colors)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
GetLinePtr(int line)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
CopyDIB(CDIB & dib)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
ReplaceColor(unsigned char oldColor,unsigned char newColor)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
operator =(CDIB & dib)574 CDIB& CDIB::operator=(CDIB& dib)
575 {
576 CopyDIB(dib);
577 return *this;
578 }
579
GetDIBits(int nStartX,int nStartY,int nCx,int nCy)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
GetDIBSize()596 DWORD CDIB::GetDIBSize()
597 {
598 return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*GetPaletteSize() + bytes*height;
599 }
600
DIBHandle()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
CreateFromHandle(HANDLE hMem,int bits)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
UseGamma(float fg,BOOL bUse)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
CreateGammaCurve()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
GetPixel(UINT x,UINT y,int & pixel)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
Make8Bit(CDIB & dib)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
SwitchFromOne(CDIB & dib)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
SwitchFromFour(CDIB & dib)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
SwitchPalette(CDIB & dib)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
ClosestColor(RGBQUAD * pRgb)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
Distance(RGBQUAD & rgb1,RGBQUAD & rgb2)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
OpenDIB(CString & csFileName)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
SaveDIB(CString & csFileName,BitmapType type)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
SaveBMP(CString & csFileName)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
OpenBMP(CString & csFileName)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
CountColors()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
EnumColors(BYTE * array)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
PaletteColor(int nIndex)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
SwitchFrom24(CDIB & dib)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 }
1023