File format fixes
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 27 Aug 2012 11:59:26 +0000 (11:59 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 27 Aug 2012 11:59:26 +0000 (11:59 +0000)
- Add check for header field in BMP decoder. This is needed to distinguish
  whether file is indeed BMP image or not.
  Without this check Blender could easily crash when it'll try to load
  non-BMP image.
  Tested with files from own HDD, but all of them has got BM header field,
  more testing would be welcome.

- Made Jpeg2000 aware of J2K codec. Originally was needed to verify .j2c
  files here in the studio, but having support of this codec would be
  nice in general.
  Currently supports only reading in this codec, writing would still
  using jp2 codec.

source/blender/imbuf/intern/bmp.c
source/blender/imbuf/intern/jp2.c
source/blender/imbuf/intern/util.c

index eb12b219da9b44409817bc27c048e9301a867af3..60dd4f65594ddb3dc3642aa375157ca86c5da33c 100644 (file)
@@ -69,16 +69,25 @@ typedef struct BMPHEADER {
 
 static int checkbmp(unsigned char *mem)
 {
+#define CHECK_HEADER_FIELD(mem, field) ((mem[0] == field[0]) && (mem[1] == field[0]))
+
        int ret_val = 0;
        BMPINFOHEADER bmi;
        unsigned int u;
 
        if (mem) {
-               if ((mem[0] == 'B') && (mem[1] == 'M')) {
+               if (CHECK_HEADER_FIELD(mem, "BM") ||
+                   CHECK_HEADER_FIELD(mem, "BA") ||
+                   CHECK_HEADER_FIELD(mem, "CI") ||
+                   CHECK_HEADER_FIELD(mem, "CP") ||
+                   CHECK_HEADER_FIELD(mem, "IC") ||
+                   CHECK_HEADER_FIELD(mem, "PT"))
+               {
                        /* skip fileheader */
                        mem += BMP_FILEHEADER_SIZE;
                }
                else {
+                       return 0;
                }
 
                /* for systems where an int needs to be 4 bytes aligned */
@@ -97,6 +106,8 @@ static int checkbmp(unsigned char *mem)
        }
 
        return(ret_val);
+
+#undef CHECK_HEADER_FIELD
 }
 
 int imb_is_a_bmp(unsigned char *buf)
index 8be7a9ea28b50edcff60c26d411218c3e1b1383d..1fe9a5ab522bc99e708a725bb1863233abfad1d7 100644 (file)
@@ -41,6 +41,7 @@
 #define JP2_FILEHEADER_SIZE 14
 
 static char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A};
+static char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00};
 
 /* We only need this because of how the presets are set */
 /* this typedef is copied from 'openjpeg-1.5.0/applications/codec/image_to_j2k.c' */
@@ -59,15 +60,19 @@ typedef struct img_folder {
 
 static int check_jp2(unsigned char *mem) /* J2K_CFMT */
 {
-       return memcmp(JP2_HEAD, mem, 12) ? 0 : 1;
+       return memcmp(JP2_HEAD, mem, sizeof(JP2_HEAD)) ? 0 : 1;
+}
+
+static int check_j2k(unsigned char *mem) /* J2K_CFMT */
+{
+       return memcmp(J2K_HEAD, mem, sizeof(J2K_HEAD)) ? 0 : 1;
 }
 
 int imb_is_a_jp2(unsigned char *buf)
-{      
+{
        return check_jp2(buf);
 }
 
-
 /**
  * sample error callback expecting a FILE* client object
  */
@@ -116,6 +121,7 @@ struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags)
        unsigned int i, i_next, w, h, planes;
        unsigned int y;
        int *r, *g, *b, *a; /* matching 'opj_image_comp.data' type */
+       int is_jp2, is_j2k;
        
        opj_dparameters_t parameters;   /* decompression parameters */
        
@@ -125,7 +131,11 @@ struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags)
        opj_dinfo_t *dinfo = NULL;  /* handle to a decompressor */
        opj_cio_t *cio = NULL;
 
-       if (check_jp2(mem) == 0) return(NULL);
+       is_jp2 = check_jp2(mem);
+       is_j2k = check_j2k(mem);
+
+       if (!is_jp2 && !is_j2k)
+               return(NULL);
 
        /* configure the event callbacks (not required) */
        memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
@@ -141,7 +151,7 @@ struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags)
        /* JPEG 2000 compressed image data */
 
        /* get a decoder handle */
-       dinfo = opj_create_decompress(CODEC_JP2);
+       dinfo = opj_create_decompress(is_jp2 ? CODEC_JP2 : CODEC_J2K);
 
        /* catch events using our callbacks and give a local context */
        opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
index 9ec22f0798e8730b8c9061e8b6adfb1de6c71cec..a765ac5c3b4e01fb1e942e8a84f0f2630118a396 100644 (file)
@@ -83,6 +83,7 @@ const char *imb_ext_image[] = {
 #endif
 #ifdef WITH_OPENJPEG
        ".jp2",
+       ".j2c",
 #endif
 #ifdef WITH_HDR
        ".hdr",