efm2/src/backends/default/thumb_image.c

166 lines
4.9 KiB
C

// generate thumbnail for images
#include "thumb.h"
// XXX: can do progressive resize down ie scale to 512 then take 512 and
// halve to 256 then halve it to 128 etc. rather than render from orig to
// target size....
static Evas_Object *im = NULL;
static Eina_Bool alpha = EINA_FALSE;
static int iw = 0, ih = 0;
static void
_thumb_image_setup(void)
{ // create and show image
im = evas_object_image_filled_add(evas_object_evas_get(subwin));
evas_object_show(im);
}
static void
_thumb_image_file_set(const char *file)
{ // set file to image, get size & alpha
evas_object_image_file_set(im, file, NULL);
evas_object_image_size_get(im, &iw, &ih);
alpha = evas_object_image_alpha_get(im);
}
static void
_thumb_image_hsv_sort_render(unsigned int *dst, int w, int h)
{ // render image down to a specific size (small) and copy to dest
void *pixels;
evas_object_resize(im, w, h);
evas_object_resize(subwin, w, h);
elm_win_render(subwin);
pixels = evas_object_image_data_get(image, EINA_FALSE);
if (!pixels) return;
memcpy(dst, pixels, w * h * sizeof(int));
evas_object_image_data_set(image, pixels);
}
static void
_thumb_image_hsv_sort_key_write(Eet_File *ef, const char *key)
{ // get rendered pixels from image representing subwin and write out AHVS key
unsigned int *data4x4, *data2x2, *data1x1;
unsigned char id2[256];
int n, i, hi, si, vi;
float h, s, v;
const int pat2x2[4] = { 0, 3, 1, 2 };
const int pat4x4[16] = { 5, 10, 6, 9,
0, 15, 3, 12,
1, 14, 7, 8,
4, 11, 2, 13 };
data4x4 = malloc(4 * 4 * sizeof(int));
data2x2 = malloc(2 * 2 * sizeof(int));
data1x1 = malloc(1 * 1 * sizeof(int));
if ((!data4x4) || (!data2x2) || (!data1x1)) goto err;
_thumb_image_hsv_sort_render(data4x4, 4, 4);
_thumb_image_hsv_sort_render(data2x2, 2, 2);
_thumb_image_hsv_sort_render(data1x1, 1, 1);
n = 0;
#define A(v) (((v) >> 24) & 0xff)
#define R(v) (((v) >> 16) & 0xff)
#define G(v) (((v) >> 8 ) & 0xff)
#define B(v) (((v) ) & 0xff)
#define HSV(p) do { \
evas_color_rgb_to_hsv(R(p), G(p), B(p), &h, &s, &v); \
hi = 20 * (h / 360.0); \
si = 20 * s; \
vi = 20 * v; \
if (si < 2) hi = 25; \
} while (0)
#define SAVEX(x) id2[n++] = 'a' + (x)
SAVEX(A(data1x1[0]));
for (i = 0; i < 4 ; i++) SAVEX(A(data2x2[pat2x2[i]]));
for (i = 0; i < 16; i++) SAVEX(A(data4x4[pat4x4[i]]));
#define STORE(val) \
HSV(data1x1[0]); \
SAVEX(val); \
for (i = 0; i < 4; i++) { \
HSV(data2x2[pat2x2[i]]); \
SAVEX(val); \
} \
for (i = 0; i < 16; i++) { \
HSV(data4x4[pat4x4[i]]); \
SAVEX(val); \
}
STORE(hi);
STORE(vi);
STORE(si);
id2[n++] = 0;
eet_write(ef, key, id2, n,
EET_COMPRESSION_NONE);
err:
free(data4x4);
free(data2x2);
free(data1x1);
}
int
thumb_image(Eet_File *ef, const char *path, const char *mime EINA_UNUSED, const char *thumb EINA_UNUSED)
{
const int sizes[] = { 512, 256, 128, 64, 32, 16, 0 };
int w, h, i;
char buf[128];
unsigned char a;
_thumb_image_setup();
// add filled image to then size accordingly
_thumb_image_file_set(path);
// if size is bunk - we can't load it...
if ((iw <= 0) || (ih < 0)) return 2;
// write a big 1024x1024 preview (but no larger than the original image)
w = iw; h = ih; scale(&w, &h, 1024, 1024, EINA_TRUE);
// resize to target size
evas_object_resize(im, w, h);
evas_object_resize(subwin, w, h);
// render our current state and pick up pixel results
elm_win_render(subwin);
// save out preview size
snprintf(buf, sizeof(buf), "image/preview");
thumb_image_write(ef, buf, image, alpha, EINA_TRUE);
snprintf(buf, sizeof(buf), "%i %i", w, h);
eet_write(ef, "image/preview/size", buf, strlen(buf) + 1,
EET_COMPRESSION_NONE);
// multiple thumb sizes so can load/pick the best one at runtime
for (i = 0; sizes[i] != 0; i++)
{
// scale down and keep aspect
w = iw; h = ih; scale(&w, &h, sizes[i], sizes[i], EINA_FALSE);
// resize to target size
evas_object_resize(im, w, h);
evas_object_resize(subwin, w, h);
// render our current state and pick up pixel results
elm_win_render(subwin);
// save out thumb size
snprintf(buf, sizeof(buf), "image/thumb/%i", sizes[i]);
thumb_image_write(ef, buf, image, alpha, EINA_TRUE);
}
_thumb_image_hsv_sort_key_write(ef, "image/sort_key");
// write original alpha flag
a = alpha;
if (alpha)
eet_write(ef, "orig/image/alpha", &a, 1,
EET_COMPRESSION_NONE);
// write original size
snprintf(buf, sizeof(buf), "%i %i", iw, ih);
eet_write(ef, "orig/image/size", buf, strlen(buf) + 1,
EET_COMPRESSION_NONE);
return 0;
}