From f22644997eaf4439cde7c84e5cf7a96578a2f691 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= <gambas@users.sourceforge.net>
Date: Mon, 26 Jan 2009 17:42:53 +0000
Subject: [PATCH] [GB.GTK] * BUG: Define the default image format when the
 gb.gtk component is used. * BUG: Image.Load() does not crash anymore.

[GB.IMAGE]
* BUG: Sometimes the conversion between formats was not done. That was
  fixed.


git-svn-id: svn://localhost/gambas/trunk@1819 867c0c6c-44f3-4631-809d-bfa615b0a4ec
---
 gb.gtk/src/CImage.cpp  |  2 +-
 gb.gtk/src/main.cpp    |  1 +
 main/lib/image/image.c | 69 ++++++++++++++++++++++++++++++++++++------
 3 files changed, 61 insertions(+), 11 deletions(-)

diff --git a/gb.gtk/src/CImage.cpp b/gb.gtk/src/CImage.cpp
index 1abf01105..e8182bd7b 100644
--- a/gb.gtk/src/CImage.cpp
+++ b/gb.gtk/src/CImage.cpp
@@ -176,7 +176,7 @@ BEGIN_METHOD(CIMAGE_load, GB_STRING path)
 		if (pic)
 		{
 			image = CIMAGE_create(pic);
-			PICTURE->getPixbuf();
+			pic->getPixbuf();
 			GB.ReturnObject(image);
 			return;
 		}
diff --git a/gb.gtk/src/main.cpp b/gb.gtk/src/main.cpp
index 456f5e14b..95e33876a 100644
--- a/gb.gtk/src/main.cpp
+++ b/gb.gtk/src/main.cpp
@@ -230,6 +230,7 @@ extern "C"
 
 		GB.LoadComponent("gb.draw");
 		GB.GetInterface("gb.image", IMAGE_INTERFACE_VERSION, &IMAGE);
+		IMAGE.SetDefaultFormat(GB_IMAGE_RGBA);
 
 		return TRUE;
 	}
diff --git a/main/lib/image/image.c b/main/lib/image/image.c
index 0e69438dc..bf37a312c 100644
--- a/main/lib/image/image.c
+++ b/main/lib/image/image.c
@@ -24,6 +24,8 @@
 
 #include "image.h"
 
+//#define DEBUG_CONVERT
+
 static int _default_format = GB_IMAGE_RGBA;
 
 static inline unsigned char *GET_END_POINTER(GB_IMG *image)
@@ -34,6 +36,12 @@ static inline unsigned char *GET_END_POINTER(GB_IMG *image)
 static inline uint PREMUL(uint x) 
 {
 	uint a = x >> 24;
+	
+	if (a == 0)
+		return 0;
+	else if (a == 0xFF)
+		return x;
+	
 	uint t = (x & 0xff00ff) * a;
 	t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
 	t &= 0xff00ff;
@@ -47,12 +55,16 @@ static inline uint PREMUL(uint x)
 
 static inline uint INV_PREMUL(uint p)
 {
+	if (ALPHA(p) == 0)
+		return 0;
+	else if (ALPHA(p) == 0xFF)
+		return p;
+	else
 	return
-		(ALPHA(p) == 0 ? 0 :
 		((ALPHA(p) << 24)
 		| (((255*RED(p))/ ALPHA(p)) << 16)
 		| (((255*GREEN(p)) / ALPHA(p)) << 8)
-		| ((255*BLUE(p)) / ALPHA(p))));
+		| ((255*BLUE(p)) / ALPHA(p)));
 }
 
 static inline uint SWAP(uint p)
@@ -120,7 +132,8 @@ static void free_image(GB_IMG *img, void *image)
 static GB_IMG_OWNER _image_owner = {
 	"gb.image",
 	free_image,
-	free_image
+	free_image,
+	NULL
 	};
 
 
