|
Blender
V2.59
|
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 }