diff options
Diffstat (limited to 'src/im_image.cpp')
-rw-r--r-- | src/im_image.cpp | 210 |
1 files changed, 178 insertions, 32 deletions
diff --git a/src/im_image.cpp b/src/im_image.cpp index 7acae43..80553a7 100644 --- a/src/im_image.cpp +++ b/src/im_image.cpp @@ -2,7 +2,7 @@ * \brief Image Manipulation * * See Copyright Notice in im_lib.h - * $Id: im_image.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + * $Id: im_image.cpp,v 1.2 2009/08/12 04:09:16 scuri Exp $ */ #include <stdlib.h> @@ -15,6 +15,7 @@ #include "im_util.h" #include "im_attrib.h" #include "im_file.h" +#include "im_convert.h" int imImageCheckFormat(int color_mode, int data_type) @@ -52,7 +53,7 @@ int imImageLineSize(int width, int color_mode, int data_type) return imImageLineCount(width, color_mode) * imDataTypeSize(data_type); } -static void iImageInit(imImage* image, int width, int height, int color_space, int data_type) +static void iImageInit(imImage* image, int width, int height, int color_space, int data_type, int has_alpha) { assert(width>0); assert(height>0); @@ -63,7 +64,7 @@ static void iImageInit(imImage* image, int width, int height, int color_space, i image->height = height; image->color_space = color_space; image->data_type = data_type; - image->has_alpha = 0; + image->has_alpha = has_alpha; image->depth = imColorModeDepth(color_space); image->line_size = image->width * imDataTypeSize(data_type); @@ -71,15 +72,20 @@ static void iImageInit(imImage* image, int width, int height, int color_space, i image->size = image->plane_size * image->depth; image->count = image->width * image->height; + int depth = image->depth+1; // add room for an alpha plane pointer, even if does not have alpha now. + if (image->data) { + /* if reallocating, preserve the data buffer */ void* data0 = image->data[0]; + free(image->data); - image->data = (void**)malloc((image->depth+1) * sizeof(void*)); // add room for alpha + image->data = (void**)malloc(depth * sizeof(void*)); + image->data[0] = data0; } else - image->data = (void**)malloc((image->depth+1) * sizeof(void*)); + image->data = (void**)malloc(depth * sizeof(void*)); } imImage* imImageInit(int width, int height, int color_space, int data_type, void* data_buffer, long* palette, int palette_count) @@ -90,7 +96,7 @@ imImage* imImageInit(int width, int height, int color_space, int data_type, void imImage* image = (imImage*)malloc(sizeof(imImage)); image->data = 0; - iImageInit(image, width, height, color_space, data_type); + iImageInit(image, width, height, color_space, data_type, 0); if (data_buffer) { @@ -119,6 +125,7 @@ imImage* imImageCreate(int width, int height, int color_space, int data_type) imImage* image = imImageInit(width, height, color_space, data_type, NULL, NULL, 0); if (!image) return NULL; + /* palette is available to BINARY, MAP and GRAY */ if (imColorModeDepth(color_space) == 1) { image->palette = (long*)malloc(256*sizeof(long)); @@ -137,6 +144,7 @@ imImage* imImageCreate(int width, int height, int color_space, int data_type) } } + /* allocate data buffer */ image->data[0] = malloc(image->size); if (!image->data[0]) { @@ -144,29 +152,11 @@ imImage* imImageCreate(int width, int height, int color_space, int data_type) return NULL; } + /* initialize data plane pointers */ for (int d = 1; d < image->depth; d++) image->data[d] = (imbyte*)(image->data[0]) + d*image->plane_size; - if ((image->color_space == IM_YCBCR || image->color_space == IM_LAB || image->color_space == IM_LUV) && - (image->data_type == IM_BYTE || image->data_type == IM_USHORT)) - { - memset(image->data[0], 0, image->plane_size); - - if (image->data_type == IM_BYTE) - { - imbyte* usdata = (imbyte*)image->data[1]; - for (int i = 0; i < 2*image->count; i++) - *usdata++ = 128; - } - else - { - imushort* usdata = (imushort*)image->data[1]; - for (int i = 0; i < 2*image->count; i++) - *usdata++ = 32768; - } - } - else - memset(image->data[0], 0, image->size); + imImageClear(image); return image; } @@ -182,6 +172,10 @@ imImage* imImageCreateBased(const imImage* image, int width, int height, int col imImage* new_image = imImageCreate(width, height, color_space, data_type); imImageCopyAttributes(image, new_image); + + if (image->has_alpha) + imImageAddAlpha(new_image); + return new_image; } @@ -213,21 +207,19 @@ void imImageReshape(imImage* image, int width, int height) old_width = width, old_height = height; - iImageInit(image, width, height, image->color_space, image->data_type); + iImageInit(image, width, height, image->color_space, image->data_type, image->has_alpha); if (old_size < image->size) { void* data0 = realloc(image->data[0], image->has_alpha? image->size+image->plane_size: image->size); if (!data0) // if failed restore the previous size - iImageInit(image, old_width, old_height, image->color_space, image->data_type); + iImageInit(image, old_width, old_height, image->color_space, image->data_type, image->has_alpha); else image->data[0] = data0; } - memset(image->data[0], 0, image->has_alpha? image->size+image->plane_size: image->size); - + /* initialize data plane pointers */ int depth = image->has_alpha? image->depth+1: image->depth; - for (int d = 1; d < depth; d++) image->data[d] = (imbyte*)image->data[0] + d*image->plane_size; } @@ -256,7 +248,30 @@ void imImageDestroy(imImage* image) void imImageClear(imImage* image) { assert(image); - memset(image->data[0], 0, image->has_alpha? image->size+image->plane_size: image->size); + + if ((image->color_space == IM_YCBCR || image->color_space == IM_LAB || image->color_space == IM_LUV) && + (image->data_type == IM_BYTE || image->data_type == IM_USHORT)) + { + memset(image->data[0], 0, image->plane_size); + + if (image->data_type == IM_BYTE) + { + imbyte* usdata = (imbyte*)image->data[1]; + for (int i = 0; i < 2*image->count; i++) + *usdata++ = 128; + } + else + { + imushort* usdata = (imushort*)image->data[1]; + for (int i = 0; i < 2*image->count; i++) + *usdata++ = 32768; + } + } + else + memset(image->data[0], 0, image->size); + + if (image->has_alpha) + memset(image->data[image->depth], 0, image->plane_size); } int imImageIsBitmap(const imImage* image) @@ -320,6 +335,124 @@ imImage* imImageClone(const imImage* image) return new_image; } +static void iImageMakeGray(imbyte *map, int count, int step) +{ + for(int i = 0; i < count; i++) + { + if (*map) + *map = 255; + map += step; + } +} + +static void iImageCopyMapAlpha(imbyte *map, imbyte *gldata, int depth, int count) +{ + gldata += depth-1; /* position at first alpha */ + for(int i = 0; i < count; i++) + { + *gldata = *map; + map++; + gldata += depth; /* skip to next alpha */ + } +} + +static void iImageExpandTranspIndex(imbyte *map, imbyte *gldata, int depth, int count, imbyte index) +{ + gldata += depth-1; /* position at first alpha */ + for(int i = 0; i < count; i++) + { + if (*map == index) + *gldata = 255; + + map++; + gldata += depth; /* skip to next alpha */ + } +} + +/* To avoid including gl.h */ +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A + +void* imImageGetOpenGLData(imImage* image, int *format) +{ + if (!imImageIsBitmap(image)) + return NULL; + + int transp_count; + imbyte* transp_index = (imbyte*)imImageGetAttribute(image, "TransparencyIndex", NULL, &transp_count); + + int glformat; + switch(image->color_space) + { + case IM_MAP: + if (image->has_alpha || transp_index) + glformat = GL_RGBA; + else + glformat = GL_RGB; + break; + case IM_RGB: + if (image->has_alpha) + glformat = GL_RGBA; + else + glformat = GL_RGB; + break; + case IM_BINARY: + default: /* IM_GRAY */ + if (image->has_alpha || transp_index) + glformat = GL_LUMINANCE_ALPHA; + else + glformat = GL_LUMINANCE; + break; + } + + int depth; + switch (glformat) + { + case GL_RGB: + depth = 3; + break; + case GL_RGBA: + depth = 4; + break; + case GL_LUMINANCE_ALPHA: + depth = 2; + break; + default: /* GL_LUMINANCE */ + depth = 1; + break; + } + + int size = image->count*depth; + imImageSetAttribute(image, "GLDATA", IM_BYTE, size, NULL); + imbyte* gldata = (imbyte*)imImageGetAttribute(image, "GLDATA", NULL, NULL); + + if (image->color_space == IM_RGB) + imConvertPacking(image->data[0], gldata, image->width, image->height, depth, IM_BYTE, 0); + else + { + memcpy(gldata, image->data[0], image->size); + + if (image->color_space == IM_MAP) + imConvertMapToRGB(gldata, image->count, depth, 1, image->palette, image->palette_count); + else if (image->color_space == IM_BINARY) + iImageMakeGray(gldata, image->count, (glformat==GL_LUMINANCE_ALPHA)? 2: 1); + + if (image->has_alpha) + iImageCopyMapAlpha((imbyte*)image->data[1], gldata, depth, image->count); + else if (transp_index) + { + int i; + for (i=0; i<transp_count; i++) + iImageExpandTranspIndex((imbyte*)image->data[0], gldata, depth, image->count, transp_index[i]); + } + } + + if (format) *format = glformat; + return gldata; +} + void imImageSetAttribute(imImage* image, const char* attrib, int data_type, int count, const void* data) { assert(image); @@ -474,6 +607,19 @@ void imImageMakeBinary(imImage *image) } } +void imImageMakeGray(imImage *image) +{ + assert(image); + + imbyte *map = (imbyte*)image->data[0]; + for(int i = 0; i < image->count; i++) + { + if (*map) + *map = 255; + map++; + } +} + static void iImageGrayCheckChange(imImage *image) { int i, do_remap = 0; |