diff --git a/src/lib/Evas.h b/src/lib/Evas.h index 18864ce..a56fd92 100644 --- a/src/lib/Evas.h +++ b/src/lib/Evas.h @@ -478,6 +478,7 @@ extern "C" { EAPI void evas_object_image_size_get (Evas_Object *obj, int *w, int *h); EAPI int evas_object_image_stride_get (Evas_Object *obj); EAPI int evas_object_image_load_error_get (Evas_Object *obj); + EAPI void *evas_object_image_data_convert (Evas_Object *obj, Evas_Colorspace to_cspace); EAPI void evas_object_image_data_set (Evas_Object *obj, void *data); EAPI void *evas_object_image_data_get (Evas_Object *obj, Evas_Bool for_writing); EAPI void evas_object_image_data_copy_set (Evas_Object *obj, void *data); diff --git a/src/lib/canvas/evas_object_image.c b/src/lib/canvas/evas_object_image.c index 6a8df55..92b0651 100644 --- a/src/lib/canvas/evas_object_image.c +++ b/src/lib/canvas/evas_object_image.c @@ -69,6 +69,8 @@ static int evas_object_image_is_opaque(Evas_Object *obj); static int evas_object_image_was_opaque(Evas_Object *obj); static int evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y); +static void *evas_object_image_data_convert_internal(Evas_Object_Image *o, void *data, Evas_Colorspace to_cspace); + static const Evas_Object_Func object_func = { /* methods (compulsory) */ @@ -708,6 +710,46 @@ evas_object_image_load_error_get(Evas_Object *obj) */ /** + * Converts the raw image data of the given image object to the + * specified colorspace. + * + * Note that this function does not modify the raw image data. + * If the requested colorspace is the same as the image colorspace + * nothing is done and NULL is returned. You should use + * evas_object_image_colorspace_get() to check the current image + * colorspace. + * + * See @ref evas_object_image_colorspace_get. + * + * @param obj The given image object. + * @param to_cspace The colorspace to which the image raw data will be converted. + * @return data A newly allocated data in the format specified by to_cspace. + * @ingroup Evas_Object_Image_Data + */ +EAPI void * +evas_object_image_data_convert(Evas_Object *obj, Evas_Colorspace to_cspace) +{ + Evas_Object_Image *o; + DATA32 *data; + + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return NULL; + MAGIC_CHECK_END(); + o = (Evas_Object_Image *)(obj->object_data); + MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE); + return NULL; + MAGIC_CHECK_END(); + if (!o->engine_data) return NULL; + if (!o->cur.cspace == to_cspace) return NULL; + data = NULL; + o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output, + o->engine_data, + 0, + &data); + return evas_object_image_data_convert_internal(o, data, to_cspace); +} + +/** * Sets the raw image data of the given image object. * * Note that the raw data must be of the same size and colorspace @@ -1126,11 +1168,22 @@ evas_object_image_save(Evas_Object *obj, const char *file, const char *key, cons { if (o->cur.has_alpha) im->flags |= RGBA_IMAGE_HAS_ALPHA; - im->image->data = data; - im->image->w = o->cur.image.w; - im->image->h = o->cur.image.h; - im->image->no_free = 1; - ok = evas_common_save_image_to_file(im, file, key, quality, compress); + if (o->cur.cspace == EVAS_COLORSPACE_ARGB8888) + im->image->data = data; + else + im->image->data = evas_object_image_data_convert_internal(o, + data, + EVAS_COLORSPACE_ARGB8888); + if (im->image->data) + { + im->image->w = o->cur.image.w; + im->image->h = o->cur.image.h; + im->image->no_free = 1; + ok = evas_common_save_image_to_file(im, file, key, quality, compress); + + if (o->cur.cspace != EVAS_COLORSPACE_ARGB8888) + free(im->image->data); + } evas_cache_image_drop(im); } @@ -2376,3 +2429,36 @@ evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y) return (a != 0); } + +static void * +evas_object_image_data_convert_internal(Evas_Object_Image *o, void *data, Evas_Colorspace to_cspace) +{ + void *out = NULL; + + if (!data) + return NULL; + + switch (o->cur.cspace) + { + case EVAS_COLORSPACE_ARGB8888: + out = evas_common_convert_argb8888_to(data, + o->cur.image.w, + o->cur.image.h, + o->cur.image.stride, + o->cur.has_alpha, + to_cspace); + break; + case EVAS_COLORSPACE_RGB565_A5P: + out = evas_common_convert_rgb565_a5p_to(data, + o->cur.image.w, + o->cur.image.h, + o->cur.image.stride, + o->cur.has_alpha, + to_cspace); + break; + default: + break; + } + + return out; +} diff --git a/src/lib/engines/common/Makefile.am b/src/lib/engines/common/Makefile.am index c15675b..3d5fd7c 100644 --- a/src/lib/engines/common/Makefile.am +++ b/src/lib/engines/common/Makefile.am @@ -21,6 +21,7 @@ evas_op_mul_main_.c \ evas_blend_main.c \ evas_blit_main.c \ evas_convert_color.c \ +evas_convert_colorspace.c \ evas_convert_gry_1.c \ evas_convert_gry_4.c \ evas_convert_gry_8.c \ diff --git a/src/lib/engines/common/evas_convert_colorspace.c b/src/lib/engines/common/evas_convert_colorspace.c new file mode 100644 index 0000000..287bd2e --- /dev/null +++ b/src/lib/engines/common/evas_convert_colorspace.c @@ -0,0 +1,69 @@ +#include "evas_common.h" + +#define CONVERT_RGB_565_TO_RGB_888(s) \ + (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \ + ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \ + ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000))) + +#define CONVERT_A5P_TO_A8(s) \ + ((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) + +static inline void * +evas_common_convert_argb8888_to_rgb565_a5p(void *data, int w, int h, int stride, Evas_Bool has_alpha) +{ +} + +static inline void * +evas_common_convert_rgb565_a5p_to_argb8888(void *data, int w, int h, int stride, Evas_Bool has_alpha) +{ + DATA16 *src, *end; + DATA32 *ret, *dst; + int r, g, b; + + src = data; + end = src + (stride * h); + ret = malloc(w * h * sizeof(DATA32)); + + dst = ret; + if (has_alpha) + { + DATA8 *alpha; + + alpha = end; + for (; src < end; src++, alpha++, dst++) + *dst = (CONVERT_A5P_TO_A8(*alpha) << 24) | + CONVERT_RGB_565_TO_RGB_888(*src); + } + else + { + for (; src < end; src++, dst++) + *dst = CONVERT_RGB_565_TO_RGB_888(*src); + } + return ret; +} + +EAPI void * +evas_common_convert_argb8888_to(void *data, int w, int h, int stride, Evas_Bool has_alpha, Evas_Colorspace cspace) +{ + switch (cspace) + { + case EVAS_COLORSPACE_RGB565_A5P: + return evas_common_convert_argb8888_to_rgb565_a5p(data, w, h, stride, has_alpha); + default: + break; + } + return NULL; +} + +EAPI void * +evas_common_convert_rgb565_a5p_to(void *data, int w, int h, int stride, Evas_Bool has_alpha, Evas_Colorspace cspace) +{ + switch (cspace) + { + case EVAS_COLORSPACE_ARGB8888: + return evas_common_convert_rgb565_a5p_to_argb8888(data, w, h, stride, has_alpha); + default: + break; + } + return NULL; +} diff --git a/src/lib/include/evas_common.h b/src/lib/include/evas_common.h index a61ed6d..4c724b1 100644 --- a/src/lib/include/evas_common.h +++ b/src/lib/include/evas_common.h @@ -998,6 +998,9 @@ EAPI void evas_common_convert_color_rgb_to_hsv (int r, int g EAPI void evas_common_convert_color_hsv_to_rgb_int (int h, int s, int v, int *r, int *g, int *b); EAPI void evas_common_convert_color_rgb_to_hsv_int (int r, int g, int b, int *h, int *s, int *v); +EAPI void *evas_common_convert_argb8888_to (void *data, int w, int h, int stride, Evas_Bool has_alpha, Evas_Colorspace cspace); +EAPI void *evas_common_convert_rgb565_a5p_to (void *data, int w, int h, int stride, Evas_Bool has_alpha, Evas_Colorspace cspace); + /****/ EAPI void evas_common_scale_init (void);