/* extract a portion of an image creating a new image */ static t_tgaimg * area2img(t_tgaimg *src, int x, int y, int width, int height, t_tgaimgtype type) { t_tgaimg *dst; int pixelsize; unsigned char *datap; unsigned char *destp; int i; if (src == NULL) return NULL; if ((x+width)>src->width) return NULL; if ((y+height)>src->height) return NULL; pixelsize = getpixelsize(src); if (pixelsize == 0) return NULL; dst = new_tgaimg(width,height,src->bpp,type); dst->data = malloc(width*height*pixelsize); datap = src->data; datap += y*src->width*pixelsize; destp = dst->data; for (i = 0; i < height; i++) { datap += x*pixelsize; memcpy(destp,datap,width*pixelsize); destp += width*pixelsize; datap += (src->width-x)*pixelsize; } return dst; }
int RLE_compress(std::FILE *f, t_tgaimg const *img) { int pixelsize; unsigned char const *datap; unsigned char *pktdata; unsigned int pktlen; t_tgapkttype pkttype; unsigned char *pktdatap; unsigned int actual=0,perceived=0; int i; pkttype = RAW; pktdatap = NULL; if (img == NULL) return -1; if (img->data == NULL) return -1; pixelsize = getpixelsize(img); if (pixelsize == 0) return -1; datap = img->data; pktdata = (unsigned char*)xmalloc(img->width*img->height*pixelsize); pktlen = 0; for (i=0; i<img->width*img->height; ) { if (pktlen == 0) { pktdatap = pktdata; std::memcpy(pktdatap,datap,pixelsize); pktlen++; i++; pktdatap += pixelsize; datap += pixelsize; pkttype = RAW; continue; } if (pktlen == 1) { if (std::memcmp(datap-pixelsize,datap,pixelsize)==0) { pkttype = RLE; } } if (pkttype == RLE) { if (std::memcmp(datap-pixelsize,datap,pixelsize)!=0 || pktlen>=128) { RLE_write_pkt(f,pkttype,pktlen,pktdata,pixelsize); actual += 1+pixelsize; perceived += pixelsize*pktlen; pktlen = 0; } else { pktlen++; i++; datap += pixelsize; } } else { if (std::memcmp(datap-pixelsize,datap,pixelsize)==0 || pktlen>=129) { datap -= pixelsize; /* push back last pixel */ i--; if (i<0) std::fprintf(stderr,"BUG!\n"); pktlen--; RLE_write_pkt(f,pkttype,pktlen,pktdata,pixelsize); actual += 1+pixelsize*pktlen; perceived += pixelsize*pktlen; pktlen = 0; } else { std::memcpy(pktdatap,datap,pixelsize); pktlen++; i++; pktdatap += pixelsize; datap += pixelsize; } } } if (pktlen) { RLE_write_pkt(f,pkttype,pktlen,pktdata,pixelsize); if (pkttype==RLE) { actual += 1+pixelsize; perceived += pixelsize*pktlen; } else { actual += 1+pixelsize*pktlen; perceived += pixelsize*pktlen; } pktlen = 0; } std::fprintf(stderr,"RLE_compress: wrote %u bytes (%u uncompressed)\n",actual,perceived); return 0; }