forked from old/legacy-imlib2
Michel Briand <michelbriand@free.fr>
mmap tga loader SVN revision: 8987
This commit is contained in:
parent
6edd0ecd3b
commit
6a5dcff3a1
|
@ -18,6 +18,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#ifndef X_DISPLAY_MISSING
|
#ifndef X_DISPLAY_MISSING
|
||||||
# include <X11/Xlib.h>
|
# include <X11/Xlib.h>
|
||||||
|
@ -213,56 +214,60 @@ char
|
||||||
load(ImlibImage * im, ImlibProgressFunction progress,
|
load(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
char progress_granularity, char immediate_load)
|
char progress_granularity, char immediate_load)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
int fd;
|
||||||
|
void *seg, *filedata;
|
||||||
|
struct stat ss;
|
||||||
int bpp, vinverted = 0;
|
int bpp, vinverted = 0;
|
||||||
int rle = 0, footer_present = 0;
|
int rle = 0, footer_present = 0;
|
||||||
|
|
||||||
tga_header header;
|
tga_header *header;
|
||||||
tga_footer footer;
|
tga_footer *footer;
|
||||||
|
|
||||||
if (im->data)
|
if (im->data)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fp = fopen(im->real_file, "rb");
|
fd = open(im->real_file, O_RDONLY);
|
||||||
if (!fp)
|
if (fd < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* read the footer first */
|
if (fstat(fd, &ss) < 0)
|
||||||
fseek(fp, 0L - (sizeof(tga_footer)), SEEK_END);
|
|
||||||
if (fread(&footer, sizeof(tga_footer), 1, fp) != 1)
|
|
||||||
{
|
{
|
||||||
fclose(fp);
|
close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seg = mmap(0, ss.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
|
if (seg == MAP_FAILED)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
filedata = seg;
|
||||||
|
header = (tga_header *) filedata;
|
||||||
|
footer = (tga_footer *) (filedata + ss.st_size - sizeof(tga_footer));
|
||||||
|
|
||||||
/* check the footer to see if we have a v2.0 TGA file */
|
/* check the footer to see if we have a v2.0 TGA file */
|
||||||
if (memcmp(footer.signature, TGA_SIGNATURE, sizeof(footer.signature)) == 0)
|
if (memcmp(footer->signature, TGA_SIGNATURE, sizeof(footer->signature)) == 0)
|
||||||
footer_present = 1;
|
footer_present = 1;
|
||||||
|
|
||||||
if (!footer_present)
|
if (!footer_present)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now read the header */
|
/* skip over header */
|
||||||
if (fseek(fp, 0, SEEK_SET) || fread(&header, sizeof(header), 1, fp) != 1)
|
filedata += sizeof(tga_header);
|
||||||
{
|
|
||||||
fclose(fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip over alphanumeric ID field */
|
/* skip over alphanumeric ID field */
|
||||||
if (header.idLength && fseek(fp, header.idLength, SEEK_CUR))
|
if (header->idLength)
|
||||||
{
|
filedata += header->idLength;
|
||||||
fclose(fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now parse the header */
|
/* now parse the header */
|
||||||
|
|
||||||
/* this flag indicated bottom-up pixel storage */
|
/* this flag indicated bottom-up pixel storage */
|
||||||
vinverted = !(header.descriptor & TGA_DESC_VERTICAL);
|
vinverted = !(header->descriptor & TGA_DESC_VERTICAL);
|
||||||
|
|
||||||
switch (header.imageType)
|
switch (header->imageType)
|
||||||
{
|
{
|
||||||
case TGA_TYPE_COLOR_RLE:
|
case TGA_TYPE_COLOR_RLE:
|
||||||
case TGA_TYPE_GRAY_RLE:
|
case TGA_TYPE_GRAY_RLE:
|
||||||
|
@ -275,27 +280,30 @@ load(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fclose(fp);
|
munmap(seg, ss.st_size);
|
||||||
|
close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bits per pixel */
|
/* bits per pixel */
|
||||||
bpp = header.bpp;
|
bpp = header->bpp;
|
||||||
|
|
||||||
if (!((bpp == 32) || (bpp == 24) || (bpp == 8)))
|
if (!((bpp == 32) || (bpp == 24) || (bpp == 8)))
|
||||||
{
|
{
|
||||||
fclose(fp);
|
munmap(seg, ss.st_size);
|
||||||
|
close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* endian-safe loading of 16-bit sizes */
|
/* endian-safe loading of 16-bit sizes */
|
||||||
im->w = (header.widthHi << 8) | header.widthLo;
|
im->w = (header->widthHi << 8) | header->widthLo;
|
||||||
im->h = (header.heightHi << 8) | header.heightLo;
|
im->h = (header->heightHi << 8) | header->heightLo;
|
||||||
|
|
||||||
if ((im->w > 32767) || (im->w < 1) || (im->h > 32767) || (im->h < 1))
|
if ((im->w > 32767) || (im->w < 1) || (im->h > 32767) || (im->h < 1))
|
||||||
{
|
{
|
||||||
im->w = 0;
|
im->w = 0;
|
||||||
fclose(fp);
|
munmap(seg, ss.st_size);
|
||||||
|
close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,8 +320,7 @@ load(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
if (((!im->data) && (im->loader)) || (immediate_load) || (progress))
|
if (((!im->data) && (im->loader)) || (immediate_load) || (progress))
|
||||||
{
|
{
|
||||||
unsigned long datasize;
|
unsigned long datasize;
|
||||||
struct stat ss;
|
unsigned char *bufptr;
|
||||||
unsigned char *buf, *bufptr;
|
|
||||||
DATA32 *dataptr;
|
DATA32 *dataptr;
|
||||||
|
|
||||||
int y, pl = 0;
|
int y, pl = 0;
|
||||||
|
@ -324,7 +331,8 @@ load(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
if (!im->data)
|
if (!im->data)
|
||||||
{
|
{
|
||||||
im->w = 0;
|
im->w = 0;
|
||||||
fclose(fp);
|
munmap(seg, ss.st_size);
|
||||||
|
close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,29 +342,13 @@ load(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
/* find out how much data must be read from the file */
|
/* find out how much data must be read from the file */
|
||||||
/* (this is NOT simply width*height*4, due to compression) */
|
/* (this is NOT simply width*height*4, due to compression) */
|
||||||
|
|
||||||
stat(im->real_file, &ss);
|
datasize = ss.st_size - sizeof(tga_header) - header->idLength -
|
||||||
datasize = ss.st_size - sizeof(tga_header) - header.idLength -
|
|
||||||
(footer_present ? sizeof(tga_footer) : 0);
|
(footer_present ? sizeof(tga_footer) : 0);
|
||||||
|
|
||||||
buf = malloc(datasize);
|
|
||||||
if (!buf)
|
|
||||||
{
|
|
||||||
im->w = 0;
|
|
||||||
fclose(fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read in the pixel data */
|
|
||||||
if (fread(buf, 1, datasize, fp) != datasize)
|
|
||||||
{
|
|
||||||
fclose(fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* buffer is ready for parsing */
|
/* buffer is ready for parsing */
|
||||||
|
|
||||||
/* bufptr is the next byte to be read from the buffer */
|
/* bufptr is the next byte to be read from the buffer */
|
||||||
bufptr = buf;
|
bufptr = filedata;
|
||||||
|
|
||||||
/* dataptr is the next 32-bit pixel to be filled in */
|
/* dataptr is the next 32-bit pixel to be filled in */
|
||||||
dataptr = im->data;
|
dataptr = im->data;
|
||||||
|
@ -536,11 +528,11 @@ load(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
} /* end for (each row) */
|
} /* end for (each row) */
|
||||||
}
|
}
|
||||||
/* end if (image is RLE) */
|
/* end if (image is RLE) */
|
||||||
free(buf);
|
|
||||||
}
|
}
|
||||||
/* end if (loading pixel data) */
|
/* end if (loading pixel data) */
|
||||||
|
|
||||||
fclose(fp);
|
munmap(seg, ss.st_size);
|
||||||
|
close(fd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue