Color Management, Stage 2: Switch color pipeline to use OpenColorIO
[blender.git] / source / blender / imbuf / intern / bmp.c
index cf2638071bb30b7e17a1955942659448bde3ff9a..df12f0b703e26ea80e5606cedd308bb5aa833560 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * ***** END GPL LICENSE BLOCK *****
  */
 
-#include "BLI_blenlib.h"
+/** \file blender/imbuf/intern/bmp.c
+ *  \ingroup imbuf
+ */
+
+#include "BLI_fileops.h"
 
 #include "imbuf.h"
 
 #include "IMB_allocimbuf.h"
 #include "IMB_filetype.h"
 
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
 /* some code copied from article on microsoft.com, copied
-  here for enhanced BMP support in the future
-  http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0197/mfcp1/mfcp1.htm&nav=/msj/0197/newnav.htm
-*/
-
-typedef struct BMPINFOHEADER{
-       unsigned int    biSize;
-       unsigned int    biWidth;
-       unsigned int    biHeight;
-       unsigned short  biPlanes;
-       unsigned short  biBitCount;
-       unsigned int    biCompression;
-       unsigned int    biSizeImage;
-       unsigned int    biXPelsPerMeter;
-       unsigned int    biYPelsPerMeter;
-       unsigned int    biClrUsed;
-       unsigned int    biClrImportant;
* here for enhanced BMP support in the future
* http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0197/mfcp1/mfcp1.htm&nav=/msj/0197/newnav.htm
+ */
+
+typedef struct BMPINFOHEADER {
+       unsigned int    biSize;
+       unsigned int    biWidth;
+       unsigned int    biHeight;
+       unsigned short  biPlanes;
+       unsigned short  biBitCount;
+       unsigned int    biCompression;
+       unsigned int    biSizeImage;
+       unsigned int    biXPelsPerMeter;
+       unsigned int    biYPelsPerMeter;
+       unsigned int    biClrUsed;
+       unsigned int    biClrImportant;
 } BMPINFOHEADER;
 
 typedef struct BMPHEADER {
@@ -67,15 +72,25 @@ typedef struct BMPHEADER {
 
 static int checkbmp(unsigned char *mem)
 {
+#define CHECK_HEADER_FIELD(mem, field) ((mem[0] == field[0]) && (mem[1] == field[1]))
+
        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 {
+               }
+               else {
+                       return 0;
                }
 
                /* for systems where an int needs to be 4 bytes aligned */
@@ -94,16 +109,18 @@ static int checkbmp(unsigned char *mem)
        }
 
        return(ret_val);
+
+#undef CHECK_HEADER_FIELD
 }
 
-int imb_is_a_bmp(unsigned char *buf) {
-       
+int imb_is_a_bmp(unsigned char *buf)
+{
        return checkbmp(buf);
 }
 
-struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags)
+struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
 {
-       struct ImBuf *ibuf = 0;
+       struct ImBuf *ibuf = NULL;
        BMPINFOHEADER bmi;
        int x, y, depth, skip, i;
        unsigned char *bmp, *rect;
@@ -111,7 +128,9 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags)
        
        (void)size; /* unused */
 
-       if (checkbmp(mem) == 0) return(0);
+       if (checkbmp(mem) == 0) return(NULL);
+
+       colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
 
        if ((mem[0] == 'B') && (mem[1] == 'M')) {
                /* skip fileheader */
@@ -126,13 +145,17 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags)
        y = LITTLE_LONG(bmi.biHeight);
        depth = LITTLE_SHORT(bmi.biBitCount);
 
-       /* printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y, 
-               depth, bmi.biBitCount); */
-       /* printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y, 
-               depth, bmi.biBitCount); */
+#if 0
+       printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y,
+              depth, bmi.biBitCount);
+       printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y,
+              depth, bmi.biBitCount);
+#endif
+
        if (flags & IB_test) {
                ibuf = IMB_allocImBuf(x, y, depth, 0);
-       } else {
+       }
+       else {
                ibuf = IMB_allocImBuf(x, y, depth, IB_rect);
                bmp = mem + skip;
                rect = (unsigned char *) ibuf->rect;
@@ -148,10 +171,11 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags)
                                rect += 4; bmp += 2;
                        }
 
