
But I'm sure that that fancier algorithm must be good for something. I wonder what sort of image it would do well on.



Could be a speed thing ...Sajt wrote:I'm not really sure what I could have been sarcastic about. I would like to see an example of what sort of situations this special algorithm is designed for.
My general research activities are in visual/multimedia computing and communications. I have published numerous algorithms for computer graphics and image processing (image coding in particular), some of which are being used by practitioners, such as a fast optimal color quantizer, and a Context-based Adaptive Lossless Image Codec (CALIC) which was developed jointly with Nasir Memon as a candidate algorithm for the new JPEG lossless standard.
It is a shame that TGA can't be used on the internet like PNG can. It is also a shame that TGA cannot easily be browsed with the thumbnail view in Windows.Teiman wrote:Oooops... hehehe.Sajt wrote:... (It's not like anyone in their right mind would use PNG for game textures, anyway.)...
Another reason: TGA loading in the engine can just use the engine code. If you have some non-traditional platform, supporting TGA loading is as easy as any other platform. You don't need .dll files to load a TGA.Teiman wrote:I was trying to avoid it, but here goes:
Why? Why is a bad idea to use PNG?
Code: Select all
/*
=========================================================
TARGA LOADING
=========================================================
*/
#pragma pack(1)
typedef struct _TargaHeader {
unsigned char id_length, colormap_type, image_type;
unsigned short colormap_index, colormap_length;
unsigned char colormap_size;
unsigned short x_origin, y_origin, width, height;
unsigned char pixel_size, attributes;
} TargaHeader;
#pragma pack()
/*
=============
LoadTGA
=============
*/
static byte *LoadTGA (char *name, int *width, int *height, qboolean alphablend)
{
TargaHeader *targa_header;
FILE *f;
int columns, rows, numPixels;
byte *pixbuf, *buf;
byte *targa_rgba;
int row, realrow, column;
qboolean upside_down, alpha, blend;
char filename[MAX_OSPATH];
sprintf (filename, "%s.tga", name);
COM_FOpenFile (filename, &f);
if (!f)
return NULL;
if (com_filesize < sizeof(TargaHeader))
Sys_Error ("LoadTGA: can't read header in %s", filename);
targa_header = malloc (com_filesize);
if (!targa_header)
Sys_Error ("LoadTGA1: error allocating %d bytes for %s", com_filesize, filename);
if (fread (targa_header, 1, com_filesize, f) != com_filesize)
Sys_Error ("LoadTGA: error reading %s", filename);
fclose (f);
targa_header->width = SwapShort (&targa_header->width);
targa_header->height = SwapShort (&targa_header->height);
if (targa_header->image_type!=2
&& targa_header->image_type!=10)
Sys_Error ("LoadTGA: %s: only type 2 and 10 targa RGB images supported, not %d", filename, targa_header->image_type);
if (targa_header->colormap_type !=0
|| (targa_header->pixel_size!=32 && targa_header->pixel_size!=24))
Sys_Error ("LoadTGA: %s: only 24 and 32 bit images supported (no colormaps, type=%d, bpp=%d)", filename, targa_header->colormap_type, targa_header->pixel_size);
columns = targa_header->width;
rows = targa_header->height;
numPixels = columns * rows;
upside_down = !(targa_header->attributes & 0x20); // true => picture is stored bottom to top
targa_rgba = malloc (numPixels*4);
if (!targa_rgba)
Sys_Error ("LoadTGA2: error allocating %d bytes for %s", numPixels*4, filename);
blend = alphablend && gl_alphablend.value;
alpha = targa_header->pixel_size == 32;
buf = (byte *)(targa_header + 1);
if (targa_header->id_length != 0)
buf += targa_header->id_length; // skip TARGA image comment
if (targa_header->image_type==2) { // Uncompressed, RGB images
for(row=rows-1; row>=0; row--) {
realrow = upside_down ? row : rows - 1 - row;
pixbuf = targa_rgba + realrow*columns*4;
ChkBounds ("LoadTGA1", buf - (byte *)targa_header + columns * targa_header->pixel_size / 8, com_filesize, filename);
ChkBounds ("LoadTGA2", pixbuf - targa_rgba + columns * 4, numPixels * 4, filename);
for(column=0; column<columns; column++) {
unsigned char red,green,blue,alphabyte;
blue = *buf++;
green = *buf++;
red = *buf++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alpha ? *buf++ : (blend ? (red + green + blue) / 3 : 255); // Better way?;
}
}
}
else if (targa_header->image_type==10) { // Runlength encoded RGB images
unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
for(row=rows-1; row>=0; row--) {
realrow = upside_down ? row : rows - 1 - row;
pixbuf = targa_rgba + realrow*columns*4;
for(column=0; column<columns; ) {
packetHeader = *buf++;
packetSize = 1 + (packetHeader & 0x7f);
ChkBounds ("LoadTGA3", pixbuf - targa_rgba + packetSize * 4, numPixels * 4, filename);
if (packetHeader & 0x80) { // run-length packet
ChkBounds ("LoadTGA4", buf - (byte *)targa_header + targa_header->pixel_size / 8, com_filesize, filename);
blue = *buf++;
green = *buf++;
red = *buf++;
alphabyte = alpha ? *buf++ : (blend ? (red + green + blue) / 3 : 255); // Better way?;
for(j=0;j<packetSize;j++) {
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
column++;
if (column==columns) { // run spans across rows
column=0;
if (row>0)
row--;
else
goto breakOut;
realrow = upside_down ? row : rows - 1 - row;
pixbuf = targa_rgba + realrow*columns*4;
}
}
}
else { // non run-length packet
ChkBounds ("LoadTGA5", buf - (byte *)targa_header + packetSize * targa_header->pixel_size / 8, com_filesize, filename);
for(j=0;j<packetSize;j++) {
blue = *buf++;
green = *buf++;
red = *buf++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alpha ? *buf++ : (blend ? (red + green + blue) / 3 : 255); // Better way?;
column++;
if (column==columns) { // pixel packet run spans across rows
column=0;
if (row>0)
row--;
else
goto breakOut;
realrow = upside_down ? row : rows - 1 - row;
pixbuf = targa_rgba + realrow*columns*4;
}
}
}
}
breakOut:;
}
}
*width = targa_header->width;
*height = targa_header->height;
free (targa_header);
return targa_rgba;
}