www.pudn.com > cximage602_full.rar > ximage.cpp


// ximage.cpp : main implementation file 
/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it 
 * CxImage version 6.0.0 02/Feb/2008 
 */ 
 
#include "ximage.h" 
 
//////////////////////////////////////////////////////////////////////////////// 
// CxImage  
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Initialize the internal structures 
 */ 
void CxImage::Startup(DWORD imagetype) 
{ 
	//init pointers 
	pDib = pSelection = pAlpha = NULL; 
	ppLayers = ppFrames = NULL; 
	//init structures 
	memset(&head,0,sizeof(BITMAPINFOHEADER)); 
	memset(&info,0,sizeof(CXIMAGEINFO)); 
	//init default attributes 
    info.dwType = imagetype; 
	info.fQuality = 90.0f; 
	info.nAlphaMax = 255; 
	info.nBkgndIndex = -1; 
	info.bEnabled = true; 
	SetXDPI(CXIMAGE_DEFAULT_DPI); 
	SetYDPI(CXIMAGE_DEFAULT_DPI); 
 
	short test = 1; 
	info.bLittleEndianHost = (*((char *) &test) == 1); 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Empty image constructor 
 * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS 
 */ 
CxImage::CxImage(DWORD imagetype) 
{ 
	Startup(imagetype); 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Call this function to destroy image pixels, alpha channel, selection and sub layers. 
 * - Attributes are not erased, but IsValid returns false. 
 * 
 * \return true if everything is freed, false if the image is a Ghost 
 */ 
bool CxImage::Destroy() 
{ 
	//free this only if it's valid and it's not a ghost 
	if (info.pGhost==NULL){ 
		if (ppLayers) {  
			for(long n=0; n Use it before Create()  
 */ 
void CxImage::CopyInfo(const CxImage &src) 
{ 
	if (pDib==NULL) memcpy(&info,&src.info,sizeof(CXIMAGEINFO)); 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * \sa Copy 
 */ 
CxImage& CxImage::operator = (const CxImage& isrc) 
{ 
	if (this != &isrc) Copy(isrc); 
	return *this; 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Initializes or rebuilds the image. 
 * \param dwWidth: width 
 * \param dwHeight: height 
 * \param wBpp: bit per pixel, can be 1, 4, 8, 24 
 * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS 
 * \return pointer to the internal pDib object; NULL if an error occurs. 
 */ 
void* CxImage::Create(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype) 
{ 
	// destroy the existing image (if any) 
	if (!Destroy()) 
		return NULL; 
 
	// prevent further actions if width or height are not vaild  
	if ((dwWidth == 0) || (dwHeight == 0)){ 
		strcpy(info.szLastError,"CxImage::Create : width and height must be greater than zero"); 
		return NULL; 
	} 
 
    // Make sure bits per pixel is valid 
    if		(wBpp <= 1)	wBpp = 1; 
    else if (wBpp <= 4)	wBpp = 4; 
    else if (wBpp <= 8)	wBpp = 8; 
    else				wBpp = 24; 
 
	// limit memory requirements (and also a check for bad parameters) 
	if (((dwWidth*dwHeight*wBpp)>>3) > CXIMAGE_MAX_MEMORY || 
		((dwWidth*dwHeight*wBpp)/wBpp) != (dwWidth*dwHeight)) 
	{ 
		strcpy(info.szLastError,"CXIMAGE_MAX_MEMORY exceeded"); 
		return NULL; 
	} 
 
	// set the correct bpp value 
    switch (wBpp){ 
        case 1: 
            head.biClrUsed = 2;	break; 
        case 4: 
            head.biClrUsed = 16; break; 
        case 8: 
            head.biClrUsed = 256; break; 
        default: 
            head.biClrUsed = 0; 
    } 
 
	//set the common image informations 
    info.dwEffWidth = ((((wBpp * dwWidth) + 31) / 32) * 4); 
    info.dwType = imagetype; 
 
    // initialize BITMAPINFOHEADER 
	head.biSize = sizeof(BITMAPINFOHEADER); // 
    head.biWidth = dwWidth;		// fill in width from parameter 
    head.biHeight = dwHeight;	// fill in height from parameter 
    head.biPlanes = 1;			// must be 1 
    head.biBitCount = (WORD)wBpp;		// from parameter 
    head.biCompression = BI_RGB;     
    head.biSizeImage = info.dwEffWidth * dwHeight; 
//    head.biXPelsPerMeter = 0; See SetXDPI 
//    head.biYPelsPerMeter = 0; See SetYDPI 
//    head.biClrImportant = 0;  See SetClrImportant 
 
	pDib = malloc(GetSize()); // alloc memory block to store our bitmap 
    if (!pDib){ 
		strcpy(info.szLastError,"CxImage::Create can't allocate memory"); 
		return NULL; 
	} 
 
	//clear the palette 
	RGBQUAD* pal=GetPalette(); 
	if (pal) memset(pal,0,GetPaletteSize()); 
	//Destroy the existing selection 
#if CXIMAGE_SUPPORT_SELECTION 
	if (pSelection) SelectionDelete(); 
#endif //CXIMAGE_SUPPORT_SELECTION 
	//Destroy the existing alpha channel 
#if CXIMAGE_SUPPORT_ALPHA 
	if (pAlpha) AlphaDelete(); 
#endif //CXIMAGE_SUPPORT_ALPHA 
 
    // use our bitmap info structure to fill in first part of 
    // our DIB with the BITMAPINFOHEADER 
    BITMAPINFOHEADER*  lpbi; 
	lpbi = (BITMAPINFOHEADER*)(pDib); 
    *lpbi = head; 
 
	info.pImage=GetBits(); 
 
    return pDib; //return handle to the DIB 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * \return pointer to the image pixels.  USE CAREFULLY  
 */ 
BYTE* CxImage::GetBits(DWORD row) 
{  
	if (pDib){ 
		if (row) { 
			if (row<(DWORD)head.biHeight){ 
				return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize() + (info.dwEffWidth * row)); 
			} else { 
				return NULL; 
			} 
		} else { 
			return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize()); 
		} 
	} 
	return NULL; 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * \return the size in bytes of the internal pDib object 
 */ 
long CxImage::GetSize() 
{ 
	return head.biSize + head.biSizeImage + GetPaletteSize(); 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Checks if the coordinates are inside the image 
 * \return true if x and y are both inside the image 
 */ 
bool CxImage::IsInside(long x, long y) 
{ 
  return (0<=y && y 0) bval = 255; 
	} 
	if (GetBpp() == 4){ 
		bval = (BYTE)(17*(0x0F & bval)); 
	} 
 
	memset(info.pImage,bval,head.biSizeImage); 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Transfers the image from an existing source image. The source becomes empty. 
 * \return true if everything is ok 
 */ 
bool CxImage::Transfer(CxImage &from, bool bTransferFrames /*=true*/) 
{ 
	if (!Destroy()) 
		return false; 
 
	memcpy(&head,&from.head,sizeof(BITMAPINFOHEADER)); 
	memcpy(&info,&from.info,sizeof(CXIMAGEINFO)); 
 
	pDib = from.pDib; 
	pSelection = from.pSelection; 
	pAlpha = from.pAlpha; 
	ppLayers = from.ppLayers; 
 
	memset(&from.head,0,sizeof(BITMAPINFOHEADER)); 
	memset(&from.info,0,sizeof(CXIMAGEINFO)); 
	from.pDib = from.pSelection = from.pAlpha = NULL; 
	from.ppLayers = NULL; 
 
	if (bTransferFrames){ 
		DestroyFrames(); 
		ppFrames = from.ppFrames; 
		from.ppFrames = NULL; 
	} 
 
	return true; 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * (this) points to the same pDib owned by (*from), the image remains in (*from) 
 * but (this) has the access to the pixels. Use carefully !!! 
 */ 
void CxImage::Ghost(const CxImage *from) 
{ 
	if (from){ 
		memcpy(&head,&from->head,sizeof(BITMAPINFOHEADER)); 
		memcpy(&info,&from->info,sizeof(CXIMAGEINFO)); 
		pDib = from->pDib; 
		pSelection = from->pSelection; 
		pAlpha = from->pAlpha; 
		ppLayers = from->ppLayers; 
		ppFrames = from->ppFrames; 
		info.pGhost=(CxImage *)from; 
	} 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * turns a 16 or 32 bit bitfield image into a RGB image 
 */ 
void CxImage::Bitfield2RGB(BYTE *src, DWORD redmask, DWORD greenmask, DWORD bluemask, BYTE bpp) 
{ 
	switch (bpp){ 
	case 16: 
	{ 
		DWORD ns[3]={0,0,0}; 
		// compute the number of shift for each mask 
		for (int i=0;i<16;i++){ 
			if ((redmask>>i)&0x01) ns[0]++; 
			if ((greenmask>>i)&0x01) ns[1]++; 
			if ((bluemask>>i)&0x01) ns[2]++; 
		} 
		ns[1]+=ns[0]; ns[2]+=ns[1];	ns[0]=8-ns[0]; ns[1]-=8; ns[2]-=8; 
		// dword aligned width for 16 bit image 
		long effwidth2=(((head.biWidth + 1) / 2) * 4); 
		WORD w; 
		long y2,y3,x2,x3; 
		BYTE *p=info.pImage; 
		// scan the buffer in reverse direction to avoid reallocations 
		for (long y=head.biHeight-1; y>=0; y--){ 
			y2=effwidth2*y; 
			y3=info.dwEffWidth*y; 
			for (long x=head.biWidth-1; x>=0; x--){ 
				x2 = 2*x+y2; 
				x3 = 3*x+y3; 
				w = (WORD)(src[x2]+256*src[1+x2]); 
				p[  x3]=(BYTE)((w & bluemask)<>ns[1]); 
				p[2+x3]=(BYTE)((w & redmask)>>ns[2]); 
			} 
		} 
		break; 
	} 
	case 32: 
	{ 
		DWORD ns[3]={0,0,0}; 
		// compute the number of shift for each mask 
		for (int i=8;i<32;i+=8){ 
			if (redmask>>i) ns[0]++; 
			if (greenmask>>i) ns[1]++; 
			if (bluemask>>i) ns[2]++; 
		} 
		// dword aligned width for 32 bit image 
		long effwidth4 = head.biWidth * 4; 
		long y4,y3,x4,x3; 
		BYTE *p=info.pImage; 
		// scan the buffer in reverse direction to avoid reallocations 
		for (long y=head.biHeight-1; y>=0; y--){ 
			y4=effwidth4*y; 
			y3=info.dwEffWidth*y; 
			for (long x=head.biWidth-1; x>=0; x--){ 
				x4 = 4*x+y4; 
				x3 = 3*x+y3; 
				p[  x3]=src[ns[2]+x4]; 
				p[1+x3]=src[ns[1]+x4]; 
				p[2+x3]=src[ns[0]+x4]; 
			} 
		} 
	} 
 
	} 
	return; 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * Creates an image from a generic buffer 
 * \param pArray: source memory buffer 
 * \param dwWidth: image width 
 * \param dwHeight: image height 
 * \param dwBitsperpixel: can be 1,4,8,24,32 
 * \param dwBytesperline: line alignment, in bytes, for a single row stored in pArray 
 * \param bFlipImage: tune this parameter if the image is upsidedown 
 * \return true if everything is ok 
 */ 
bool CxImage::CreateFromArray(BYTE* pArray,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage) 
{ 
	if (pArray==NULL) return false; 
	if (!((dwBitsperpixel==1)||(dwBitsperpixel==4)||(dwBitsperpixel==8)|| 
		(dwBitsperpixel==24)||(dwBitsperpixel==32))) return false; 
 
	if (!Create(dwWidth,dwHeight,dwBitsperpixel)) return false; 
 
	if (dwBitsperpixel<24) SetGrayPalette(); 
 
#if CXIMAGE_SUPPORT_ALPHA 
	if (dwBitsperpixel==32) AlphaCreate(); 
#endif //CXIMAGE_SUPPORT_ALPHA 
 
	BYTE *dst,*src; 
 
	for (DWORD y = 0; yrgbRed,c1->rgbGreen,c1->rgbBlue); 
	int g2 = (int)RGB2GRAY(c2->rgbRed,c2->rgbGreen,c2->rgbBlue); 
	 
	return (g1-g2); 
} 
//////////////////////////////////////////////////////////////////////////////// 
/** 
 * simply calls "if (memblock) free(memblock);". 
 * Useful when calling Encode for a memory buffer, 
 * from a DLL compiled with different memory management options. 
 * CxImage::FreeMemory will use the same memory environment used by Encode.  
 * \author [livecn] 
 */ 
void CxImage::FreeMemory(void* memblock) 
{ 
	if (memblock) 
		free(memblock); 
} 
//////////////////////////////////////////////////////////////////////////////// 
//EOF