better loading partially written TARGA's, dont read over the end of the buffer and...
authorCampbell Barton <ideasman42@gmail.com>
Mon, 27 Jul 2009 22:41:35 +0000 (22:41 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 27 Jul 2009 22:41:35 +0000 (22:41 +0000)
source/blender/imbuf/intern/IMB_targa.h
source/blender/imbuf/intern/readimage.c
source/blender/imbuf/intern/targa.c

index 956bc512b977cfac133480335837d8448037e9ed..7759e4bc772adbce0f966ddee6e5aac8ee885f43 100644 (file)
@@ -41,7 +41,7 @@ struct ImBuf;
 
 int imb_is_a_targa(void *buf);
 
-struct ImBuf *imb_loadtarga(unsigned char *mem, int flags);
+struct ImBuf *imb_loadtarga(unsigned char *mem, int size, int flags);
 short imb_savetarga(struct ImBuf * ibuf, char *name, int flags);
 
 #endif
index 1a6ab104bcf595ad1a2d2b21ef6f4094645a494f..4104a8db65ce63a53f6b25658edb59817a0eb432 100644 (file)
@@ -143,7 +143,7 @@ ImBuf *IMB_ibImageFromMemory(int *mem, int size, int flags) {
                ibuf = imb_bmp_decode((uchar *)mem, size, flags);
                if (ibuf) return(ibuf);
 
-               ibuf = imb_loadtarga((uchar *)mem, flags);
+               ibuf = imb_loadtarga((uchar *)mem, size, flags);
                if (ibuf) return(ibuf);
 
                ibuf = imb_loaddpx((uchar *)mem, size, flags);
@@ -229,7 +229,7 @@ struct ImBuf *IMB_loadiffmem(int *mem, int flags) {
                }
        }
 
-       ibuf = imb_loadtarga((uchar *) mem,flags);
+       ibuf = imb_loadtarga((uchar *) mem,maxlen,flags);
        if (ibuf) return(ibuf);
 
        if (IB_verbose) fprintf(stderr,"Unknown fileformat\n");
index 303e5685503418ccf140a429f9b2b12feeb540ce..4e6326a1fd61f8d50433dbdf2d7168a773506861 100644 (file)
@@ -365,8 +365,24 @@ int imb_is_a_targa(void *buf) {
        return checktarga(&tga, buf);
 }
 
-static void decodetarga(struct ImBuf *ibuf, unsigned char *mem, int psize)
+static void complete_partial_load(struct ImBuf *ibuf, unsigned int *rect)
 {
+       int size = (ibuf->x * ibuf->y) - (rect - ibuf->rect);
+       if(size) {
+               printf("decodetarga: incomplete file, %.1f%% missing\n", 100*((float)size / (ibuf->x * ibuf->y)));
+
+               /* not essential but makes displaying partially rendered TGA's less ugly  */
+               memset(rect, 0, size);
+       }
+       else {
+               /* shouldnt happen */
+               printf("decodetarga: incomplete file, all pixels written\n");
+       }
+}
+
+static void decodetarga(struct ImBuf *ibuf, unsigned char *mem, int mem_size, int psize)
+{
+       unsigned char *mem_end = mem+mem_size;
        int count, col, size;
        unsigned int *rect;
        uchar * cp = (uchar *) &col;
@@ -380,9 +396,13 @@ static void decodetarga(struct ImBuf *ibuf, unsigned char *mem, int psize)
        /* set alpha */
        cp[0] = 0xff;
        cp[1] = cp[2] = 0;
-       
+
        while(size > 0){
                count = *mem++;
+
+               if(mem>mem_end)
+                       goto partial_load;
+
                if (count >= 128) {
                        /*if (count == 128) printf("TARGA: 128 in file !\n");*/
                        count -= 127;
@@ -452,15 +472,28 @@ static void decodetarga(struct ImBuf *ibuf, unsigned char *mem, int psize)
                                        }
                                        *rect++ = col;
                                        count --;
+
+                                       if(mem>mem_end)
+                                               goto partial_load;
                                }
+
+                               if(mem>mem_end)
+                                       goto partial_load;
                        }
                }
        }
-       if (size) printf("decodetarga: count would overwrite %d pixels\n", -size);
+       if (size) {
+               printf("decodetarga: count would overwrite %d pixels\n", -size);
+       }
+       return;
+
+partial_load:
+       complete_partial_load(ibuf, rect);
 }
 
-static void ldtarga(struct ImBuf * ibuf,unsigned char * mem, int psize)
+static void ldtarga(struct ImBuf * ibuf,unsigned char * mem, int mem_size, int psize)
 {
+       unsigned char *mem_end = mem+mem_size;
        int col,size;
        unsigned int *rect;
        uchar * cp = (uchar *) &col;
@@ -476,6 +509,9 @@ static void ldtarga(struct ImBuf * ibuf,unsigned char * mem, int psize)
        cp[1] = cp[2] = 0;
 
        while(size > 0){
+               if(mem>mem_end)
+                       goto partial_load;
+
                if (psize & 2){
                        if (psize & 1){
                                /* order = bgra */
@@ -505,10 +541,14 @@ static void ldtarga(struct ImBuf * ibuf,unsigned char * mem, int psize)
                *rect++ = col;
                size--;
        }
+       return;
+
+partial_load:
+       complete_partial_load(ibuf, rect);
 }
 
 
-struct ImBuf *imb_loadtarga(unsigned char *mem, int flags)
+struct ImBuf *imb_loadtarga(unsigned char *mem, int mem_size, int flags)
 {
        TARGA tga;
        struct ImBuf * ibuf;
@@ -579,18 +619,18 @@ struct ImBuf *imb_loadtarga(unsigned char *mem, int flags)
        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);
+               if (tga.pixsize <= 8) ldtarga(ibuf,mem,mem_size,0);
+               else if (tga.pixsize <= 16) ldtarga(ibuf,mem,mem_size,1);
+               else if (tga.pixsize <= 24) ldtarga(ibuf,mem,mem_size,2);
+               else if (tga.pixsize <= 32) ldtarga(ibuf,mem,mem_size,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);
+               if (tga.pixsize <= 8) decodetarga(ibuf,mem,mem_size,0);
+               else if (tga.pixsize <= 16) decodetarga(ibuf,mem,mem_size,1);
+               else if (tga.pixsize <= 24) decodetarga(ibuf,mem,mem_size,2);
+               else if (tga.pixsize <= 32) decodetarga(ibuf,mem,mem_size,3);
                break;
        }