Makes usage of those funcs much more clear, we even had mixed '!strcmp(foo, bar)' and 'strcmp(foo, bar) == 0' in several places...
199 lines
4.7 KiB
C
199 lines
4.7 KiB
C
/*
|
|
* ***** 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 *****
|
|
*/
|
|
|
|
/** \file blender/imbuf/intern/thumbs_blend.c
|
|
* \ingroup imbuf
|
|
*/
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include "zlib.h"
|
|
|
|
#include "BLI_utildefines.h"
|
|
#include "BLI_endian_switch.h"
|
|
#include "BLI_fileops.h"
|
|
|
|
#include "BLO_blend_defs.h"
|
|
|
|
#include "BKE_global.h"
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
#include "IMB_imbuf.h"
|
|
#include "IMB_thumbs.h"
|
|
|
|
/* extracts the thumbnail from between the 'REND' and the 'GLOB'
|
|
* chunks of the header, don't use typical blend loader because its too slow */
|
|
|
|
static ImBuf *loadblend_thumb(gzFile gzfile)
|
|
{
|
|
char buf[12];
|
|
int bhead[24 / sizeof(int)]; /* max size on 64bit */
|
|
char endian, pointer_size;
|
|
char endian_switch;
|
|
int sizeof_bhead;
|
|
|
|
/* read the blend file header */
|
|
if (gzread(gzfile, buf, 12) != 12)
|
|
return NULL;
|
|
if (!STREQLEN(buf, "BLENDER", 7))
|
|
return NULL;
|
|
|
|
if (buf[7] == '-')
|
|
pointer_size = 8;
|
|
else if (buf[7] == '_')
|
|
pointer_size = 4;
|
|
else
|
|
return NULL;
|
|
|
|
sizeof_bhead = 16 + pointer_size;
|
|
|
|
if (buf[8] == 'V')
|
|
endian = B_ENDIAN; /* big: PPC */
|
|
else if (buf[8] == 'v')
|
|
endian = L_ENDIAN; /* little: x86 */
|
|
else
|
|
return NULL;
|
|
|
|
endian_switch = ((ENDIAN_ORDER != endian)) ? 1 : 0;
|
|
|
|
while (gzread(gzfile, bhead, sizeof_bhead) == sizeof_bhead) {
|
|
if (endian_switch)
|
|
BLI_endian_switch_int32(&bhead[1]); /* length */
|
|
|
|
if (bhead[0] == REND) {
|
|
gzseek(gzfile, bhead[1], SEEK_CUR); /* skip to the next */
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* using 'TEST' since new names segfault when loading in old blenders */
|
|
if (bhead[0] == TEST) {
|
|
ImBuf *img = NULL;
|
|
int size[2];
|
|
|
|
if (gzread(gzfile, size, sizeof(size)) != sizeof(size))
|
|
return NULL;
|
|
|
|
if (endian_switch) {
|
|
BLI_endian_switch_int32(&size[0]);
|
|
BLI_endian_switch_int32(&size[1]);
|
|
}
|
|
/* length */
|
|
bhead[1] -= sizeof(int) * 2;
|
|
|
|
/* inconsistent image size, quit early */
|
|
if (bhead[1] != size[0] * size[1] * sizeof(int))
|
|
return NULL;
|
|
|
|
/* finally malloc and read the data */
|
|
img = IMB_allocImBuf(size[0], size[1], 32, IB_rect | IB_metadata);
|
|
|
|
if (gzread(gzfile, img->rect, bhead[1]) != bhead[1]) {
|
|
IMB_freeImBuf(img);
|
|
img = NULL;
|
|
}
|
|
|
|
return img;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ImBuf *IMB_loadblend_thumb(const char *path)
|
|
{
|
|
gzFile gzfile;
|
|
/* not necessarily a gzip */
|
|
gzfile = BLI_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 stride_x = (margin_r - margin_l) - 2;
|
|
|
|
for (y = 0; y < height; y++) {
|
|
for (x = 0; x < width; x++, px += 4) {
|
|
int hline = 0, vline = 0;
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|