[evolution-patches] Plugin for resizing inline attachments (images)



Hi,

 I have written a e-plugin to resize inline display of images to
available width.

It basically converts the part to a pixbuf, resizes it and decodes to a
jpeg (a pixbuf when tried saving to a buffer, has to be decoded to some
format) and is converted to a part and passed to the default handler.
This is the approach, i have followed. It still saves the original
file. 

There is a alternate approach as well.

Every image is written with a <img src="xxxx" > tag. Get the image size
from the part, and if it is more than the available width, then add a
width="xxx" so that gtkhtml automatically resizes it for bigger images.


Thanks
Srini.

--- /dev/null	2005-03-20 01:06:14.000000000 +0530
+++ image-resize-plugin.c	2005-06-14 10:16:28.000000000 +0530
@@ -0,0 +1,170 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ *  Author: Srinivasa Ragavan <sragavan novell com>
+ *
+ *  Copyright 2004 Novell, Inc. (www.novell.com)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of version 2 of the GNU General Public
+ *  License as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+ 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+
+#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
+#include <libgnomeui/libgnomeui.h>
+#endif 
+
+#include <camel/camel-mime-part.h>
+#include <camel/camel-stream-mem.h>
+
+#include <mail/em-format.h>
+#include <mail/em-format-html.h>
+#include <mail/em-format-hook.h>
+#include <e-util/e-mktemp.h>
+
+void org_gnome_evolution_format_image_resize(void *ep, EMFormatHookTarget *t);
+
+static gboolean
+save_to_buffer (char *buffer, int len, GError **err, CamelStream *stream)
+{
+	return camel_stream_write (stream, buffer, len) != -1;
+	
+}
+void
+org_gnome_evolution_format_image_resize(void *ep, EMFormatHookTarget *t)
+{
+	CamelStream *out = NULL, *stream = NULL;
+	CamelMimePart *mainpart;
+	CamelDataWrapper *content, *dw;
+	GtkWidget *image = NULL;
+	GdkPixbuf *pixbuf=NULL;
+	GdkPixbufLoader *loader;
+	int orig_width, orig_height, avail_width, avail_height;
+	float ratio = 1.0;
+	char buffer [1024];
+	int len = 0;
+
+	out = camel_stream_mem_new ();
+	if (out == NULL)
+		goto fail;
+	
+	content = camel_medium_get_content_object((CamelMedium *)t->part);
+	if (content == NULL)
+		goto fail;
+	if (camel_data_wrapper_decode_to_stream(content, out) == -1
+	    || camel_stream_flush(out) == -1) {
+		goto fail;
+	}
+	camel_stream_reset (out);
+	
+	loader = gdk_pixbuf_loader_new();
+	do {
+		len = camel_stream_read(out, buffer, sizeof (buffer));
+		if (len > 0) 
+			gdk_pixbuf_loader_write(loader, buffer, len, NULL);
+	} while (len>0);
+	
+	camel_object_unref(out);
+	out = NULL;
+	
+	gdk_pixbuf_loader_close(loader, NULL);
+	pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+
+	avail_height = ((GtkWidget *)((EMFormatHTML *) t->format)->html)->allocation.height;
+	avail_width = ((GtkWidget *)((EMFormatHTML *) t->format)->html)->allocation.width;
+	
+	orig_height = gdk_pixbuf_get_height (pixbuf);
+	orig_width = gdk_pixbuf_get_width (pixbuf);
+
+	/* Lets make it to the 95% of the space*/
+	avail_width = avail_width *95 / 100; 
+
+	if (orig_width > avail_width)
+		ratio = (float)orig_width / (float)avail_width;
+	else
+		goto fail; /* We just pass to the default handler. We dont have to shrink further */
+
+	orig_width = (int) (orig_width / ratio);
+	orig_height = (int) (orig_height / ratio);
+
+#ifdef HAVE_LIBGNOMEUI_GNOME_THUMBNAIL_H
+	pixbuf = gnome_thumbnail_scale_down_pixbuf (pixbuf, orig_width, orig_height);
+#else
+	pixbuf = gdk_pixbuf_scale_simple(pixbuf, orig_width, orig_height, GDK_INTERP_BILINEAR);
+#endif
+
+	stream = camel_stream_mem_new ();
+
+	if (!gdk_pixbuf_save_to_callback (pixbuf, (GdkPixbufSaveFunc)save_to_buffer, stream, "jpeg", NULL, NULL)) {
+		g_warning ("Image-resize-plugin: Unable to resize\n");
+		goto fail;
+	}
+
+	mainpart = camel_mime_part_new();
+
+	dw = camel_data_wrapper_new();
+	camel_data_wrapper_construct_from_stream(dw, stream);
+	camel_object_unref(stream);
+
+	camel_mime_part_set_encoding(mainpart, CAMEL_TRANSFER_ENCODING_BINARY);
+	
+	camel_medium_set_content_object((CamelMedium *)mainpart, dw);
+	camel_object_unref(dw);
+
+
+	camel_data_wrapper_set_mime_type((CamelDataWrapper *)mainpart, camel_data_wrapper_get_mime_type (content));
+	
+	camel_mime_part_set_filename(mainpart, camel_mime_part_get_filename (t->part));
+
+	t->item->handler.old->handler(t->format, t->stream, mainpart, t->item->handler.old);
+
+	camel_object_unref (mainpart);
+
+	goto ok;
+fail:
+	if (out)
+		camel_object_unref (out);
+	if (stream)
+		camel_object_unref (stream);
+
+	t->item->handler.old->handler(t->format, t->stream, t->part, t->item->handler.old);
+ok:
+
+	if (pixbuf)
+		gdk_pixbuf_unref (pixbuf);
+	
+	if (image)
+		gtk_widget_destroy (image);
+	return;
+}
+
+int e_plugin_lib_enable(EPluginLib *ep, int enable);
+
+int
+e_plugin_lib_enable(EPluginLib *ep, int enable)
+{
+	int ok = 0;
+
+	if (enable) {
+		printf("Enabling the image resize plug-in\n");
+	}
+
+	return ok;
+}
--- /dev/null	2005-03-20 01:06:14.000000000 +0530
+++ Makefile.am	2005-06-13 13:57:01.000000000 +0530
@@ -0,0 +1,16 @@
+INCLUDES =						\
+	-I$(top_srcdir)					\
+	-I$(top_srcdir)/camel                           \
+	$(EVOLUTION_MAIL_CFLAGS)			
+
+ EVO_PLUGIN_RULE@
+
+plugin_DATA = org-gnome-evolution-image-resize-plugin.eplug
+plugin_LTLIBRARIES = liborg-gnome-evolution-image-resize-plugin.la
+
+liborg_gnome_evolution_image_resize_plugin_la_SOURCES = image-resize-plugin.c
+liborg_gnome_evolution_image_resize_plugin_la_LDFLAGS = -module -avoid-version
+liborg_gnome_evolution_image_resize_plugin_la_LIBADD =			\
+	$(EVOLUTION_MAIL_LIBS)
+
+EXTRA_DIST = org-gnome-evolution-image-resize-plugin.eplug.in 
--- /dev/null	2005-03-20 01:06:14.000000000 +0530
+++ org-gnome-evolution-image-resize-plugin.eplug.in	2005-06-14 10:14:01.000000000 +0530
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+<e-plugin-list>
+  <e-plugin
+    type="shlib"
+    id="org.gnome.evolution.plugin.image-resize-plugin"
+    location="@PLUGINDIR@/liborg-gnome-evolution-image-resize-plugin.so"
+    load-on-startup="true"   
+    domain="+GETTEXT_PACKAGE+"
+    localedir="+LOCALEDIR+"
+    name="Image resize">
+    <description>A simple plugin which scales down image attachments to fit to available width.</description>
+    <author name="Srinivasa Ragavan" email="sragavan novell com"/>
+
+    <hook class="org.gnome.evolution.mail.format:1.0">
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/gif"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/jpeg"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/png"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/x-png"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/tiff"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/x-bmp"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/bmp"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/svg"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/x-cmu-raster"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/x-ico"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/x-portable-anymap"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/x-portable-bitmap"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/x-portable-graymap"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/x-portable-pixmap"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/x-xpixmap"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/jpg"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+
+      <group id="EMFormatHTMLDisplay">
+	<item flags="inline_disposition" mime_type="image/pjpeg"
+	  format="org_gnome_evolution_format_image_resize"/>
+      </group>
+    </hook>
+  </e-plugin>
+</e-plugin-list>


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