@@ -139,6 +152,10 @@ static void convert_image(uchar *dst, int dst_format, uchar *src, int src_format
 	uint *p, *pm;
 	bool psrc, pdst;
 
+	#ifdef DEBUG_CONVERT
+	fprintf(stderr, "convert_image: src_format = %d dst_format = %d\n", src_format, dst_format);
+	#endif
+
 	len = w * h * sizeof(uint);
 	dm = &d[len];
 
@@ -148,6 +165,10 @@ static void convert_image(uchar *dst, int dst_format, uchar *src, int src_format
 	pdst = GB_IMAGE_FMT_IS_PREMULTIPLIED(dst_format);
 	dst_format = GB_IMAGE_FMT_CLEAR_PREMULTIPLIED(dst_format);
 
+	#ifdef DEBUG_CONVERT
+	fprintf(stderr, "convert_image: after: src_format = %d dst_format = %d\n", src_format, dst_format);
+	#endif
+
   if (dst_format == GB_IMAGE_BGRA || dst_format == GB_IMAGE_BGRX)
   {
     switch (src_format)
@@ -197,11 +218,17 @@ static void convert_image(uchar *dst, int dst_format, uchar *src, int src_format
   
 __0123:         
 
+	#ifdef DEBUG_CONVERT
+	fprintf(stderr, "convert_image: 0123\n");
+	#endif
   memcpy(dst, src, len);
   goto __PREMULTIPLIED;
 
 __3210:
 
+	#ifdef DEBUG_CONVERT
+	fprintf(stderr, "convert_image: 3210\n");
+	#endif
   while (d != dm)
   {
     d[0] = s[3];
@@ -215,6 +242,10 @@ __3210:
 
 __2103:
 
+	#ifdef DEBUG_CONVERT
+	fprintf(stderr, "convert_image: 2103\n");
+	#endif
+
   while (d != dm)
   {
     d[0] = s[2];
@@ -228,6 +259,10 @@ __2103:
   
 __1230:
 
+	#ifdef DEBUG_CONVERT
+	fprintf(stderr, "convert_image: 1230\n");
+	#endif
+	
   while (d != dm)
   {
     d[0] = s[1];
@@ -241,6 +276,10 @@ __1230:
 
 __012X:
 
+	#ifdef DEBUG_CONVERT
+	fprintf(stderr, "convert_image: 012X\n");
+	#endif
+	
   while (d != dm)
   {
     d[0] = s[0];
@@ -254,6 +293,10 @@ __012X:
 
 __210X:
 
+	#ifdef DEBUG_CONVERT
+	fprintf(stderr, "convert_image: 210X\n");
+	#endif
+	
   while (d != dm)
   {
     d[0] = s[2];
@@ -275,6 +318,9 @@ __PREMULTIPLIED:
 	
 	if (psrc)
 	{
+		#ifdef DEBUG_CONVERT
+		fprintf(stderr, "convert_image: premultiplied -> normal\n");
+		#endif
 		// convert premultiplied to normal
 		while (p != pm)
 		{
@@ -284,6 +330,9 @@ __PREMULTIPLIED:
 	}
 	else
 	{
+		#ifdef DEBUG_CONVERT
+		fprintf(stderr, "convert_image: normal -> premultiplied\n");
+		#endif
 		// convert normal to premultiplied
 		while (p != pm)
 		{
@@ -314,6 +363,7 @@ void IMAGE_create(GB_IMG *img, int width, int height, int format)
 	img->format = format;
 	GB.Alloc(POINTER(&img->data), IMAGE_size(img));
 	img->owner = &_image_owner;
+	img->owner_handle = img->data;
 }
 
 void IMAGE_create_with_data(GB_IMG *img, int width, int height, int format, unsigned char *data)
@@ -322,21 +372,20 @@ void IMAGE_create_with_data(GB_IMG *img, int width, int height, int format, unsi
 	memcpy(img->data, data, IMAGE_size(img));
 }
 
-static void IMAGE_convert(GB_IMG *img, int format)
+static void IMAGE_convert(GB_IMG *img, int dst_format)
 {
 	uchar *data;
+	int src_format = img->format;
 	
-	if (format == img->format)
+	if (src_format == dst_format)
 		return;
 	
-	//fprintf(stderr, "convert image %p: %d -> %d\n", img, img->format, format);
-	
 	//IMAGE_create(&tmp, img->width, img->height, format);
-	img->format = format;
+	img->format = dst_format;
 	GB.Alloc(POINTER(&data), IMAGE_size(img));
-	convert_image(data, format, img->data, img->format, img->width, img->height);
+	convert_image(data, dst_format, img->data, src_format, img->width, img->height);
 	//GB.Free(POINTER(&img->data));
-	IMAGE_take(img, &_image_owner, NULL, img->width, img->height, data);
+	IMAGE_take(img, &_image_owner, data, img->width, img->height, data);
 }
 
 // Check if a temporary handle is needed, and create it if needed by calling the owner "temp" function