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