Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/imbuf/intern/targa.c')
-rw-r--r--source/blender/imbuf/intern/targa.c632
1 files changed, 632 insertions, 0 deletions
diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c
new file mode 100644
index 00000000000..dd1451a939a
--- /dev/null
+++ b/source/blender/imbuf/intern/targa.c
@@ -0,0 +1,632 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-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 *****
+ * $Id$
+ */
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#include <io.h>
+#endif
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_cmap.h"
+#include "IMB_targa.h"
+
+
+/* this one is only def-ed once, strangely... related to GS? */
+#define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0])
+
+/***/
+
+typedef struct TARGA
+{
+ unsigned char numid;
+ unsigned char maptyp;
+ unsigned char imgtyp;
+ short maporig;
+ short mapsize;
+ unsigned char mapbits;
+ short xorig;
+ short yorig;
+ short xsize;
+ short ysize;
+ unsigned char pixsize;
+ unsigned char imgdes;
+} TARGA;
+
+/***/
+
+static int tga_out1(unsigned int data, FILE *file)
+{
+ uchar *p;
+
+ p = (uchar *) & data;
+ if (putc(p[0],file) == EOF) return(EOF);
+ return (~EOF);
+}
+
+static int tga_out2(unsigned int data, FILE * file)
+{
+ uchar *p;
+
+ p = (uchar *) & data;
+ if (putc(p[0],file) == EOF) return(EOF);
+ if (putc(p[1],file) == EOF) return(EOF);
+ return (~EOF);
+}
+
+
+static int tga_out3(unsigned int data, FILE * file)
+{
+ uchar *p;
+
+ p = (uchar *) & data;
+ if (putc(p[2],file) == EOF) return(EOF);
+ if (putc(p[1],file) == EOF) return(EOF);
+ if (putc(p[0],file) == EOF) return(EOF);
+ return (~EOF);
+}
+
+
+static int tga_out4(unsigned int data, FILE * file)
+{
+ uchar *p;
+
+ p = (uchar *) & data;
+ /* volgorde = bgra */
+ if (putc(p[2],file) == EOF) return(EOF);
+ if (putc(p[1],file) == EOF) return(EOF);
+ if (putc(p[0],file) == EOF) return(EOF);
+ if (putc(p[3],file) == EOF) return(EOF);
+ return (~EOF);
+}
+
+static short makebody_tga(ImBuf * ibuf, FILE * file, int (*out)(unsigned int, FILE*))
+{
+ register int last,this;
+ register int copy, bytes;
+ register unsigned int *rect, *rectstart, *temp;
+ int y;
+
+ for (y = 0; y < ibuf->y; y++) {
+ bytes = ibuf->x - 1;
+ rectstart = rect = ibuf->rect + (y * ibuf->x);
+ last = *rect++;
+ this = *rect++;
+ copy = last^this;
+ while (bytes > 0){
+ if (copy){
+ do{
+ last = this;
+ this = *rect++;
+ if (last == this){
+ if (this == rect[-3]){ /* drie dezelfde? */
+ bytes --; /* bytes goed zetten */
+ break;
+ }
+ }
+ }while (--bytes != 0);
+
+ copy = rect-rectstart;
+ copy --;
+ if (bytes) copy -= 2;
+
+ temp = rect;
+ rect = rectstart;
+
+ while (copy){
+ last = copy;
+ if (copy>=128) last = 128;
+ copy -= last;
+ if (fputc(last-1,file) == EOF) return(0);
+ do{
+ if (out(*rect++,file) == EOF) return(0);
+ }while(--last != 0);
+ }
+ rectstart = rect;
+ rect = temp;
+ last = this;
+
+ copy = FALSE;
+ } else {
+ while (*rect++ == this){ /* zoek naar eerste afwijkende byte */
+ if (--bytes == 0) break; /* of einde regel */
+ }
+ rect --;
+ copy = rect-rectstart;
+ rectstart = rect;
+ bytes --;
+ this = *rect++;
+
+ while (copy){
+ if (copy>128){
+ if (fputc(255,file) == EOF) return(0);
+ copy -= 128;
+ } else {
+ if (copy == 1){
+ if (fputc(0,file) == EOF) return(0);
+ } else if (fputc(127 + copy,file) == EOF) return(0);
+ copy = 0;
+ }
+ if (out(last,file) == EOF) return(0);
+ }
+ copy=TRUE;
+ }
+ }
+ }
+ return (1);
+}
+
+static int dumptarga(struct ImBuf * ibuf, FILE * file)
+{
+ int size;
+ uchar *rect;
+
+ if (ibuf == 0) return (0);
+ if (ibuf->rect == 0) return (0);
+
+ size = ibuf->x * ibuf->y;
+ rect = (uchar *) ibuf->rect;
+
+ if (ibuf->depth <= 8) {
+ while(size > 0){
+ if (putc(*rect, file) == EOF) return (0);
+ size--;
+ rect += 4;
+ }
+ } else if (ibuf->depth <= 16) {
+ while(size > 0){
+ putc(rect[0], file);
+ if (putc(rect[1], file) == EOF) return (0);
+ size--;
+ rect += 4;
+ }
+ } else if (ibuf->depth <= 24) {
+ while(size > 0){
+ putc(rect[2], file);
+ putc(rect[1], file);
+ if (putc(rect[0], file) == EOF) return (0);
+ size--;
+ rect += 4;
+ }
+ } else if (ibuf->depth <= 32) {
+ while(size > 0){
+ putc(rect[2], file);
+ putc(rect[1], file);
+ putc(rect[0], file);
+ if (putc(rect[3], file) == EOF) return (0);
+ size--;
+ rect += 4;
+ }
+ } else return (0);
+
+ return (1);
+}
+
+
+short imb_savetarga(struct ImBuf * ibuf, int file, int flags)
+{
+ char buf[20];
+ FILE *fildes;
+ int i;
+ short ok;
+
+ if (ibuf == 0) return (0);
+ if (ibuf->rect == 0) return (0);
+
+ memset(buf,0,sizeof(buf));
+
+ /* buf[0] = 0; lengte string */
+
+ buf[16] = (ibuf->depth + 0x7 ) & ~0x7;
+ if (ibuf->cmap) {
+ buf[1] = 1;
+ buf[2] = 9;
+ buf[3] = ibuf->mincol & 0xff;
+ buf[4] = ibuf->mincol >> 8;
+ buf[5] = ibuf->maxcol & 0xff;
+ buf[6] = ibuf->maxcol >> 8;
+ buf[7] = 24;
+ if ((flags & IB_ttob) == 0) {
+ IMB_flipy(ibuf);
+ buf[17] = 0x20;
+ }
+ } else if (ibuf->depth > 8 ){
+ buf[2] = 10;
+ } else{
+ buf[2] = 11;
+ }
+
+ if (ibuf->ftype == RAWTGA) buf[2] &= ~8;
+
+ buf[8] = ibuf->xorig & 0xff;
+ buf[9] = ibuf->xorig >> 8;
+ buf[10] = ibuf->yorig & 0xff;
+ buf[11] = ibuf->yorig >> 8;
+
+ buf[12] = ibuf->x & 0xff;
+ buf[13] = ibuf->x >> 8;
+ buf[14] = ibuf->y & 0xff;
+ buf[15] = ibuf->y >> 8;
+
+ if (flags & IB_ttob) buf[17] ^= 0x20;
+
+ if (write(file, buf, 18) != 18) return (0);
+ if (ibuf->cmap){
+ for (i = 0 ; i<ibuf->maxcol ; i++){
+ if (write(file,((uchar *)(ibuf->cmap + i)) + 1,3) != 3) return (0);
+ }
+ }
+ fildes = fdopen(file,"ab");
+
+ if (ibuf->cmap && (flags & IB_cmap) == 0) IMB_converttocmap(ibuf);
+
+ if (ibuf->ftype == RAWTGA) {
+ ok = dumptarga(ibuf, fildes);
+ } else {
+ switch((ibuf->depth + 7) >> 3){
+ case 1:
+ ok = makebody_tga(ibuf, fildes, tga_out1);
+ break;
+ case 2:
+ ok = makebody_tga(ibuf, fildes, tga_out2);
+ break;
+ case 3:
+ ok = makebody_tga(ibuf, fildes, tga_out3);
+ break;
+ case 4:
+ ok = makebody_tga(ibuf, fildes, tga_out4);
+ break;
+ }
+ }
+
+ fclose(fildes);
+ return (ok);
+}
+
+
+static int checktarga(TARGA *tga, unsigned char *mem)
+{
+ tga->numid = mem[0];
+ tga->maptyp = mem[1];
+ tga->imgtyp = mem[2];
+
+ tga->maporig = GSS(mem+3);
+ tga->mapsize = GSS(mem+5);
+ tga->mapbits = mem[7];
+ tga->xorig = GSS(mem+8);
+ tga->yorig = GSS(mem+10);
+ tga->xsize = GSS(mem+12);
+ tga->ysize = GSS(mem+14);
+ tga->pixsize = mem[16];
+ tga->imgdes = mem[17];
+
+ if (tga->maptyp > 1) return(0);
+ switch (tga->imgtyp){
+ case 1: /* raw cmap */
+ case 2: /* raw rgb */
+ case 3: /* raw b&w */
+ case 9: /* cmap */
+ case 10: /* rgb */
+ case 11: /* b&w */
+ break;
+ default:
+ return(0);
+ }
+ if (tga->mapsize && tga->mapbits > 32) return(0);
+ if (tga->xsize <= 0 || tga->xsize >= 4096) return(0);
+ if (tga->ysize <= 0 || tga->ysize >= 4096) return(0);
+ if (tga->pixsize > 32) return(0);
+ if (tga->pixsize == 0) return(0);
+ return(1);
+}
+
+int imb_is_a_targa(void *buf) {
+ TARGA tga;
+
+ return checktarga(&tga, buf);
+}
+
+static void decodetarga(struct ImBuf *ibuf, unsigned char *mem, int psize)
+/* struct ImBuf *ibuf; */
+/* uchar *mem; */
+/* int psize; */
+{
+ int count, col, size;
+ unsigned int *rect;
+ uchar * cp = (uchar *) &col;
+
+ if (ibuf == 0) return;
+ if (ibuf->rect == 0) return;
+
+ size = ibuf->x * ibuf->y;
+ rect = ibuf->rect;
+
+ /* alpha zetten */
+ cp[0] = 0xff;
+ cp[1] = cp[2] = 0;
+
+ while(size > 0){
+ count = *mem++;
+ if (count >= 128) {
+ /*if (count == 128) printf("TARGA: 128 in file !\n");*/
+ count -= 127;
+
+ if (psize & 2){
+ if (psize & 1){
+ /* volgorde = bgra */
+ cp[0] = mem[3];
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 4;
+ } else{
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 3;
+ }
+ } else{
+ if (psize & 1){
+ col = (mem[0] << 8) + mem[1];
+ mem += 2;
+ } else{
+ col = *mem++;
+ }
+ }
+
+ size -= count;
+ if (size >= 0) {
+ while (count > 0) {
+ *rect++ = col;
+ count--;
+ }
+ }
+ } else{
+ count ++;
+ size -= count;
+ if (size >= 0) {
+ while (count > 0){
+ if (psize & 2){
+ if (psize & 1){
+ /* volgorde = bgra */
+ cp[0] = mem[3];
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 4;
+ } else{
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 3;
+ }
+ } else{
+ if (psize & 1){
+ col = (mem[0] << 8) + mem[1];
+ mem += 2;
+ } else{
+ col = *mem++;
+ }
+ }
+ *rect++ = col;
+ count --;
+ }
+ }
+ }
+ }
+ if (size) printf("decodetarga: count would overwrite %d pixels\n", -size);
+}
+
+static void ldtarga(struct ImBuf * ibuf,unsigned char * mem, int psize)
+{
+ int col,size;
+ unsigned int *rect;
+ uchar * cp = (uchar *) &col;
+
+ if (ibuf == 0) return;
+ if (ibuf->rect == 0) return;
+
+ size = ibuf->x * ibuf->y;
+ rect = ibuf->rect;
+
+ /* alpha zetten */
+ cp[0] = 0xff;
+ cp[1] = cp[2] = 0;
+
+ while(size > 0){
+ if (psize & 2){
+ if (psize & 1){
+ /* volgorde = bgra */
+ cp[0] = mem[3];
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = (mem[3] << 24) + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 4;
+ } else{
+ /* zet alpha bij 24 bits kleuren */
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ /*col = 0xff000000 + (mem[0] << 16) + (mem[1] << 8) + mem[2];*/
+ mem += 3;
+ }
+ } else{
+ if (psize & 1){
+ col = (mem[1] << 8) + mem[0];
+ mem += 2;
+ } else{
+ col = *mem++;
+ }
+ }
+ *rect++ = col;
+ size--;
+ }
+}
+
+
+struct ImBuf *imb_loadtarga(unsigned char *mem, int flags)
+{
+ TARGA tga;
+ struct ImBuf * ibuf;
+ int col, count, size;
+ unsigned int * rect;
+ uchar * cp = (uchar *) &col;
+
+ if (checktarga(&tga,mem) == 0) return(0);
+
+ if (flags & IB_test) ibuf = IMB_allocImBuf(tga.xsize,tga.ysize,tga.pixsize,0,0);
+ else ibuf = IMB_allocImBuf(tga.xsize,tga.ysize,(tga.pixsize + 0x7) & ~0x7,1,0);
+
+ if (ibuf == 0) return(0);
+ ibuf->ftype = TGA;
+ ibuf->xorig = tga.xorig;
+ ibuf->yorig = tga.yorig;
+ mem = mem + 18 + tga.numid;
+
+ cp[0] = 0xff;
+ cp[1] = cp[2] = 0;
+
+ if (tga.mapsize){
+ ibuf->mincol = tga.maporig;
+ ibuf->maxcol = tga.mapsize;
+ imb_addcmapImBuf(ibuf);
+ ibuf->cbits = 8;
+ for (count = 0 ; count < ibuf->maxcol ; count ++) {
+ switch (tga.mapbits >> 3) {
+ case 4:
+ cp[0] = mem[3];
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ mem += 4;
+ break;
+ case 3:
+ cp[1] = mem[0];
+ cp[2] = mem[1];
+ cp[3] = mem[2];
+ mem += 3;
+ break;
+ case 2:
+ col = (mem[1] << 8) + mem[0];
+ mem += 2;
+ break;
+ case 1:
+ col = *mem++;
+ break;
+ }
+ ibuf->cmap[count] = col;
+ }
+
+ size = 0;
+ for (col = ibuf->maxcol - 1; col > 0; col >>= 1) size++;
+ ibuf->depth = size;
+
+ if (tga.mapbits != 32) { /* alpha bits zetten */
+ ibuf->cmap[0] &= BIG_LONG(0x00ffffff);
+ }
+ }
+
+ if (flags & IB_test) return (ibuf);
+
+ if (tga.imgtyp != 1 && tga.imgtyp != 9) IMB_freecmapImBuf(ibuf); /* kan soms gebeuren (beuh) */
+
+ switch(tga.imgtyp){
+ case 1:
+ case 2:
+ case 3:
+ if (tga.pixsize <= 8) ldtarga(ibuf,mem,0);
+ else if (tga.pixsize <= 16) ldtarga(ibuf,mem,1);
+ else if (tga.pixsize <= 24) ldtarga(ibuf,mem,2);
+ else if (tga.pixsize <= 32) ldtarga(ibuf,mem,3);
+ break;
+ case 9:
+ case 10:
+ case 11:
+ if (tga.pixsize <= 8) decodetarga(ibuf,mem,0);
+ else if (tga.pixsize <= 16) decodetarga(ibuf,mem,1);
+ else if (tga.pixsize <= 24) decodetarga(ibuf,mem,2);
+ else if (tga.pixsize <= 32) decodetarga(ibuf,mem,3);
+ break;
+ }
+
+ if (ibuf->cmap){
+ if ((flags & IB_cmap) == 0) IMB_applycmap(ibuf);
+ }
+
+ if (tga.pixsize == 16 && ibuf->cmap == 0){
+ rect = ibuf->rect;
+ for (size = ibuf->x * ibuf->y; size > 0; size --){
+ col = *rect;
+ col = ((col & 0x1f) << 19) + ((col & 0x3e0) << 6) + ((col & 0x7c00) >> 7) ;
+ col += (col & 0xe0e0e0) >> 5;
+ *rect++ = col + 0xff000000;
+ }
+ ibuf->depth = 24;
+ }
+
+ if (tga.imgtyp == 3 || tga.imgtyp == 11){
+ uchar *crect;
+ unsigned int *lrect, col;
+
+ crect = (uchar *) ibuf->rect;
+ lrect = (unsigned int *) ibuf->rect;
+
+ for (size = ibuf->x * ibuf->y; size > 0; size --){
+ col = *lrect++;
+
+ crect[0] = 255;
+ crect[1] = crect[2] = crect[3] = col;
+ crect += 4;
+ }
+ }
+
+ if (flags & IB_ttob) tga.imgdes ^= 0x20;
+ if (tga.imgdes & 0x20) IMB_flipy(ibuf);
+
+ if (ibuf) {
+ if (ibuf->rect && (flags & IB_cmap)==0)
+ IMB_convert_rgba_to_abgr((ibuf->x+ibuf->skipx)*ibuf->y, ibuf->rect);
+ }
+
+ return(ibuf);
+}