Exemple #1
1
void FontGen::SaveTarga()
{
    char fileName[256];
    sprintf(fileName, "%s.tga", font_def.name);

    int start_line = TEX_HEIGHT - texture_height;
    WriteTGA(fileName, bmbits + TEX_WIDTH * 3 * start_line, TEX_WIDTH, texture_height, compressTga, monochrome);
}
Exemple #2
1
void
WriteGlyphAsTGA(FT_Library &library,
                const std::string &fileName,
                wchar_t ch,
                FT_Face &face,
                int size,
                const Pixel32 &fontCol,
                const Pixel32 outlineCol,
                float outlineWidth)
{
	// Set the size to use.
	if (FT_Set_Char_Size(face, size << 6, size << 6, 90, 90) == 0)
	{
		// Load the glyph we are looking for.
		FT_UInt gindex = FT_Get_Char_Index(face, ch);
		if (FT_Load_Glyph(face, gindex, FT_LOAD_NO_BITMAP) == 0)
		{
			// Need an outline for this to work.
			if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
			{
				// Render the basic glyph to a span list.
				Spans spans;
				RenderSpans(library, &face->glyph->outline, &spans);

				// Next we need the spans for the outline.
				Spans outlineSpans;

				// Set up a stroker.
				FT_Stroker stroker;
				FT_Stroker_New(library, &stroker);
				FT_Stroker_Set(stroker,
					       (int)(outlineWidth * 64),
					       FT_STROKER_LINECAP_ROUND,
					       FT_STROKER_LINEJOIN_ROUND,
					       0);

				FT_Glyph glyph;
				if (FT_Get_Glyph(face->glyph, &glyph) == 0)
				{
					FT_Glyph_StrokeBorder(&glyph, stroker, 0, 1);
					// Again, this needs to be an outline to work.
					if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
					{
						// Render the outline spans to the span list
						FT_Outline *o =
						  &reinterpret_cast<FT_OutlineGlyph>(glyph)->outline;
						RenderSpans(library, o, &outlineSpans);
					}

					// Clean up afterwards.
					FT_Stroker_Done(stroker);
					FT_Done_Glyph(glyph);

					// Now we need to put it all together.
					if (!spans.empty())
					{
						// Figure out what the bounding rect is for both the span lists.
						Rect rect(spans.front().x,
							  spans.front().y,
							  spans.front().x,
							  spans.front().y);
						for (Spans::iterator s = spans.begin();
						     s != spans.end(); ++s)
						{
							rect.Include(Vec2(s->x, s->y));
							rect.Include(Vec2(s->x + s->width - 1, s->y));
						}
						for (Spans::iterator s = outlineSpans.begin();
						     s != outlineSpans.end(); ++s)
						{
							rect.Include(Vec2(s->x, s->y));
							rect.Include(Vec2(s->x + s->width - 1, s->y));
						}

#if 0
						// This is unused in this test but you would need this to draw
						// more than one glyph.
						float bearingX = face->glyph->metrics.horiBearingX >> 6;
						float bearingY = face->glyph->metrics.horiBearingY >> 6;
						float advance = face->glyph->advance.x >> 6;
#endif

						// Get some metrics of our image.
						int imgWidth = rect.Width(),
						  imgHeight = rect.Height(),
						  imgSize = imgWidth * imgHeight;

						// Allocate data for our image and clear it out to transparent.
						Pixel32 *pxl = new Pixel32[imgSize];
						memset(pxl, 0, sizeof(Pixel32) * imgSize);

						// Loop over the outline spans and just draw them into the
						// image.
						for (Spans::iterator s = outlineSpans.begin();
						     s != outlineSpans.end(); ++s)
						  for (int w = 0; w < s->width; ++w)
						    pxl[(int)((imgHeight - 1 - (s->y - rect.ymin)) * imgWidth
							      + s->x - rect.xmin + w)] =
						      Pixel32(outlineCol.r, outlineCol.g, outlineCol.b,
							      s->coverage);

						// Then loop over the regular glyph spans and blend them into
						// the image.
						for (Spans::iterator s = spans.begin();
						     s != spans.end(); ++s)
						  for (int w = 0; w < s->width; ++w)
						  {
							  Pixel32 &dst =
							    pxl[(int)((imgHeight - 1 - (s->y - rect.ymin)) * imgWidth
								      + s->x - rect.xmin + w)];
							  Pixel32 src = Pixel32(fontCol.r, fontCol.g, fontCol.b,
										s->coverage);
							  dst.r = (int)(dst.r + ((src.r - dst.r) * src.a) / 255.0f);
							  dst.g = (int)(dst.g + ((src.g - dst.g) * src.a) / 255.0f);
							  dst.b = (int)(dst.b + ((src.b - dst.b) * src.a) / 255.0f);
							  dst.a = MIN(255, dst.a + src.a);
						  }

						// Dump the image to disk.
						WriteTGA(fileName, pxl, imgWidth, imgHeight);

						delete [] pxl;
					}
				}
Exemple #3
0
/*
-----------------------------------------------------------------------------
 Function: 

 Parameters:

 Returns:

 Notes: 
-----------------------------------------------------------------------------
*/
PRIVATE void R_ScreenShot_f( void ) 
{
	W8		*buffer;
	char	picname[ 80 ]; 
	char	checkname[ MAX_OSPATH ];
	int		i;
	FILE	*f;

	// create the scrnshots directory if it doesn't exist
	my_snprintf( checkname, sizeof( checkname ), "%s/scrnshot", FS_Gamedir() );
	FS_CreateDirectory( checkname );

// 
// find a file name to save it to 
// 
	my_strlcpy( picname, "scrn00.tga", sizeof( picname ) );

	for( i = 0 ; i <= 99 ; ++i ) 
	{ 
		picname[ 4 ] = i / 10 + '0'; 
		picname[ 5 ] = i % 10 + '0'; 
		my_snprintf( checkname, sizeof( checkname ), "%s/scrnshot/%s", FS_Gamedir(), picname );
		f = fopen( checkname, "rb" );
		if( ! f )
		{
			break;	// file doesn't exist
		}

		fclose( f );
	} 

	if( i == 100 ) 
	{
		Com_Printf( "R_ScreenShot_f: Couldn't create a file\n" ); 
		return;
 	}


	buffer = MM_MALLOC( viddef.width * viddef.height * 3 );
	

	pfglReadPixels( 0, 0, viddef.width, viddef.height, GL_RGB, GL_UNSIGNED_BYTE, buffer ); 

	
	WriteTGA( checkname, 24, viddef.width, viddef.height, buffer, 1, 1 );
	

	MM_FREE( buffer );
	Com_Printf( "Wrote %s\n", picname );
}
Exemple #4
0
/*
-----------------------------------------------------------------------------
 Function: SavePic() -Save graphic lump in targa image format.
 
 Parameters: chunk -[in] Chunk number to save.
             version -[in] extension version. 
                        1 -WL6
                        2 -SOD 
 
 Returns: Nothing.
 
 Notes: 
-----------------------------------------------------------------------------
*/
PRIVATE void SavePic( W32 chunknum, W16 version, W8 *buffer, W8 *buffer2 )
{
    W16 i;
    W16 temp;    
    char filename[32];
    char *fname;
    W8 *ptr;
    W8 *pic;
	W32	picnum;
	W16 width, height;
    W16 linewidth, plane, sx, sy;
    W8 r,g,b;
	W16 rgb;
	W8 *tpalette = gamepal;	
    static W16 offset = 0;


	if( ( (chunknum == WL1_N_BLANKPIC ||
		chunknum == WL1_NOKEYPIC ) && (version & WL1_PAK) ) )
	{
		return;
	}

	if( ( (chunknum == N_BLANKPIC ||
		chunknum == NOKEYPIC ) && (version & WL6_PAK) ) )
	{
		return;
	}

	if( ( (chunknum == SDM_N_BLANKPIC ||
		chunknum == SDM_NOKEYPIC ) && (version & SDM_PAK) ) )
	{
		return;
	}

	if( ( (chunknum == SOD_N_BLANKPIC ||
		chunknum == SOD_NOKEYPIC ) && (version & SOD_PAK) ) )
	{
		return;
	}
	
	// Spear used multiple palettes, so
	// pull out the one we need.
	if( version & SDM_PAK )
	{
		switch( chunknum )
        {
			case SDM_TITLE1PIC:
            case SDM_TITLE2PIC:
                CA_CacheGrChunk( SDM_TITLEPALETTE, version );
                tpalette =  grsegs[ SDM_TITLEPALETTE ];
                break;

			 default:
                tpalette = gamepal;
                break;  
		}
	}

	if( version & SOD_PAK )
	{    
        switch( chunknum )
        {
            case SOD_IDGUYS1PIC:
            case SOD_IDGUYS2PIC:
                CA_CacheGrChunk( SOD_IDGUYSPALETTE, version );
                tpalette = grsegs[ SOD_IDGUYSPALETTE ];
                break;

            case SOD_TITLE1PIC:
            case SOD_TITLE2PIC:
                CA_CacheGrChunk( SOD_TITLEPALETTE, version );
                tpalette =  grsegs[ SOD_TITLEPALETTE ];
                break;

            case SOD_ENDSCREEN11PIC:
                CA_CacheGrChunk( SOD_END1PALETTE, version );
                tpalette =  grsegs[ SOD_END1PALETTE ];
                break;

            case SOD_ENDSCREEN12PIC:
                CA_CacheGrChunk( SOD_END2PALETTE, version );
                tpalette =  grsegs[ SOD_END2PALETTE ];
                break;

            case SOD_ENDSCREEN3PIC:
                CA_CacheGrChunk( SOD_END3PALETTE, version );
                tpalette =  grsegs[ SOD_END3PALETTE ];
                break;

            case SOD_ENDSCREEN4PIC:
                CA_CacheGrChunk( SOD_END4PALETTE, version );
                tpalette =  grsegs[ SOD_END4PALETTE ];
                break;

            case SOD_ENDSCREEN5PIC:
                CA_CacheGrChunk( SOD_END5PALETTE, version );
                tpalette =  grsegs[ SOD_END5PALETTE ];
                break;

            case SOD_ENDSCREEN6PIC:
                CA_CacheGrChunk( SOD_END6PALETTE, version );
                tpalette =  grsegs[ SOD_END6PALETTE ];
                break;

            case SOD_ENDSCREEN7PIC:
                CA_CacheGrChunk( SOD_END7PALETTE, version );
                tpalette =  grsegs[ SOD_END7PALETTE ];
                break;

            case SOD_ENDSCREEN8PIC:
                CA_CacheGrChunk( SOD_END8PALETTE, version );
                tpalette =  grsegs[ SOD_END8PALETTE ];
                break;

            case SOD_ENDSCREEN9PIC:
                CA_CacheGrChunk( SOD_END9PALETTE, version );
                tpalette =  grsegs[ SOD_END9PALETTE ];
                break;

            default:
                tpalette = gamepal;
                break;    

        }    // End switch chunknum

    } // End if version & SOD_PAK
  
STATUSBARHACK:

	picnum = chunknum - STARTPICS;

	pic = grsegs[ chunknum ];
	width = pictable[ picnum ].width;
	height= pictable[ picnum ].height;



    linewidth = width / 4;	
    for( i = 0; i < ( width * height ); ++i, pic++ )
    {
        plane = i / ( (width * height) / 4 );
        sx = ( ( i % ( linewidth ) ) * 4 ) + plane;
        sy = ( ( i / linewidth ) % height );        
	    
        ptr = buffer + ( (sx*2) + (sy * width)*2); 
		
      
		temp = (*pic) * 3;        
		r = tpalette[ temp ] >> 1;
        g = tpalette[ temp+1 ];
        b = tpalette[ temp+2 ] >> 1;

        rgb = (b << 11) | (g << 5) | r;
        ptr[ 0 ] = rgb & 0xff;
        ptr[ 1 ] = rgb >> 8;	  
    }


//
//	Hacks to reassemble images
//
	if( version & WL1_PAK )
	{
		if( chunknum == WL1_STATUSBARPIC )
		{
			memcpy( buffer2, buffer, width * height * 2 );	// Save Status bar pic
			CA_CacheGrChunk( WL1_NOKEYPIC, version );	// cache NOKEYPIC 
			chunknum = WL1_NOKEYPIC;

			goto STATUSBARHACK;
		}
		else if( chunknum == WL1_H_BOTTOMINFOPIC )
		{
			MergeImages( buffer, 2, 304, 91, 16, 24, 4,
						 buffer2, 2, 91, 91, 16, 0, 0 );
			MergeImages( buffer, 2, 304, 91, 16, 192, 4,
						 buffer2, 2, 91, 91, 16, 0, 16 );


			hq2x_32( buffer2, buffer, 91, 16, (91*2)*4 );
			RGB32toRGB24( buffer, buffer, 182*32*4 );

			cs_snprintf( filename, sizeof( filename ), "%s/%s.tga", LGFXDIR, "PLAQUE_PAGE" );

			WriteTGA( filename, 24, 182, 32, buffer, 0, 0 );
			
			hq2x_32( buffer2 + (16 * 91 * 2), buffer, 91, 16, (91*2)*4 );
			RGB32toRGB24( buffer, buffer, 182*32*4 );

			cs_snprintf( filename, sizeof( filename ), "%s/%s.tga", LGFXDIR, "PLAQUE_BLANK" );

			WriteTGA( filename, 24, 182, 32, buffer, 0, 1 );

			return;
		}
		else if( chunknum == WL1_NOKEYPIC )
		{
			chunknum = WL1_STATUSBARPIC;
			MergePics( buffer, buffer2, width, height, 2, 320, 240, 4 );
			MergePics( buffer, buffer2, width, height, 2, 320, 240, 4+height );

			memcpy( buffer, buffer2, 320 * 40 * 2 );
			width = 320;
			height = 40;
		}
		else if( chunknum == WL1_L_COLONPIC )
		{
			memset( buffer2, 0, 256*64*2 );

			MergePics( buffer, buffer2, width, height, 2, 256, 160, 16 );

			return;
		}
		else if( chunknum == WL1_L_EXPOINTPIC )
		{
			MergePics( buffer, buffer2, width, height, 2, 256, 16, 0 );			

			return;
		}
		else if( chunknum == WL1_L_APOSTROPHEPIC )
		{
			W16 i;			
			
			MergePics( buffer, buffer2, width, height, 2, 256, 112, 0 );
				
			memcpy( buffer, buffer2, 256 * 64 * 2 );

			
			for( i = 0 ; i < 256 * 64 * 2 ; i += 2 )
			{
				if( buffer[ i ] == 0 && buffer[ i + 1 ] == 0 )
				{
					 buffer[ i + 1 ] = 66;	
				}				
			}

			offset = 0;
			width = 256;
			height = 64;
		}
		else if( chunknum == WL1_L_PERCENTPIC )
		{
			offset = 16; // this is for L_APIC...

			MergePics( buffer, buffer2, width, height, 2, 256, 80, 0 );			

			return;
		}
		else if( chunknum >= WL1_L_NUM0PIC && chunknum <= WL1_L_NUM9PIC  )
		{
			MergePics( buffer, buffer2, width, height, 2, 256, offset, 16 );

			offset += width;
			
			return;
		}	
		else if( chunknum >= WL1_N_0PIC && chunknum < WL1_N_9PIC )
		{
			MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
			
			offset += width + 1;

			return;			
		}
		else if( chunknum == WL1_N_9PIC )
		{
			W32 i;
			
			MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
			
			memcpy( buffer, buffer2, 90 * height * 2 );

			for( i = 0 ; i < 90 * 16 * 2 ; i += 2 )
			{
				if( ! (i % 9) && i != 0 )
				{
					buffer[ i - 2 ] = 0;
					buffer[ i - 1 ] = 160;
				}
			}

			width = 90;
			offset = 0;
		}
		else if( chunknum >= WL1_L_APIC && chunknum <= WL1_L_ZPIC )
		{
			static W32 yoffset = 32;

			MergePics( buffer, buffer2, width, height, 2, 256, offset, yoffset );
			
			offset += width;			
			
			if( offset >= 256 )
			{
				offset = 0;
				yoffset += 16;
			}

			return;
		}	
		else if( chunknum == WL1_FACE5CPIC )
		{
			// hmmm... Why is this one messed up?

			MergeImages( buffer, 2, 24, 18, height-2, 8, 2,
						 buffer2, 2, 24, 18, height-2, 0, 0 );
			MergeImages( buffer, 2, 24, 8, height-3, 0, 3,
						 buffer2, 2, 24, 8, height-2, 16, 0 );

			MergeImages( buffer, 2, 24, 18, 2, 9, 0,
						 buffer2, 2, 24, 18, 2, 0, height-2 );
			MergeImages( buffer, 2, 24, 7, 3, 1, 0,
						 buffer2, 2, 24, 7, 3, 16, height-3 );

			memcpy( buffer, buffer2, 24 * 32 * 2 );
	

			buffer[ (30 * 24 * 2) + (3 * 2) ] = 73;
			buffer[ (30 * 24 * 2) + (3 * 2) + 1 ] = 74;

			buffer[ (31 * 24 * 2) + (3 * 2) ] = 73;
			buffer[ (31 * 24 * 2) + (3 * 2) + 1 ] = 74;



			buffer[ (29 * 24 * 2) + (23 * 2) ] = 73;
			buffer[ (29 * 24 * 2) + (23 * 2) + 1 ] = 74;

			buffer[ (30 * 24 * 2) + (23 * 2) ] = 73;
			buffer[ (30 * 24 * 2) + (23 * 2) + 1 ] = 74;

			buffer[ (31 * 24 * 2) + (23 * 2) ] = 73;
			buffer[ (31 * 24 * 2) + (23 * 2) + 1 ] = 74;



			buffer[ (29 * 24 * 2) + (19 * 2) ] = 255;
			buffer[ (29 * 24 * 2) + (19 * 2) + 1 ] = 100;

			buffer[ (30 * 24 * 2) + (19 * 2) ] = 63;
			buffer[ (30 * 24 * 2) + (19 * 2) + 1 ] = 117;

			buffer[ (31 * 24 * 2) + (19 * 2) ] = 52;
			buffer[ (31 * 24 * 2) + (19 * 2) + 1 ] = 59;



			buffer[ (30 * 24 * 2) + (7 * 2) ] = 19;
			buffer[ (30 * 24 * 2) + (7 * 2) + 1 ] = 59;

			buffer[ (31 * 24 * 2) + (7 * 2) ] = 19;
			buffer[ (31 * 24 * 2) + (7 * 2) + 1 ] = 59;



			buffer[ (30 * 24 * 2) + (11 * 2) ] = 91;
			buffer[ (30 * 24 * 2) + (11 * 2) + 1 ] = 84;

			buffer[ (31 * 24 * 2) + (11 * 2) ] = 190;
			buffer[ (31 * 24 * 2) + (11 * 2) + 1 ] = 92;


			buffer[ (30 * 24 * 2) + (15 * 2) ] = 249;
			buffer[ (30 * 24 * 2) + (15 * 2) + 1 ] = 75;

			buffer[ (31 * 24 * 2) + (15 * 2) ] = 190;
			buffer[ (31 * 24 * 2) + (15 * 2) + 1 ] = 92;
		}
	}
	else if( version & WL6_PAK ) 
	{
		if( chunknum == STATUSBARPIC )
		{
			memcpy( buffer2, buffer, width * height * 2 );	// Save Status bar pic
			CA_CacheGrChunk( NOKEYPIC, version );	// cache NOKEYPIC 
			chunknum = NOKEYPIC;

			goto STATUSBARHACK;
		}
		else if( chunknum == H_BOTTOMINFOPIC )
		{
			MergeImages( buffer, 2, 304, 91, 16, 24, 4,
						 buffer2, 2, 91, 91, 16, 0, 0 );
			MergeImages( buffer, 2, 304, 91, 16, 192, 4,
						 buffer2, 2, 91, 91, 16, 0, 16 );


			hq2x_32( buffer2, buffer, 91, 16, (91*2)*4 );
			RGB32toRGB24( buffer, buffer, 182*32*4 );

			cs_snprintf( filename, sizeof( filename ), "%s/%s.tga", LGFXDIR, "PLAQUE_PAGE" );

			WriteTGA( filename, 24, 182, 32, buffer, 0, 0 );
			
			hq2x_32( buffer2 + (16 * 91 * 2), buffer, 91, 16, (91*2)*4 );
			RGB32toRGB24( buffer, buffer, 182*32*4 );

			cs_snprintf( filename, sizeof( filename ), "%s/%s.tga", LGFXDIR, "PLAQUE_BLANK" );

			WriteTGA( filename, 24, 182, 32, buffer, 0, 1 );

			return;
		}
		else if( chunknum == NOKEYPIC )
		{
			chunknum = STATUSBARPIC;
			MergePics( buffer, buffer2, width, height, 2, 320, 240, 4 );
			MergePics( buffer, buffer2, width, height, 2, 320, 240, 4+height );

			memcpy( buffer, buffer2, 320 * 40 * 2 );
			width = 320;
			height = 40;
		}
		else if( chunknum == L_COLONPIC )
		{
			memset( buffer2, 0, 256*64*2 );

			MergePics( buffer, buffer2, width, height, 2, 256, 160, 16 );

			return;
		}
		else if( chunknum == L_EXPOINTPIC )
		{
			MergePics( buffer, buffer2, width, height, 2, 256, 16, 0 );			

			return;
		}
		else if( chunknum == L_APOSTROPHEPIC )
		{
			W16 i;			
			
			MergePics( buffer, buffer2, width, height, 2, 256, 112, 0 );
				
			memcpy( buffer, buffer2, 256 * 64 * 2 );

			
			for( i = 0 ; i < 256 * 64 * 2 ; i += 2 )
			{
				if( buffer[ i ] == 0 && buffer[ i + 1 ] == 0 )
				{
					 buffer[ i + 1 ] = 66;	
				}				
			}

			offset = 0;
			width = 256;
			height = 64;
		}
		else if( chunknum == L_PERCENTPIC )
		{
			offset = 16; // this is for L_APIC...

			MergePics( buffer, buffer2, width, height, 2, 256, 80, 0 );			

			return;
		}
		else if( chunknum >= L_NUM0PIC && chunknum <= L_NUM9PIC  )
		{
			MergePics( buffer, buffer2, width, height, 2, 256, offset, 16 );

			offset += width;
			
			return;
		}		
		else if( chunknum >= N_0PIC && chunknum < N_9PIC )
		{
			MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
			
			offset += width + 1;

			return;			
		}
		else if( chunknum == N_9PIC )
		{
			W32 i;
			
			MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
			
			memcpy( buffer, buffer2, 90 * height * 2 );

			for( i = 0 ; i < 90 * 16 * 2 ; i += 2 )
			{
				if( ! (i % 9) && i != 0 )
				{
					buffer[ i - 2 ] = 0;
					buffer[ i - 1 ] = 160;
				}
			}

			width = 90;
			offset = 0;
		}
		else if( chunknum >= L_APIC && chunknum <= L_ZPIC )
		{
			static W32 yoffset = 32;

			MergePics( buffer, buffer2, width, height, 2, 256, offset, yoffset );
			
			offset += width;			
			
			if( offset >= 256 )
			{
				offset = 0;
				yoffset += 16;
			}


			return;
		}			
	}
	else if( version & SDM_PAK )
	{
		if( chunknum == SDM_STATUSBARPIC )
		{
			memcpy( buffer2, buffer, width * height * 2 );	// Save Status bar pic
			CA_CacheGrChunk( SDM_NOKEYPIC, version );	// cache SOD_NOKEYPIC 
			chunknum = SDM_NOKEYPIC;

			goto STATUSBARHACK;
		}
		else if( chunknum == SDM_NOKEYPIC )
		{			
			chunknum = SDM_STATUSBARPIC;
			MergePics( buffer, buffer2, width, height, 2, 320, 240, 4 );
			MergePics( buffer, buffer2, width, height, 2, 320, 240, 4+height );

			memcpy( buffer, buffer2, 320 * 40 * 2 );
			width = 320;
			height = 40;
		}
		else if( chunknum == SDM_L_COLONPIC )
		{
			memset( buffer2, 0, 256*64*2 );

			MergePics( buffer, buffer2, width, height, 2, 256, 160, 16 );

			return;
		}
		else if( chunknum == SDM_L_EXPOINTPIC )
		{
			MergePics( buffer, buffer2, width, height, 2, 256, 16, 0 );			

			return;
		}
		else if( chunknum == SDM_L_APOSTROPHEPIC )
		{
			W16 i;			
			
			MergePics( buffer, buffer2, width, height, 2, 256, 112, 0 );
				
			memcpy( buffer, buffer2, 256 * 64 * 2 );

			
			for( i = 0 ; i < 256 * 64 * 2 ; i += 2 )
			{
				if( buffer[ i ] == 0 && buffer[ i + 1 ] == 0 )
				{
					 buffer[ i + 1 ] = 66;	
				}				
			}

			offset = 0;
			width = 256;
			height = 64;
		}
		else if( chunknum == SDM_L_PERCENTPIC )
		{
			offset = 16; // this is for L_APIC...

			MergePics( buffer, buffer2, width, height, 2, 256, 80, 0 );			

			return;
		}
		else if( chunknum >= SDM_L_NUM0PIC && chunknum <= SDM_L_NUM9PIC  )
		{
			MergePics( buffer, buffer2, width, height, 2, 256, offset, 16 );

			offset += width;
			
			return;
		}		
		else if( chunknum >= SDM_N_0PIC && chunknum < SDM_N_9PIC )
		{
			MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
			
			offset += width + 1;

			return;	
		}
		else if( chunknum == SDM_N_9PIC )
		{
			W32 i;
			
			MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
			
			memcpy( buffer, buffer2, 90 * height * 2 );

			for( i = 0 ; i < 90 * 16 * 2 ; i += 2 )
			{
				if( ! (i % 9) && i != 0 )
				{
					buffer[ i - 2 ] = 0;
					buffer[ i - 1 ] = 160;
				}
			}

			width = 90;
			offset = 0;
		}
		else if( chunknum >= SDM_L_APIC && chunknum <= SDM_L_ZPIC )
		{
			static W32 yoffset = 32;

			MergePics( buffer, buffer2, width, height, 2, 256, offset, yoffset );
			
			offset += width;			
			
			if( offset >= 256 )
			{
				offset = 0;
				yoffset += 16;
			}

			return;
		}		
		else if( chunknum == SDM_TITLE1PIC )
		{
			memcpy( buffer2+offset, buffer, (width*height*2) );
			offset += width*height*2;
			
			return;
		}
		else if( chunknum == SDM_TITLE2PIC )
		{
			memcpy( buffer2+offset, buffer, (width*height*2) );
			memcpy( buffer, buffer2, 320*200*2 );
			height = 200;
			offset = 0;
		}		
    }
	else if( version & SOD_PAK )
	{
		if( chunknum == SOD_STATUSBARPIC )
		{
			memcpy( buffer2, buffer, width * height * 2 );	// Save Status bar pic
			CA_CacheGrChunk( SOD_NOKEYPIC, version );	// cache SOD_NOKEYPIC 
			chunknum = SOD_NOKEYPIC;

			goto STATUSBARHACK;
		}
		else if( chunknum == SOD_NOKEYPIC )
		{			
			chunknum = SOD_STATUSBARPIC;
			MergePics( buffer, buffer2, width, height, 2, 320, 240, 4 );
			MergePics( buffer, buffer2, width, height, 2, 320, 240, 4+height );

			memcpy( buffer, buffer2, 320 * 40 * 2 );
			width = 320;
			height = 40;
		}
		else if( chunknum == SOD_L_COLONPIC )
		{
			memset( buffer2, 0, 256*64*2 );

			MergePics( buffer, buffer2, width, height, 2, 256, 160, 16 );

			return;
		}
		else if( chunknum == SOD_L_EXPOINTPIC )
		{
			MergePics( buffer, buffer2, width, height, 2, 256, 16, 0 );			

			return;
		}
		else if( chunknum == SOD_L_APOSTROPHEPIC )
		{
			W16 i;			
			
			MergePics( buffer, buffer2, width, height, 2, 256, 112, 0 );
				
			memcpy( buffer, buffer2, 256 * 64 * 2 );

			
			for( i = 0 ; i < 256 * 64 * 2 ; i += 2 )
			{
				if( buffer[ i ] == 0 && buffer[ i + 1 ] == 0 )
				{
					 buffer[ i + 1 ] = 66;	
				}				
			}

			offset = 0;
			width = 256;
			height = 64;
		}
		else if( chunknum == SOD_L_PERCENTPIC )
		{
			offset = 16; // this is for L_APIC...

			MergePics( buffer, buffer2, width, height, 2, 256, 80, 0 );			

			return;
		}
		else if( chunknum >= SOD_L_NUM0PIC && chunknum <= SOD_L_NUM9PIC  )
		{
			MergePics( buffer, buffer2, width, height, 2, 256, offset, 16 );

			offset += width;
			
			return;
		}		
		else if( chunknum >= SOD_N_0PIC && chunknum < SOD_N_9PIC )
		{
			MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
			
			offset += width + 1;

			return;	
		}
		else if( chunknum == SOD_N_9PIC )
		{
			W32 i;
			
			MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
			
			memcpy( buffer, buffer2, 90 * height * 2 );

			for( i = 0 ; i < 90 * 16 * 2 ; i += 2 )
			{
				if( ! (i % 9) && i != 0 )
				{
					buffer[ i - 2 ] = 0;
					buffer[ i - 1 ] = 160;
				}
			}

			width = 90;
			offset = 0;
		}
		else if( chunknum >= SOD_L_APIC && chunknum <= SOD_L_ZPIC )
		{
			static W32 yoffset = 32;

			MergePics( buffer, buffer2, width, height, 2, 256, offset, yoffset );
			
			offset += width;			
			
			if( offset >= 256 )
			{
				offset = 0;
				yoffset += 16;
			}

			return;
		}
		else if( chunknum == SOD_IDGUYS1PIC )
		{
			memcpy( buffer2+offset, buffer, (width*height*2) );
			offset += width*height*2;
			
			return;
		}
		else if( chunknum == SOD_IDGUYS2PIC )
		{
			memcpy( buffer2+offset, buffer, (width*height*2) );
			memcpy( buffer, buffer2, 320*200*2 );
			height = 200;
			offset = 0;
		}
		else if( chunknum == SOD_TITLE1PIC )
		{
			memcpy( buffer2+offset, buffer, (width*height*2) );
			offset += width*height*2;
			
			return;
		}
		else if( chunknum == SOD_TITLE2PIC )
		{
			memcpy( buffer2+offset, buffer, (width*height*2) );
			memcpy( buffer, buffer2, 320*200*2 );
			height = 200;
			offset = 0;
		}		
    }
//
//	End of images hacks 
//
	

	if( version & WL1_PAK )
	{
		fname = GetLumpFileName_WL1( chunknum );
	}
	else if( version & WL6_PAK )
	{
        fname = GetLumpFileName_WL6( chunknum );
    }
	else if( version & SDM_PAK )
	{
        fname = GetLumpFileName_SDM( chunknum );        
    }
	else if( version & SOD_PAK )
	{
        fname = GetLumpFileName_SOD( chunknum );        
    }	
    else
    {
        printf( "Unknown file extension!\n" );

        return; 
    }
    
    if( fname == NULL )
    {
        printf( "File name not found for item: (%d)\n", chunknum );
        
		return;
    }
    
	cs_snprintf( filename, sizeof( filename ), "%s/%s.tga", LGFXDIR, fname );
	
    
    hq2x_32( buffer, buffer2, width, height, (width*2)*4 );


	// Get rid of alpha channel
	RGB32toRGB24( buffer2, buffer2, (width*2)*(height*2)*4 );
	
	
	WriteTGA( filename, 24, (width*2), (height*2), buffer2, 0, 1 );
	
	return;
}
Exemple #5
0
/*
-----------------------------------------------------------------------------
 Function: Fontline() -Extract and save font.
 
 Parameters: fontnumber -[in] font to save.
             version -[in] extension version. 
                        1 -WL6
                        2 -SOD 
 
 Returns: Nothing.
 
 Notes: Font must be cached in grsegs[] before calling.
-----------------------------------------------------------------------------
*/
PRIVATE void Fontline( W32 fontnumber, W16 version )
{
	fontstruct	*font;
	W16 i;
	W16 x, y;
	W16 px, py;
	W8 *buffer;	
	W8 *source;
	W8 *ptr;	
	char filename[ 256 ];
	

	font = (fontstruct *)grsegs[ fontnumber ];	
	

	buffer = MM_MALLOC( FONTWIDTH * FONTHEIGHT * 4 );
	if( buffer == NULL )
		return;

	ptr = buffer;
	for( x = 0; x < FONTWIDTH; ++x )
	{
		for( y = 0; y < FONTHEIGHT; ++y, ptr += 4 )
		{
			ptr[ 0 ] = ptr[ 1 ] = ptr[ 2 ] = 0xFF;
			ptr[ 3 ] = 0x00;
		}
	}

	px = py = 0;
	for( i = 0; i < 256; ++i )
	{		
		if( ! font->width[ i ] )
			continue;
		 
		if( px + font->width[ i ] > FONTWIDTH-1 )
		{
			py += font->height;
			px = 0;
		}
			
		source = ((PW8) font) + font->location[ i ];

		ptr = buffer + (py * FONTWIDTH + px) * 4;
		for( y = 0; y < font->height; ++y, ptr += FONTWIDTH * 4 )
		{
			for( x = 0; x < font->width[ i ]; ++x )
			{
				if( *source++ )	
				{
					ptr[ x * 4 + 3 ] = 0xFF;
				}
			}
		}
		
		px += 16;

	} // end for i = 0; i < 256; ++i


	cs_snprintf( filename, sizeof( filename ), "%s/font%d.tga", LGFXDIR, fontnumber );
	
	WriteTGA( filename, 32, FONTWIDTH, FONTHEIGHT, buffer, 0, 1 );	
	
	MM_FREE( buffer );

}
Exemple #6
0
int main( int argc, char * argv[] )
{	
	printf( "networked physics demo\n" );

    bool shadows = true;
    bool playback = false;
    bool video = false;

    for ( int i = 1; i < argc; ++i )
    {
        if ( strcmp( argv[i], "playback" ) == 0 )
        {
            printf( "playback\n" );
            playback = true;
        }
        else if ( strcmp( argv[i], "video" ) == 0 )
        {
            printf( "video\n" );
            video = true;
        }
    }

	net::InitializeSockets();
	while ( !net::IsInitialized() )
	{
		printf( "error: failed to initialize sockets\n" );
		net::ShutdownSockets();
		return 1;
	}

#ifndef PROFILE
	
	int displayWidth, displayHeight;
	GetDisplayResolution( displayWidth, displayHeight );

    #ifdef LETTERBOX
    displayWidth = 1280;
    displayHeight = 800;
    #endif

	printf( "display resolution is %d x %d\n", displayWidth, displayHeight );

	HideMouseCursor();
	
	if ( !OpenDisplay( "Networked Physics", displayWidth, displayHeight ) )
	{
		printf( "error: failed to open display" );
		return 1;
	}
	
#endif

	int currentDemo = 0;
	Demo * demo = CreateDemo( 0 );
	assert( demo );
	demo->InitializeWorld();
    renderInterface = new render::Interface( displayWidth, displayHeight );	
    #ifndef PROFILE
	demo->SetRenderInterface( renderInterface );
    #endif

	uint32_t frame = 0;

    // create 2 pixel buffer objects, you need to delete them when program exits.
    // glBufferDataARB with NULL pointer reserves only memory space.
    const int NumPBOs = 2;
    GLuint pboIds[NumPBOs];
    int index = 0;
    const int dataSize = displayWidth * displayHeight * 3;
    if ( video )
    {
        glGenBuffersARB( NumPBOs, pboIds );
        for ( int i = 0; i < NumPBOs; ++i )
        {
            glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[i] );
            glBufferDataARB( GL_PIXEL_UNPACK_BUFFER_ARB, dataSize, 0, GL_STREAM_DRAW_ARB );
        }
        glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, 0 );
    }

    // record input to a file
    // read it back in playback mode for recording video
    FILE * inputFile = fopen( "output/recordedInputs", playback ? "rb" : "wb" );
    if ( !inputFile )
    {
        printf( "failed to open input file\n" );
        return 1;
    }

    bool quit = false;
	while ( !quit )
	{
		#ifdef PROFILE
		printf( "profiling frame %d\n", frame );
		#endif
		
		platform::Input input;
        
        if ( !playback )
        {
            input = platform::Input::Sample();
            fwrite( &input, sizeof( platform::Input ), 1, inputFile );
            fflush( inputFile );
        }
        else
        {
            const int size = sizeof( platform::Input );
            if ( !fread( &input, size, 1, inputFile ) )
                quit = true;
        }

		#ifdef PROFILE
		if ( frame > 500 )
			input.left = frame % 2;
		else if ( frame > 100 && ( frame % 5 ) == 0 )
			input.left  = true;
		input.z = true;
		#endif
		
		if ( input.alt )
		{
			int demoIndex = -1;
			
			if ( input.one )
				demoIndex = 0;
				
			if ( input.two )
				demoIndex = 1;
				
			if ( input.three )
				demoIndex = 2;
				
			if ( input.four )
				demoIndex = 3;
				
			if ( input.five )
				demoIndex = 4;
				
			if ( input.six )
				demoIndex = 5;
				
			if ( input.seven )
				demoIndex = 6;
				
			if ( input.eight )
				demoIndex = 7;
				
			if ( input.nine )
				demoIndex = 8;
				
			if ( input.zero )
				demoIndex = 9;

			static bool enterDownLastFrame = false;
			if ( input.enter && !enterDownLastFrame )
				shadows = !shadows;
			enterDownLastFrame = input.enter;
				
			if ( demoIndex != -1 )
			{
				Demo * newDemo = CreateDemo( demoIndex );
				if ( newDemo )
				{
					#ifndef PROFILE
                    renderInterface->ClearScreen();
                    #ifdef LETTERBOX
                    renderInterface->LetterBox( 80 );
                    #endif
					UpdateDisplay( 1 );
					#endif
                    
					delete demo;
					demo = newDemo;
					assert( demo );
					demo->InitializeWorld();
					#ifndef PROFILE
					demo->SetRenderInterface( renderInterface );
					#endif
					currentDemo = demoIndex;
				}
			}
		}
		
		static bool escapeDownLastFrame = false;		
		if ( input.escape && !escapeDownLastFrame )
		{
            #ifndef PROFILE
            renderInterface->ClearScreen();
            #ifdef LETTERBOX
            renderInterface->LetterBox( 80 );
            #endif
            UpdateDisplay( 1 );
            #endif

			delete demo;
			demo = CreateDemo( currentDemo );
			assert( demo );
			demo->InitializeWorld();
			#ifndef PROFILE
			demo->SetRenderInterface( renderInterface );
			#endif
		}
		escapeDownLastFrame = input.escape;
		
		demo->ProcessInput( !input.alt ? input : platform::Input() );

		demo->Update( DeltaTime );

        if ( video )
        {
            // "index" is used to read pixels from framebuffer to a PBO
            // "nextIndex" is used to update pixels in the other PBO
            index = ( index + 1 ) % NumPBOs;
            int prevIndex = ( index + NumPBOs - 1 ) % NumPBOs;

            // set the target framebuffer to read
            glReadBuffer( GL_FRONT );

            // read pixels from framebuffer to PBO
            // glReadPixels() should return immediately.
            glBindBufferARB( GL_PIXEL_PACK_BUFFER_ARB, pboIds[index] );
            glReadPixels( 0, 0, displayWidth, displayHeight, GL_BGR, GL_UNSIGNED_BYTE, 0 );
            if ( frame > (unsigned) NumPBOs )
            {
                // map the PBO to process its data by CPU
                glBindBufferARB( GL_PIXEL_PACK_BUFFER_ARB, pboIds[prevIndex] );
                GLubyte * ptr = (GLubyte*) glMapBufferARB( GL_PIXEL_PACK_BUFFER_ARB,
                                                           GL_READ_ONLY_ARB );
                if ( ptr )
                {
                    char filename[256];
                    sprintf( filename, "output/frame-%05d.tga", frame - NumPBOs );
                    #ifdef LETTERBOX
                    WriteTGA( filename, displayWidth, displayHeight - 80, ptr + displayWidth * 3 * 40 );
                    #else
                    WriteTGA( filename, displayWidth, displayHeight, ptr );
                    #endif
                    glUnmapBufferARB( GL_PIXEL_PACK_BUFFER_ARB );
                }
            }

            // back to conventional pixel operation
            glBindBufferARB( GL_PIXEL_PACK_BUFFER_ARB, 0 );
        }

        demo->WaitForSim();
		
		#ifndef PROFILE

    		demo->Render( DeltaTime, shadows );

            #ifdef LETTERBOX
            renderInterface->LetterBox( 80 );
            #endif

            UpdateDisplay( video ? 0 : 1 );
        
		#endif

		frame ++;
	}

    #ifndef PROFILE
	CloseDisplay();
    #endif

	delete demo;
    delete renderInterface;

	printf( "shutdown\n" );
	
	net::ShutdownSockets();

	return 0;
}
Exemple #7
0
image_t *ImageLoad( const char *filename )
{
	int			i;
	image_t		*image;
	char		name[ 1024 ];
	int			size;
	byte		*buffer = NULL;
	qboolean	alphaHack = qfalse;

	
	/* init */
	ImageInit();
	
	/* dummy check */
	if( filename == NULL || filename[ 0 ] == '\0' )
		return NULL;
	
	/* strip file extension off name */
	strcpy( name, filename );
	StripExtension( name );
	
	/* try to find existing image */
	image = ImageFind( name );
	if( image != NULL )
	{
		image->refCount++;
		return image;
	}
	
	/* none found, so find first non-null image */
	image = NULL;
	for( i = 0; i < MAX_IMAGES; i++ )
	{
		if( images[ i ].name == NULL )
		{
			image = &images[ i ];
			break;
		}
	}
	
	/* too many images? */
	if( image == NULL )
		Error( "MAX_IMAGES (%d) exceeded, there are too many image files referenced by the map.", MAX_IMAGES );
	
	/* set it up */
	image->name = safe_malloc( strlen( name ) + 1 );
	strcpy( image->name, name );
	
	/* attempt to load tga */
	StripExtension( name );
	strcat( name, ".tga" );
	size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
	if( size > 0 )
		LoadTGABuffer( buffer, buffer + size, &image->pixels, &image->width, &image->height );
	else
	{
		/* attempt to load png */
		StripExtension( name );
		strcat( name, ".png" );
		size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
		if( size > 0 )
			LoadPNGBuffer( buffer, size, &image->pixels, &image->width, &image->height );
		else
		{
			/* attempt to load jpg */
			StripExtension( name );
			strcat( name, ".jpg" );
			size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
			if( size > 0 )
			{
				if( LoadJPGBuff( buffer, size, &image->pixels, &image->width, &image->height ) == -1 && image->pixels != NULL )
					Sys_Printf( "WARNING: LoadJPGBuff: %s\n", (unsigned char*) image->pixels );
				alphaHack = qtrue;
			}
			else
			{
				/* attempt to load dds */
				StripExtension( name );
				strcat( name, ".dds" );
				size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
				if( size > 0 )
				{
					LoadDDSBuffer( buffer, size, &image->pixels, &image->width, &image->height );
					
					/* debug code */
					#if 1
					{
						ddsPF_t	pf;
						DDSGetInfo( (ddsBuffer_t*) buffer, NULL, NULL, &pf );
						Sys_Printf( "pf = %d\n", pf );
						if( image->width > 0 )
						{
							StripExtension( name );
							strcat( name, "_converted.tga" );
							WriteTGA( "C:\\games\\quake3\\baseq3\\textures\\rad\\dds_converted.tga", image->pixels, image->width, image->height );
						}
					}
					#endif
				}
			}
		}
	}
	
	/* free file buffer */
	free( buffer );
	
	/* make sure everything's kosher */
	if( size <= 0 || image->width <= 0 || image->height <= 0 || image->pixels == NULL )
	{
		//%	Sys_Printf( "size = %d  width = %d  height = %d  pixels = 0x%08x (%s)\n",
		//%		size, image->width, image->height, image->pixels, name );
		free( image->name );
		image->name = NULL;
		return NULL;
	}
	
	/* set filename */
	image->filename = safe_malloc( strlen( name ) + 1 );
	strcpy( image->filename, name );
	
	/* set count */
	image->refCount = 1;
	numImages++;

	if(alphaHack)
	{
		StripExtension( name );
		strcat( name, "_alpha.jpg" );
		size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
		if( size > 0 )
		{
			unsigned char *pixels;
			int width, height;
			if( LoadJPGBuff( buffer, size, &pixels, &width, &height ) == -1 && pixels != NULL )
				Sys_Printf( "WARNING: LoadJPGBuff: %s\n", (unsigned char*) image->pixels );
			if(pixels && width == image->width && height == image->height)
			{
				int i;
				for(i = 0; i < width*height; ++i)
					image->pixels[4*i+3] = pixels[4*i+2]; // copy alpha from blue channel
			}
			free(pixels);
			free(buffer);
		}
	}
	
	/* return the image */
	return image;
}
void CImage::WriteTGA (const char *dir, const char *filename) {
    string path = dir;
    path += SEP;
    path += filename;
    WriteTGA (path.c_str());
}
Exemple #9
0
/*
==============
WriteRenderBump

==============
*/
static void WriteRenderBump( renderBump_t *rb, int outLinePixels ) {
	int		width, height;
	int		i;
	idStr	filename;

	renderModelManager->FreeModel( rb->highModel );

	FreeTriHash( rb->hash );

	width = rb->width;
	height = rb->height;

#if 0
	// save the non-outlined version
	filename = source;
	filename.setFileExtension();
	filename.append( "_nooutline.tga" );
	common->Printf( "writing %s\n", filename.c_str() );
	WriteTGA( filename, globalPic, width, height );
#endif

	// outline the image several times to help bilinear filtering across disconnected
	// edges, and mip-mapping
	for ( i = 0 ; i < outLinePixels ; i++ ) {
		OutlineNormalMap( rb->localPic, width, height, 128, 128, 128 );
		OutlineNormalMap( rb->globalPic, width, height, 128, 128, 128 );
		OutlineColorMap( rb->colorPic, width, height, 128, 128, 128 );
	}

	// filter down if we are anti-aliasing
	for ( i = 0 ; i < rb->antiAlias ; i++ ) {
		byte	*old;

		old = rb->localPic;
		rb->localPic = R_MipMap( rb->localPic, width, height, false );
		Mem_Free( old );

		old = rb->globalPic;
		rb->globalPic = R_MipMap( rb->globalPic, width, height, false );
		Mem_Free( old );

		old = rb->colorPic;
		rb->colorPic = R_MipMap( rb->colorPic, width, height, false );
		Mem_Free( old );

		width >>= 1;
		height >>= 1;
	}

	// write out the local map
	filename = rb->outputName;
	filename.SetFileExtension( ".tga" );
	common->Printf( "writing %s (%i,%i)\n", filename.c_str(), width, height );
	R_WriteTGA( filename, rb->localPic, width, height );

	if ( rb->saveGlobalMap ) {
		filename = rb->outputName;
		filename.StripFileExtension();
		filename.Append( "_global.tga" );
		common->Printf( "writing %s (%i,%i)\n", filename.c_str(), width, height );
		R_WriteTGA( filename, rb->globalPic, width, height );
	}

	if ( rb->saveColorMap ) {
		filename = rb->outputName;
		filename.StripFileExtension();
		filename.Append( "_color.tga" );
		common->Printf( "writing %s (%i,%i)\n", filename.c_str(), width, height );
		R_WriteTGA( filename, rb->colorPic, width, height );
	}

	Mem_Free( rb->localPic );
	Mem_Free( rb->globalPic );
	Mem_Free( rb->colorPic );
	Mem_Free( rb->edgeDistances );
}
Exemple #10
0
image_t        *ImageLoad(const char *filename)
{
    int             i;
    image_t        *image;
    char            name[1024];
    int             size;
    byte           *buffer = NULL;


    /* init */
    ImageInit();

    /* dummy check */
    if(filename == NULL || filename[0] == '\0')
        return NULL;

    /* strip file extension off name */
    strcpy(name, filename);
    StripExtension(name);

    /* try to find existing image */
    image = ImageFind(name);
    if(image != NULL)
    {
        image->refCount++;
        return image;
    }

    /* none found, so find first non-null image */
    image = NULL;
    for(i = 0; i < MAX_IMAGES; i++)
    {
        if(images[i].name == NULL)
        {
            image = &images[i];
            break;
        }
    }

    /* too many images? */
    if(image == NULL)
        Error("MAX_IMAGES (%d) exceeded, there are too many image files referenced by the map.", MAX_IMAGES);

    /* set it up */
    image->name = safe_malloc(strlen(name) + 1);
    strcpy(image->name, name);

#if 1
    /* attempt to load tga */
    StripExtension(name);
    strcat(name, ".tga");
    size = vfsLoadFile((const char *)name, (void **)&buffer, 0);
    if(size > 0)
        LoadTGABuffer(buffer, &image->pixels, &image->width, &image->height);
    else
    {
#if 1
        /* attempt to load png */
        StripExtension(name);
        strcat(name, ".png");
        size = vfsLoadFile((const char *)name, (void **)&buffer, 0);
        if(size > 0)
            LoadPNGBuffer(buffer, &image->pixels, &image->width, &image->height);
        else
        {
#if 1
            /* attempt to load jpg */
            StripExtension(name);
            strcat(name, ".jpg");
            size = vfsLoadFile((const char *)name, (void **)&buffer, 0);
            if(size > 0)
            {
                LoadJPGBuffer((const char *)name, buffer, size, &image->pixels, &image->width, &image->height);
                if(image->pixels == NULL)
                    Sys_Printf("WARNING: LoadJPGBuffer: '%s'\n", image->name);
            }
            else
            {
#if 1
                /* attempt to load dds */
                StripExtension(name);
                strcat(name, ".dds");
                size = vfsLoadFile((const char *)name, (void **)&buffer, 0);
                if(size > 0)
                {
                    LoadDDSBuffer(buffer, size, &image->pixels, &image->width, &image->height);

                    /* debug code */
#if 0
                    {
                        ddsPF_t         pf;

                        DDSGetInfo((ddsBuffer_t *) buffer, NULL, NULL, &pf);
                        Sys_Printf("pf = %d\n", pf);
                        if(image->width > 0)
                        {
                            StripExtension(name);
                            strcat(name, "_converted.tga");
                            WriteTGA("C:\\games\\quake3\\baseq3\\textures\\rad\\dds_converted.tga", image->pixels, image->width,
                                     image->height);
                        }
                    }
#endif							// dds debug
                }
#endif							// ignore dds
            }
#endif							// ignore jpg dds
        }
#endif							// ignore png jpg dds
    }
#endif							// ignore all images

    /* free file buffer */
    free(buffer);

    /* make sure everything's kosher */
    if(size <= 0 || image->width <= 0 || image->height <= 0 || image->pixels == NULL)
    {
        //% Sys_Printf( "size = %d  width = %d  height = %d  pixels = 0x%08x (%s)\n",
        //%     size, image->width, image->height, image->pixels, name );
        free(image->name);
        image->name = NULL;
        return NULL;
    }

    /* set filename */
    image->filename = safe_malloc(strlen(name) + 1);
    strcpy(image->filename, name);

    /* set count */
    image->refCount = 1;
    numImages++;

    /* return the image */
    return image;
}