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 * Contributor(s): Campbell Barton. 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00028 #include <string.h> 00029 00030 #include "zlib.h" 00031 00032 #include "BLI_utildefines.h" 00033 00034 #include "BKE_utildefines.h" 00035 #include "BKE_global.h" 00036 00037 #include "IMB_imbuf_types.h" 00038 #include "IMB_imbuf.h" 00039 #include "IMB_thumbs.h" 00040 00041 #include "MEM_guardedalloc.h" 00042 00043 /* extracts the thumbnail from between the 'REND' and the 'GLOB' 00044 * chunks of the header, dont use typical blend loader because its too slow */ 00045 00046 static ImBuf *loadblend_thumb(gzFile gzfile) 00047 { 00048 char buf[12]; 00049 int bhead[24/sizeof(int)]; /* max size on 64bit */ 00050 char endian, pointer_size; 00051 char endian_switch; 00052 int sizeof_bhead ; 00053 00054 /* read the blend file header */ 00055 if(gzread(gzfile, buf, 12) != 12) 00056 return NULL; 00057 if(strncmp(buf, "BLENDER", 7)) 00058 return NULL; 00059 00060 if(buf[7]=='-') 00061 pointer_size= 8; 00062 else if(buf[7]=='_') 00063 pointer_size= 4; 00064 else 00065 return NULL; 00066 00067 sizeof_bhead = 16 + pointer_size; 00068 00069 if(buf[8]=='V') 00070 endian= B_ENDIAN; /* big: PPC */ 00071 else if(buf[8]=='v') 00072 endian= L_ENDIAN; /* little: x86 */ 00073 else 00074 return NULL; 00075 00076 endian_switch = ((ENDIAN_ORDER != endian)) ? 1 : 0; 00077 00078 while(gzread(gzfile, bhead, sizeof_bhead) == sizeof_bhead) { 00079 if(endian_switch) 00080 SWITCH_INT(bhead[1]); /* length */ 00081 00082 if (bhead[0]==REND) { 00083 gzseek(gzfile, bhead[1], SEEK_CUR); /* skip to the next */ 00084 } 00085 else { 00086 break; 00087 } 00088 } 00089 00090 /* using 'TEST' since new names segfault when loading in old blenders */ 00091 if(bhead[0] == TEST) { 00092 ImBuf *img= NULL; 00093 int size[2]; 00094 00095 if(gzread(gzfile, size, sizeof(size)) != sizeof(size)) 00096 return NULL; 00097 00098 if(endian_switch) { 00099 SWITCH_INT(size[0]); 00100 SWITCH_INT(size[1]); 00101 } 00102 /* length */ 00103 bhead[1] -= sizeof(int) * 2; 00104 00105 /* inconsistent image size, quit early */ 00106 if(bhead[1] != size[0] * size[1] * sizeof(int)) 00107 return NULL; 00108 00109 /* finally malloc and read the data */ 00110 img= IMB_allocImBuf(size[0], size[1], 32, IB_rect | IB_metadata); 00111 00112 if(gzread(gzfile, img->rect, bhead[1]) != bhead[1]) { 00113 IMB_freeImBuf(img); 00114 img= NULL; 00115 } 00116 00117 return img; 00118 } 00119 00120 return NULL; 00121 } 00122 00123 ImBuf *IMB_loadblend_thumb(const char *path) 00124 { 00125 gzFile gzfile; 00126 00127 /* not necessarily a gzip */ 00128 gzfile = gzopen(path, "rb"); 00129 00130 if (NULL == gzfile ) { 00131 return NULL; 00132 } 00133 else { 00134 ImBuf *img= loadblend_thumb(gzfile); 00135 00136 /* read ok! */ 00137 gzclose(gzfile); 00138 00139 return img; 00140 } 00141 } 00142 00143 /* add a fake passepartout overlay to a byte buffer, use for blend file thumbnails */ 00144 #define MARGIN 2 00145 00146 void IMB_overlayblend_thumb(unsigned int *thumb, int width, int height, float aspect) 00147 { 00148 unsigned char *px= (unsigned char *)thumb; 00149 int margin_l = MARGIN; 00150 int margin_b = MARGIN; 00151 int margin_r = width - MARGIN; 00152 int margin_t = height - MARGIN; 00153 00154 if(aspect < 1.0f) { 00155 margin_l= (int)((width - ((float)width * aspect)) / 2.0f); 00156 margin_l += MARGIN; 00157 CLAMP(margin_l, MARGIN, (width/2)); 00158 margin_r = width - margin_l; 00159 } 00160 else if (aspect > 1.0f) { 00161 margin_b= (int)((height - ((float)height / aspect)) / 2.0f); 00162 margin_b += MARGIN; 00163 CLAMP(margin_b, MARGIN, (height/2)); 00164 margin_t = height - margin_b; 00165 } 00166 00167 { 00168 int x, y; 00169 int stride_x= (margin_r - margin_l) - 2; 00170 00171 for(y=0; y < height; y++) { 00172 for(x=0; x < width; x++, px+=4) { 00173 int hline= 0, vline= 0; 00174 if((x > margin_l && x < margin_r) && (y > margin_b && y < margin_t)) { 00175 /* interior. skip */ 00176 x += stride_x; 00177 px += stride_x * 4; 00178 } else if( (hline=(((x == margin_l || x == margin_r)) && y >= margin_b && y <= margin_t)) || 00179 (vline=(((y == margin_b || y == margin_t)) && x >= margin_l && x <= margin_r)) 00180 ) { 00181 /* dashed line */ 00182 if((hline && y % 2) || (vline && x % 2)) { 00183 px[0]= px[1]= px[2]= 0; 00184 px[3] = 255; 00185 } 00186 } 00187 else { 00188 /* outside, fill in alpha, like passepartout */ 00189 px[0] *= 0.5f; 00190 px[1] *= 0.5f; 00191 px[2] *= 0.5f; 00192 px[3] = (px[3] * 0.5f) + 96; 00193 } 00194 } 00195 } 00196 } 00197 }