www.pudn.com > Direct3D-3ds_loader-render.rar > Image.cpp


// Image.cpp: implementation of the Image class. 
// 
////////////////////////////////////////////////////////////////////// 
#include "StdAfx.h" 
 
#include  
#include "Image.h" 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
Image::Image() 
{ 
	planes=0; sizeX=0; sizeY=0; data=NULL; isBGR=0; 
} 
 
Image::~Image() 
{ 
	if(data!=NULL)delete [] data; 
} 
 
Image::Image(const Image &in) 
{ 
	planes=0; sizeX=0; sizeY=0; data=NULL; isBGR=0; 
	Set( in); 
} 
 
int Image::Load(char *filename) 
{ 
	char p[5]; 
	int ret = 0; 
 
	char* pdest = strrchr( filename, '.' );		// find '.' 
	if( pdest[0]!=NULL)pdest++; 
	strncpy( p, pdest, 4); 
	strlwr(p);				// Convert a string to lowercase 
 
	if( !strcmp(p,"bmp"))		ret = LoadBMP( filename); 
	else if( !strcmp(p,"jpg"))	ret = LoadJPG( filename); 
	else if( !strcmp(p,"jpeg"))	ret = LoadJPG( filename); 
	else if( !strcmp(p,"tga"))	ret = LoadTGA( filename); 
	if(ret) return 1; 
	MessageBox(NULL, filename, "Nenájdený súbor", MB_OK ); 
	return 0; 
} 
 
void Image::Set(const Image &in) 
{ 
	if(in.planes<0 || in.planes>4)return; 
	if(in.sizeX<1 || in.sizeY<1) return; 
	if(in.data==NULL)return; 
	planes = in.planes; 
	sizeX = in.sizeX;  
	sizeY = in.sizeY;  
	isBGR = in.isBGR; 
	if(data!=NULL) delete [] data; 
	data = new unsigned char[sizeX*sizeY*planes]; 
	if(data==NULL)return; 
	memcpy( data, in.data, sizeX*sizeY*planes); 
} 
 
int Image::SaveBMP(char *filename) 
{ 
	BITMAPFILEHEADER fileheader; 
	BITMAPINFOHEADER infoheader; 
	FILE *sub; 
	if(data==NULL || planes !=3)return 0; 
	 
	int line_size = planes*sizeX; 
	if(line_size%4)line_size += 4 - line_size%4; 
	 
	fileheader.bfType = 0x4D42; // Magic identifier   - "BM"	| identifikacia BMP suboru musi byt "BM" 
	fileheader.bfSize = planes*sizeX*sizeY+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);	// File size in bytes			| velkos suboru v byte 
	fileheader.bfReserved1 = 0; 
	fileheader.bfReserved2 = 0; 
	fileheader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);	// Offset to image data, bytes	| posun na zaciatok dat 
	 
	infoheader.biSize = sizeof(BITMAPINFOHEADER);	// Header size in bytes			| velkost hlavicky BITMAPINFOHEADER 
	infoheader.biWidth = sizeX;	// Width of image			| sirka obrazka - sizeX 
	infoheader.biHeight = sizeY;	// Height of image			| vyska obrazka - sizeY 
	infoheader.biPlanes = 1;		// Number of colour planes	| pocet farebnych rovin musi bit 1 
	infoheader.biBitCount = 24;		// Bits per pixel			| bitov na pixel moze bit 1,4,8,24 
	infoheader.biCompression = 0;	// Compression type			| typ compresie , 0 - bez kompresie 
	infoheader.biSizeImage = line_size*infoheader.biHeight ;	// Image size in bytes		| velkost obrazka v byte 
	infoheader.biXPelsPerMeter = 0;	// Pixels per meter X		| pixelov na meter v smere x 
	infoheader.biYPelsPerMeter = 0;	// Pixels per meter Y		| pixelov na meter v smere y 
	infoheader.biClrUsed = 0;		// Number of colours		| pocet  farieb v palete, ak 0 vsetky su pouzivane 
	infoheader.biClrImportant = 0;	// Important colours		| dolezite farby v palete, ak 0 vsetky su dolezite 
	 
	sub = fopen(filename,"wb"); 
	if(sub==NULL)return 0; 
	fwrite( &fileheader, sizeof(BITMAPFILEHEADER), 1, sub); 
	fwrite( &infoheader, sizeof(BITMAPINFOHEADER), 1, sub); 
	 
	unsigned char* p = new unsigned char[line_size*sizeY]; 
	for(int y=0; y>= (7-x%8); 
			index &= 0x01; 
			data[(y*sizeX+x)*planes+0] = pal[index].rgbRed; 
			data[(y*sizeX+x)*planes+1] = pal[index].rgbGreen; 
			data[(y*sizeX+x)*planes+2] = pal[index].rgbBlue; 
		} 
	} 
	if(pom_data!=NULL)delete []pom_data; 
	return 1; 
} 
 
