img_t *img_parse_tga(int len, const char *data, lua_State *L) { // TODO: make this routine safer // it's possible to crash this in a whole bunch of ways const char *p = data; const char *dend = data+len; int x,y,i; img_tgahead_t head; // read header assert((unsigned long)len >= (unsigned long)sizeof(img_tgahead_t)); //memcpy(&head, p, sizeof(img_tgahead_t)); //p += sizeof(img_tgahead_t); // header has to be read semiproperly because gcc has no idea what packed means since 4.7 memcpy(&head.idlen, p + 0, 1); memcpy(&head.cmtype, p + 1, 1); memcpy(&head.imgtype, p + 2, 1); memcpy(&head.cmoffs, p + 3, 2); memcpy(&head.cmlen, p + 5, 2); memcpy(&head.cmbpp, p + 7, 1); memcpy(&head.xstart, p + 8, 2); memcpy(&head.ystart, p + 10, 2); memcpy(&head.width, p + 12, 2); memcpy(&head.height, p + 14, 2); memcpy(&head.bpp, p + 16, 1); memcpy(&head.flags, p + 17, 1); p += 18; int bplen = ((head.bpp-1)>>3)+1; assert((unsigned long)len >= (unsigned long)(sizeof(img_tgahead_t) + head.idlen)); // skip ID field p += head.idlen; // jump to palette // load palette if necessary uint32_t *palette = (head.cmtype == 1 ? (uint32_t*)malloc(head.cmlen*4) : NULL); if(palette != NULL) { int tclen = ((head.cmbpp-1)>>3)+1; assert((unsigned long)len >= (unsigned long)(sizeof(img_tgahead_t) + head.idlen + head.cmlen*tclen)); memset(palette, 0, 4*head.cmlen); for(i = 0; i < head.cmlen; i++) { // TODO check what happens when the offset is different uint32_t tmp_col = 0; memcpy(&tmp_col, p, tclen); p += tclen; palette[i] = img_convert_color_to_32(tmp_col, head.cmbpp); //printf("%6i %08X\n", i, palette[i]); } }
img_t *img_parse_tga(int len, const char *data) { // TODO: make this routine safer // it's possible to crash this in a whole bunch of ways const char *p = data; const char *dend = data+len; int x,y,i; img_tgahead_t head; // read header memcpy(&head, p, sizeof(img_tgahead_t)); p += sizeof(img_tgahead_t); // skip ID field p += head.idlen; // jump to palette // load palette if necessary uint32_t *palette = (head.cmtype == 1 ? (uint32_t*)malloc(head.cmlen*4) : NULL); if(palette != NULL) for(i = 0; i < head.cmlen; i++) { // TODO check what happens when the offset is different uint32_t tmp_col; int tclen = ((head.cmbpp-1)>>3)+1; memcpy(&tmp_col, p, tclen); p += tclen; palette[i] = img_convert_color_to_32(tmp_col, head.cmbpp); //printf("%6i %08X\n", i, palette[i]); } // allocate + stash int iw, ih; iw = head.width; ih = head.height; #ifdef USE_OPENGL expandtex_gl(&iw, &ih); #endif printf("TEX: %i %i\n", iw, ih); img_t *img = (img_t*)malloc(sizeof(img_t)+4*iw*ih); // TODO: check if NULL img->head = head; img->udtype = UD_IMG; #ifdef USE_OPENGL img->tex = 0; img->tex_dirty = 1; #endif // copy stuff int bplen = ((head.bpp-1)>>3)+1; int idx = (head.flags & 32 ? 0 : head.height-1)*iw; for(y = 0; y < head.height; y++) { if(head.imgtype & 8) { // RLE x = 0; uint32_t tmp_col; while(x < head.width) { int rle = (int)(uint8_t)(*p++); if(rle & 0x80) { rle &= 0x7F; memcpy(&tmp_col, p, bplen); p += bplen; for(i = 0; i <= rle && x < head.width && p < dend; i++, x++) img->pixels[idx++] = tmp_col; } else { for(i = 0; i <= rle && x < head.width && p < dend; i++, x++) { memcpy(&tmp_col, p, bplen); p += bplen; img->pixels[idx++] = tmp_col; } } } } else { // raw uint32_t tmp_col; for(x = 0; x < head.width && p < dend; x++) { memcpy(&tmp_col, p, bplen); p += bplen; img->pixels[idx++] = tmp_col; } } idx += iw-head.width; if(!(head.flags & 32)) idx -= 2*iw; } // convert pixels if((head.imgtype&7) == 1) { for(i = iw*ih-1; i >= 0; i--) img->pixels[i] = palette[(img->pixels[i] + head.cmoffs) % head.cmlen]; //printf("cm %i %i\n", head.cmoffs, head.cmlen); } else { for(i = iw*ih-1; i >= 0; i--) img->pixels[i] = img_convert_color_to_32(img->pixels[i], head.bpp); } // free palette free(palette); // now return! return img; }