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