Eeshlo's fix for the unit problem with texture paths exporting to yafray
[blender.git] / source / blender / imbuf / intern / bmp_decode.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #ifdef _WIN32
34 #include "BLI_winstuff.h"
35 #endif
36 #include "BLI_blenlib.h"
37
38 #include "imbuf.h"
39 #include "imbuf_patch.h"
40
41 #include "IMB_imbuf_types.h"
42 #include "IMB_imbuf.h"
43 #include "IMB_allocimbuf.h"
44 #include "IMB_cmap.h"
45 #include "IMB_bmp.h"
46
47 #ifdef HAVE_CONFIG_H
48 #include <config.h>
49 #endif
50
51 // some code copied from article on microsoft.com, copied
52 // here for enhanced BMP support in the future
53 // http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0197/mfcp1/mfcp1.htm&nav=/msj/0197/newnav.htm
54
55 /*
56 LPBYTE CDib::GetBits()
57  {
58    return (LPBYTE)m_pbmih + // start of bitmap +
59      m_pbmih->biSize +      // size of header +
60      GetNumPaletteColors()  // (num colors *
61        *sizeof(RGBQUAD);    // size each entry)
62  }
63
64 UINT CDib::GetNumPaletteColors()
65  {
66     UINT nColors=m_pbmih->biClrUsed;
67     if (nColors==0 && m_pbmih->biBitCount<=8)
68        nColors = 1<<m_pbmih->biBitCount;
69     return nColors;
70  }
71
72 */
73
74 typedef struct BMPINFOHEADER{
75         unsigned int    biSize;
76         int                             biWidth;
77         int                             biHeight;
78         unsigned short  biPlanes;
79         unsigned short  biBitCount;
80         unsigned int    biCompression;
81         unsigned int    biSizeImage;
82         int                             biXPelsPerMeter;
83         int                             biYPelsPerMeter;
84         unsigned int    biClrUsed;
85         unsigned int    biClrImportant;
86 } BMPINFOHEADER;
87
88 #define BMP_FILEHEADER_SIZE 14
89
90 static int checkbmp(unsigned char *mem)
91 {
92         int ret_val = 0;
93         BMPINFOHEADER bmi;
94         unsigned int u;
95
96         if (mem) {
97                 if ((mem[0] == 'B') && (mem[1] == 'M')) {
98                         // skip fileheader
99                         mem += BMP_FILEHEADER_SIZE;
100                 }
101
102                 // for systems where an int needs to be 4 bytes aligned
103                 memcpy(&bmi, mem, sizeof(bmi));
104
105                 u = LITTLE_LONG(bmi.biSize);
106                 // we only support uncompressed 24 or 32 bits images for now
107                 if (u >= sizeof(BMPINFOHEADER)) {
108                         if ((bmi.biCompression == 0) && (bmi.biClrUsed == 0)) {
109                                 u = LITTLE_SHORT(bmi.biBitCount);
110                                 if (u >= 16) {
111                                         ret_val = 1;
112                                 }
113                         }
114                 }
115         }
116
117         return(ret_val);
118 }
119
120 int imb_is_a_bmp(void *buf) {
121         
122         return checkbmp(buf);
123 }
124
125 struct ImBuf *imb_bmp_decode(unsigned char *mem, int size, int flags)
126 {
127         struct ImBuf *ibuf = 0;
128         BMPINFOHEADER bmi;
129         int x, y, depth, skip, i;
130         unsigned char *bmp, *rect;
131         unsigned short col;
132
133         if (checkbmp(mem) == 0) return(0);
134
135         if ((mem[0] == 'B') && (mem[1] == 'M')) {
136                 // skip fileheader
137                 mem += BMP_FILEHEADER_SIZE;
138         }
139
140         // for systems where an int needs to be 4 bytes aligned
141         memcpy(&bmi, mem, sizeof(bmi));
142
143         skip = LITTLE_LONG(bmi.biSize);
144         x = LITTLE_LONG(bmi.biWidth);
145         y = LITTLE_LONG(bmi.biHeight);
146         depth = LITTLE_SHORT(bmi.biBitCount);
147
148         // printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y, depth, bmi.biBitCount);
149         if (flags & IB_test) {
150                 ibuf = IMB_allocImBuf(x, y, depth, 0, 0);
151         } else {
152                 ibuf = IMB_allocImBuf(x, y, depth, IB_rect, 0);
153                 bmp = mem + skip;
154                 rect = (unsigned char *) ibuf->rect;
155
156                 if (depth == 16) {
157                         for (i = x * y; i > 0; i--) {
158                                 col = bmp[0] + (bmp[1] << 8);
159                                 rect[0] = ((col >> 10) & 0x1f) << 3;
160                                 rect[1] = ((col >>  5) & 0x1f) << 3;
161                                 rect[2] = ((col >>  0) & 0x1f) << 3;
162                                 
163                                 rect[3] = 255;
164                                 rect += 4; bmp += 2;
165                         }
166
167                 } else if (depth == 24) {
168                         for (i = x * y; i > 0; i--) {
169                                 rect[0] = bmp[2];
170                                 rect[1] = bmp[1];
171                                 rect[2] = bmp[0];
172                                 
173                                 rect[3] = 255;
174                                 rect += 4; bmp += 3;
175                         }
176                 } else if (depth == 32) {
177                         for (i = x * y; i > 0; i--) {
178                                 rect[0] = bmp[0];
179                                 rect[1] = bmp[1];
180                                 rect[2] = bmp[2];
181                                 rect[3] = bmp[3];
182                                 rect += 4; bmp += 4;
183                         }
184                 }
185         }
186
187         if (ibuf) {
188                 ibuf->ftype = BMP;
189         }
190         
191         return(ibuf);
192 }
193