⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 targa_provider_generic.cpp

📁 这是一款2d游戏引擎
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				*a = 255;
			}
//
		}

		pos += 2;
		break;

	case 24:
		*b = file[pos];
		*g = file[pos+1];
		*r = file[pos+2];
		*a = 255;

		if (transparent && 
			*r == trans_redcol &&
			*g == trans_greencol &&
			*b == trans_bluecol)
		{
			*a = 0;
			ret = false;
		}

		pos += 3;
		break;

	case 32:
		*a = file[pos+3];
		if (use_alphapixels && !(*a))
		{
			*r = trans_redcol;
			*g = trans_greencol;
			*b = trans_bluecol;

			ret = false;
		}
		else
		{
			*b = file[pos];
			*g = file[pos+1];
			*r = file[pos+2];
			
			if (transparent && 
				*r == trans_redcol &&
				*g == trans_greencol &&
				*b == trans_bluecol)
			{
				*a = 0;
				ret = false;
			}
//
			else
			if (ignore_alphachannel) 
			{
				// else if we're not using any alphapixels at all, then alpha should be 255.
				*a = 255;
			}
//
		}

		pos += 4;
		break;
	}

	return ret;
}

/*
	Read and convert a colormap-index into an rgba-color.
	This function speculates in an index to exist in the 
	file directly at the current position.
*/
void CL_TargaProvider_Generic::read_from_colormap(
	unsigned char *a,
	unsigned char *b,
	unsigned char *g,
	unsigned char *r)
{
	if (pos >= filesize)
		throw CL_Error("Invalid targa file!?");

	// if the colormap is <= 256 entries large, the
	// index will be contained in a byte - 
	// otherwise in a short
	int entry;
	if (map_length <= 256)
	{
		entry = file[pos++];
	}
	else
	{
		entry = *((unsigned short *) &file[pos]);
		SWAP_IF_BIG(entry);
		pos += 2;
	}

	if (entry < 0 || entry >= map_length)
		throw CL_Error("Invalid targa file!?");

	// convert index-value to rgba-values using the colormap
	*r = color_map[entry*4+0];
	*g = color_map[entry*4+1];
	*b = color_map[entry*4+2];
	*a = color_map[entry*4+3];
}

/*
	CODE FOR DECODING TYPE 1 TARGA FILES
*/
void CL_TargaProvider_Generic::read_colormapped()
{
	read_header(true);

	image = new unsigned char[pitch * height * 4];

	int ystart = map_direction_y == 1 ? 0 : height-1;
	int xstart = map_direction_x == 1 ? 0 : pitch-1;

	for (int y = ystart;y>=0&&y<height;y+=map_direction_y)
	{
		for (int x = xstart; x>=0 && x<pitch;x+=map_direction_x)
		{
			read_from_colormap(&image[(x+y*pitch)*4],
								 &image[(x+y*pitch)*4+1],
								 &image[(x+y*pitch)*4+2],
								 &image[(x+y*pitch)*4+3]);
		}
	}
}

