Merging r43501 through r43720 form trunk into soc-2011-tomato
[blender.git] / source / blender / imbuf / intern / thumbs_blend.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Campbell Barton.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/imbuf/intern/thumbs_blend.c
24  *  \ingroup imbuf
25  */
26
27
28 #include <string.h>
29
30 #include "zlib.h"
31
32 #include "BLI_utildefines.h"
33
34 #include "BKE_utildefines.h"
35 #include "BKE_global.h"
36
37 #include "IMB_imbuf_types.h"
38 #include "IMB_imbuf.h"
39 #include "IMB_thumbs.h"
40
41 #include "MEM_guardedalloc.h"
42
43 /* extracts the thumbnail from between the 'REND' and the 'GLOB'
44  * chunks of the header, dont use typical blend loader because its too slow */
45
46 static ImBuf *loadblend_thumb(gzFile gzfile)
47 {
48         char buf[12];
49         int bhead[24/sizeof(int)]; /* max size on 64bit */
50         char endian, pointer_size;
51         char endian_switch;
52         int sizeof_bhead ;
53
54         /* read the blend file header */
55         if(gzread(gzfile, buf, 12) != 12)
56                 return NULL;
57         if(strncmp(buf, "BLENDER", 7))
58                 return NULL;
59
60         if(buf[7]=='-')
61                 pointer_size= 8;
62         else if(buf[7]=='_')
63                 pointer_size= 4;
64         else
65                 return NULL;
66
67         sizeof_bhead = 16 + pointer_size;
68
69         if(buf[8]=='V')
70                 endian= B_ENDIAN; /* big: PPC */
71         else if(buf[8]=='v')
72                 endian= L_ENDIAN; /* little: x86 */
73         else
74                 return NULL;
75
76         endian_switch = ((ENDIAN_ORDER != endian)) ? 1 : 0;
77
78         while(gzread(gzfile, bhead, sizeof_bhead) == sizeof_bhead) {
79                 if(endian_switch)
80                         SWITCH_INT(bhead[1]); /* length */
81
82                 if (bhead[0]==REND) {
83                         gzseek(gzfile, bhead[1], SEEK_CUR); /* skip to the next */
84                 }
85                 else {
86                         break;
87                 }
88         }
89
90         /* using 'TEST' since new names segfault when loading in old blenders */
91         if(bhead[0] == TEST) {
92                 ImBuf *img= NULL;
93                 int size[2];
94
95                 if(gzread(gzfile, size, sizeof(size)) != sizeof(size))
96                         return NULL;
97
98                 if(endian_switch) {
99                         SWITCH_INT(size[0]);
100                         SWITCH_INT(size[1]);
101                 }
102                 /* length */
103                 bhead[1] -= sizeof(int) * 2;
104
105                 /* inconsistent image size, quit early */
106                 if(bhead[1] != size[0] * size[1] * sizeof(int))
107                         return NULL;
108         
109                 /* finally malloc and read the data */
110                 img= IMB_allocImBuf(size[0], size[1], 32, IB_rect | IB_metadata);
111         
112                 if(gzread(gzfile, img->rect, bhead[1]) != bhead[1]) {
113                         IMB_freeImBuf(img);
114                         img= NULL;
115                 }
116         
117                 return img;
118         }
119         
120         return NULL;
121 }
122
123 ImBuf *IMB_loadblend_thumb(const char *path)
124 {
125         gzFile gzfile;
126
127         /* not necessarily a gzip */
128         gzfile = gzopen(path, "rb");
129
130         if (NULL == gzfile ) {
131                 return NULL;
132         }
133         else {
134                 ImBuf *img= loadblend_thumb(gzfile);
135
136                 /* read ok! */
137                 gzclose(gzfile);
138
139                 return img;
140         }
141 }
142
143 /* add a fake passepartout overlay to a byte buffer, use for blend file thumbnails */
144 #define MARGIN 2
145
146 void IMB_overlayblend_thumb(unsigned int *thumb, int width, int height, float aspect)
147 {
148         unsigned char *px= (unsigned char *)thumb;
149         int margin_l = MARGIN;
150         int margin_b = MARGIN;
151         int margin_r = width - MARGIN;
152         int margin_t = height - MARGIN;
153
154         if(aspect < 1.0f) {
155                 margin_l= (int)((width - ((float)width * aspect)) / 2.0f);
156                 margin_l += MARGIN;
157                 CLAMP(margin_l, MARGIN, (width/2));
158                 margin_r = width - margin_l;
159         }
160         else if (aspect > 1.0f) {
161                 margin_b= (int)((height - ((float)height / aspect)) / 2.0f);
162                 margin_b += MARGIN;
163                 CLAMP(margin_b, MARGIN, (height/2));
164                 margin_t = height - margin_b;
165         }
166
167         {       
168                 int x, y;
169                 int stride_x= (margin_r - margin_l) - 2;
170                 
171                 for(y=0; y < height; y++) {
172                         for(x=0; x < width; x++, px+=4) {
173                                 int hline= 0, vline= 0;
174                                 if((x > margin_l && x < margin_r) && (y > margin_b && y < margin_t)) {
175                                         /* interior. skip */
176                                         x  += stride_x;
177                                         px += stride_x * 4;
178                                 } else if(      (hline=(((x == margin_l || x == margin_r)) && y >= margin_b && y <= margin_t)) ||
179                                                         (vline=(((y == margin_b || y == margin_t)) && x >= margin_l && x <= margin_r))
180                                 ) {
181                                         /* dashed line */
182                                         if((hline && y % 2) || (vline && x % 2)) {
183                                                 px[0]= px[1]= px[2]= 0;
184                                                 px[3] = 255;
185                                         }
186                                 }
187                                 else {
188                                         /* outside, fill in alpha, like passepartout */
189                                         px[0] *= 0.5f;
190                                         px[1] *= 0.5f;
191                                         px[2] *= 0.5f;
192                                         px[3] = (px[3] * 0.5f) + 96;
193                                 }
194                         }
195                 }
196         }
197 }