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