Blender V2.61 - r43446

thumbs_blend.c

Go to the documentation of this file.
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 }