bitmap.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 840 行 · 第 1/2 页

CPP
840
字号
		}
		if ( numCounted != 0 )
		{
			aCol[a]=cCol/255.0f/numCounted;
		}
	}
	for(int y=0;y<ysize;++y)
	{
		for(int x=0;x<xsize;++x)
		{
			if(mem[(y*xsize+x)*4+0]==red && mem[(y*xsize+x)*4+1]==green && mem[(y*xsize+x)*4+2]==blue) {
				mem[(y*xsize+x)*4+0]= (unsigned char) (aCol.x*255);
				mem[(y*xsize+x)*4+1]= (unsigned char) (aCol.y*255);
				mem[(y*xsize+x)*4+2]= (unsigned char) (aCol.z*255);
				mem[(y*xsize+x)*4+3]=0;
			}
		}
	}
}


// Depreciated (Only used by GUI which will be replaced by CEGUI anyway)
void CBitmap::SetTransparent( unsigned char red, unsigned char green, unsigned char blue )
{
	for ( unsigned int y = 0; y < xsize; y++ )
	{
		for ( unsigned int x = 0; x < xsize; x++ )
		{
			unsigned int index = (y*xsize + x)*4;
			if ( mem[index+0] == red &&
				mem[index+1] == green &&
				mem[index+2] == blue )
			{
				// set transparent
				mem[index+3] = 0;
			}
		}
	}
}


void CBitmap::Renormalize(float3 newCol)
{
	float3 aCol;
	//	float3 aSpread;

	float3 colorDif;
	//	float3 spreadMul;
	for(int a=0;a<3;++a){
		int cCol=0;
		int numCounted=0;
		for(int y=0;y<ysize;++y){
			for(int x=0;x<xsize;++x){
				if(mem[(y*xsize+x)*4+3]!=0){
					cCol+=mem[(y*xsize+x)*4+a];
					++numCounted;
				}
			}
		}
		aCol[a]=cCol/255.0f/numCounted;
		cCol/=xsize*ysize;
		colorDif[a]=newCol[a]-aCol[a];

/*		int spread=0;
        for(int y=0;y<ysize;++y){
        for(int x=0;x<xsize;++x){
        if(mem[(y*xsize+x)*4+3]!=0){
        int dif=mem[(y*xsize+x)*4+a]-cCol;
        spread+=abs(dif);
        }
        }
        }
        aSpread.xyz[a]=spread/255.0f/numCounted;
        spreadMul.xyz[a]=(float)(newSpread[a]/aSpread[a]);*/
	}
	for(int a=0;a<3;++a){
		for(int y=0;y<ysize;++y){
			for(int x=0;x<xsize;++x){
				float nc=float(mem[(y*xsize+x)*4+a])/255.0f+colorDif[a];
				/*				float r=newCol.xyz[a]+(nc-newCol.xyz[a])*spreadMul.xyz[a];*/
				mem[(y*xsize+x)*4+a]=(unsigned char)(std::min(255.f,std::max(0.f,nc*255)));
			}
		}
	}
}


// Unused
CBitmap CBitmap::GetRegion(int startx, int starty, int width, int height)
{
	CBitmap bm;

	delete[] bm.mem;
	bm.mem=SAFE_NEW unsigned char[width*height*4];
	bm.xsize=width;
	bm.ysize=height;

	for(int y=0;y<height;++y){
		for(int x=0;x<width;++x){
			bm.mem[(y*width+x)*4]=mem[((starty+y)*xsize+startx+x)*4];
			bm.mem[(y*width+x)*4+1]=mem[((starty+y)*xsize+startx+x)*4+1];
			bm.mem[(y*width+x)*4+2]=mem[((starty+y)*xsize+startx+x)*4+2];
			bm.mem[(y*width+x)*4+3]=mem[((starty+y)*xsize+startx+x)*4+3];
		}
	}

	return bm;
}


CBitmap CBitmap::CreateMipmapLevel(void)
{
	CBitmap bm;

	delete[] bm.mem;
	bm.xsize=xsize/2;
	bm.ysize=ysize/2;
	bm.mem=SAFE_NEW unsigned char[bm.xsize*bm.ysize*4];

	for(int y=0;y<ysize/2;++y){
		for(int x=0;x<xsize/2;++x){
			float r=0,g=0,b=0,a=0;
			for(int y2=0;y2<2;++y2){
				for(int x2=0;x2<2;++x2){
					r+=mem[((y*2+y2)*xsize+x*2+x2)*4+0];
					g+=mem[((y*2+y2)*xsize+x*2+x2)*4+1];
					b+=mem[((y*2+y2)*xsize+x*2+x2)*4+2];
					a+=mem[((y*2+y2)*xsize+x*2+x2)*4+3];
				}
			}
			bm.mem[(y*bm.xsize+x)*4]=(unsigned char)(r/4);
			bm.mem[(y*bm.xsize+x)*4+1]=(unsigned char)(g/4);
			bm.mem[(y*bm.xsize+x)*4+2]=(unsigned char)(b/4);
			bm.mem[(y*bm.xsize+x)*4+3]=(unsigned char)(a/4);
		}
	}

	return bm;

}


