From 6700b4a603c6d0c4a198979b2d899b912d7c31e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= Date: Sat, 17 Jan 2009 01:11:36 +0000 Subject: [PATCH] [GB.IMAGE] * NEW: Put the Image.MakeTransparent() method in gb.image. * NEW: Compiles the image.c source file with full optimization. git-svn-id: svn://localhost/gambas/trunk@1804 867c0c6c-44f3-4631-809d-bfa615b0a4ec --- gb.qt/src/CImage.cpp | 115 -------------------------------- main/lib/image/CImage.c | 7 ++ main/lib/image/Makefile.am | 4 ++ main/lib/image/image.c | 133 +++++++++++++++++++++++++++++++++++-- 4 files changed, 138 insertions(+), 121 deletions(-) diff --git a/gb.qt/src/CImage.cpp b/gb.qt/src/CImage.cpp index 5f9dc0b65..56e4008d0 100644 --- a/gb.qt/src/CImage.cpp +++ b/gb.qt/src/CImage.cpp @@ -349,119 +349,6 @@ BEGIN_METHOD(CIMAGE_draw, GB_OBJECT img; GB_INTEGER x; GB_INTEGER y; GB_INTEGER END_METHOD -// Comes from the GIMP - -typedef - struct { - float r; - float b; - float g; - float a; - } - RGB; - -static void color_to_alpha(RGB *src, const RGB *color) -{ - RGB alpha; - - alpha.a = src->a; - - if (color->r < 0.0001) - alpha.r = src->r; - else if (src->r > color->r) - alpha.r = (src->r - color->r) / (1.0 - color->r); - else if (src->r < color->r) - alpha.r = (color->r - src->r) / color->r; - else alpha.r = 0.0; - - if (color->g < 0.0001) - alpha.g = src->g; - else if (src->g > color->g) - alpha.g = (src->g - color->g) / (1.0 - color->g); - else if (src->g < color->g) - alpha.g = (color->g - src->g) / (color->g); - else alpha.g = 0.0; - - if (color->b < 0.0001) - alpha.b = src->b; - else if (src->b > color->b) - alpha.b = (src->b - color->b) / (1.0 - color->b); - else if (src->b < color->b) - alpha.b = (color->b - src->b) / (color->b); - else alpha.b = 0.0; - - if (alpha.r > alpha.g) - { - if (alpha.r > alpha.b) - { - src->a = alpha.r; - } - else - { - src->a = alpha.b; - } - } - else if (alpha.g > alpha.b) - { - src->a = alpha.g; - } - else - { - src->a = alpha.b; - } - - if (src->a < 0.0001) - return; - - src->r = (src->r - color->r) / src->a + color->r; - src->g = (src->g - color->g) / src->a + color->g; - src->b = (src->b - color->b) / src->a + color->b; - - src->a *= alpha.a; -} - -BEGIN_METHOD(CIMAGE_make_transparent, GB_INTEGER color) - - check_image(THIS); - - QImage *img = QIMAGE; - uchar *b = img->bits(); - uchar *g = b + 1; - uchar *r = b + 2; - uchar *a = b + 3; - uchar *end = img->bits() + img->numBytes(); - uint color = VARGOPT(color, 0xFFFFFFL); - RGB rgb_color; - RGB rgb_src; - - rgb_color.b = (color & 0xFF) / 255.0; - rgb_color.g = ((color >> 8) & 0xFF) / 255.0; - rgb_color.r = ((color >> 16) & 0xFF) / 255.0; - rgb_color.a = 1.0; - - while (b != end) - { - rgb_src.b = *b / 255.0; - rgb_src.g = *g / 255.0; - rgb_src.r = *r / 255.0; - rgb_src.a = *a / 255.0; - - color_to_alpha(&rgb_src, &rgb_color); - - *b = 255.0 * rgb_src.b + 0.5; - *g = 255.0 * rgb_src.g + 0.5; - *r = 255.0 * rgb_src.r + 0.5; - *a = 255.0 * rgb_src.a + 0.5; - - b += 4; - g += 4; - r += 4; - a += 4; - } - -END_METHOD - - GB_DESC CImageDesc[] = { @@ -471,8 +358,6 @@ GB_DESC CImageDesc[] = GB_METHOD("Save", NULL, CIMAGE_save, "(Path)s[(Quality)i]"), GB_METHOD("Resize", NULL, CIMAGE_resize, "(Width)i(Height)i"), - GB_METHOD("MakeTransparent", NULL, CIMAGE_make_transparent, "[(Color)i]"), - GB_METHOD("Copy", "Image", CIMAGE_copy, "[(X)i(Y)i(Width)i(Height)i]"), GB_METHOD("Stretch", "Image", CIMAGE_stretch, "(Width)i(Height)i[(Smooth)b]"), GB_METHOD("Flip", "Image", CIMAGE_flip, NULL), diff --git a/main/lib/image/CImage.c b/main/lib/image/CImage.c index 01a6c6e4c..b6a517dbb 100644 --- a/main/lib/image/CImage.c +++ b/main/lib/image/CImage.c @@ -103,6 +103,12 @@ BEGIN_METHOD(CIMAGE_replace, GB_INTEGER src; GB_INTEGER dst; GB_BOOLEAN noteq) END_METHOD +BEGIN_METHOD(CIMAGE_make_transparent, GB_INTEGER color) + + IMAGE_make_transparent(THIS_IMAGE, VARGOPT(color, 0xFFFFFF)); + +END_METHOD + GB_DESC CImageDesc[] = { GB_DECLARE("Image", sizeof(CIMAGE)), @@ -127,6 +133,7 @@ GB_DESC CImageDesc[] = GB_METHOD("Clear", NULL, CIMAGE_clear, NULL), GB_METHOD("Fill", NULL, CIMAGE_fill, "(Color)i"), GB_METHOD("MakeGray", NULL, CIMAGE_make_gray, NULL), + GB_METHOD("MakeTransparent", NULL, CIMAGE_make_transparent, "[(Color)i]"), GB_METHOD("Replace", NULL, CIMAGE_replace, "(OldColor)i(NewColor)i[(NotEqual)b]"), GB_END_DECLARE diff --git a/main/lib/image/Makefile.am b/main/lib/image/Makefile.am index 9372ca17a..0bfede1ec 100644 --- a/main/lib/image/Makefile.am +++ b/main/lib/image/Makefile.am @@ -16,4 +16,8 @@ gb_image_la_SOURCES = \ gb.image.h \ main.h main.c +image.lo: image.c + $(LTCOMPILE) -O3 $(CFLAGS) -MT image.o -MD -MP -MF $(DEPDIR)/image.Tpo -c -o image.o image.c + mv -f $(DEPDIR)/image.Tpo $(DEPDIR)/image.Po + diff --git a/main/lib/image/image.c b/main/lib/image/image.c index 1bafd04d0..98e938f5f 100644 --- a/main/lib/image/image.c +++ b/main/lib/image/image.c @@ -77,6 +77,24 @@ static GB_COLOR to_GB_COLOR(uint col, int format) return col ^ 0xFF000000; } +static inline uint BGRA_to_format(uint col, int format) +{ + if (GB_IMAGE_FMT_IS_PREMULTIPLIED(format)) + col = PREMUL(col); + if (GB_IMAGE_FMT_IS_SWAPPED(format)) + col = SWAP(col); + return col; +} + +static inline uint BGRA_from_format(uint col, int format) +{ + if (GB_IMAGE_FMT_IS_SWAPPED(format)) + col = SWAP(col); + if (GB_IMAGE_FMT_IS_PREMULTIPLIED(format)) + col = INV_PREMUL(col); + return col; +} + static inline bool is_valid(GB_IMG *img, int x, int y) { return !(x >= img->width || y >= img->height || x < 0 || y < 0); @@ -259,8 +277,6 @@ int IMAGE_size(GB_IMG *img) void IMAGE_create(GB_IMG *img, int width, int height, int format) { - int size; - if (width <= 0 || height <= 0) { GB_BASE save = img->ob; @@ -403,10 +419,6 @@ void IMAGE_make_gray(GB_IMG *img) } } -void IMAGE_make_transparent(GB_IMG *img, GB_COLOR color) -{ -} - GB_COLOR IMAGE_get_pixel(GB_IMG *img, int x, int y) { uint col; @@ -455,3 +467,112 @@ void IMAGE_replace(GB_IMG *img, GB_COLOR src, GB_COLOR dst, bool noteq) } } +// Comes from the GIMP + +typedef + struct { + float r; + float b; + float g; + float a; + } + FLOAT_RGB; + +static void color_to_alpha(FLOAT_RGB *src, const FLOAT_RGB *color) +{ + FLOAT_RGB alpha; + + alpha.a = src->a; + + if (color->r < 0.0001) + alpha.r = src->r; + else if (src->r > color->r) + alpha.r = (src->r - color->r) / (1.0 - color->r); + else if (src->r < color->r) + alpha.r = (color->r - src->r) / color->r; + else alpha.r = 0.0; + + if (color->g < 0.0001) + alpha.g = src->g; + else if (src->g > color->g) + alpha.g = (src->g - color->g) / (1.0 - color->g); + else if (src->g < color->g) + alpha.g = (color->g - src->g) / (color->g); + else alpha.g = 0.0; + + if (color->b < 0.0001) + alpha.b = src->b; + else if (src->b > color->b) + alpha.b = (src->b - color->b) / (1.0 - color->b); + else if (src->b < color->b) + alpha.b = (color->b - src->b) / (color->b); + else alpha.b = 0.0; + + if (alpha.r > alpha.g) + { + if (alpha.r > alpha.b) + { + src->a = alpha.r; + } + else + { + src->a = alpha.b; + } + } + else if (alpha.g > alpha.b) + { + src->a = alpha.g; + } + else + { + src->a = alpha.b; + } + + if (src->a < 0.0001) + return; + + src->r = (src->r - color->r) / src->a + color->r; + src->g = (src->g - color->g) / src->a + color->g; + src->b = (src->b - color->b) / src->a + color->b; + + src->a *= alpha.a; +} + +void IMAGE_make_transparent(GB_IMG *img, GB_COLOR col) +{ + uint *p = (uint *)img->data; + uint *pm = (uint *)(img->data + IMAGE_size(img)); + uint color; + FLOAT_RGB rgb_color; + FLOAT_RGB rgb_src; + + color = from_GB_COLOR(col, img->format); + rgb_color.b = BLUE(color) / 255.0; + rgb_color.g = GREEN(color) / 255.0; + rgb_color.r = RED(color) / 255.0; + rgb_color.a = 1.0; + + while (p != pm) + { + color = BGRA_from_format(*p, img->format); + rgb_src.b = BLUE(color) / 255.0; + rgb_src.g = GREEN(color) / 255.0; + rgb_src.r = RED(color) / 255.0; + rgb_src.a = ALPHA(color) / 255.0; + + color_to_alpha(&rgb_src, &rgb_color); + + color = RGBA( + (unsigned char)(255.0 * rgb_src.r + 0.5), + (unsigned char)(255.0 * rgb_src.g + 0.5), + (unsigned char)(255.0 * rgb_src.b + 0.5), + (unsigned char)(255.0 * rgb_src.a + 0.5) + ); + + *p = BGRA_to_format(color, img->format); + p++; + } +} + + +