static void *load_tga(FILE *fp, int *xsz, int *ysz) { struct tga_header hdr; unsigned long x, y, sz; int i; uint32_t *pix, ppixel = 0; int rle_mode = 0, rle_pix_left = 0; int rdalpha; /* read header */ fseek(fp, 0, SEEK_SET); hdr.idlen = fgetc(fp); hdr.cmap_type = fgetc(fp); hdr.img_type = fgetc(fp); hdr.cmap_first = read_int16_le(fp); hdr.cmap_len = read_int16_le(fp); hdr.cmap_entry_sz = fgetc(fp); hdr.img_x = read_int16_le(fp); hdr.img_y = read_int16_le(fp); hdr.img_width = read_int16_le(fp); hdr.img_height = read_int16_le(fp); hdr.img_bpp = fgetc(fp); hdr.img_desc = fgetc(fp); if(feof(fp)) { return 0; } /* only read true color images */ if(!IS_RGBA(hdr.img_type)) { fprintf(stderr, "only true color tga images supported\n"); return 0; } fseek(fp, hdr.idlen, SEEK_CUR); /* skip the image ID */ /* skip the color map if it exists */ if(hdr.cmap_type == 1) { fseek(fp, hdr.cmap_len * hdr.cmap_entry_sz / 8, SEEK_CUR); } x = hdr.img_width; y = hdr.img_height; sz = x * y; if(!(pix = malloc(sz * 4))) { return 0; } rdalpha = hdr.img_desc & 0xf; for(i=0; i<y; i++) { uint32_t *ptr; int j; ptr = pix + ((hdr.img_desc & 0x20) ? i : y-(i+1)) * x; for(j=0; j<x; j++) { /* if the image is raw, then just read the next pixel */ if(!IS_RLE(hdr.img_type)) { ppixel = read_pixel(fp, rdalpha); } else { /* otherwise, for RLE... */ /* if we have pixels left in the packet ... */ if(rle_pix_left) { /* if it's a raw packet, read the next pixel, otherwise keep the same */ if(!rle_mode) { ppixel = read_pixel(fp, rdalpha); } rle_pix_left--; } else { /* read the RLE packet header */ unsigned char packet_hdr = getc(fp); rle_mode = (packet_hdr & 128); /* last bit shows the mode for this packet (1: rle, 0: raw) */ rle_pix_left = (packet_hdr & ~128); /* the rest gives the count of pixels minus one (we also read one here, so no +1) */ ppixel = read_pixel(fp, rdalpha); /* and read the first pixel of the packet */ } } *ptr++ = ppixel; if(feof(fp)) break; } } *xsz = x; *ysz = y; return pix; }
void *load_tga(FILE *fp, unsigned long *xsz, unsigned long *ysz) { struct tga_header hdr; unsigned long x, y, sz; int i; uint32_t *pix; /* read header */ fseek(fp, 0, SEEK_SET); hdr.idlen = fgetc(fp); hdr.cmap_type = fgetc(fp); hdr.img_type = fgetc(fp); hdr.cmap_first = read_int16_le(fp); hdr.cmap_len = read_int16_le(fp); hdr.cmap_entry_sz = fgetc(fp); hdr.img_x = read_int16_le(fp); hdr.img_y = read_int16_le(fp); hdr.img_width = read_int16_le(fp); hdr.img_height = read_int16_le(fp); hdr.img_bpp = fgetc(fp); hdr.img_desc = fgetc(fp); if(feof(fp)) { fclose(fp); return 0; } /* only read true color images */ if(hdr.img_type != 2) { fclose(fp); fprintf(stderr, "only true color tga images supported\n"); return 0; } fseek(fp, hdr.idlen, SEEK_CUR); /* skip the image ID */ /* skip the color map if it exists */ if(hdr.cmap_type == 1) { fseek(fp, hdr.cmap_len * hdr.cmap_entry_sz / 8, SEEK_CUR); } x = hdr.img_width; y = hdr.img_height; sz = x * y; if(!(pix = malloc(sz * 4))) { fclose(fp); return 0; } for(i=0; i<y; i++) { uint32_t *ptr; int j; ptr = pix + ((hdr.img_desc & 0x20) ? i : y-(i+1)) * x; for(j=0; j<x; j++) { unsigned char r, g, b, a; r = fgetc(fp); g = fgetc(fp); b = fgetc(fp); a = (hdr.img_desc & 0xf) ? fgetc(fp) : 255; *ptr++ = PACK_COLOR32(a, r, g, b); if(feof(fp)) break; } } fclose(fp); *xsz = x; *ysz = y; return pix; }