www.pudn.com > BloodVessel.rar > ximapal.cpp


// xImaPal.cpp : Palette and Pixel functions 
/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it 
 * CxImage version 5.99c 17/Oct/2004 
 */ 
 
#include "ximage.h" 
 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * returns the palette dimension in byte 
 */ 
DWORD CxImage::GetPaletteSize() 
{ 
	return (head.biClrUsed * sizeof(RGBQUAD)); 
} 
//////////////////////////////////////////////////////////////////////////////// 
void CxImage::SetPaletteColor(BYTE idx, BYTE r, BYTE g, BYTE b, BYTE alpha) 
{ 
	if ((pDib)&&(head.biClrUsed)){ 
		BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER); 
		if (idx=head.biWidth)||(y>=head.biHeight)) { 
		if (info.nBkgndIndex != -1)	return (BYTE)info.nBkgndIndex; 
		else return *info.pImage; 
	} 
	if (head.biBitCount==8){ 
		return info.pImage[y*info.dwEffWidth + x]; 
	} else { 
		BYTE pos; 
		BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)]; 
		if (head.biBitCount==4){ 
			pos = (BYTE)(4*(1-x%2)); 
			iDst &= (0x0F<> pos); 
		} else if (head.biBitCount==1){ 
			pos = (BYTE)(7-x%8); 
			iDst &= (0x01<> pos); 
		} 
	} 
	return 0; 
} 
//////////////////////////////////////////////////////////////////////////////// 
BYTE CxImage::BlindGetPixelIndex(const long x,const long y) 
{ 
#ifdef _DEBUG 
	if ((pDib==NULL) || (head.biClrUsed==0) || !IsInside(x,y)) throw 0; 
#endif 
 
	if (head.biBitCount==8){ 
		return info.pImage[y*info.dwEffWidth + x]; 
	} else { 
		BYTE pos; 
		BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)]; 
		if (head.biBitCount==4){ 
			pos = (BYTE)(4*(1-x%2)); 
			iDst &= (0x0F<> pos); 
		} else if (head.biBitCount==1){ 
			pos = (BYTE)(7-x%8); 
			iDst &= (0x01<> pos); 
		} 
	} 
	return 0; 
} 
//////////////////////////////////////////////////////////////////////////////// 
RGBQUAD CxImage::GetPixelColor(long x,long y, bool bGetAlpha) 
{ 
//	RGBQUAD rgb={0,0,0,0}; 
	RGBQUAD rgb=info.nBkgndColor; // 
	if ((pDib==NULL)||(x<0)||(y<0)|| 
		(x>=head.biWidth)||(y>=head.biHeight)){ 
		if (info.nBkgndIndex != -1){ 
			if (head.biBitCount<24) return GetPaletteColor((BYTE)info.nBkgndIndex); 
			else return info.nBkgndColor; 
		} else if (pDib) return GetPixelColor(0,0); 
		return rgb; 
	} 
 
	if (head.biClrUsed){ 
		rgb = GetPaletteColor(GetPixelIndex(x,y)); 
	} else { 
		BYTE* iDst  = info.pImage + y*info.dwEffWidth + x*3; 
		rgb.rgbBlue = *iDst++; 
		rgb.rgbGreen= *iDst++; 
		rgb.rgbRed  = *iDst; 
	} 
#if CXIMAGE_SUPPORT_ALPHA 
	if (pAlpha && bGetAlpha) rgb.rgbReserved = AlphaGet(x,y); 
#else 
	rgb.rgbReserved = 0; 
#endif //CXIMAGE_SUPPORT_ALPHA 
	return rgb; 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * This is (a bit) faster version of GetPixelColor.  
 * It tests bounds only in debug mode (_DEBUG defined). 
 *  
 * It is an error to request out-of-borders pixel with this method.  
 * In DEBUG mode an exception will be thrown, and data will be violated in non-DEBUG mode.  
 * \author ***bd*** 2.2004 
 */ 
RGBQUAD CxImage::BlindGetPixelColor(const long x,const long y) 
{ 
  RGBQUAD rgb; 
#ifdef _DEBUG 
	if ((pDib==NULL) || !IsInside(x,y)) throw 0; 
#endif 
 
	if (head.biClrUsed){ 
		return GetPaletteColor(BlindGetPixelIndex(x,y)); 
	} 
 
	BYTE* iDst  = info.pImage + y*info.dwEffWidth + x*3; 
	rgb.rgbBlue = *iDst++; 
	rgb.rgbGreen= *iDst++; 
	rgb.rgbRed  = *iDst; 
#if CXIMAGE_SUPPORT_ALPHA 
	if (pAlpha) rgb.rgbReserved = pAlpha[x+y*head.biWidth]; 
#else 
	rgb.rgbReserved = 0; 
#endif //CXIMAGE_SUPPORT_ALPHA 
	return rgb; 
} 
//////////////////////////////////////////////////////////////////////////////// 
BYTE CxImage::GetPixelGray(long x, long y) 
{ 
	RGBQUAD color = GetPixelColor(x,y); 
	return (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue); 
} 
//////////////////////////////////////////////////////////////////////////////// 
void CxImage::SetPixelIndex(long x,long y,BYTE i) 
{ 
	if ((pDib==NULL)||(head.biClrUsed==0)|| 
		(x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) return ; 
 
	if (head.biBitCount==8){ 
		info.pImage[y*info.dwEffWidth + x]=i; 
		return; 
	} else { 
		BYTE pos; 
		BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3); 
		if (head.biBitCount==4){ 
			pos = (BYTE)(4*(1-x%2)); 
			*iDst &= ~(0x0F<=head.biWidth)||(y>=head.biHeight)) return; 
	if (head.biClrUsed) 
		SetPixelIndex(x,y,GetNearestIndex(c)); 
	else { 
		BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3; 
		*iDst++ = c.rgbBlue; 
		*iDst++ = c.rgbGreen; 
		*iDst   = c.rgbRed; 
#if CXIMAGE_SUPPORT_ALPHA 
		if (bSetAlpha) AlphaSet(x,y,c.rgbReserved); 
#endif //CXIMAGE_SUPPORT_ALPHA 
	} 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Blends the current pixel color with a new color. 
 * \param x,y = pixel 
 * \param c = new color 
 * \param blend = can be from 0 (no effect) to 1 (full effect). 
 * \param bSetAlpha = if true, blends also the alpha component stored in c.rgbReserved 
 */ 
void CxImage::BlendPixelColor(long x,long y,RGBQUAD c, float blend, bool bSetAlpha) 
{ 
	if ((pDib==NULL)||(x<0)||(y<0)|| 
		(x>=head.biWidth)||(y>=head.biHeight)) return; 
 
	int a0 = (int)(256*blend); 
	int a1 = 256 - a0; 
 
	RGBQUAD c0 = BlindGetPixelColor(x,y); 
	c.rgbRed  = (BYTE)((c.rgbRed * a0 + c0.rgbRed * a1)>>8); 
	c.rgbBlue  = (BYTE)((c.rgbBlue * a0 + c0.rgbBlue * a1)>>8); 
	c.rgbGreen  = (BYTE)((c.rgbGreen * a0 + c0.rgbGreen * a1)>>8); 
 
	if (head.biClrUsed) 
		SetPixelIndex(x,y,GetNearestIndex(c)); 
	else { 
		BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3; 
		*iDst++ = c.rgbBlue; 
		*iDst++ = c.rgbGreen; 
		*iDst   = c.rgbRed; 
#if CXIMAGE_SUPPORT_ALPHA 
		if (bSetAlpha) AlphaSet(x,y,c.rgbReserved); 
#endif //CXIMAGE_SUPPORT_ALPHA 
	} 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Returns the best palette index that matches a specified color. 
 */ 
BYTE CxImage::GetNearestIndex(RGBQUAD c) 
{ 
	if ((pDib==NULL)||(head.biClrUsed==0)) return 0; 
 
	//  check matching with the previous result 
	if (info.last_c_isvalid && (*(long*)&info.last_c == *(long*)&c)) return info.last_c_index; 
	info.last_c = c; 
	info.last_c_isvalid = true; 
 
	BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER); 
	long distance=200000; 
	int i,j = 0; 
	long k,l; 
	int m = (int)(head.biClrImportant==0 ? head.biClrUsed : head.biClrImportant); 
	for(i=0,l=0;i100) perc=100; 
	for(i=0;i=0){ 
		if (head.biClrUsed){ 
			if (GetPixelIndex(x,y) == info.nBkgndIndex) return true; 
		} else { 
			RGBQUAD ct = info.nBkgndColor; 
			RGBQUAD c = GetPixelColor(x,y,false); 
			if (*(long*)&c==*(long*)&ct) return true; 
		} 
	} 
 
#if CXIMAGE_SUPPORT_ALPHA 
	if (pAlpha) return AlphaGet(x,y)==0; 
#endif 
 
	return false; 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Checks if image has the same palette, if any. 
 * \param img = image to compare. 
 * \param bCheckAlpha = check also the rgbReserved field. 
 */ 
bool CxImage::IsSamePalette(CxImage &img, bool bCheckAlpha) 
{ 
	if (head.biClrUsed != img.head.biClrUsed) 
		return false; 
	if (head.biClrUsed == 0) 
		return false; 
 
	RGBQUAD c1,c2; 
	for (DWORD n=0; n256) { 
		head.biClrImportant = 0; 
		return; 
	} 
 
	switch(head.biBitCount){ 
	case 1: 
		head.biClrImportant = min(ncolors,2); 
		break; 
	case 4: 
		head.biClrImportant = min(ncolors,16); 
		break; 
	case 8: 
		head.biClrImportant = ncolors; 
		break; 
	} 
	return; 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Returns pointer to pixel. Currently implemented only for truecolor images. 
 *   
 * \param  x,y - coordinates 
 * 
 * \return pointer to first byte of pixel data 
 * 
 * \author ***bd*** 2.2004 
 */ 
void* CxImage::BlindGetPixelPointer(const long x, const long y) 
{ 
  if (!IsIndexed()) 
    return info.pImage + y*info.dwEffWidth + x*3; 
  else 
    return 0; 
} 
//////////////////////////////////////////////////////////////////////////////// 
void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, COLORREF cr) 
{ 
	DrawLine(StartX, EndX, StartY, EndY, RGBtoRGBQUAD(cr)); 
} 
//////////////////////////////////////////////////////////////////////////////// 
void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, RGBQUAD color, bool bSetAlpha) 
{ 
	if (!pDib) return; 
	////////////////////////////////////////////////////// 
	// Draws a line using the Bresenham line algorithm 
	// Thanks to Jordan DeLozier  
	////////////////////////////////////////////////////// 
	int x1 = StartX; 
	int y1 = StartY; 
	int x = x1;                       // Start x off at the first pixel 
	int y = y1;                       // Start y off at the first pixel 
	int x2 = EndX; 
	int y2 = EndY; 
 
	int xinc1,xinc2,yinc1,yinc2;      // Increasing values 
	int den, num, numadd,numpixels;    
	int deltax = abs(x2 - x1);        // The difference between the x's 
	int deltay = abs(y2 - y1);        // The difference between the y's 
 
	// Get Increasing Values 
	if (x2 >= x1) {                // The x-values are increasing 
		xinc1 = 1; 
		xinc2 = 1; 
	} else {                         // The x-values are decreasing 
		xinc1 = -1; 
		xinc2 = -1; 
	} 
 
	if (y2 >= y1) {                // The y-values are increasing 
		yinc1 = 1; 
		yinc2 = 1; 
	} else {                         // The y-values are decreasing 
		yinc1 = -1; 
		yinc2 = -1; 
	} 
 
	// Actually draw the line 
	if (deltax >= deltay)         // There is at least one x-value for every y-value 
	{ 
		xinc1 = 0;                  // Don't change the x when numerator >= denominator 
		yinc2 = 0;                  // Don't change the y for every iteration 
		den = deltax; 
		num = deltax / 2; 
		numadd = deltay; 
		numpixels = deltax;         // There are more x-values than y-values 
	} 
	else                          // There is at least one y-value for every x-value 
	{ 
		xinc2 = 0;                  // Don't change the x for every iteration 
		yinc1 = 0;                  // Don't change the y when numerator >= denominator 
		den = deltay; 
		num = deltay / 2; 
		numadd = deltax; 
		numpixels = deltay;         // There are more y-values than x-values 
	} 
	 
	for (int curpixel = 0; curpixel <= numpixels; curpixel++) 
	{ 
		// Draw the current pixel 
		SetPixelColor(x,y,color,bSetAlpha); 
		 
		num += numadd;              // Increase the numerator by the top of the fraction 
		if (num >= den)             // Check if numerator >= denominator 
		{ 
			num -= den;               // Calculate the new numerator value 
			x += xinc1;               // Change the x as appropriate 
			y += yinc1;               // Change the y as appropriate 
		} 
		x += xinc2;                 // Change the x as appropriate 
		y += yinc2;                 // Change the y as appropriate 
	} 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Sets a palette with standard colors for 4 and 8 bpp images. 
 */ 
void CxImage::SetStdPalette() 
{ 
	if (!pDib) return; 
	switch (head.biBitCount){ 
	case 8: 
		{ 
			const BYTE pal256[1024] = {0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0, 
			192,220,192,0,240,202,166,0,212,240,255,0,177,226,255,0,142,212,255,0,107,198,255,0, 
			72,184,255,0,37,170,255,0,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0, 
			50,80,0,212,227,255,0,177,199,255,0,142,171,255,0,107,143,255,0,72,115,255,0,37,87,255,0,0, 
			85,255,0,0,73,220,0,0,61,185,0,0,49,150,0,0,37,115,0,0,25,80,0,212,212,255,0,177,177,255,0, 
			142,142,255,0,107,107,255,0,72,72,255,0,37,37,255,0,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0, 
			0,0,115,0,0,0,80,0,227,212,255,0,199,177,255,0,171,142,255,0,143,107,255,0,115,72,255,0, 
			87,37,255,0,85,0,255,0,73,0,220,0,61,0,185,0,49,0,150,0,37,0,115,0,25,0,80,0,240,212,255,0, 
			226,177,255,0,212,142,255,0,198,107,255,0,184,72,255,0,170,37,255,0,170,0,255,0,146,0,220,0, 
			122,0,185,0,98,0,150,0,74,0,115,0,50,0,80,0,255,212,255,0,255,177,255,0,255,142,255,0,255,107,255,0, 
			255,72,255,0,255,37,255,0,254,0,254,0,220,0,220,0,185,0,185,0,150,0,150,0,115,0,115,0,80,0,80,0, 
			255,212,240,0,255,177,226,0,255,142,212,0,255,107,198,0,255,72,184,0,255,37,170,0,255,0,170,0, 
			220,0,146,0,185,0,122,0,150,0,98,0,115,0,74,0,80,0,50,0,255,212,227,0,255,177,199,0,255,142,171,0, 
			255,107,143,0,255,72,115,0,255,37,87,0,255,0,85,0,220,0,73,0,185,0,61,0,150,0,49,0,115,0,37,0, 
			80,0,25,0,255,212,212,0,255,177,177,0,255,142,142,0,255,107,107,0,255,72,72,0,255,37,37,0,254,0, 
			0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,0,255,227,212,0,255,199,177,0,255,171,142,0, 
			255,143,107,0,255,115,72,0,255,87,37,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0,115,37,0, 
			0,80,25,0,0,255,240,212,0,255,226,177,0,255,212,142,0,255,198,107,0,255,184,72,0,255,170,37,0, 
			255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,0,255,255,212,0,255,255,177,0, 
			255,255,142,0,255,255,107,0,255,255,72,0,255,255,37,0,254,254,0,0,220,220,0,0,185,185,0,0,150,150,0, 
			0,115,115,0,0,80,80,0,0,240,255,212,0,226,255,177,0,212,255,142,0,198,255,107,0,184,255,72,0, 
			170,255,37,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0,50,80,0,0,227,255,212,0, 
			199,255,177,0,171,255,142,0,143,255,107,0,115,255,72,0,87,255,37,0,85,255,0,0,73,220,0,0,61,185,0, 
			0,49,150,0,0,37,115,0,0,25,80,0,0,212,255,212,0,177,255,177,0,142,255,142,0,107,255,107,0,72,255,72,0, 
			37,255,37,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,212,255,227,0,177,255,199,0, 
			142,255,171,0,107,255,143,0,72,255,115,0,37,255,87,0,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0, 
			115,37,0,0,80,25,0,212,255,240,0,177,255,226,0,142,255,212,0,107,255,198,0,72,255,184,0,37,255,170,0, 
			0,255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,212,255,255,0,177,255,255,0, 
			142,255,255,0,107,255,255,0,72,255,255,0,37,255,255,0,0,254,254,0,0,220,220,0,0,185,185,0,0, 
			150,150,0,0,115,115,0,0,80,80,0,242,242,242,0,230,230,230,0,218,218,218,0,206,206,206,0,194,194,194,0, 
			182,182,182,0,170,170,170,0,158,158,158,0,146,146,146,0,134,134,134,0,122,122,122,0,110,110,110,0, 
			98,98,98,0,86,86,86,0,74,74,74,0,62,62,62,0,50,50,50,0,38,38,38,0,26,26,26,0,14,14,14,0,240,251,255,0, 
			164,160,160,0,128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0}; 
			memcpy(GetPalette(),pal256,1024); 
			break; 
		} 
	case 4: 
		{ 
			const BYTE pal16[64]={0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0, 
								128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0}; 
			memcpy(GetPalette(),pal16,64); 
			break; 
		} 
	} 
	return; 
} 
////////////////////////////////////////////////////////////////////////////////