CBitmap CBitmap::CreateRescaled(int newx, int newy)
{
	CBitmap bm;

	delete[] bm.mem;
	bm.xsize=newx;
	bm.ysize=newy;
	bm.mem=SAFE_NEW unsigned char[bm.xsize*bm.ysize*4];

	float dx=float(xsize)/newx;
	float dy=float(ysize)/newy;

	float cy=0;
	for(int y=0;y<newy;++y){
		int sy=(int)cy;
		cy+=dy;
		int ey=(int)cy;
		if(ey==sy)
			ey=sy+1;

		float cx=0;
		for(int x=0;x<newx;++x){
			int sx=(int)cx;
			cx+=dx;
			int ex=(int)cx;
			if(ex==sx)
				ex=sx+1;

			int r=0,g=0,b=0,a=0;
			for(int y2=sy;y2<ey;++y2){
				for(int x2=sx;x2<ex;++x2){
					r+=mem[(y2*xsize+x2)*4+0];
					g+=mem[(y2*xsize+x2)*4+1];
					b+=mem[(y2*xsize+x2)*4+2];
					a+=mem[(y2*xsize+x2)*4+3];
				}
			}
			bm.mem[(y*bm.xsize+x)*4+0]=r/((ex-sx)*(ey-sy));
			bm.mem[(y*bm.xsize+x)*4+1]=g/((ex-sx)*(ey-sy));
			bm.mem[(y*bm.xsize+x)*4+2]=b/((ex-sx)*(ey-sy));
			bm.mem[(y*bm.xsize+x)*4+3]=a/((ex-sx)*(ey-sy));
		}
	}
	return bm;
}


void CBitmap::InvertColors()
{
	if (type != BitmapTypeStandardRGBA) {
		return;
	}
	for(int y = 0; y < ysize; ++y) {
		for(int x = 0; x < xsize; ++x) {
			const int base = ((y * xsize) + x) * 4;
			mem[base + 0] = 0xFF - mem[base + 0];
			mem[base + 1] = 0xFF - mem[base + 1];
			mem[base + 2] = 0xFF - mem[base + 2];
			// do not invert alpha
		}
	}
}


void CBitmap::GrayScale()
{
	if (type != BitmapTypeStandardRGBA) {
		return;
	}
	for(int y = 0; y < ysize; ++y) {
		for(int x = 0; x < xsize; ++x) {
			const int base = ((y * xsize) + x) * 4;
			const float illum =
				(mem[base + 0] * 0.299f) +
				(mem[base + 1] * 0.587f) +
				(mem[base + 2] * 0.114f);
			const unsigned int  ival = (unsigned int)(illum * (256.0f / 255.0f));
			const unsigned char cval = (ival <= 0xFF) ? ival : 0xFF;
			mem[base + 0] = cval;
			mem[base + 1] = cval;
			mem[base + 2] = cval;
		}
	}
}


static ILubyte TintByte(ILubyte value, float tint)
{
	float f = (float)value;
	f = std::max(0.0f, std::min(255.0f, f * tint));
	return (ILubyte)f;
}


void CBitmap::Tint(const float tint[3])
{
	if (type != BitmapTypeStandardRGBA) {
		return;
	}
	for (int y = 0; y < ysize; y++) {
		for (int x = 0; x < xsize; x++) {
			const int base = ((y * xsize) + x) * 4;
			mem[base + 0] = TintByte(mem[base + 0], tint[0]);
			mem[base + 1] = TintByte(mem[base + 1], tint[1]);
			mem[base + 2] = TintByte(mem[base + 2], tint[2]);
			// don't touch the alpha channel
		}
	}
}


void CBitmap::ReverseYAxis()
{
	unsigned char* buf=SAFE_NEW unsigned char[xsize*ysize*4];

	for(int y=0;y<ysize;++y){
		for(int x=0;x<xsize;++x){
			buf[((ysize-1-y)*xsize+x)*4+0]=mem[((y)*xsize+x)*4+0];
			buf[((ysize-1-y)*xsize+x)*4+1]=mem[((y)*xsize+x)*4+1];
			buf[((ysize-1-y)*xsize+x)*4+2]=mem[((y)*xsize+x)*4+2];
			buf[((ysize-1-y)*xsize+x)*4+3]=mem[((y)*xsize+x)*4+3];
		}
	}
	delete[] mem;
	mem=buf;
}


#if defined(__APPLE__)

