Re: [gtk-list] Re: Image Libraries



On Tue, Feb 01, 2000 at 08:11:04PM -0800, Timothy M. Shead wrote:

> My concern with gdk-pixbuf is that it seems to wrap libart, which is
> drawing-oriented.  It may make sense to use its' interface as a
> starting point, however.  On that note, we should probably take this
> off the list ...  anyone who's interested in this topic is welcome
> to drop me a line directly.

Ok, but just for fun, I'm publishing my (ugly) patch, in case anyone
else is interested in hacking on gdk-pixbuf directly, or you want to
use this as a start.

Ciao,
-- 
David N. Welton, Developer, Linuxcare, Inc.
415.354.4878 x241 tel, 415.701.7457 fax
davidw@linuxcare.com, http://www.linuxcare.com/
Linuxcare. Support for the revolution.
diff -r -u /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-data.c gdk-pixbuf-0.5.0/gdk-pixbuf/gdk-pixbuf-data.c
--- /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-data.c	Thu Dec  2 12:44:41 1999
+++ gdk-pixbuf-0.5.0/gdk-pixbuf/gdk-pixbuf-data.c	Mon Jan 31 21:07:54 2000
@@ -67,3 +67,11 @@
 
 	return gdk_pixbuf_new_from_art_pixbuf (art_pixbuf);
 }