int Image::LoadBMP4bit(FILE *f, BITMAPFILEHEADER &fileheader, BITMAPINFOHEADER &infoheader) 
{ 
	RGBQUAD pal[16]; 
	unsigned int countpal; 
 
	if(infoheader.biBitCount!=4)return 0; 
	if(infoheader.biClrUsed==0)countpal=4; 
	else countpal=infoheader.biClrUsed; 
	if(fread( pal, sizeof(RGBQUAD), countpal, f)!=countpal) 
	{ 
		fclose(f); 
		return 0; 
	} 
 
	unsigned char* pom_data; 
	int line_size = infoheader.biWidth/2+infoheader.biWidth%2; 
	if(line_size%4)line_size += 4 - line_size%4; 
	pom_data = new unsigned char[line_size*infoheader.biHeight]; 
	if(pom_data==NULL){	fclose(f); return 0; } 
	if(!fread( pom_data, line_size*infoheader.biHeight, 1, f)) 
	{	 
		fclose(f); 
		delete [] pom_data; 
		return 0;  
	} 
	fclose(f); 
 
	sizeX=infoheader.biWidth; 
	sizeY=infoheader.biHeight; 
	planes=3; 
	isBGR=0; 
 
	if(data!=NULL)delete [] data; 
	data = new unsigned char[planes*sizeX*sizeY]; 
	if(data==NULL){ delete [] pom_data; return 0; } 
 
	for(int y=0; y>4; 
			data[(y*sizeX+x)*planes+0] = pal[index].rgbRed; 
			data[(y*sizeX+x)*planes+1] = pal[index].rgbGreen; 
			data[(y*sizeX+x)*planes+2] = pal[index].rgbBlue; 
		} 
	} 
	if(pom_data!=NULL)delete []pom_data; 
	return 1; 
} 
 
