Beispiel #1
0
void R_LoadTGA(const char *name, byte **pic, int *width, int *height, byte alphaByte)
{
	unsigned columns, rows, numPixels;
	byte     *pixbuf;
	int      row, column;
	byte     *buf_p;
	byte     *end;
	union
	{
		byte *b;
		void *v;
	} buffer;
	TargaHeader targa_header;
	byte        *targa_rgba;
	int         length;

	*pic = NULL;

	if (width)
	{
		*width = 0;
	}
	if (height)
	{
		*height = 0;
	}

	//
	// load the file
	//
	length = ri.FS_ReadFile(( char * ) name, &buffer.v);
	if (!buffer.b || length < 0)
	{
		return;
	}

	if (length < 18)
	{
		ri.FS_FreeFile(buffer.v);
		Ren_Drop("LoadTGA: header too short (%s)\n", name);
	}

	buf_p = buffer.b;
	end   = buffer.b + length;

	targa_header.id_length     = buf_p[0];
	targa_header.colormap_type = buf_p[1];
	targa_header.image_type    = buf_p[2];

	memcpy(&targa_header.colormap_index, &buf_p[3], 2);
	memcpy(&targa_header.colormap_length, &buf_p[5], 2);
	targa_header.colormap_size = buf_p[7];
	memcpy(&targa_header.x_origin, &buf_p[8], 2);
	memcpy(&targa_header.y_origin, &buf_p[10], 2);
	memcpy(&targa_header.width, &buf_p[12], 2);
	memcpy(&targa_header.height, &buf_p[14], 2);
	targa_header.pixel_size = buf_p[16];
	targa_header.attributes = buf_p[17];

	targa_header.colormap_index  = LittleShort(targa_header.colormap_index);
	targa_header.colormap_length = LittleShort(targa_header.colormap_length);
	targa_header.x_origin        = LittleShort(targa_header.x_origin);
	targa_header.y_origin        = LittleShort(targa_header.y_origin);
	targa_header.width           = LittleShort(targa_header.width);
	targa_header.height          = LittleShort(targa_header.height);

	buf_p += 18;

	if (targa_header.image_type != 2
	    && targa_header.image_type != 10
	    && targa_header.image_type != 3)
	{
		ri.FS_FreeFile(buffer.v);
		Ren_Drop("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
	}

	if (targa_header.colormap_type != 0)
	{
		ri.FS_FreeFile(buffer.v);
		Ren_Drop("LoadTGA: colormaps not supported\n");
	}

	if ((targa_header.pixel_size != 32 && targa_header.pixel_size != 24) && targa_header.image_type != 3)
	{
		ri.FS_FreeFile(buffer.v);
		Ren_Drop("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
	}

	columns   = targa_header.width;
	rows      = targa_header.height;
	numPixels = columns * rows * 4;

	if (!columns || !rows || numPixels > 0x7FFFFFFF || numPixels / columns / 4 != rows)
	{
		ri.FS_FreeFile(buffer.v);
		Ren_Drop("LoadTGA: %s has an invalid image size\n", name);
	}

	targa_rgba = R_GetImageBuffer(numPixels, BUFFER_IMAGE, name);

	if (targa_header.id_length != 0)
	{
		if (buf_p + targa_header.id_length > end)
		{
			ri.Free(targa_rgba);
			ri.FS_FreeFile(buffer.v);
			Ren_Drop("LoadTGA: header too short (%s)\n", name);
		}

		buf_p += targa_header.id_length;  // skip TARGA image comment
	}

	if (targa_header.image_type == 2 || targa_header.image_type == 3)
	{
		if (buf_p + columns * rows * targa_header.pixel_size / 8 > end)
		{
			ri.Free(targa_rgba);
			ri.FS_FreeFile(buffer.v);
			Ren_Drop("LoadTGA: file truncated (%s)\n", name);
		}

		// Uncompressed RGB or gray scale image
		for (row = rows - 1; row >= 0; row--)
		{
			pixbuf = targa_rgba + row * columns * 4;
			for (column = 0; column < columns; column++)
			{
				unsigned char red, green, blue, alpha;
				switch (targa_header.pixel_size)
				{
				case 8:
					blue      = *buf_p++;
					green     = blue;
					red       = blue;
					*pixbuf++ = red;
					*pixbuf++ = green;
					*pixbuf++ = blue;
					*pixbuf++ = alphaByte;
					break;
				case 24:
					blue      = *buf_p++;
					green     = *buf_p++;
					red       = *buf_p++;
					*pixbuf++ = red;
					*pixbuf++ = green;
					*pixbuf++ = blue;
					*pixbuf++ = alphaByte;
					break;
				case 32:
					blue      = *buf_p++;
					green     = *buf_p++;
					red       = *buf_p++;
					alpha     = *buf_p++;
					*pixbuf++ = red;
					*pixbuf++ = green;
					*pixbuf++ = blue;
					*pixbuf++ = alpha;
					break;
				default:
					ri.Free(targa_rgba);
					ri.FS_FreeFile(buffer.v);
					Ren_Drop("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name);
					break;
				}
			}
		}
	}
	else if (targa_header.image_type == 10)   // Runlength encoded RGB images
	{
		unsigned char red, green, blue, alpha, packetHeader, packetSize, j;

		red   = 0;
		green = 0;
		blue  = 0;
		alpha = alphaByte;

		for (row = rows - 1; row >= 0; row--)
		{
			pixbuf = targa_rgba + row * columns * 4;
			for (column = 0; column < columns; )
			{
				if (buf_p + 1 > end)
				{
					Ren_Drop("LoadTGA: file truncated (%s)\n", name);
				}
				packetHeader = *buf_p++;
				packetSize   = 1 + (packetHeader & 0x7f);
				if (packetHeader & 0x80)          // run-length packet
				{
					if (buf_p + targa_header.pixel_size / 8 > end)
					{
						Ren_Drop("LoadTGA: file truncated (%s)\n", name);
					}
					switch (targa_header.pixel_size)
					{
					case 24:
						blue  = *buf_p++;
						green = *buf_p++;
						red   = *buf_p++;
						alpha = alphaByte;
						break;
					case 32:
						blue  = *buf_p++;
						green = *buf_p++;
						red   = *buf_p++;
						alpha = *buf_p++;
						break;
					default:
						ri.Free(targa_rgba);
						ri.FS_FreeFile(buffer.v);
						Ren_Drop("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name);
						break;
					}

					for (j = 0; j < packetSize; j++)
					{
						*pixbuf++ = red;
						*pixbuf++ = green;
						*pixbuf++ = blue;
						*pixbuf++ = alpha;
						column++;
						if (column == columns)   // run spans across rows
						{
							column = 0;
							if (row > 0)
							{
								row--;
							}
							else
							{
								goto breakOut;
							}
							pixbuf = targa_rgba + row * columns * 4;
						}
					}
				}
				else                              // non run-length packet
				{
					if (buf_p + targa_header.pixel_size / 8 * packetSize > end)
					{
						ri.Free(targa_rgba);
						ri.FS_FreeFile(buffer.v);
						Ren_Drop("LoadTGA: file truncated (%s)\n", name);
					}
					for (j = 0; j < packetSize; j++)
					{
						switch (targa_header.pixel_size)
						{
						case 24:
							blue      = *buf_p++;
							green     = *buf_p++;
							red       = *buf_p++;
							*pixbuf++ = red;
							*pixbuf++ = green;
							*pixbuf++ = blue;
							*pixbuf++ = alphaByte;
							break;
						case 32:
							blue      = *buf_p++;
							green     = *buf_p++;
							red       = *buf_p++;
							alpha     = *buf_p++;
							*pixbuf++ = red;
							*pixbuf++ = green;
							*pixbuf++ = blue;
							*pixbuf++ = alpha;
							break;
						default:
							ri.Free(targa_rgba);
							ri.FS_FreeFile(buffer.v);
							Ren_Drop("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name);
							break;
						}
						column++;
						if (column == columns)   // pixel packet run spans across rows
						{
							column = 0;
							if (row > 0)
							{
								row--;
							}
							else
							{
								goto breakOut;
							}
							pixbuf = targa_rgba + row * columns * 4;
						}
					}
				}
			}
breakOut:;
		}
	}

#if 1
	// this is the chunk of code to ensure a behavior that meets TGA specs
	// bk0101024 - fix from Leonardo
	// bit 5 set => top-down
	if (targa_header.attributes & 0x20)
	{
		unsigned char *flip;
		unsigned char *src, *dst;

		//Ren_Warning( "WARNING: '%s' TGA file header declares top-down image, flipping\n", name);

		flip = (unsigned char *)ri.Hunk_AllocateTempMemory(columns * 4);
		for (row = 0; row < rows / 2; row++)
		{
			src = targa_rgba + row * 4 * columns;
			dst = targa_rgba + (rows - row - 1) * 4 * columns;

			memcpy(flip, src, columns * 4);
			memcpy(src, dst, columns * 4);
			memcpy(dst, flip, columns * 4);
		}
		ri.Hunk_FreeTempMemory(flip);
	}
#else
	// instead we just print a warning
	if (targa_header.attributes & 0x20)
	{
		Ren_Warning("WARNING: '%s' TGA file header declares top-down image, ignoring\n", name);
	}
#endif

	if (width)
	{
		*width = columns;
	}
	if (height)
	{
		*height = rows;
	}

	*pic = targa_rgba;

	ri.FS_FreeFile(buffer.v);
}
Beispiel #2
0
void R_LoadPCX(const char *filename, byte **pic, int *width, int *height, byte alphaByte)
{
	union
	{
		byte *b;
		void *v;
	} raw;
	byte           *end;
	pcx_t          *pcx;
	int            len;
	unsigned char  dataByte = 0, runLength = 0;
	byte           *out, *pix;
	unsigned short w, h;
	byte           *pic8;
	byte           *palette;
	int            i;
	unsigned       size = 0;

	if (width)
	{
		*width = 0;
	}
	if (height)
	{
		*height = 0;
	}
	*pic = NULL;

	// load the file
	len = ri.FS_ReadFile(( char * ) filename, &raw.v);
	if (!raw.b || len < 0)
	{
		return;
	}

	if ((unsigned)len < sizeof(pcx_t))
	{
		Ren_Print("PCX truncated: %s\n", filename);
		ri.FS_FreeFile(raw.v);
		return;
	}

	// parse the PCX file
	pcx = (pcx_t *)raw.b;
	end = raw.b + len;

	w    = LittleShort(pcx->xmax) + 1;
	h    = LittleShort(pcx->ymax) + 1;
	size = w * h;

	if (pcx->manufacturer != 0x0a
	    || pcx->version != 5
	    || pcx->encoding != 1
	    || pcx->color_planes != 1
	    || pcx->bits_per_pixel != 8
	    || w >= 1024
	    || h >= 1024)
	{
		Ren_Print("Bad or unsupported pcx file %s (%dx%d@%d)\n", filename, w, h, pcx->bits_per_pixel);
		return;
	}

	pix = pic8 = R_GetImageBuffer(size, BUFFER_IMAGE, filename);

	raw.b = pcx->data;
	// FIXME: should use bytes_per_line but original q3 didn't do that either
	while (pix < pic8 + size)
	{
		if (runLength > 0)
		{
			*pix++ = dataByte;
			--runLength;
			continue;
		}

		if (raw.b + 1 > end)
		{
			break;
		}
		dataByte = *raw.b++;

		if ((dataByte & 0xC0) == 0xC0)
		{
			if (raw.b + 1 > end)
			{
				break;
			}
			runLength = dataByte & 0x3F;
			dataByte  = *raw.b++;
		}
		else
		{
			runLength = 1;
		}
	}

	if (pix < pic8 + size)
	{
		Ren_Print("PCX file truncated: %s\n", filename);
		ri.FS_FreeFile(pcx);
		ri.Free(pic8);
	}

	if (raw.b - (byte *)pcx >= end - (byte *)769 || end[-769] != 0x0c)
	{
		Ren_Print("PCX missing palette: %s\n", filename);
		ri.FS_FreeFile(pcx);
		ri.Free(pic8);
		return;
	}

	palette = end - 768;

	pix = out = ri.Z_Malloc(4 * size);
	for (i = 0 ; i < size ; i++)
	{
		unsigned char p = pic8[i];
		pix[0] = palette[p * 3];
		pix[1] = palette[p * 3 + 1];
		pix[2] = palette[p * 3 + 2];
		pix[3] = 255;
		pix   += 4;
	}

	if (width)
	{
		*width = w;
	}
	if (height)
	{
		*height = h;
	}

	*pic = out;

	ri.FS_FreeFile(pcx);
	ri.Free(pic8);
}
Beispiel #3
0
void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *height, byte alphaByte)
{
	/* This struct contains the JPEG decompression parameters and pointers to
	 * working space (which is allocated as needed by the JPEG library).
	 */
	struct jpeg_decompress_struct cinfo = { NULL };

	/* We use our private extension JPEG error handler.
	 * Note that this struct must live as long as the main JPEG parameter
	 * struct, to avoid dangling-pointer problems.
	 */
	my_jpeg_error_mgr jerr;

	/* More stuff */
	JSAMPARRAY   buffer;        /* Output row buffer */
	unsigned int row_stride;    /* physical row width in output buffer */
	unsigned int pixelcount, memcount;
	unsigned int sindex, dindex;
	byte         *out;
	int          len;
	union
	{
		byte *b;
		void *v;
	} fbuffer;
	byte *buf;

	/* In this example we want to open the input file before doing anything else,
	 * so that the setjmp() error recovery below can assume the file is open.
	 * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
	 * requires it in order to read binary files.
	 */

	len = ri.FS_ReadFile(( char * ) filename, &fbuffer.v);
	if (!fbuffer.b || len < 0)
	{
		return;
	}

	/* Step 1: allocate and initialize JPEG decompression object */

	/* We have to set up the error handler first, in case the initialization
	 * step fails.  (Unlikely, but it could happen if you are out of memory.)
	 * This routine fills in the contents of struct jerr, and returns jerr's
	 * address which we place into the link field in cinfo.
	 */
	cinfo.err                 = jpeg_std_error(&jerr.pub);
	cinfo.err->error_exit     = R_JPGErrorExit;
	cinfo.err->output_message = R_JPGOutputMessage;

	/* Now we can initialize the JPEG decompression object. */
	jpeg_create_decompress(&cinfo);

	/* deep error handling */
	if (setjmp(jerr.jmpbuf))
	{
		// There was an error in jpeg decompression. Abort.
		return;
	}

	/* Step 2: specify data source (eg, a file) */

	jpeg_mem_src(&cinfo, fbuffer.b, len);

	/* Step 3: read file parameters with jpeg_read_header() */

	( void ) jpeg_read_header(&cinfo, TRUE);
	/* We can ignore the return value from jpeg_read_header since
	 *   (a) suspension is not possible with the stdio data source, and
	 *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
	 * See libjpeg.doc for more info.
	 */

	/* Step 4: set parameters for decompression */

	/*
	* Make sure it always converts images to RGB color space. This will
	* automatically convert 8-bit greyscale images to RGB as well.
	*/
	cinfo.out_color_space = JCS_RGB;

	/* In this example, we don't need to change any of the defaults set by
	 * jpeg_read_header(), so we do nothing here.
	 */

	/* Step 5: Start decompressor */
	( void ) jpeg_start_decompress(&cinfo);
	/* We can ignore the return value since suspension is not possible
	 * with the stdio data source.
	 */

	/* We may need to do some setup of our own at this point before reading
	 * the data.  After jpeg_start_decompress() we have the correct scaled
	 * output image dimensions available, as well as the output colormap
	 * if we asked for color quantization.
	 * In this example, we need to make an output work buffer of the right size.
	 */
	/* JSAMPLEs per row in output buffer */

	pixelcount = cinfo.output_width * cinfo.output_height;

	if (!cinfo.output_width || !cinfo.output_height
	    || ((pixelcount * 4) / cinfo.output_width) / 4 != cinfo.output_height
	    || pixelcount > 0x1FFFFFFF || cinfo.output_components != 3
	    )
	{
		// Free the memory to make sure we don't leak memory
		ri.FS_FreeFile(fbuffer.v);
		jpeg_destroy_decompress(&cinfo);

		Ren_Drop("LoadJPG: %s has an invalid image format: %dx%d*4=%d, components: %d", filename,
		         cinfo.output_width, cinfo.output_height, pixelcount * 4, cinfo.output_components);
	}

	memcount   = pixelcount * 4;
	row_stride = cinfo.output_width * cinfo.output_components;

	out = R_GetImageBuffer(memcount, BUFFER_IMAGE, filename);

	*width  = cinfo.output_width;
	*height = cinfo.output_height;

	/* Step 6: while (scan lines remain to be read) */
	/*           jpeg_read_scanlines(...); */

	/* Here we use the library's state variable cinfo.output_scanline as the
	 * loop counter, so that we don't have to keep track ourselves.
	 */
	while (cinfo.output_scanline < cinfo.output_height)
	{
		/* jpeg_read_scanlines expects an array of pointers to scanlines.
		 * Here the array is only one element long, but you could ask for
		 * more than one scanline at a time if that's more convenient.
		 */
		buf    = ((out + (row_stride * cinfo.output_scanline)));
		buffer = &buf;
		( void ) jpeg_read_scanlines(&cinfo, buffer, 1);
	}

	buf = out;

	// Expand from RGB to RGBA
	sindex = pixelcount * cinfo.output_components;
	dindex = memcount;

	do
	{
		buf[--dindex] = 255;
		buf[--dindex] = buf[--sindex];
		buf[--dindex] = buf[--sindex];
		buf[--dindex] = buf[--sindex];

	}
	while (sindex);

	*pic = out;

	/* Step 7: Finish decompression */

	( void ) jpeg_finish_decompress(&cinfo);
	/* We can ignore the return value since suspension is not possible
	 * with the stdio data source.
	 */

	/* Step 8: Release JPEG decompression object */

	/* This is an important step since it will release a good deal of memory. */
	jpeg_destroy_decompress(&cinfo);

	/* After finish_decompress, we can close the input file.
	 * Here we postpone it until after no more JPEG errors are possible,
	 * so as to simplify the setjmp error logic above.  (Actually, I don't
	 * think that jpeg_destroy can do an error exit, but why assume anything...)
	 */
	ri.FS_FreeFile(fbuffer.v);

	/* At this point you may want to check to see whether any corrupt-data
	 * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
	 */

	/* And we're done! */
}
void R_LoadBMP(const char *name, byte **pic, int *width, int *height)
{
	int      columns, rows;
	unsigned numPixels;
	byte     *pixbuf;
	int      row, column;
	byte     *buf_p;
	byte     *end;
	union
	{
		byte *b;
		void *v;
	} buffer;
	int         length;
	BMPHeader_t bmpHeader;
	byte        *bmpRGBA;

	*pic = NULL;

	if (width)
	{
		*width = 0;
	}

	if (height)
	{
		*height = 0;
	}

	// load the file
	length = ri.FS_ReadFile(( char * ) name, &buffer.v);
	if (!buffer.b || length < 0)
	{
		return;
	}

	if (length < 54)
	{
		ri.Error(ERR_DROP, "LoadBMP: header too short (%s)\n", name);
	}

	buf_p = buffer.b;
	end   = buffer.b + length;

	bmpHeader.id[0]            = *buf_p++;
	bmpHeader.id[1]            = *buf_p++;
	bmpHeader.fileSize         = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.reserved0        = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.bitmapDataOffset = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.bitmapHeaderSize = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.width            = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.height           = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.planes           = LittleShort(*( short * ) buf_p);
	buf_p                     += 2;
	bmpHeader.bitsPerPixel     = LittleShort(*( short * ) buf_p);
	buf_p                     += 2;
	bmpHeader.compression      = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.bitmapDataSize   = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.hRes             = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.vRes             = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.colors           = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;
	bmpHeader.importantColors  = LittleLong(*( int * ) buf_p);
	buf_p                     += 4;

	if (bmpHeader.bitsPerPixel == 8)
	{
		if (buf_p + sizeof(bmpHeader.palette) > end)
		{
			ri.Error(ERR_DROP, "LoadBMP: header too short (%s)\n", name);
		}

		Com_Memcpy(bmpHeader.palette, buf_p, sizeof(bmpHeader.palette));
		buf_p += sizeof(bmpHeader.palette);
	}

	if (buffer.b + bmpHeader.bitmapDataOffset > end)
	{
		ri.Error(ERR_DROP, "LoadBMP: invalid offset value in header (%s)\n", name);
	}

	buf_p = buffer.b + bmpHeader.bitmapDataOffset;

	if (bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M')
	{
		ri.Error(ERR_DROP, "LoadBMP: only Windows-style BMP files supported (%s)\n", name);
	}
	if (bmpHeader.fileSize != length)
	{
		ri.Error(ERR_DROP, "LoadBMP: header size does not match file size (%u vs. %u) (%s)\n", bmpHeader.fileSize, length, name);
	}
	if (bmpHeader.compression != 0)
	{
		ri.Error(ERR_DROP, "LoadBMP: only uncompressed BMP files supported (%s)\n", name);
	}
	if (bmpHeader.bitsPerPixel < 8)
	{
		ri.Error(ERR_DROP, "LoadBMP: monochrome and 4-bit BMP files not supported (%s)\n", name);
	}

	switch (bmpHeader.bitsPerPixel)
	{
	case 8:
	case 16:
	case 24:
	case 32:
		break;
	default:
		ri.Error(ERR_DROP, "LoadBMP: illegal pixel_size '%hu' in file '%s'\n", bmpHeader.bitsPerPixel, name);
		break;
	}

	columns = bmpHeader.width;
	rows    = bmpHeader.height;
	if (rows < 0)
	{
		rows = -rows;
	}
	numPixels = columns * rows;

	if (columns <= 0 || !rows || numPixels > 0x1FFFFFFF // 4*1FFFFFFF == 0x7FFFFFFC < 0x7FFFFFFF
	    || ((numPixels * 4) / columns) / 4 != rows)
	{
		ri.Error(ERR_DROP, "LoadBMP: %s has an invalid image size\n", name);
	}
	if (buf_p + numPixels * bmpHeader.bitsPerPixel / 8 > end)
	{
		ri.Error(ERR_DROP, "LoadBMP: file truncated (%s)\n", name);
	}

	if (width)
	{
		*width = columns;
	}
	if (height)
	{
		*height = rows;
	}

	bmpRGBA = R_GetImageBuffer(numPixels * 4, BUFFER_IMAGE);
	*pic    = bmpRGBA;


	for (row = rows - 1; row >= 0; row--)
	{
		pixbuf = bmpRGBA + row * columns * 4;

		for (column = 0; column < columns; column++)
		{
			unsigned char  red, green, blue, alpha;
			int            palIndex;
			unsigned short shortPixel;

			switch (bmpHeader.bitsPerPixel)
			{
			case 8:
				palIndex  = *buf_p++;
				*pixbuf++ = bmpHeader.palette[palIndex][2];
				*pixbuf++ = bmpHeader.palette[palIndex][1];
				*pixbuf++ = bmpHeader.palette[palIndex][0];
				*pixbuf++ = 0xff;
				break;
			case 16:
				shortPixel = *( unsigned short * ) pixbuf;
				pixbuf    += 2;
				*pixbuf++  = (shortPixel & (31 << 10)) >> 7;
				*pixbuf++  = (shortPixel & (31 << 5)) >> 2;
				*pixbuf++  = (shortPixel & (31)) << 3;
				*pixbuf++  = 0xff;
				break;

			case 24:
				blue      = *buf_p++;
				green     = *buf_p++;
				red       = *buf_p++;
				*pixbuf++ = red;
				*pixbuf++ = green;
				*pixbuf++ = blue;
				*pixbuf++ = 255;
				break;
			case 32:
				blue      = *buf_p++;
				green     = *buf_p++;
				red       = *buf_p++;
				alpha     = *buf_p++;
				*pixbuf++ = red;
				*pixbuf++ = green;
				*pixbuf++ = blue;
				*pixbuf++ = alpha;
				break;
			}
		}
	}

	ri.FS_FreeFile(buffer.v);
}