/*
	CODE FOR DECODING TYPE 2 TARGA FILES
*/
void CL_TargaProvider_Generic::read_uncompressed_rgb()
{
	read_header(false);

	int ystart = map_direction_y == 1 ? 0 : height-1;
	int xstart = map_direction_x == 1 ? 0 : pitch-1;

	image = new unsigned char[pitch * height * 4];
	switch (bpp)
	{
	case 16:
		{
			for (int y = ystart;y>=0&&y<height;y+=map_direction_y)
			{
				for (int x = xstart; x>=0 && x<pitch;x+=map_direction_x)
				{
					bool v = read_rgb_16(&image[(x+y*pitch)*4+0], 
										&image[(x+y*pitch)*4+1],
										&image[(x+y*pitch)*4+2],
										&image[(x+y*pitch)*4+3]);
					if (v)
					{
						if (x < bounding_left) bounding_left = x;
						if (y < bounding_top) bounding_top = y;
						if (x > bounding_right) bounding_right = x;
						if (y > bounding_bottom) bounding_bottom = y;
					}
				}
			}
		}
		break;
	
	case 24:
		{
			for (int y = ystart;y>=0&&y<height;y+=map_direction_y)
			{
				for (int x = xstart; x>=0 && x<pitch;x+=map_direction_x)
				{
					bool v = read_rgb_24(&image[(x+y*pitch)*4+0], 
												&image[(x+y*pitch)*4+1],
												&image[(x+y*pitch)*4+2],
												&image[(x+y*pitch)*4+3]);
					if (v)
					{
						if (x < bounding_left) bounding_left = x;
						if (y < bounding_top) bounding_top = y;
						if (x > bounding_right) bounding_right = x;
						if (y > bounding_bottom) bounding_bottom = y;
					}

				}
			}
		}
		break;

	case 32:
		{
			for (int y = ystart;y>=0&&y<height;y+=map_direction_y)
			{
				for (int x = xstart; x>=0 && x<pitch;x+=map_direction_x)
				{
					bool v = read_rgb_32(&image[(x+y*pitch)*4+0], 
										&image[(x+y*pitch)*4+1],
										&image[(x+y*pitch)*4+2],
										&image[(x+y*pitch)*4+3]);
					if (v)
					{
						if (x < bounding_left) bounding_left = x;
						if (y < bounding_top) bounding_top = y;
						if (x > bounding_right) bounding_right = x;
						if (y > bounding_bottom) bounding_bottom = y;
					}
				}
			}
		}
		break;

	default: 
		throw CL_Error("Unknown bpp!");
	}
}

/*
	CODE FOR DECODING TYPE 9 TARGA FILES
*/

void CL_TargaProvider_Generic::read_runlength_encoded_colormapped_rgb()
{
	read_header(true);

	image = new unsigned char[pitch * height * 4];
	
	int ystart = map_direction_y == 1 ? 0 : height-1;
	int xstart = map_direction_x == 1 ? 0 : pitch-1;

	int line = ystart;
	int xpos = xstart;
	while (line >= 0 && line < height)
	{
		unsigned char head = file[pos++];
		unsigned char type = (head & 128)>>7;
		unsigned char repcount = (head & 127)+1;

		switch (type)
		{
		// RAW PACKET
		case 0:
			for (;repcount>0;repcount--)
			{
				read_from_colormap(&image[(xpos+line*pitch)*4],
									 &image[(xpos+line*pitch)*4+1],
									 &image[(xpos+line*pitch)*4+2],
									 &image[(xpos+line*pitch)*4+3]);

				xpos+=map_direction_x;
				if (xpos < 0 || xpos >= pitch)
				{
					xpos = xstart;
					line += map_direction_y;
				}
			}
			break;

		// RUNLENGTH ENCODED PACKET
		case 1:
			{
				unsigned char r, g, b, a;
				read_from_colormap(&r, &g, &b, &a);
				
				for (;repcount>0;repcount--)
				{
					image[((line*pitch+xpos)*4)+0] = r;
					image[((line*pitch+xpos)*4)+1] = g;
					image[((line*pitch+xpos)*4)+2] = b;
					image[((line*pitch+xpos)*4)+3] = a;

					xpos+=map_direction_x;
					if (xpos < 0 || xpos >= pitch)
					{
						xpos = xstart;
						line += map_direction_y;
					}
				}
			}
			break;
		}
	}
}