int Image::LoadBMP8bit(FILE *f, BITMAPFILEHEADER &fileheader, BITMAPINFOHEADER &infoheader) 
{ 
	RGBQUAD pal[256]; 
	unsigned int countpal; 
 
	if(infoheader.biBitCount!=8)return 0; 
	if(infoheader.biClrUsed==0)countpal=256; 
	else countpal=infoheader.biClrUsed; 
	if(fread( pal, sizeof(RGBQUAD), countpal, f)!=countpal) 
	{ 
		fclose(f); 
		return 0; 
	} 
 
	unsigned char* pom_data; 
	int line_size = infoheader.biWidth; 
	if(line_size%4)line_size += 4 - line_size%4; 
	pom_data = new unsigned char[line_size*infoheader.biHeight]; 
	if(pom_data==NULL){	fclose(f); return 0; } 
	if(!fread( pom_data, line_size*infoheader.biHeight, 1, f)) 
	{	 
		fclose(f); 
		delete [] pom_data; 
		return 0;  
	} 
	fclose(f); 
 
	sizeX=infoheader.biWidth; 
	sizeY=infoheader.biHeight; 
	planes=3; 
	isBGR=0; 
 
	if(data!=NULL)delete [] data; 
	data = new unsigned char[planes*sizeX*sizeY]; 
	if(data==NULL){ delete [] pom_data; return 0; } 
 
	for(int y=0; y> 3 for more speed). 
			// Next, we calculate the stride and allocate enough memory for the pixels. 
			channels = bits / 8; 
			stride = channels * width; 
			data = new unsigned char[stride * height]; 
 
			// Load in all the pixel data line by line 
			for(int y = 0; y < height; y++) 
			{ 
				// Store a pointer to the current line of pixels 
				unsigned char *pLine = &(data[stride * y]); 
 
				// Read in the current line of pixels 
				fread(pLine, stride, 1, pFile); 
			} 
			isBGR=1; 
		} 
		// Check if the image is a 16 bit image (RGB stored in 1 unsigned short) 
		else if(bits == 16) 
		{ 
			unsigned short pixels = 0; 
			int r=0, g=0, b=0; 
 
			// Since we convert 16-bit images to 24 bit, we hardcode the channels to 3. 
			// We then calculate the stride and allocate memory for the pixels. 
			channels = 3; 
			stride = channels * width; 
			data = new unsigned char[stride * height]; 
 
			// Load in all the pixel data pixel by pixel 
			for(int j = 0; j < width*height; j++) 
			{ 
				// Read in the current pixel 
				fread(&pixels, sizeof(unsigned short), 1, pFile); 
				 
				// To convert a 16-bit pixel into an R, G, B, we need to 
				// do some masking and such to isolate each color value. 
				// 0x1f = 11111 in binary, so since 5 bits are reserved in 
				// each unsigned short for the R, G and B, we bit shift and mask 
				// to find each value.  We then bit shift up by 3 to get the full color. 
				b = (pixels & 0x1f) << 3; 
				g = ((pixels >> 5) & 0x1f) << 3; 
				r = ((pixels >> 10) & 0x1f) << 3; 
				 
				// This essentially assigns the color to our array and swaps the 
				// B and R values at the same time. 
				data[j * 3 + 0] = r; 
				data[j * 3 + 1] = g; 
				data[j * 3 + 2] = b; 
			} 
		}	 
		else 
			return 0; 
	} 
	// Else, it must be Run-Length Encoded (RLE) 
	else 
	{ 
		int j=0; 
		byte rleID = 0; 
		int colorsRead = 0; 
		channels = bits / 8; 
		stride = channels * width; 
 
		data = new unsigned char[stride * height]; 
		byte *pColors = new byte [channels]; 
 
		while(j < width*height) 
		{ 
			fread(&rleID, sizeof(byte), 1, pFile); 
			 
			if(rleID < 128) 
			{ 
				rleID++; 
				while(rleID) 
				{ 
					fread(pColors, sizeof(byte) * channels, 1, pFile); 
					data[colorsRead + 0] = pColors[2]; 
					data[colorsRead + 1] = pColors[1]; 
					data[colorsRead + 2] = pColors[0]; 
 
					if(bits == 32)data[colorsRead + 3] = pColors[3]; 
					j++; 
					rleID--; 
					colorsRead += channels; 
				} 
			} 
			else 
			{ 
				rleID -= 127; 
				fread(pColors, sizeof(byte) * channels, 1, pFile); 
 
				while(rleID) 
				{ 
					data[colorsRead + 0] = pColors[2]; 
					data[colorsRead + 1] = pColors[1]; 
					data[colorsRead + 2] = pColors[0]; 
 
					if(bits == 32)data[colorsRead + 3] = pColors[3]; 
					j++; 
					rleID--; 
					colorsRead += channels; 
				} 
				 
			} 
				 
		} 
	} 
	fclose(pFile); 
 
	planes = channels; 
	sizeX    = width; 
	sizeY    = height; 
	Flip(); 
	return 1; 
} 
 
void Image::BGRtoRGB() 
{ 
	if(!isBGR || planes<3 || data==NULL)return; 
	for(int y=0; y>1; 
			data[(y*sizeX+x)*planes+1] = data[(y*sizeX+x)*planes+1]>>1; 
			data[(y*sizeX+x)*planes+2] = data[(y*sizeX+x)*planes+2]>>1; 
		} 
	} 
} 
 