Handle CBitmap::GetPtrDataRef(unsigned char *data, unsigned int size,
	const std::string &filename)
{
	// Load Data Reference
	Handle dataRef;
	Handle fileNameHandle;
	PointerDataRefRecord ptrDataRefRec;
	ComponentInstance dataRefHandler;
	unsigned char pstr[255];

	ptrDataRefRec.data = data;
	ptrDataRefRec.dataLength = size;

	/*err = */PtrToHand(&ptrDataRefRec, &dataRef, sizeof(PointerDataRefRecord));

	// Open a Data Handler for the Data Reference
	/*err = */OpenADataHandler(dataRef, PointerDataHandlerSubType, NULL,
		(OSType)0, NULL, kDataHCanRead, &dataRefHandler);

	// Convert From CString in filename to a PascalString in pstr
	if (filename.length() > 255) {
		CopyCStringToPascal(filename.c_str(), pstr);
		//hmm...not good, pascal string limit is 255!
		//do some error handling maybe?!
	}

	// Add filename extension
	/*err = */PtrToHand(pstr, &fileNameHandle, filename.length() + 1);
	/*err = */DataHSetDataRefExtension(dataRefHandler, fileNameHandle,
		kDataRefExtensionFileName);
	DisposeHandle(fileNameHandle);

	// Release old handler which does not have the extensions
	DisposeHandle(dataRef);

	// Grab the SAFE_NEW version of the data ref from the data handler
	/*err = */ DataHGetDataRef(dataRefHandler, &dataRef);

	return dataRef;
}


unsigned char *CBitmap::LoadTextureData(const std::string &filename,
	unsigned char *data, unsigned int sizeData, int &xsize,
	int &ysize, bool &hasAlpha)
{
	unsigned char *imageData = 0;
	GWorldPtr gworld = 0;
	OSType pixelFormat;
	int rowStride;
	GraphicsImportComponent gicomp;
	Rect rectImage;
	GDHandle origDevice;
	CGrafPtr origPort;
	ImageDescriptionHandle desc;
	int depth;

	// Data Handle for file data ( & load data from file )
	Handle dataRef = GetPtrDataRef(data, sizeData, filename);

	// GraphicsImporter - Get Importer for our filetype
	GetGraphicsImporterForDataRef(dataRef, 'ptr ', &gicomp);

	// GWorld - Get Texture Info
	if (noErr != GraphicsImportGetNaturalBounds(gicomp, &rectImage)) {
		return 0;
	}
	xsize = (unsigned int)(rectImage.right - rectImage.left);
	ysize = (unsigned int)(rectImage.bottom - rectImage.top);

	// ImageDescription - Get Image Description
	if (noErr != GraphicsImportGetImageDescription(gicomp, &desc)) {
		CloseComponent(gicomp);
		return 0;
	}

	// ImageDescription - Get Bit Depth
	HLock(reinterpret_cast<char **>(desc));
	if (depth == 32) { // Only if it returns 32 does the image have an alpha chanel!
		hasAlpha = true;
	} else {
		hasAlpha = false;
	}

	// GWorld - Pixel Format stuff
	pixelFormat = k32ARGBPixelFormat; // Make sure its forced...NOTE: i'm pretty sure this cannot be RGBA!

	// GWorld - Row stride
	rowStride = xsize * 4; // (width * depth_bpp / 8)

	// GWorld - Allocate output buffer
	imageData = SAFE_NEW unsigned char[rowStride * ysize];

	// GWorld - Actually Create IT!
	QTNewGWorldFromPtr(&gworld, pixelFormat, &rectImage, 0, 0, 0, imageData, rowStride);
	if (!gworld) {
		delete imageData;
		CloseComponent(gicomp);
		DisposeHandle(reinterpret_cast<char **>(desc));
		return 0;
	}

	// Save old Graphics Device and Graphics Port to reset to later
	GetGWorld (&origPort, &origDevice);

	// GraphicsImporter - Set Destination GWorld (our buffer)
	if (noErr != GraphicsImportSetGWorld(gicomp, gworld, 0)) {
		DisposeGWorld(gworld);
		delete imageData;
		CloseComponent(gicomp);
		DisposeHandle(reinterpret_cast<char **>(desc));
		return 0;
	}

	// GraphicsImporter - Set Quality Level
	if (noErr != GraphicsImportSetQuality(gicomp, codecLosslessQuality)) {
		DisposeGWorld(gworld);
		delete imageData;
		CloseComponent(gicomp);
		DisposeHandle(reinterpret_cast<char **>(desc));
		return 0;
	}

	// Lock pixels so that we can draw to our memory texture
	if (!GetGWorldPixMap(gworld) || !LockPixels(GetGWorldPixMap(gworld))) {
		DisposeGWorld(gworld);
		delete imageData;
		CloseComponent(gicomp);
		DisposeHandle(reinterpret_cast<char **>(desc));
		return 0;
	}

	//*** Draw GWorld into our Memory Texture!
	GraphicsImportDraw(gicomp);

	// Clean up
	UnlockPixels(GetGWorldPixMap(gworld));
	SetGWorld(origPort, origDevice); // set graphics port to offscreen (we don't need it now)
	DisposeGWorld(gworld);
	CloseComponent(gicomp);
	DisposeHandle(reinterpret_cast<char **>(desc));

	return imageData;

}

#endif /* __APPLE__ */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?