Image_LoadImage: read pixel data in 1K chunks instead of calling getc in a loop

git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@957 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
Eric Wasylishen 2014-08-05 20:41:47 +00:00
parent d9f78442fe
commit a0f475ebcd

View file

@ -24,6 +24,39 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static char loadfilename[MAX_OSPATH]; //file scope so that error messages can use it static char loadfilename[MAX_OSPATH]; //file scope so that error messages can use it
typedef struct stdio_buffer_s {
FILE *f;
unsigned char buffer[1024];
int size;
int pos;
} stdio_buffer_t;
static stdio_buffer_t *Buf_Alloc(FILE *f)
{
stdio_buffer_t *buf = calloc(1, sizeof(stdio_buffer_t));
buf->f = f;
return buf;
}
static void Buf_Free(stdio_buffer_t *buf)
{
free(buf);
}
static inline int Buf_GetC(stdio_buffer_t *buf)
{
if (buf->pos >= buf->size)
{
buf->size = fread(buf->buffer, 1, sizeof(buf->buffer), buf->f);
buf->pos = 0;
if (buf->size == 0)
return EOF;
}
return buf->buffer[buf->pos++];
}
/* /*
============ ============
Image_LoadImage Image_LoadImage
@ -151,6 +184,7 @@ byte *Image_LoadTGA (FILE *fin, int *width, int *height)
byte *targa_rgba; byte *targa_rgba;
int realrow; //johnfitz -- fix for upside-down targas int realrow; //johnfitz -- fix for upside-down targas
qboolean upside_down; //johnfitz -- fix for upside-down targas qboolean upside_down; //johnfitz -- fix for upside-down targas
stdio_buffer_t *buf;
targa_header.id_length = fgetc(fin); targa_header.id_length = fgetc(fin);
targa_header.colormap_type = fgetc(fin); targa_header.colormap_type = fgetc(fin);
@ -182,6 +216,8 @@ byte *Image_LoadTGA (FILE *fin, int *width, int *height)
if (targa_header.id_length != 0) if (targa_header.id_length != 0)
fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment
buf = Buf_Alloc(fin);
if (targa_header.image_type==2) // Uncompressed, RGB images if (targa_header.image_type==2) // Uncompressed, RGB images
{ {
for(row=rows-1; row>=0; row--) for(row=rows-1; row>=0; row--)
@ -196,19 +232,19 @@ byte *Image_LoadTGA (FILE *fin, int *width, int *height)
switch (targa_header.pixel_size) switch (targa_header.pixel_size)
{ {
case 24: case 24:
blue = getc(fin); blue = Buf_GetC(buf);
green = getc(fin); green = Buf_GetC(buf);
red = getc(fin); red = Buf_GetC(buf);
*pixbuf++ = red; *pixbuf++ = red;
*pixbuf++ = green; *pixbuf++ = green;
*pixbuf++ = blue; *pixbuf++ = blue;
*pixbuf++ = 255; *pixbuf++ = 255;
break; break;
case 32: case 32:
blue = getc(fin); blue = Buf_GetC(buf);
green = getc(fin); green = Buf_GetC(buf);
red = getc(fin); red = Buf_GetC(buf);
alphabyte = getc(fin); alphabyte = Buf_GetC(buf);
*pixbuf++ = red; *pixbuf++ = red;
*pixbuf++ = green; *pixbuf++ = green;
*pixbuf++ = blue; *pixbuf++ = blue;
@ -229,23 +265,23 @@ byte *Image_LoadTGA (FILE *fin, int *width, int *height)
//johnfitz //johnfitz
for(column=0; column<columns; ) for(column=0; column<columns; )
{ {
packetHeader=getc(fin); packetHeader=Buf_GetC(buf);
packetSize = 1 + (packetHeader & 0x7f); packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) // run-length packet if (packetHeader & 0x80) // run-length packet
{ {
switch (targa_header.pixel_size) switch (targa_header.pixel_size)
{ {
case 24: case 24:
blue = getc(fin); blue = Buf_GetC(buf);
green = getc(fin); green = Buf_GetC(buf);
red = getc(fin); red = Buf_GetC(buf);
alphabyte = 255; alphabyte = 255;
break; break;
case 32: case 32:
blue = getc(fin); blue = Buf_GetC(buf);
green = getc(fin); green = Buf_GetC(buf);
red = getc(fin); red = Buf_GetC(buf);
alphabyte = getc(fin); alphabyte = Buf_GetC(buf);
break; break;
default: /* avoid compiler warnings */ default: /* avoid compiler warnings */
blue = red = green = alphabyte = 0; blue = red = green = alphabyte = 0;
@ -279,19 +315,19 @@ byte *Image_LoadTGA (FILE *fin, int *width, int *height)
switch (targa_header.pixel_size) switch (targa_header.pixel_size)
{ {
case 24: case 24:
blue = getc(fin); blue = Buf_GetC(buf);
green = getc(fin); green = Buf_GetC(buf);
red = getc(fin); red = Buf_GetC(buf);
*pixbuf++ = red; *pixbuf++ = red;
*pixbuf++ = green; *pixbuf++ = green;
*pixbuf++ = blue; *pixbuf++ = blue;
*pixbuf++ = 255; *pixbuf++ = 255;
break; break;
case 32: case 32:
blue = getc(fin); blue = Buf_GetC(buf);
green = getc(fin); green = Buf_GetC(buf);
red = getc(fin); red = Buf_GetC(buf);
alphabyte = getc(fin); alphabyte = Buf_GetC(buf);
*pixbuf++ = red; *pixbuf++ = red;
*pixbuf++ = green; *pixbuf++ = green;
*pixbuf++ = blue; *pixbuf++ = blue;
@ -320,6 +356,7 @@ byte *Image_LoadTGA (FILE *fin, int *width, int *height)
} }
} }
Buf_Free(buf);
fclose(fin); fclose(fin);
*width = (int)(targa_header.width); *width = (int)(targa_header.width);
@ -360,6 +397,7 @@ byte *Image_LoadPCX (FILE *f, int *width, int *height)
int x, y, w, h, readbyte, runlength, start; int x, y, w, h, readbyte, runlength, start;
byte *p, *data; byte *p, *data;
byte palette[768]; byte palette[768];
stdio_buffer_t *buf;
start = ftell (f); //save start of file (since we might be inside a pak file, SEEK_SET might not be the start of the pcx) start = ftell (f); //save start of file (since we might be inside a pak file, SEEK_SET might not be the start of the pcx)
@ -391,18 +429,20 @@ byte *Image_LoadPCX (FILE *f, int *width, int *height)
//back to start of image data //back to start of image data
fseek (f, start + sizeof(pcx), SEEK_SET); fseek (f, start + sizeof(pcx), SEEK_SET);
buf = Buf_Alloc(f);
for (y=0; y<h; y++) for (y=0; y<h; y++)
{ {
p = data + y * w * 4; p = data + y * w * 4;
for (x=0; x<(pcx.bytes_per_line); ) //read the extra padding byte if necessary for (x=0; x<(pcx.bytes_per_line); ) //read the extra padding byte if necessary
{ {
readbyte = fgetc(f); readbyte = Buf_GetC(buf);
if(readbyte >= 0xC0) if(readbyte >= 0xC0)
{ {
runlength = readbyte & 0x3F; runlength = readbyte & 0x3F;
readbyte = fgetc(f); readbyte = Buf_GetC(buf);
} }
else else
runlength = 1; runlength = 1;
@ -419,6 +459,8 @@ byte *Image_LoadPCX (FILE *f, int *width, int *height)
} }
} }
Buf_Free(buf);
fclose(f); fclose(f);
*width = w; *width = w;