/*
	CODE FOR DECODING TYPE 10 TARGA FILES
*/
void CL_TargaProvider_Generic::read_runlength_encoded_rgb()
{
	read_header(false);

	image = new unsigned char[pitch * height * 4];

	int ystart = map_direction_y == 1 ? 0 : height-1;
	int xstart = map_direction_x == 1 ? 0 : pitch-1;

	int line = ystart;
	int xpos = xstart;
	while (line >= 0 && line < height)
	{
		unsigned char head = file[pos++];
		unsigned char type = (head & 128)>>7;
		unsigned char repcount = (head & 127)+1;

		switch (type)
		{
		// RAW PACKET
		case 0:
			for (;repcount>0;repcount--)
			{
				bool v = read_rgb(&image[((line*pitch+xpos)*4)+0], 
									&image[((line*pitch+xpos)*4)+1],
									&image[((line*pitch+xpos)*4)+2],
									&image[((line*pitch+xpos)*4)+3]);
				if (v)
				{
					if (xpos < bounding_left) bounding_left = xpos;
					if (line < bounding_top) bounding_top = line;
					if (xpos > bounding_right) bounding_right = xpos;
					if (line > bounding_bottom) bounding_bottom = line;
				}

				xpos+=map_direction_x;
				if (xpos < 0 || xpos >= pitch)
				{
					xpos = xstart;
					line += map_direction_y;
				}
			}
			break;

		// RUNLENGTH ENCODED PACKET
		case 1:
			{
				unsigned char r, g, b, a;
				bool v = read_rgb(&r, &g, &b, &a);
				
				for (;repcount>0;repcount--)
				{
					image[((line*pitch+xpos)*4)+0] = r;
					image[((line*pitch+xpos)*4)+1] = g;
					image[((line*pitch+xpos)*4)+2] = b;
					image[((line*pitch+xpos)*4)+3] = a;

					if (v)
					{
						if (xpos < bounding_left) bounding_left = xpos;
						if (line < bounding_top) bounding_top = line;
						if (xpos > bounding_right) bounding_right = xpos;
						if (line > bounding_bottom) bounding_bottom = line;
					}

					xpos+=map_direction_x;
					if (xpos < 0 || xpos >= pitch)
					{
						xpos = xstart;
						line += map_direction_y;
					}
				}
			}
			break;
		}
	}
}

void *CL_TargaProvider_Generic::get_data()
{
	return image+bounding_left*4+bounding_top*pitch*4;
}

/*
	Lock the surfaceprovider - which basically means open the file
	and read the image into a temporary memory buffer - until
	unlock() is called.
*/
void CL_TargaProvider_Generic::perform_lock()
{
	if (locked) return;

	cl_assert(provider != NULL);
	input_source = provider->open_source(filename.c_str());
	cl_assert(input_source!=NULL);

	no_sprs = 1;

	filesize = input_source->size();
	file = new unsigned char[filesize];
	cl_assert(file != NULL);

	int num_bytes_read = input_source->read(file, filesize);
	cl_assert(num_bytes_read == ((int) filesize));

	// read the data
	read_data();

	if (bounding_left > bounding_right) bounding_left = bounding_right;
	if (bounding_top > bounding_bottom) bounding_top = bounding_bottom;

	delete[] file;
	delete input_source;
	file = NULL;

	locked = true;

	// this could be integrated better, but since this targa class
	// look like shit, and I'm too tired to clean it, I just hack CL_PixelBuffer
	// support into it. -- mbn 9. feb 2002

	CL_PixelBuffer_Generic::format.enable_colorkey(uses_src_colorkey());
	CL_PixelBuffer_Generic::format.set_colorkey(get_src_colorkey());
	CL_PixelBuffer_Generic::format.set_depth(get_depth());
	CL_PixelBuffer_Generic::format.set_red_mask(get_red_mask());
	CL_PixelBuffer_Generic::format.set_green_mask(get_green_mask());
	CL_PixelBuffer_Generic::format.set_blue_mask(get_blue_mask());
	CL_PixelBuffer_Generic::format.set_alpha_mask(get_alpha_mask());
	CL_PixelBuffer_Generic::pitch = get_pitch();
	CL_PixelBuffer_Generic::width = get_width();
	CL_PixelBuffer_Generic::height = get_height();
}

void CL_TargaProvider_Generic::perform_unlock()
{
	locked = false;
	delete[] color_map;
	delete[] image;

	image = color_map = NULL;
}

⌨️ 快捷键说明

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