Blender  V2.59
thumbs_blend.c
Go to the documentation of this file.
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 }