Blender V2.61 - r43446

targa.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #ifdef WIN32
00034 #include <io.h>
00035 #endif
00036 #include "BLI_blenlib.h"
00037 #include "MEM_guardedalloc.h"
00038 
00039 #include "imbuf.h"
00040 
00041 #include "IMB_imbuf_types.h"
00042 #include "IMB_imbuf.h"
00043 
00044 #include "IMB_allocimbuf.h"
00045 #include "IMB_filetype.h"
00046 
00047 
00048 /* this one is only def-ed once, strangely... related to GS? */
00049 #define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0])
00050 
00051 /***/
00052 
00053 typedef struct TARGA 
00054 {
00055     unsigned char numid;    
00056     unsigned char maptyp;
00057     unsigned char imgtyp;   
00058     short maporig;
00059     short mapsize;
00060     unsigned char mapbits;
00061     short xorig;
00062     short yorig;
00063     short xsize;
00064     short ysize;
00065     unsigned char pixsize;
00066     unsigned char imgdes;
00067 } TARGA;
00068 
00069 /***/
00070 
00071 static int tga_out1(unsigned int data, FILE *file)
00072 {
00073     uchar *p;
00074 
00075     p = (uchar *) & data;
00076     if (putc(p[0],file) == EOF) return(EOF);
00077     return (~EOF);
00078 }
00079 
00080 static int tga_out2(unsigned int data, FILE * file)
00081 {
00082     uchar *p;
00083 
00084     p = (uchar *) & data;
00085     if (putc(p[0],file) == EOF) return(EOF);
00086     if (putc(p[1],file) == EOF) return(EOF);
00087     return (~EOF);
00088 }
00089 
00090 
00091 static int tga_out3(unsigned int data, FILE * file)
00092 {
00093     uchar *p;
00094 
00095     p = (uchar *) & data;
00096     if (putc(p[2],file) == EOF) return(EOF);
00097     if (putc(p[1],file) == EOF) return(EOF);
00098     if (putc(p[0],file) == EOF) return(EOF);
00099     return (~EOF);
00100 }
00101 
00102 
00103 static int tga_out4(unsigned int data, FILE * file)
00104 {
00105     uchar *p;
00106 
00107     p = (uchar *) & data;
00108     /* order = bgra */
00109     if (putc(p[2],file) == EOF) return(EOF);
00110     if (putc(p[1],file) == EOF) return(EOF);
00111     if (putc(p[0],file) == EOF) return(EOF);
00112     if (putc(p[3],file) == EOF) return(EOF);
00113     return (~EOF);
00114 }
00115 
00116 static short makebody_tga(ImBuf * ibuf, FILE * file, int (*out)(unsigned int, FILE*))
00117 {
00118     register int last,this;
00119     register int copy, bytes;
00120     register unsigned int *rect, *rectstart, *temp;
00121     int y;
00122     
00123     for (y = 0; y < ibuf->y; y++) {
00124         bytes = ibuf->x - 1;
00125         rectstart = rect = ibuf->rect + (y * ibuf->x);
00126         last = *rect++;
00127         this = *rect++;
00128         copy = last^this;
00129         while (bytes > 0){
00130             if (copy){
00131                 do{
00132                     last = this;
00133                     this = *rect++;
00134                     if (last == this){
00135                         if (this == rect[-3]){  /* three the same? */
00136                             bytes --;       /* set bytes */
00137                             break;
00138                         }
00139                     }
00140                 }while (--bytes != 0);
00141 
00142                 copy = rect-rectstart;
00143                 copy --;
00144                 if (bytes) copy -= 2;
00145 
00146                 temp = rect;
00147                 rect = rectstart;
00148 
00149                 while (copy){
00150                     last = copy;
00151                     if (copy>=128) last = 128;
00152                     copy -= last;
00153                     if (fputc(last-1,file) == EOF) return(0);
00154                     do{
00155                         if (out(*rect++,file) == EOF) return(0);
00156                     }while(--last != 0);
00157                 }
00158                 rectstart = rect;
00159                 rect = temp;
00160                 last = this;
00161 
00162                 copy = FALSE;
00163             } else {
00164                 while (*rect++ == this){        /* seek for first different byte */
00165                     if (--bytes == 0) break;    /* oor end of line */
00166                 }
00167                 rect --;
00168                 copy = rect-rectstart;
00169                 rectstart = rect;
00170                 bytes --;
00171                 this = *rect++;
00172 
00173                 while (copy){
00174                     if (copy>128){
00175                         if (fputc(255,file) == EOF) return(0);
00176                         copy -= 128;
00177                     } else {
00178                         if (copy == 1){
00179                             if (fputc(0,file) == EOF) return(0);
00180                         } else if (fputc(127 + copy,file) == EOF) return(0);
00181                         copy = 0;
00182                     }
00183                     if (out(last,file) == EOF) return(0);
00184                 }
00185                 copy=TRUE;
00186             }
00187         }
00188     }
00189     return (1);
00190 }
00191 
00192 static int dumptarga(struct ImBuf * ibuf, FILE * file)
00193 {
00194     int size;
00195     uchar *rect;
00196 
00197     if (ibuf == NULL) return (0);
00198     if (ibuf->rect == NULL) return (0);
00199 
00200     size = ibuf->x * ibuf->y;
00201     rect = (uchar *) ibuf->rect;
00202 
00203     if (ibuf->planes <= 8) {
00204         while(size > 0){
00205             if (putc(*rect, file) == EOF) return (0);
00206             size--;
00207             rect += 4;
00208         }
00209     } else if (ibuf->planes <= 16) {
00210         while(size > 0){
00211             putc(rect[0], file);
00212             if (putc(rect[1], file) == EOF) return (0);
00213             size--;
00214             rect += 4;
00215         }
00216     } else if (ibuf->planes <= 24) {
00217         while(size > 0){
00218             putc(rect[2], file);
00219             putc(rect[1], file);
00220             if (putc(rect[0], file) == EOF) return (0);
00221             size--;
00222             rect += 4;
00223         }
00224     } else if (ibuf->planes <= 32) {
00225         while(size > 0){
00226             putc(rect[2], file);
00227             putc(rect[1], file);
00228             putc(rect[0], file);
00229             if (putc(rect[3], file) == EOF) return (0);
00230             size--;
00231             rect += 4;
00232         }
00233     } else return (0);
00234     
00235     return (1);
00236 }
00237 
00238 
00239 int imb_savetarga(struct ImBuf * ibuf, const char *name, int flags)
00240 {
00241     char buf[20]= {0};
00242     FILE *fildes;
00243     short ok = 0;
00244     
00245     (void)flags; /* unused */
00246 
00247     buf[16] = (ibuf->planes + 0x7 ) & ~0x7;
00248     if (ibuf->planes > 8 ){
00249         buf[2] = 10;
00250     } else{
00251         buf[2] = 11;
00252     }
00253 
00254     if (ibuf->ftype == RAWTGA) buf[2] &= ~8;
00255     
00256     buf[8] = 0;
00257     buf[9] = 0;
00258     buf[10] = 0;
00259     buf[11] = 0;
00260 
00261     buf[12] = ibuf->x & 0xff;
00262     buf[13] = ibuf->x >> 8;
00263     buf[14] = ibuf->y & 0xff;
00264     buf[15] = ibuf->y >> 8;
00265 
00266     /* Don't forget to indicate that your 32 bit
00267      * targa uses 8 bits for the alpha channel! */
00268     if (ibuf->planes==32) {
00269         buf[17] |= 0x08;
00270     }
00271     fildes = fopen(name,"wb");
00272         if (!fildes) return 0;
00273 
00274     if (fwrite(buf, 1, 18,fildes) != 18) {
00275         fclose(fildes);
00276         return (0);
00277     }
00278 
00279     if (ibuf->ftype == RAWTGA) {
00280         ok = dumptarga(ibuf, fildes);
00281     } else {        
00282         switch((ibuf->planes + 7) >> 3){
00283         case 1:
00284             ok = makebody_tga(ibuf, fildes, tga_out1);
00285             break;
00286         case 2:
00287             ok = makebody_tga(ibuf, fildes, tga_out2);
00288             break;
00289         case 3:
00290             ok = makebody_tga(ibuf, fildes, tga_out3);
00291             break;
00292         case 4:
00293             ok = makebody_tga(ibuf, fildes, tga_out4);
00294             break;
00295         }
00296     }
00297     
00298     fclose(fildes);
00299     return (ok);
00300 }
00301 
00302 
00303 static int checktarga(TARGA *tga, unsigned char *mem)
00304 {
00305     tga->numid = mem[0];
00306     tga->maptyp = mem[1];
00307     tga->imgtyp = mem[2];
00308 
00309     tga->maporig = GSS(mem+3);
00310     tga->mapsize = GSS(mem+5);
00311     tga->mapbits = mem[7];
00312     tga->xorig = GSS(mem+8);
00313     tga->yorig = GSS(mem+10);
00314     tga->xsize = GSS(mem+12);
00315     tga->ysize = GSS(mem+14);
00316     tga->pixsize = mem[16];
00317     tga->imgdes = mem[17];
00318 
00319     if (tga->maptyp > 1) return(0);
00320     switch (tga->imgtyp){
00321     case 1:         /* raw cmap */
00322     case 2:         /* raw rgb */
00323     case 3:         /* raw b&w */
00324     case 9:         /* cmap */
00325     case 10:            /* rgb */
00326     case 11:            /* b&w */
00327         break;
00328     default:
00329         return(0);
00330     }
00331     if (tga->mapsize && tga->mapbits > 32) return(0);
00332     if (tga->xsize <= 0 || tga->xsize >= 8192) return(0);
00333     if (tga->ysize <= 0 || tga->ysize >= 8192) return(0);
00334     if (tga->pixsize > 32) return(0);
00335     if (tga->pixsize == 0) return(0);
00336     return(1);
00337 }
00338 
00339 int imb_is_a_targa(unsigned char *buf)
00340 {
00341     TARGA tga;
00342     
00343     return checktarga(&tga, buf);
00344 }
00345 
00346 static void complete_partial_load(struct ImBuf *ibuf, unsigned int *rect)
00347 {
00348     int size = (ibuf->x * ibuf->y) - (rect - ibuf->rect);
00349     if(size) {
00350         printf("decodetarga: incomplete file, %.1f%% missing\n", 100*((float)size / (ibuf->x * ibuf->y)));
00351 
00352         /* not essential but makes displaying partially rendered TGA's less ugly  */
00353         memset(rect, 0, size);
00354     }
00355     else {
00356         /* shouldnt happen */
00357         printf("decodetarga: incomplete file, all pixels written\n");
00358     }
00359 }
00360 
00361 static void decodetarga(struct ImBuf *ibuf, unsigned char *mem, size_t mem_size, int psize)
00362 {
00363     unsigned char *mem_end = mem+mem_size;
00364     int count, col, size;
00365     unsigned int *rect;
00366     uchar * cp = (uchar *) &col;
00367     
00368     if (ibuf == NULL) return;
00369     if (ibuf->rect == NULL) return;
00370 
00371     size = ibuf->x * ibuf->y;
00372     rect = ibuf->rect;
00373     
00374     /* set alpha */
00375     cp[0] = 0xff;
00376     cp[1] = cp[2] = 0;
00377 
00378     while(size > 0){
00379         count = *mem++;
00380 
00381         if(mem>mem_end)
00382             goto partial_load;
00383 
00384         if (count >= 128) {
00385             /*if (count == 128) printf("TARGA: 128 in file !\n");*/
00386             count -= 127;
00387 
00388             if (psize & 2){
00389                 if (psize & 1){
00390                     /* order = bgra */
00391                     cp[0] = mem[3];
00392                     cp[1] = mem[0];
00393                     cp[2] = mem[1];
00394                     cp[3] = mem[2];
00395                     /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
00396                     mem += 4;
00397                 } else{
00398                     cp[1] = mem[0];
00399                     cp[2] = mem[1];
00400                     cp[3] = mem[2];
00401                     /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
00402                     mem += 3;
00403                 }
00404             } else{
00405                 if (psize & 1){
00406                     cp[0] = mem[0];
00407                     cp[1] = mem[1];
00408                     mem += 2;
00409                 } else{
00410                     col = *mem++;
00411                 }
00412             }
00413 
00414             size -= count;
00415             if (size >= 0) {
00416                 while (count > 0) {
00417                     *rect++ = col;
00418                     count--;
00419                 }
00420             }
00421         } else{
00422             count ++;
00423             size -= count;
00424             if (size >= 0) {
00425                 while (count > 0){
00426                     if (psize & 2){
00427                         if (psize & 1){
00428                             /* order = bgra */
00429                             cp[0] = mem[3];
00430                             cp[1] = mem[0];
00431                             cp[2] = mem[1];
00432                             cp[3] = mem[2];
00433                             /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
00434                             mem += 4;
00435                         } else{
00436                             cp[1] = mem[0];
00437                             cp[2] = mem[1];
00438                             cp[3] = mem[2];
00439                             /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
00440                             mem += 3;
00441                         }
00442                     } else{
00443                         if (psize & 1){
00444                             cp[0] = mem[0];
00445                             cp[1] = mem[1];
00446                             mem += 2;
00447                         } else{
00448                             col = *mem++;
00449                         }
00450                     }
00451                     *rect++ = col;
00452                     count --;
00453 
00454                     if(mem>mem_end)
00455                         goto partial_load;
00456                 }
00457 
00458                 if(mem>mem_end)
00459                     goto partial_load;
00460             }
00461         }
00462     }
00463     if (size) {
00464         printf("decodetarga: count would overwrite %d pixels\n", -size);
00465     }
00466     return;
00467 
00468 partial_load:
00469     complete_partial_load(ibuf, rect);
00470 }
00471 
00472 static void ldtarga(struct ImBuf * ibuf,unsigned char * mem, size_t mem_size, int psize)
00473 {
00474     unsigned char *mem_end = mem+mem_size;
00475     int col,size;
00476     unsigned int *rect;
00477     uchar * cp = (uchar *) &col;
00478 
00479     if (ibuf == NULL) return;
00480     if (ibuf->rect == NULL) return;
00481 
00482     size = ibuf->x * ibuf->y;
00483     rect = ibuf->rect;
00484 
00485     /* set alpha */
00486     cp[0] = 0xff;
00487     cp[1] = cp[2] = 0;
00488 
00489     while(size > 0){
00490         if(mem>mem_end)
00491             goto partial_load;
00492 
00493         if (psize & 2){
00494             if (psize & 1){
00495                 /* order = bgra */
00496                 cp[0] = mem[3];
00497                 cp[1] = mem[0];
00498                 cp[2] = mem[1];
00499                 cp[3] = mem[2];
00500                 /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
00501                 mem += 4;
00502             } else{
00503                 /* set alpha for 24 bits colors */
00504                 cp[1] = mem[0];
00505                 cp[2] = mem[1];
00506                 cp[3] = mem[2];
00507                 /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
00508                 mem += 3;
00509             }
00510         } else{
00511             if (psize & 1){
00512                 cp[0] = mem[0];
00513                 cp[1] = mem[1];
00514                 mem += 2;
00515             } else{
00516                 col = *mem++;
00517             }
00518         }
00519         *rect++ = col;
00520         size--;
00521     }
00522     return;
00523 
00524 partial_load:
00525     complete_partial_load(ibuf, rect);
00526 }
00527 
00528 
00529 struct ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags)
00530 {
00531     TARGA tga;
00532     struct ImBuf * ibuf;
00533     int col, count, size;
00534     unsigned int *rect, *cmap= NULL /*, mincol= 0*/, maxcol= 0;
00535     uchar * cp = (uchar *) &col;
00536     
00537     if (checktarga(&tga,mem) == 0) return(NULL);
00538 
00539     if (flags & IB_test) ibuf = IMB_allocImBuf(tga.xsize,tga.ysize,tga.pixsize, 0);
00540     else ibuf = IMB_allocImBuf(tga.xsize,tga.ysize,(tga.pixsize + 0x7) & ~0x7, IB_rect);
00541 
00542     if (ibuf == NULL) return(NULL);
00543     ibuf->ftype = TGA;
00544     ibuf->profile = IB_PROFILE_SRGB;
00545     mem = mem + 18 + tga.numid;
00546     
00547     cp[0] = 0xff;
00548     cp[1] = cp[2] = 0;
00549     
00550     if (tga.mapsize){
00551         /* load color map */
00552         /*mincol = tga.maporig;*/ /*UNUSED*/
00553         maxcol = tga.mapsize;
00554         cmap = MEM_callocN(sizeof(unsigned int)*maxcol, "targa cmap");
00555 
00556         for (count = 0 ; count < maxcol ; count ++) {
00557             switch (tga.mapbits >> 3) {
00558                 case 4:
00559                     cp[0] = mem[3];
00560                     cp[1] = mem[0];
00561                     cp[2] = mem[1];
00562                     cp[3] = mem[2];
00563                     mem += 4;
00564                     break;
00565                 case 3:
00566                     cp[1] = mem[0];
00567                     cp[2] = mem[1];
00568                     cp[3] = mem[2];
00569                     mem += 3;
00570                     break;
00571                 case 2:
00572                     cp[1] = mem[1];
00573                     cp[0] = mem[0];
00574                     mem += 2;
00575                     break;
00576                 case 1:
00577                     col = *mem++;
00578                     break;
00579             }
00580             cmap[count] = col;
00581         }
00582         
00583         size = 0;
00584         for (col = maxcol - 1; col > 0; col >>= 1) size++;
00585         ibuf->planes = size;
00586 
00587         if (tga.mapbits != 32) {    /* set alpha bits  */
00588             cmap[0] &= BIG_LONG(0x00ffffffl);
00589         }
00590     }
00591     
00592     if (flags & IB_test) return (ibuf);
00593 
00594     if (tga.imgtyp != 1 && tga.imgtyp != 9) { /* happens sometimes (beuh) */
00595         if(cmap) {
00596             MEM_freeN(cmap); 
00597             cmap= NULL;
00598         }
00599     }
00600 
00601     switch(tga.imgtyp){
00602     case 1:
00603     case 2:
00604     case 3:
00605         if (tga.pixsize <= 8) ldtarga(ibuf,mem,mem_size,0);
00606         else if (tga.pixsize <= 16) ldtarga(ibuf,mem,mem_size,1);
00607         else if (tga.pixsize <= 24) ldtarga(ibuf,mem,mem_size,2);
00608         else if (tga.pixsize <= 32) ldtarga(ibuf,mem,mem_size,3);
00609         break;
00610     case 9:
00611     case 10:
00612     case 11:
00613         if (tga.pixsize <= 8) decodetarga(ibuf,mem,mem_size,0);
00614         else if (tga.pixsize <= 16) decodetarga(ibuf,mem,mem_size,1);
00615         else if (tga.pixsize <= 24) decodetarga(ibuf,mem,mem_size,2);
00616         else if (tga.pixsize <= 32) decodetarga(ibuf,mem,mem_size,3);
00617         break;
00618     }
00619     
00620     if(cmap) {
00621         /* apply color map */
00622         rect = ibuf->rect;
00623         for(size = ibuf->x * ibuf->y; size>0; --size, ++rect) {
00624             col = *rect;
00625             if (col >= 0 && col < maxcol) *rect = cmap[col];
00626         }
00627 
00628         MEM_freeN(cmap);
00629     }
00630     
00631     if (tga.pixsize == 16) {
00632         rect = ibuf->rect;
00633         for (size = ibuf->x * ibuf->y; size > 0; --size, ++rect){
00634             col = *rect;
00635             cp = (uchar*)rect; 
00636             mem = (uchar*)&col;
00637 
00638             cp[3] = ((mem[1] << 1) & 0xf8);
00639             cp[2] = ((mem[0] & 0xe0) >> 2) + ((mem[1] & 0x03) << 6);
00640             cp[1] = ((mem[0] << 3) & 0xf8);
00641             cp[1] += cp[1] >> 5;
00642             cp[2] += cp[2] >> 5;
00643             cp[3] += cp[3] >> 5;
00644             cp[0] = 0xff;
00645         }
00646         ibuf->planes = 24;
00647     }
00648     
00649     if (tga.imgtyp == 3 || tga.imgtyp == 11){
00650         uchar *crect;
00651         unsigned int *lrect, col;
00652         
00653         crect = (uchar *) ibuf->rect;
00654         lrect = (unsigned int *) ibuf->rect;
00655         
00656         for (size = ibuf->x * ibuf->y; size > 0; size --){
00657             col = *lrect++;
00658             
00659             crect[0] = 255;
00660             crect[1] = crect[2] = crect[3] = col;
00661             crect += 4;
00662         }
00663     }
00664     
00665     if (tga.imgdes & 0x20) IMB_flipy(ibuf);
00666 
00667     if (ibuf && ibuf->rect)
00668         IMB_convert_rgba_to_abgr(ibuf);
00669     
00670     return(ibuf);
00671 }