diff options
Diffstat (limited to 'source/blender/imbuf/intern/thumbs_blend.c')
-rw-r--r-- | source/blender/imbuf/intern/thumbs_blend.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c new file mode 100644 index 00000000000..7f1c903e9de --- /dev/null +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -0,0 +1,208 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <string.h> + +#include "zlib.h" + +#include "BKE_utildefines.h" +#include "BKE_global.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_thumbs.h" + +#include "MEM_guardedalloc.h" + +/* extracts the thumbnail from between the 'REND' and the 'GLOB' + * chunks of the header, dont use typical blend loader because its too slow */ + +static ImBuf *loadblend_thumb(gzFile gzfile) +{ + char buf[8]; + int code= 0; + char endian, pointer_size; + char endian_switch; + int len, im_len, x, y; + ImBuf *img= NULL; + + + /* read the blend file header */ + if(gzread(gzfile, buf, 8) != 8) + return NULL; + if(strncmp(buf, "BLENDER", 7)) + return NULL; + + if(buf[7]=='-') + pointer_size= 8; + else if(buf[7]=='_') + pointer_size= 4; + else + return NULL; + + /* read the next 4 bytes, only need the first char, ignore the version */ + /* endian and vertsion (ignored) */ + if(gzread(gzfile, buf, 4) != 4) + return NULL; + + if(buf[0]=='V') + endian= B_ENDIAN; /* big: PPC */ + else if(buf[0]=='v') + endian= L_ENDIAN; /* little: x86 */ + else + return NULL; + + while(gzread(gzfile, &code, sizeof(int)) == sizeof(int)) { + endian_switch = ((ENDIAN_ORDER != endian)) ? 1 : 0; + + if(gzread(gzfile, buf, sizeof(int)) != sizeof(int)) + return NULL; + + len = *( (int *)((void *)buf) ); + + if(endian_switch) + SWITCH_INT(len); + + /* finally read the rest of the bhead struct, pointer and 2 ints */ + if(gzread(gzfile, buf, pointer_size) != pointer_size) + return NULL; + if(gzread(gzfile, buf, sizeof(int) * 2) != sizeof(int) * 2) + return NULL; + + /* we dont actually care whats in the bhead */ + if (code==REND) { + gzseek(gzfile, len, SEEK_CUR); /* skip to the next */ + } + else { + break; + } + } + + /* using 'TEST' since new names segfault when loading in old blenders */ + if(code != TEST) + return NULL; + + if(gzread(gzfile, &x, sizeof(int)) != sizeof(int)) + return NULL; + if(gzread(gzfile, &y, sizeof(int)) != sizeof(int)) + return NULL; + + len -= sizeof(int) * 2; + + if(endian_switch) { + SWITCH_INT(x); + SWITCH_INT(y); + } + + /* inconsistant image size, quit early */ + im_len = x * y * sizeof(int); + if(im_len != len) + return NULL; + + /* finally malloc and read the data */ + img= IMB_allocImBuf(x, y, 32, IB_rect | IB_metadata, 0); + + if(gzread(gzfile, img->rect, len) != len) { + IMB_freeImBuf(img); + img= NULL; + } + + return img; +} + +ImBuf *IMB_loadblend_thumb(const char *path) +{ + gzFile gzfile; + + /* not necessarily a gzip */ + gzfile = gzopen(path, "rb"); + + if (NULL == gzfile ) { + return NULL; + } + else { + ImBuf *img= loadblend_thumb(gzfile); + + /* read ok! */ + gzclose(gzfile); + + return img; + } +} + +/* add a fake passepartout overlay to a byte buffer, use for blend file thumbnails */ +#define MARGIN 2 + +void IMB_overlayblend_thumb(unsigned int *thumb, int width, int height, float aspect) +{ + unsigned char *px= (unsigned char *)thumb; + int margin_l = MARGIN; + int margin_b = MARGIN; + int margin_r = width - MARGIN; + int margin_t = height - MARGIN; + + if(aspect < 1.0f) { + margin_l= (int)((width - ((float)width * aspect)) / 2.0f); + margin_l += MARGIN; + CLAMP(margin_l, MARGIN, (width/2)); + margin_r = width - margin_l; + } + else if (aspect > 1.0f) { + margin_b= (int)((height - ((float)height / aspect)) / 2.0f); + margin_b += MARGIN; + CLAMP(margin_b, MARGIN, (height/2)); + margin_t = height - margin_b; + } + + { + int x, y; + int hline, vline; + int stride_x= (margin_r - margin_l) - 2; + + for(y=0; y < height; y++) { + for(x=0; x < width; x++, px+=4) { + if((x > margin_l && x < margin_r) && (y > margin_b && y < margin_t)) { + /* interior. skip */ + x += stride_x; + px += stride_x * 4; + } else if( (hline=(((x == margin_l || x == margin_r)) && y >= margin_b && y <= margin_t)) || + (vline=(((y == margin_b || y == margin_t)) && x >= margin_l && x <= margin_r)) + ) { + /* dashed line */ + if((hline && y % 2) || (vline && x % 2)) { + px[0]= px[1]= px[2]= 0; + px[3] = 255; + } + } + else { + /* outside, fill in alpha, like passepartout */ + px[0] *= 0.5f; + px[1] *= 0.5f; + px[2] *= 0.5f; + px[3] = (px[3] * 0.5f) + 96; + } + } + } + } +} |