Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include "BLI_blenlib.h" 00034 00035 #include "imbuf.h" 00036 00037 #include "IMB_imbuf_types.h" 00038 #include "IMB_imbuf.h" 00039 #include "IMB_allocimbuf.h" 00040 #include "IMB_filetype.h" 00041 00042 /* some code copied from article on microsoft.com, copied 00043 here for enhanced BMP support in the future 00044 http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0197/mfcp1/mfcp1.htm&nav=/msj/0197/newnav.htm 00045 */ 00046 00047 typedef struct BMPINFOHEADER{ 00048 unsigned int biSize; 00049 unsigned int biWidth; 00050 unsigned int biHeight; 00051 unsigned short biPlanes; 00052 unsigned short biBitCount; 00053 unsigned int biCompression; 00054 unsigned int biSizeImage; 00055 unsigned int biXPelsPerMeter; 00056 unsigned int biYPelsPerMeter; 00057 unsigned int biClrUsed; 00058 unsigned int biClrImportant; 00059 } BMPINFOHEADER; 00060 00061 typedef struct BMPHEADER { 00062 unsigned short biType; 00063 unsigned int biSize; 00064 unsigned short biRes1; 00065 unsigned short biRes2; 00066 unsigned int biOffBits; 00067 } BMPHEADER; 00068 00069 #define BMP_FILEHEADER_SIZE 14 00070 00071 static int checkbmp(unsigned char *mem) 00072 { 00073 int ret_val = 0; 00074 BMPINFOHEADER bmi; 00075 unsigned int u; 00076 00077 if (mem) { 00078 if ((mem[0] == 'B') && (mem[1] == 'M')) { 00079 /* skip fileheader */ 00080 mem += BMP_FILEHEADER_SIZE; 00081 } else { 00082 } 00083 00084 /* for systems where an int needs to be 4 bytes aligned */ 00085 memcpy(&bmi, mem, sizeof(bmi)); 00086 00087 u = LITTLE_LONG(bmi.biSize); 00088 /* we only support uncompressed 24 or 32 bits images for now */ 00089 if (u >= sizeof(BMPINFOHEADER)) { 00090 if ((bmi.biCompression == 0) && (bmi.biClrUsed == 0)) { 00091 u = LITTLE_SHORT(bmi.biBitCount); 00092 if (u >= 16) { 00093 ret_val = 1; 00094 } 00095 } 00096 } 00097 } 00098 00099 return(ret_val); 00100 } 00101 00102 int imb_is_a_bmp(unsigned char *buf) 00103 { 00104 return checkbmp(buf); 00105 } 00106 00107 struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags) 00108 { 00109 struct ImBuf *ibuf = NULL; 00110 BMPINFOHEADER bmi; 00111 int x, y, depth, skip, i; 00112 unsigned char *bmp, *rect; 00113 unsigned short col; 00114 00115 (void)size; /* unused */ 00116 00117 if (checkbmp(mem) == 0) return(NULL); 00118 00119 if ((mem[0] == 'B') && (mem[1] == 'M')) { 00120 /* skip fileheader */ 00121 mem += BMP_FILEHEADER_SIZE; 00122 } 00123 00124 /* for systems where an int needs to be 4 bytes aligned */ 00125 memcpy(&bmi, mem, sizeof(bmi)); 00126 00127 skip = LITTLE_LONG(bmi.biSize); 00128 x = LITTLE_LONG(bmi.biWidth); 00129 y = LITTLE_LONG(bmi.biHeight); 00130 depth = LITTLE_SHORT(bmi.biBitCount); 00131 00132 /* printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y, 00133 depth, bmi.biBitCount); */ 00134 /* printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y, 00135 depth, bmi.biBitCount); */ 00136 if (flags & IB_test) { 00137 ibuf = IMB_allocImBuf(x, y, depth, 0); 00138 } else { 00139 ibuf = IMB_allocImBuf(x, y, depth, IB_rect); 00140 bmp = mem + skip; 00141 rect = (unsigned char *) ibuf->rect; 00142 00143 if (depth == 16) { 00144 for (i = x * y; i > 0; i--) { 00145 col = bmp[0] + (bmp[1] << 8); 00146 rect[0] = ((col >> 10) & 0x1f) << 3; 00147 rect[1] = ((col >> 5) & 0x1f) << 3; 00148 rect[2] = ((col >> 0) & 0x1f) << 3; 00149 00150 rect[3] = 255; 00151 rect += 4; bmp += 2; 00152 } 00153 00154 } else if (depth == 24) { 00155 for (i = y; i > 0; i--) { 00156 int j; 00157 for (j = x ; j > 0; j--) { 00158 rect[0] = bmp[2]; 00159 rect[1] = bmp[1]; 00160 rect[2] = bmp[0]; 00161 00162 rect[3] = 255; 00163 rect += 4; bmp += 3; 00164 } 00165 /* for 24-bit images, rows are padded to multiples of 4 */ 00166 bmp += x % 4; 00167 } 00168 } else if (depth == 32) { 00169 for (i = x * y; i > 0; i--) { 00170 rect[0] = bmp[2]; 00171 rect[1] = bmp[1]; 00172 rect[2] = bmp[0]; 00173 rect[3] = bmp[3]; 00174 rect += 4; bmp += 4; 00175 } 00176 } 00177 } 00178 00179 if (ibuf) { 00180 ibuf->ftype = BMP; 00181 ibuf->profile = IB_PROFILE_SRGB; 00182 } 00183 00184 return(ibuf); 00185 } 00186 00187 /* Couple of helper functions for writing our data */ 00188 static int putIntLSB(unsigned int ui,FILE *ofile) 00189 { 00190 putc((ui>>0)&0xFF,ofile); 00191 putc((ui>>8)&0xFF,ofile); 00192 putc((ui>>16)&0xFF,ofile); 00193 return putc((ui>>24)&0xFF,ofile); 00194 } 00195 00196 static int putShortLSB(unsigned short us,FILE *ofile) 00197 { 00198 putc((us>>0)&0xFF,ofile); 00199 return putc((us>>8)&0xFF,ofile); 00200 } 00201 00202 /* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */ 00203 int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags) 00204 { 00205 BMPINFOHEADER infoheader; 00206 int bytesize, extrabytes, x, y, t, ptr; 00207 uchar *data; 00208 FILE *ofile; 00209 00210 (void)flags; /* unused */ 00211 00212 extrabytes = (4 - ibuf->x*3 % 4) % 4; 00213 bytesize = (ibuf->x * 3 + extrabytes) * ibuf->y; 00214 00215 data = (uchar *) ibuf->rect; 00216 ofile = fopen(name,"wb"); 00217 if (!ofile) return 0; 00218 00219 putShortLSB(19778,ofile); /* "BM" */ 00220 putIntLSB(0,ofile); /* This can be 0 for BI_RGB bitmaps */ 00221 putShortLSB(0,ofile); /* Res1 */ 00222 putShortLSB(0,ofile); /* Res2 */ 00223 putIntLSB(BMP_FILEHEADER_SIZE + sizeof(infoheader),ofile); 00224 00225 putIntLSB(sizeof(infoheader),ofile); 00226 putIntLSB(ibuf->x,ofile); 00227 putIntLSB(ibuf->y,ofile); 00228 putShortLSB(1,ofile); 00229 putShortLSB(24,ofile); 00230 putIntLSB(0,ofile); 00231 putIntLSB(bytesize + BMP_FILEHEADER_SIZE + sizeof(infoheader),ofile); 00232 putIntLSB(0,ofile); 00233 putIntLSB(0,ofile); 00234 putIntLSB(0,ofile); 00235 putIntLSB(0,ofile); 00236 00237 /* Need to write out padded image data in bgr format */ 00238 for (y=0;y<ibuf->y;y++) { 00239 for (x=0;x<ibuf->x;x++) { 00240 ptr=(x + y * ibuf->x) * 4; 00241 if (putc(data[ptr+2],ofile) == EOF) return 0; 00242 if (putc(data[ptr+1],ofile) == EOF) return 0; 00243 if (putc(data[ptr],ofile) == EOF) return 0; 00244 } 00245 /* add padding here */ 00246 for (t=0;t<extrabytes;t++) if (putc(0,ofile) == EOF) return 0; 00247 } 00248 if (ofile) { 00249 fflush(ofile); 00250 fclose(ofile); 00251 } 00252 return 1; 00253 }