-               } else if (depth == 24) {
+               }
+               else if (depth == 24) {
                        for (i = y; i > 0; i--) {
                                int j;
-                               for (j = x ; j > 0; j--) {
+                               for (j = x; j > 0; j--) {
                                        rect[0] = bmp[2];
                                        rect[1] = bmp[1];
                                        rect[2] = bmp[0];
@@ -162,7 +186,8 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags)
                                /* for 24-bit images, rows are padded to multiples of 4 */
                                bmp += x % 4;   
                        }
-               } else if (depth == 32) {
+               }
+               else if (depth == 32) {
                        for (i = x * y; i > 0; i--) {
                                rect[0] = bmp[2];
                                rect[1] = bmp[1];
@@ -175,28 +200,29 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags)
 
        if (ibuf) {
                ibuf->ftype = BMP;
-               ibuf->profile = IB_PROFILE_SRGB;
        }
        
        return(ibuf);
 }
 
 /* Couple of helper functions for writing our data */
-static int putIntLSB(unsigned int ui,FILE *ofile) { 
-       putc((ui>>0)&0xFF,ofile); 
-       putc((ui>>8)&0xFF,ofile); 
-       putc((ui>>16)&0xFF,ofile); 
-       return putc((ui>>24)&0xFF,ofile); 
+static int putIntLSB(unsigned int ui, FILE *ofile)
+{
+       putc((ui >> 0) & 0xFF, ofile);
+       putc((ui >> 8) & 0xFF, ofile);
+       putc((ui >> 16) & 0xFF, ofile);
+       return putc((ui >> 24) & 0xFF, ofile);
 }
 
-static int putShortLSB(unsigned short us,FILE *ofile) { 
-       putc((us>>0)&0xFF,ofile); 
-       return putc((us>>8)&0xFF,ofile); 
+static int putShortLSB(unsigned short us, FILE *ofile)
+{
+       putc((us >> 0) & 0xFF, ofile);
+       return putc((us >> 8) & 0xFF, ofile);
 } 
 
 /* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */
-int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags) {
-
+int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags)
+{
        BMPINFOHEADER infoheader;
        int bytesize, extrabytes, x, y, t, ptr;
        uchar *data;
@@ -204,41 +230,41 @@ int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags) {
        
        (void)flags; /* unused */
 
-       extrabytes = (4 - ibuf->x*3 % 4) % 4;
+       extrabytes = (4 - ibuf->x * 3 % 4) % 4;
        bytesize = (ibuf->x * 3 + extrabytes) * ibuf->y;
 
        data = (uchar *) ibuf->rect;
-       ofile = fopen(name,"wb");
-               if (!ofile) return 0;
-
-       putShortLSB(19778,ofile); /* "BM" */
-       putIntLSB(0,ofile); /* This can be 0 for BI_RGB bitmaps */
-       putShortLSB(0,ofile); /* Res1 */
-       putShortLSB(0,ofile); /* Res2 */
-       putIntLSB(BMP_FILEHEADER_SIZE + sizeof(infoheader),ofile); 
-
-       putIntLSB(sizeof(infoheader),ofile);
-       putIntLSB(ibuf->x,ofile);
-       putIntLSB(ibuf->y,ofile);
-       putShortLSB(1,ofile);
-       putShortLSB(24,ofile);
-       putIntLSB(0,ofile);
-       putIntLSB(bytesize + BMP_FILEHEADER_SIZE + sizeof(infoheader),ofile);
-       putIntLSB(0,ofile);
-       putIntLSB(0,ofile);
-       putIntLSB(0,ofile);
-       putIntLSB(0,ofile);
+       ofile = BLI_fopen(name, "wb");
+       if (!ofile) return 0;
+
+       putShortLSB(19778, ofile); /* "BM" */
+       putIntLSB(0, ofile); /* This can be 0 for BI_RGB bitmaps */
+       putShortLSB(0, ofile); /* Res1 */
+       putShortLSB(0, ofile); /* Res2 */
+       putIntLSB(BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile);
+
+       putIntLSB(sizeof(infoheader), ofile);
+       putIntLSB(ibuf->x, ofile);
+       putIntLSB(ibuf->y, ofile);
+       putShortLSB(1, ofile);
+       putShortLSB(24, ofile);
+       putIntLSB(0, ofile);
+       putIntLSB(bytesize + BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile);
+       putIntLSB(0, ofile);
+       putIntLSB(0, ofile);
+       putIntLSB(0, ofile);
+       putIntLSB(0, ofile);
 
        /* Need to write out padded image data in bgr format */
-       for (y=0;y<ibuf->y;y++) {
-               for (x=0;x<ibuf->x;x++) {
-                       ptr=(x + y * ibuf->x) * 4;
-                       if (putc(data[ptr+2],ofile) == EOF) return 0;
-                       if (putc(data[ptr+1],ofile) == EOF) return 0;
-                       if (putc(data[ptr],ofile) == EOF) return 0;
+       for (y = 0; y < ibuf->y; y++) {
+               for (x = 0; x < ibuf->x; x++) {
+                       ptr = (x + y * ibuf->x) * 4;
+                       if (putc(data[ptr + 2], ofile) == EOF) return 0;
+                       if (putc(data[ptr + 1], ofile) == EOF) return 0;
+                       if (putc(data[ptr], ofile) == EOF) return 0;
                }
                /* add padding here */
-               for (t=0;t<extrabytes;t++) if (putc(0,ofile) == EOF) return 0;
+               for (t = 0; t < extrabytes; t++) if (putc(0, ofile) == EOF) return 0;
        }
        if (ofile) {
                fflush(ofile);