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