+
+GdkPixbuf *
+gdk_pixbuf_clone(GdkPixbuf *pixbuf)
+{    
+    g_assert(pixbuf != NULL);
+    g_assert(pixbuf->art_pixbuf != NULL);
+    return gdk_pixbuf_new_from_art_pixbuf (pixbuf->art_pixbuf);
+}
diff -r -u /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-io.c gdk-pixbuf-0.5.0/gdk-pixbuf/gdk-pixbuf-io.c
--- /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-io.c	Sat Jan  1 19:59:22 2000
+++ gdk-pixbuf-0.5.0/gdk-pixbuf/gdk-pixbuf-io.c	Tue Feb  1 17:20:11 2000
@@ -168,17 +168,17 @@
 
 
 GdkPixbufModule file_formats [] = {
-	{ "png",  pixbuf_check_png, NULL,  NULL, NULL, NULL, NULL, NULL },
-	{ "jpeg", pixbuf_check_jpeg, NULL, NULL, NULL, NULL, NULL, NULL },
-	{ "tiff", pixbuf_check_tiff, NULL, NULL, NULL, NULL, NULL, NULL },
-	{ "gif",  pixbuf_check_gif, NULL,  NULL, NULL, NULL, NULL, NULL },
+	{ "png",  pixbuf_check_png, NULL,NULL,  NULL, NULL, NULL, NULL, NULL },
+	{ "jpeg", pixbuf_check_jpeg, NULL, NULL,NULL, NULL, NULL, NULL, NULL },
+	{ "tiff", pixbuf_check_tiff, NULL,NULL, NULL, NULL, NULL, NULL, NULL },
+	{ "gif",  pixbuf_check_gif, NULL,NULL,  NULL, NULL, NULL, NULL, NULL },
 #define XPM_FILE_FORMAT_INDEX 4
-	{ "xpm",  pixbuf_check_xpm, NULL,  NULL, NULL, NULL, NULL, NULL },
-	{ "pnm",  pixbuf_check_pnm, NULL,  NULL, NULL, NULL, NULL, NULL },
-	{ "ras",  pixbuf_check_sunras, NULL,  NULL, NULL, NULL, NULL, NULL },
-	{ "ico",  pixbuf_check_ico, NULL,  NULL, NULL, NULL, NULL, NULL },
-	{ "bmp",  pixbuf_check_bmp, NULL,  NULL, NULL, NULL, NULL, NULL },
-	{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+	{ "xpm",  pixbuf_check_xpm, NULL,NULL,  NULL, NULL, NULL, NULL, NULL },
+	{ "pnm",  pixbuf_check_pnm, NULL,NULL,  NULL, NULL, NULL, NULL, NULL },
+	{ "ras",  pixbuf_check_sunras, NULL,NULL,  NULL, NULL, NULL, NULL, NULL },
+	{ "ico",  pixbuf_check_ico, NULL,NULL,  NULL, NULL, NULL, NULL, NULL },
+	{ "bmp",  pixbuf_check_bmp, NULL,NULL,  NULL, NULL, NULL, NULL, NULL },
+	{ NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
 
@@ -223,6 +223,8 @@
 	if (g_module_symbol (module, "image_load", &load_sym))
 		image_module->load = load_sym;
 
+	if (g_module_symbol (module, "image_save", &load_sym))
+		image_module->save = load_sym;
         if (g_module_symbol (module, "image_load_xpm_data", &load_sym))
 		image_module->load_xpm_data = load_sym;
 
@@ -341,4 +343,50 @@
 
 	pixbuf = (* load_xpm_data) (data);
 	return pixbuf;
+}
+
+/**
+ * gdk_pixbuf_save_to_file:
+ * @filename: Name of file to save.
+ *
+ * Saves pixbuf to a file.
+ * 
+ **/
+int gdk_pixbuf_save_to_file (const char *filename, GdkPixbuf *pixbuf, char *format)
+{
+    int size;
+    int i;
+    FILE *f;
+    guchar buffer [128];
+    GdkPixbufModule *image_module = NULL;
+    
+    f = fopen (filename, "w");
+    if (!f)
+    {
+	g_warning ("Cannot open for write: %s", filename);
+	return -1;
+    }    
+    
+    for (i = 0; file_formats [i].module_name; i++) {
+	if(!strncmp((file_formats [i].module_name), format, strlen(format)))
+	    image_module = &(file_formats[i]);
+    }
+
+    if (!image_module) {
+	g_warning ("Unable to find handler for file: %s", filename);
+	fclose (f);
+	return -1;
+    }
+    
+    if (image_module->module == NULL)
+	gdk_pixbuf_load_module (image_module);
+
+    if (image_module->save == NULL) {
+	fclose (f);
+	return -1;
+    }
+    
+    (* image_module->save) (f, pixbuf);
+    fclose (f);
+    return 0;
 }
diff -r -u /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-io.h gdk-pixbuf-0.5.0/gdk-pixbuf/gdk-pixbuf-io.h
--- /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf-io.h	Fri Jan  7 10:29:13 2000
+++ gdk-pixbuf-0.5.0/gdk-pixbuf/gdk-pixbuf-io.h	Wed Jan 26 21:52:49 2000
@@ -55,6 +55,7 @@
 	gboolean (* format_check) (guchar *buffer, int size);
 	GModule *module;
 	GdkPixbuf *(* load) (FILE *f);
+	int (* save) (FILE *f, GdkPixbuf *pixbuf);
         GdkPixbuf *(* load_xpm_data) (const char **data);
 
         /* Incremental loading */
diff -r -u /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf.c gdk-pixbuf-0.5.0/gdk-pixbuf/gdk-pixbuf.c
--- /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf.c	Fri Jan 21 14:54:44 2000
+++ gdk-pixbuf-0.5.0/gdk-pixbuf/gdk-pixbuf.c	Tue Feb  1 12:59:43 2000
@@ -98,7 +98,7 @@
 
 	pixbuf = g_new (GdkPixbuf, 1);
 	pixbuf->ref_count = 1;
-	pixbuf->art_pixbuf = art_pixbuf;
+	pixbuf->art_pixbuf = art_pixbuf_duplicate(art_pixbuf);
 
 	return pixbuf;
 }
diff -r -u /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf.h gdk-pixbuf-0.5.0/gdk-pixbuf/gdk-pixbuf.h
--- /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/gdk-pixbuf.h	Fri Jan 21 14:54:44 2000
+++ gdk-pixbuf-0.5.0/gdk-pixbuf/gdk-pixbuf.h	Wed Jan 26 23:48:20 2000
@@ -110,6 +110,8 @@
 /* Simple loading */
 
 GdkPixbuf *gdk_pixbuf_new_from_file (const char *filename);
+    
+int gdk_pixbuf_save_to_file (const char *filename, GdkPixbuf *pixbuf, char *format);
 
 GdkPixbuf *gdk_pixbuf_new_from_data (guchar *data,
 				     ArtPixFormat format,
@@ -118,6 +120,8 @@
 				     int rowstride,
 				     ArtDestroyNotify dfunc,
 				     gpointer dfunc_data);
+GdkPixbuf *gdk_pixbuf_clone(GdkPixbuf *pixbuf);
+
 
 GdkPixbuf *gdk_pixbuf_new_from_xpm_data (const char **data);
 
diff -r -u /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/io-jpeg.c gdk-pixbuf-0.5.0/gdk-pixbuf/io-jpeg.c
--- /home/davidw/gnome/gdk-pixbuf/gdk-pixbuf/io-jpeg.c	Wed Jan  5 15:06:13 2000
+++ gdk-pixbuf-0.5.0/gdk-pixbuf/io-jpeg.c	Tue Feb  1 17:42:23 2000
@@ -87,6 +87,7 @@
 	struct error_handler_data     jerr;
 } JpegProgContext;
 
+int image_save (FILE *f, GdkPixbuf *pixbuf);
 GdkPixbuf *image_load (FILE *f);
 gpointer image_begin_load (ModulePreparedNotifyFunc func, 
 			   ModuleUpdatedNotifyFunc func2,
@@ -547,4 +548,143 @@
 	}
 
 	return TRUE;
