summaryrefslogtreecommitdiff
path: root/src/im_image.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/im_image.cpp')
-rw-r--r--src/im_image.cpp210
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;