/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ #include "imbuf.h" #define OBJECTBLOK "cdi" uchar decdyuvtab[]={ 0, 1, 4, 9, 16, 27, 44, 79, 128, 177, 212, 229, 240, 247, 252, 255 }; uint dyuvstart = 0x108080; /* volgorde = yuv */ void setdyuvstart(uint start) { dyuvstart = start; } uint getdyuvstart() { return (dyuvstart); } void decdyuv(ibuf,ihdr,idat) struct ImBuf *ibuf; struct Ihdr *ihdr; uchar *idat; { short x,y,skip; uchar *rect,dy,du,dv,code; skip = 4 * (ihdr->lsize - ihdr->w); rect = (uchar *) ibuf->rect; dy = ihdr->yuvstart.y; du = ihdr->yuvstart.u; dv = ihdr->yuvstart.v; setdyuvstart((dy << 16) + (du << 8) + dv); for(y=ihdr->h;y>0;y--){ dy = ihdr->yuvstart.y; du = ihdr->yuvstart.u; dv = ihdr->yuvstart.v; for(x=0;xw;x++){ rect[0] = 0xff; code = *(idat++); dy += decdyuvtab[code & 0xf]; rect[1] = dy; if (x & 1){ dv += decdyuvtab[code >> 4]; rect[3]=dv; } else{ du += decdyuvtab[code >> 4]; rect[2]=du; } rect +=4; } rect += skip; } rect = (uchar *) ibuf->rect; for(y=ihdr->h;y>0;y--){ du = ihdr->yuvstart.u; dv = ihdr->yuvstart.v; for(x=0;x<(ihdr->w-1);x++){ if (x & 1){ dv = rect[3]; rect[2] = (du + rect[6]) >> 1; } else{ du = rect[2]; rect[3] = (dv + rect[7]) >> 1; } rect +=4; } if (x & 1){ rect[2] = du; } else{ rect[3] = dv; } rect +=4; rect += skip; } cspace(ibuf,dyuvrgb); } void dec_rl7(ibuf,ihdr,idat) struct ImBuf *ibuf; struct Ihdr *ihdr; register uchar *idat; { int x,y,code,len, step; uchar *rect; extern void rectfill(); if (ibuf->rect){ /* rect wissen */ rectoptot(ibuf, 0, rectfill, 0); rect = ((uchar *) ibuf->rect) + 3; step = 4; } else { rect = ibuf->chardata; step = 1; } for(y=ihdr->h;y>0;y--){ x=ihdr->w; while (x>0){ code = *(idat++); if (code & 128){ code &= ~128; len = *(idat ++); if (len < 2){ if (len == 0) len = x; else printf("Error in rl7: len = 1.\n"); } x -= len; for (;len>0;len--){ *rect = code; rect += step; } } else { *rect = code; rect += step; x--; } } if (x) { printf("error in RL7\n"); break; } } } void dec_rl3(ibuf,ihdr,idat) struct ImBuf *ibuf; struct Ihdr *ihdr; register uchar *idat; { int x,y,code,len; register uint *rect; rect = ibuf->rect; for(y=ihdr->h;y>0;y--){ x=ihdr->w / 2; while (x>0){ code = *(idat++); if (code & 128){ code &= ~128; len = *(idat ++); if (len < 2){ if (len == 0) len = x; else printf("Error in rl3: len = 1.\n"); } x -= len; for (;len>0;len--){ *(rect++) = (code >> 4) & 0x7; *(rect++) = code & 0x7; } } else { *(rect++) = (code >> 4) & 0x7; *(rect++) = code & 0x7; x--; } } if (x) { printf("error in RL3\n"); break; } } } uchar *enc_rl7_scanl(buf,rect,x) uchar *buf; int *rect; int x; { short last,this,xstart; uchar *wbuf; wbuf = buf; for (xstart = x - 1; xstart>0 ; xstart--) *(buf++) = *(rect++); buf[0] = buf[-1]; /* zodat ie op 't eind altijd met een run moet eindigen */ buf = wbuf; last = *(buf++); x--; while (x>0){ x--; if ((this = *(buf)++) == last){ *(wbuf++) = last | 128; xstart = x + 1; while (x > 0){ x--; if ((this = *(buf++)) != last) break; } if (x) { xstart -= x; while (xstart > 255) { *(wbuf++) = 255; *(wbuf++) = last | 128; xstart -= 255; } if (xstart != 1) *(wbuf++) = xstart; else wbuf[-1] = last & ~128; } else *(wbuf++) = 0; } else { *(wbuf++) = last & ~128; } last = this; } return(wbuf); } void codedyuv(uchar *buf, uchar *enc, int x, int start) { int col, dif, code, ncol; int i; col = start; for (i = 0; i> 1; while (i <= cntr) enc[i++] = dec; } while (i <= next) enc[i++] = dec; } short enc_dyuv(ibuf,file) struct ImBuf *ibuf; int file; { uchar *_bufy, *_bufu, *_bufv, *_rect; uchar *bufy, *bufu, *bufv, *rect; uchar enctab[256]; int x, y, sizex, halfx, size, start; short ok = TRUE; if (ibuf == 0) return(0); if (ibuf->rect == 0 && ibuf->chardata == 0) return(0); if (ibuf->chardata){ size = ((ibuf->x + 3) & ~3) * ibuf->y; if (write(file, ibuf->chardata, size) != size) return(FALSE); return(TRUE); } /*cspace(ibuf, rgbbeta);*/ cspace(ibuf, rgbdyuv); make_encdyuvtab(enctab); sizex = ibuf->x; halfx = sizex >> 1; _bufy = mallocN(sizex, "y"); _bufu = mallocN(halfx, "u"); _bufv = mallocN(halfx, "v"); if (_bufy == 0 || _bufu == 0 || _bufv == 0){ if (_bufy) freeN(_bufy); if (_bufu) freeN(_bufu); if (_bufv) freeN(_bufv); return(0); } start = getdyuvstart(); _rect = (uchar *) ibuf->rect; for (y = ibuf->y; y>0; y--){ rect = _rect + 2; bufy = _bufy; for (x = sizex; x>0; x--){ *bufy++ = *rect; rect += 4; } rect = _rect + 1; bufu = _bufu; for (x = halfx; x>0; x--){ *bufu++ = (rect[0] + rect[4]) >> 1; rect += 8; } rect = _rect + 3; bufv = _bufv; for (x = halfx; x>0; x--){ *bufv++ = (rect[0] + rect[4]) >> 1; rect += 8; } codedyuv(_bufy, enctab, sizex, (start >> 16) & 0xff); codedyuv(_bufu, enctab, halfx, (start >> 8) & 0xff); codedyuv(_bufv, enctab, halfx, (start >> 0) & 0xff); bufy = _bufy; bufu = _bufu; bufv = _bufv; for (x = 0; xx + 1); if (buf==0) return (FALSE); y = ibuf->y; x = ibuf->x; rect = ibuf->rect; for (;y>0;y--){ end = enc_rl7_scanl(buf,rect,x); rect += x; size = end-buf; if (write(file,buf,size) != size){ ok = FALSE; break; } } free(buf); return(ok); } uchar *enc_rl3_scanl(buf,rect,x) uchar *buf; int *rect; int x; { short last,this,xstart; uchar *wbuf; x /= 2; wbuf = buf; for (xstart = x - 1; xstart>0 ; xstart--){ last = (*(rect++) & 0x7) << 4; *(buf++) = last | (*(rect++) & 0x7); } buf[0] = buf[-1]; /* zodat ie op 't eind altijd met een run moet eindigen */ /* mocht dit niet werken bij rl3 verander dan xstart = x-1 weer in x en zet 'n vlag als de laatste pixel een unieke pixel was. Bij rl7 kon namelijk de laatste unieke pixel ook index nul hebben, zodat daarop vergelijken een fout kon veroorzaken */ buf = wbuf; last = *(buf++); x--; while (x>0){ x--; if ((this = *(buf)++) == last){ *(wbuf++) = last | 128; xstart = x + 1; while (x > 0){ x--; if ((this = *(buf++)) != last) break; } if (x) { xstart -= x; while (xstart > 255) { *(wbuf++) = 255; *(wbuf++) = last | 128; xstart -= 255; } if (xstart != 1) *(wbuf++) = xstart; else wbuf[-1] = last | 8; } else *(wbuf++) = 0; } else { *(wbuf++) = last | 8; } last = this; } return(wbuf); } short enc_rl3(ibuf,file) struct ImBuf *ibuf; int file; { short ok=TRUE; int x,y,size; uchar *buf,*end; uint *rect; buf = malloc((ibuf->x / 2) + 1); if (buf==0) return (FALSE); y = ibuf->y; x = ibuf->x; rect = ibuf->rect; for (;y>0;y--){ end = enc_rl3_scanl(buf,rect,x); rect += x; size = end-buf; if (write(file,buf,size) != size){ ok = FALSE; break; } } free(buf); return(ok); } void decclut8(ibuf,ihdr,idat) struct ImBuf *ibuf; struct Ihdr *ihdr; uchar *idat; { uint * rect; int i; rect = ibuf->rect; for (i = ibuf->x * ibuf->y; i > 0; i--){ *rect++ = *idat++; } } struct ImBuf *loadcdi(iffmem,flags) int *iffmem,flags; { int chunk,totlen,len,*mem,*cmap=0,cmapofs,cmaplen; uchar *idat=0; struct Ihdr ihdr; struct ImBuf *ibuf=0; mem=iffmem; ihdr.w=0; if (GL(mem) != FORM) return (0); if (GL(mem+2) != IMAG) return (0); totlen= (GL(mem+1) + 1) & ~1; mem += 3; totlen -= 4; while(totlen>0){ chunk=GL(mem); len= (GL(mem+1) + 1) & ~1; mem += 2; totlen -= len+8; switch (chunk){ case IHDR: memcpy(&ihdr,mem,sizeof(struct Ihdr)); break; case PLTE: cmap=mem+1; cmapofs = ((ushort *)mem)[0]; cmaplen = ((ushort *)mem)[1]; break; case IDAT: idat=(uchar *)mem; break; } mem = (int *)((uchar *)mem +len); if (idat) break; } if (ihdr.w==0) return (0); if (idat==0) return (0); /* printf("w:%d w:%d h:%d model:%d\n",ihdr.w,ihdr.lsize,ihdr.h,ihdr.model); printf("dpth:%d dyuvk:%d y:%d u:%d v:%d\n",ihdr.depth,ihdr.dyuvkind,ihdr.yuvstart.y,ihdr.yuvstart.u,ihdr.yuvstart.v); */ if (flags & IB_test) ibuf=allocImBuf(ihdr.w,ihdr.h,24,0,0); else if (flags & IB_char) ibuf=allocImBuf(ihdr.w,ihdr.h,24,IB_char | IB_charonlong,0); else ibuf=allocImBuf(ihdr.w,ihdr.h,24,IB_rect,0); if (ibuf==0) return (0); ibuf->ftype = (CDI | ihdr.model); if (cmap){ /* printf("cmapofs: %d cmaplen:%d \n",cmapofs,cmaplen); */ ibuf->maxcol = cmaplen; addcmapImBuf(ibuf); makecolarray(ibuf,cmap); } if (flags & IB_test){ if (flags & IB_freem) free(iffmem); return(ibuf); } switch(ihdr.model){ case DYUV: if (flags & IB_char && ibuf->chardata) memcpy(ibuf->chardata, idat, ihdr.lsize * ihdr.h); else /*if (flags & IB_rect)*/ decdyuv(ibuf,&ihdr,idat); break; case CLUT7: case CLUT8: if (flags & IB_char && ibuf->chardata) memcpy(ibuf->chardata, idat, ihdr.lsize * ihdr.h); else /*if (flags & IB_rect)*/ decclut8(ibuf,&ihdr,idat); break; case RL7: dec_rl7(ibuf,&ihdr,idat); break; case RL3: dec_rl3(ibuf,&ihdr,idat); break; default: freeImBuf(ibuf); return(0); } if (ibuf->cmap != 0 && (flags & IB_cmap) == 0) applycmap(ibuf); if (flags & IB_freem) free(iffmem); if ((flags & IB_ttob) == 0) flipy(ibuf); if (ibuf) { if (ibuf->rect) convert_rgba_to_abgr((ibuf->x+ibuf->skipx)*ibuf->y, ibuf->rect); } return (ibuf); }