+}
+
+#define DATABIG unsigned long long
+#define DATA64  unsigned long long
+#define DATA32  unsigned int
+#define DATA16  unsigned short
+#define DATA8   unsigned char
+
+struct ImLib_JPEG_error_mgr
+{
+   struct jpeg_error_mgr   pub;
+   sigjmp_buf              setjmp_buffer;
+};
+typedef struct ImLib_JPEG_error_mgr *emptr;
+void _JPEGFatalErrorHandler(j_common_ptr cinfo);
+void _JPEGErrorHandler(j_common_ptr cinfo);
+void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level);
+
+void
+_JPEGFatalErrorHandler(j_common_ptr cinfo)
+{
+   emptr               errmgr;
+   
+   errmgr = (emptr) cinfo->err;
+/*   cinfo->err->output_message(cinfo);*/
+   siglongjmp(errmgr->setjmp_buffer, 1);
+   return;
+}
+
+void
+_JPEGErrorHandler(j_common_ptr cinfo)
+{
+   emptr               errmgr;
+   
+   errmgr = (emptr) cinfo->err;
+/*   cinfo->err->output_message(cinfo);*/
+/*   siglongjmp(errmgr->setjmp_buffer, 1);*/
+   return;
+}
+
+void
+_JPEGErrorHandler2(j_common_ptr cinfo, int msg_level)
+{
+   emptr               errmgr;
+   
+   errmgr = (emptr) cinfo->err;
+/*   cinfo->err->output_message(cinfo);*/
+/*   siglongjmp(errmgr->setjmp_buffer, 1);*/
+   return;
+   msg_level = 0;
+}
+
+
+int image_save(FILE *f, GdkPixbuf *pixbuf)
+{
+    struct              jpeg_compress_struct cinfo;
+    DATA8              *buf;
+    DATA8             *ptr;
+    JSAMPROW           *jbuf;
+    int                 y = 0, quality = 100;
+    int                 i, j, pl = 0;
+    int                 w, h = 0;
+    char                pper = 0;
+    struct              ImLib_JPEG_error_mgr jerr;
+
+    ArtPixBuf           *apixbuf;
+	
+    apixbuf = pixbuf->art_pixbuf;
+    w = apixbuf->width;
+    h = apixbuf->height;
+
+    /* no image data? abort */
+    if (!apixbuf->pixels)
+	return 0;
+    /* allocate a small buffer to convert image data */
+    buf = malloc(w * 3 * sizeof(DATA8));
+    if (!buf)
+	return 0;
+
+    /* set up error handling */
+    jerr.pub.error_exit = _JPEGFatalErrorHandler;
+    jerr.pub.emit_message = _JPEGErrorHandler2;
+    jerr.pub.output_message = _JPEGErrorHandler;
+    cinfo.err = jpeg_std_error(&(jerr.pub));
+    if (sigsetjmp(jerr.setjmp_buffer, 1))
+    {
+	jpeg_destroy_compress(&cinfo);
+	free(buf);
+	fclose(f);
+	return 1;
+    }
+
+    /* setup compress params */
+    jpeg_create_compress(&cinfo);
+    jpeg_stdio_dest(&cinfo, f);
+    cinfo.image_width      = w;
+    cinfo.image_height     = h;
+    cinfo.input_components = 3;
+    cinfo.in_color_space   = JCS_RGB;
+ 
+    /* look for tags attached to image to get extra parameters liek quality */
+    /* settigns etc. - thsi si the "api" to hint for extra information for */
+    /* saver modules */
+/*     tag = __imlib_GetTag(im, "quality");
+    if (tag)
+	quality = tag->val;
+    if (quality < 1)
+	quality = 1;
+    if (quality > 100)
+	quality = 100;  */
+
+    /* set up jepg compression parameters */
+    jpeg_set_defaults(&cinfo);
+    jpeg_set_quality(&cinfo, quality, TRUE);
+    jpeg_start_compress(&cinfo, TRUE);
+    /* get the start pointer */
+    ptr = apixbuf->pixels;
+    /* go one scanline at a time... and save */
+    i = 0;
+    while (cinfo.next_scanline < cinfo.image_height)
+    {
+	/* convert scanline from ARGB to RGB packed */
+ 	for (j = 0; j < w; j++)
+	{
+
+	    buf[j*3] = ptr[i*w*3 + j*3] ;
+	    *(&buf[j*3] + 1) = *(&ptr[i*w*3 + j*3] + 1);
+	    *(&buf[j*3] + 2) = *(&ptr[i*w*3 + j*3] + 2) ;
+	}  
+	/* write scanline */
+	jbuf = (JSAMPROW *)(&buf);
+	jpeg_write_scanlines(&cinfo, jbuf, 1);
+	i++;
+	y++;
+    }
+    /* finish off */
+    jpeg_finish_compress(&cinfo);   
+    free(buf);
+    return 0;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]