void Image::invShift()			// invertovana a potom jas*0.5 
{ 
	if(data==NULL)return; 
	for(int y=0; y>1; 
			data[(y*sizeX+x)*planes+1] = (255-data[(y*sizeX+x)*planes+1])>>1; 
			data[(y*sizeX+x)*planes+2] = (255-data[(y*sizeX+x)*planes+2])>>1; 
		} 
	} 
} 
 
int Image::resize(int newx, int newy) 
{ 
	unsigned char *old_data = data; 
	int old_sizeX = sizeX; 
	int old_sizeY = sizeY; 
	float *d; 
 
	sizeX = newx; 
	sizeY = newy; 
	data = new unsigned char[sizeX*sizeY*planes]; 
	if(data==NULL) 
	{ 
		data = old_data; 
		sizeX = old_sizeX; 
		sizeY = old_sizeY; 
		return 0; 
	} 
 
	d = new float[old_sizeX*old_sizeY*planes]; 
	if(d==NULL) 
	{ 
		delete [] data; 
		data = old_data; 
		sizeX = old_sizeX; 
		sizeY = old_sizeY; 
		return 0; 
	} 
 
	for(int j=0; j 2.0 
		yf = (float)fmod(yf,1.0);			// zvysok po deleni 1 
		for(int x=0; x 2.0 
			xf = (float)fmod(xf,1.0);			// zvysok po deleni 1 
		 
			for(int c=0; c= old_sizeY-1 
					{ 
						iy = old_sizeY-1; 
						a = (1.f-xf)*d[(iy*old_sizeX+ix)*planes+c]+xf*d[(iy*old_sizeX+ix+1)*planes+c]; 
					} 
					else if(iy= old_sizeX-1 && iy>=1;		// /2 
	data = new unsigned char[planes*sizeX*sizeY]; 
	if(data==NULL) 
	{ 
		data = old_data; 
		sizeX = old_sizeX; 
		sizeY = old_sizeY; 
		return 0; 
	} 
 
	for(int y=0; y>1; 
			if(planes>1)data[(y*sizeX+x)*planes+1] = ((unsigned int)old_data[(y*old_sizeX+2*x)*planes+1]+(unsigned int)old_data[(y*old_sizeX+2*x+1)*planes+1])>>1; 
			if(planes>2)data[(y*sizeX+x)*planes+2] = ((unsigned int)old_data[(y*old_sizeX+2*x)*planes+2]+(unsigned int)old_data[(y*old_sizeX+2*x+1)*planes+2])>>1; 
			if(planes>3)data[(y*sizeX+x)*planes+3] = ((unsigned int)old_data[(y*old_sizeX+2*x)*planes+3]+(unsigned int)old_data[(y*old_sizeX+2*x+1)*planes+3])>>1; 
		} 
	} 
	delete [] old_data; 
	return 1; 
} 
 
int Image::resizeToHalfY() 
{ 
	unsigned char *old_data = data; 
	int old_sizeX = sizeX; 
	int old_sizeY = sizeY;; 
 
	if(sizeY<=1)return 0; 
	 
	sizeY >>=1;		// /2 
	data = new unsigned char[planes*sizeX*sizeY]; 
	if(data==NULL) 
	{ 
		data = old_data; 
		sizeX = old_sizeX; 
		sizeY = old_sizeY; 
		return 0; 
	} 
 
	for(int y=0; y>1; 
			if(planes>1)data[(y*sizeX+x)*planes+1] = ((unsigned int)old_data[(2*y*old_sizeX+x)*planes+1]+(unsigned int)old_data[((2*y+1)*old_sizeX+x)*planes+1])>>1; 
			if(planes>2)data[(y*sizeX+x)*planes+2] = ((unsigned int)old_data[(2*y*old_sizeX+x)*planes+2]+(unsigned int)old_data[((2*y+1)*old_sizeX+x)*planes+2])>>1; 
			if(planes>3)data[(y*sizeX+x)*planes+3] = ((unsigned int)old_data[(2*y*old_sizeX+x)*planes+3]+(unsigned int)old_data[((2*y+1)*old_sizeX+x)*planes+3])>>1; 
		} 
	} 
	delete [] old_data; 
	return 1; 
} 
 
int Image::resizeToHalfXY() 
{ 
	unsigned char *old_data = data; 
	int old_sizeX = sizeX; 
	int old_sizeY = sizeY; 
 
	if(sizeX<=1 && sizeY<=1)return 0; 
	 
	sizeX >>=1;		// /2 
	sizeY >>=1;		// /2 
	data = new unsigned char[planes*sizeX*sizeY]; 
	if(data==NULL) 
	{ 
		data = old_data; 
		sizeX = old_sizeX; 
		sizeY = old_sizeY; 
		return 0; 
	} 
 
	for(int y=0; y>2; 
			if(planes>1)data[(y*sizeX+x)*planes+1] = ( 
							(unsigned int)old_data[(2*y*old_sizeX+2*x)*planes+1]+ 
							(unsigned int)old_data[((2*y+1)*old_sizeX+2*x)*planes+1]+ 
							(unsigned int)old_data[(2*y*old_sizeX+2*x+1)*planes+1]+ 
							(unsigned int)old_data[((2*y+1)*old_sizeX+2*x+1)*planes+1])>>2; 
			if(planes>2)data[(y*sizeX+x)*planes+2] = ( 
							(unsigned int)old_data[(2*y*old_sizeX+2*x)*planes+2]+ 
							(unsigned int)old_data[((2*y+1)*old_sizeX+2*x)*planes+2]+ 
							(unsigned int)old_data[(2*y*old_sizeX+2*x+1)*planes+2]+ 
							(unsigned int)old_data[((2*y+1)*old_sizeX+2*x+1)*planes+2])>>2; 
			if(planes>3)data[(y*sizeX+x)*planes+3] = ( 
							(unsigned int)old_data[(2*y*old_sizeX+2*x)*planes+3]+ 
							(unsigned int)old_data[((2*y+1)*old_sizeX+2*x)*planes+3]+ 
							(unsigned int)old_data[(2*y*old_sizeX+2*x+1)*planes+3]+ 
							(unsigned int)old_data[((2*y+1)*old_sizeX+2*x+1)*planes+3])>>2; 
		} 
	} 
	delete [] old_data; 
	return 1; 
} 
 
void Image::Flip()				// up - down 
{ 
	unsigned char *old = data; 
	if(data==NULL)return; 
	data = new unsigned char[planes*sizeX*sizeY]; 
	if(data==NULL) 
	{ 
		data = old; 
		return; 
	} 
 
	for(int y=0; y=sizeX)x=sizeX-1; else if(x<0)x=0;		// clamp 
	if(y>=sizeY)y=sizeY-1; else if(y<0)y=0;		// clamp 
	return data[(sizeX*y+x)*planes+plane]; 
} 
 
float Image::evaluateMask(  int x, int y, int plane, \ 
							float m11, float m12, float m13, \ 
							float m21, float m22, float m23, \ 
							float m31, float m32, float m33 ) 
{ 
	float r; 
 
	r  = m11*getSavePoint( x-1, y-1, plane); 
	r += m12*getSavePoint( x  , y-1, plane); 
	r += m13*getSavePoint( x+1, y-1, plane); 
	r += m21*getSavePoint( x-1, y  , plane); 
	r += m22*getSavePoint( x  , y  , plane); 
	r += m23*getSavePoint( x+1, y  , plane); 
	r += m31*getSavePoint( x-1, y+1, plane); 
	r += m32*getSavePoint( x  , y+1, plane); 
	r += m33*getSavePoint( x+1, y+1, plane); 
	return r/255.f; 
} 
 
void Image::Filter( int maska, int plane, float strong) 
{ 
	if(data==NULL)return; 
	unsigned char *new_data = new unsigned char[sizeX*sizeY*3]; 
	if(new_data==NULL)return; 
	if(plane>=planes)plane = planes-1; 
 
	float dx,dy;		// dx derivacia vysky (farby) v smere x, dy derivacia v smere y 
 
	for(int x=0; x