Index: plugins/garble/xp/abiword-garble-png.cpp
===================================================================
--- plugins/garble/xp/abiword-garble-png.cpp	(revision 0)
+++ plugins/garble/xp/abiword-garble-png.cpp	(revision 0)
@@ -0,0 +1,119 @@
+/* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
+
+/* AbiSource
+ * 
+ * Copyright (C) 2009 Marc 'Foddex' Oude Kotte <foddex@foddex.net>
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * 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 Place - Suite 330, Boston, MA  
+ * 02111-1307, USA.
+ */
+
+#include "abiword-garble.h"
+
+struct png_read_data {
+	void*	data;
+	size_t	size;
+	size_t	pos;
+};
+
+//-----------------------------------------------------------------------------
+static void _png_read(png_structp png_ptr, png_bytep data, png_size_t length) {
+
+	png_read_data* _data = (png_read_data*) png_get_io_ptr( png_ptr );
+	memcpy( data, (char*)_data->data + _data->pos, length );
+	_data->pos += length;
+}
+
+//-----------------------------------------------------------------------------
+void _png_write( png_structp png_ptr, png_bytep data, png_size_t length ) {
+
+	string* _data = (string*) png_get_io_ptr( png_ptr );
+	size_t offset = _data->size();
+	_data->resize( offset + length );
+	memcpy( &(*_data)[offset], data, length );
+}
+
+//-----------------------------------------------------------------------------
+bool abiword_document::garble_png( void*& data, size_t& size ) {
+
+	png_bytep * dib;
+	png_uint_32 width;
+	png_uint_32 height;
+	int compression_type;
+	int filter_type;
+	int interlace_type;
+	int bit_depth;
+	int color_type;
+	png_uint_32 rowbytes;
+
+	// read PNG data
+	{
+		png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (void*) NULL, NULL, NULL );
+		if (!png_ptr)
+			return false;
+		png_infop info_ptr = png_create_info_struct(png_ptr);
+		if (!info_ptr) {
+			png_destroy_read_struct( &png_ptr, (png_infopp)NULL, (png_infopp)NULL );
+			return false;
+		}
+		png_read_data _png_read_data = { data, size, 0 };
+		png_set_read_fn( png_ptr, (void*)&_png_read_data, &_png_read );
+		png_read_info( png_ptr, info_ptr );
+		png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type );
+		png_set_packing( png_ptr );
+		png_set_expand( png_ptr );
+		png_set_strip_16( png_ptr );
+		png_set_gray_to_rgb( png_ptr );
+		png_set_strip_alpha( png_ptr );
+		png_set_interlace_handling( png_ptr );
+		png_set_bgr( png_ptr );
+		rowbytes = info_ptr->rowbytes;
+		png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
+	}
+
+	// we don't care about the image data itself, we just want a random garbled
+	// image of the same size
+	dib = (png_bytep*) malloc( sizeof(png_bytep) * height );
+	for (size_t i=0; i<height; ++i) {
+		dib[i] = (png_byte*) malloc( rowbytes );
+		garble_image_line( reinterpret_cast<char*>( dib[i] ), rowbytes );
+	}
+
+	{
+		// write it back
+		png_structp png_ptrw = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
+		if (!png_ptrw)
+			return false;
+		png_infop info_ptrw = png_create_info_struct( png_ptrw );
+		png_set_IHDR( png_ptrw, info_ptrw, width, height, bit_depth, color_type, interlace_type, compression_type, filter_type );
+		string newdata;
+		png_set_write_fn( png_ptrw, (void*)&newdata, &_png_write, NULL );
+		png_write_info( png_ptrw, info_ptrw );
+		png_write_image( png_ptrw, dib );
+		png_write_end( png_ptrw, NULL );
+		png_destroy_write_struct( &png_ptrw, NULL );
+
+		free(data);
+		size = newdata.size();
+		data = malloc( size );
+		memcpy( data, &newdata[0], size );
+	}
+
+	// cleanup
+	for (size_t i=0; i<height; i++)
+		free( dib[i] );
+	free( dib );
+	return true;
+}
Index: plugins/garble/xp/abiword-garble.cpp
===================================================================
--- plugins/garble/xp/abiword-garble.cpp	(revision 28128)
+++ plugins/garble/xp/abiword-garble.cpp	(working copy)
@@ -134,112 +134,21 @@
 }
 
 //-----------------------------------------------------------------------------
-/*static*/ void abiword_document::_png_read(png_structp png_ptr, png_bytep data, png_size_t length) {
+void abiword_document::garble_image_line( char* line, size_t bytes ) {
 
-	png_read_data* _data = (png_read_data*) png_get_io_ptr( png_ptr );
-	memcpy( data, (char*)_data->data + _data->pos, length );
-	_data->pos += length;
-}
-
-//-----------------------------------------------------------------------------
-/*static*/ void abiword_document::_png_write( png_structp png_ptr, png_bytep data, png_size_t length ) {
-
-	string* _data = (string*) png_get_io_ptr( png_ptr );
-	size_t offset = _data->size();
-	_data->resize( offset + length );
-	memcpy( &(*_data)[offset], data, length );
-}
-
-//-----------------------------------------------------------------------------
-bool abiword_document::garble_png( void*& data, size_t& size ) {
-
-	png_bytep * dib;
-	png_uint_32 width;
-	png_uint_32 height;
-	int compression_type;
-	int filter_type;
-	int interlace_type;
-	int bit_depth;
-	int color_type;
-	png_uint_32 rowbytes;
-
-	// read PNG data
-	{
-		png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (void*) NULL, NULL, NULL );
-		if (!png_ptr)
-			return false;
-		png_infop info_ptr = png_create_info_struct(png_ptr);
-		if (!info_ptr) {
-			png_destroy_read_struct( &png_ptr, (png_infopp)NULL, (png_infopp)NULL );
-			return false;
-		}
-		png_read_data _png_read_data = { data, size, 0 };
-		png_set_read_fn( png_ptr, (void*)&_png_read_data, &abiword_document::_png_read );
-		png_read_info( png_ptr, info_ptr );
-		png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type );
-		png_set_packing( png_ptr );
-		png_set_expand( png_ptr );
-		png_set_strip_16( png_ptr );
-		png_set_gray_to_rgb( png_ptr );
-		png_set_strip_alpha( png_ptr );
-		png_set_interlace_handling( png_ptr );
-		png_set_bgr( png_ptr );
-		rowbytes = info_ptr->rowbytes;
-		png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
-	}
-
-	// we don't care about the image data itself, we just want a random garbled
-	// image of the same size
-	dib = (png_bytep*) malloc( sizeof(png_bytep) * height );
-	png_byte newChar = 0;
+	char newChar = 0;
 	size_t count = 0;
-	for (size_t i=0; i<height; ++i) {
-		dib[i] = (png_byte*) malloc( rowbytes );
-		for (size_t j=0; j<rowbytes; ++j) {
-			if (count==0) {
-				newChar = UT_rand();
-				count = 1 + (UT_rand() % 768);
-			}
-			--count;
-
-			dib[i][j] = newChar;
+	for (size_t j=0; j<bytes; ++j) {
+		if (count==0) {
+			newChar = UT_rand();
+			count = 1 + (UT_rand() % 768);
 		}
+		--count;
+		line[j] = newChar;
 	}
-
-	{
-		// write it back
-		png_structp png_ptrw = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
-		if (!png_ptrw)
-			return false;
-		png_infop info_ptrw = png_create_info_struct( png_ptrw );
-		png_set_IHDR( png_ptrw, info_ptrw, width, height, bit_depth, color_type, interlace_type, compression_type, filter_type );
-		string newdata;
-		png_set_write_fn( png_ptrw, (void*)&newdata, &abiword_document::_png_write, NULL );
-		png_write_info( png_ptrw, info_ptrw );
-		png_write_image( png_ptrw, dib );
-		png_write_end( png_ptrw, NULL );
-		png_destroy_write_struct( &png_ptrw, NULL );
-
-		free(data);
-		size = newdata.size();
-		data = malloc( size );
-		memcpy( data, &newdata[0], size );
-	}
-
-	// cleanup
-	for (size_t i=0; i<height; i++)
-		free( dib[i] );
-	free( dib );
-	return true;
 }
 
 //-----------------------------------------------------------------------------
-bool abiword_document::garble_jpeg( void*&, size_t& ) {
-
-	return false;
-}
-
-//-----------------------------------------------------------------------------
 void abiword_document::garble_image_node( xmlNodePtr node ) {
 
 	// find mime type and whether or not it's base64 encoded
@@ -488,6 +397,18 @@
 //-----------------------------------------------------------------------------
 // Abiword Plugin Interface 
 //-----------------------------------------------------------------------------
+#ifdef ABI_PLUGIN_BUILTIN
+#define abi_plugin_register abipgn_garble_register
+#define abi_plugin_unregister abipgn_garble_unregister
+#define abi_plugin_supports_version abipgn_garble_supports_version
+// dll exports break static linking
+#define ABI_BUILTIN_FAR_CALL extern "C"
+#else
+#define ABI_BUILTIN_FAR_CALL ABI_FAR_CALL
+ABI_PLUGIN_DECLARE("AbiGarble")
+#endif
+
+//-----------------------------------------------------------------------------
 ABI_BUILTIN_FAR_CALL int abi_plugin_register( XAP_ModuleInfo* mi ) {
 
     mi->name = "AbiGarble";
Index: plugins/garble/xp/abiword-garble.h
===================================================================
--- plugins/garble/xp/abiword-garble.h	(revision 28128)
+++ plugins/garble/xp/abiword-garble.h	(working copy)
@@ -26,7 +26,9 @@
 #include <vector>
 #include <gsf/gsf-utils.h>
 #include "ut_rand.h"
+#include "ut_jpeg.h"
 #include "ut_go_file.h"
+#include "ut_bytebuf.h"
 #include "png.h"
 #include "xap_Module.h"
 #include "xap_App.h"
@@ -37,31 +39,11 @@
 
 using namespace std;
 
-#ifdef ABI_PLUGIN_BUILTIN
-#define abi_plugin_register abipgn_garble_register
-#define abi_plugin_unregister abipgn_garble_unregister
-#define abi_plugin_supports_version abipgn_garble_supports_version
-// dll exports break static linking
-#define ABI_BUILTIN_FAR_CALL extern "C"
-#else
-#define ABI_BUILTIN_FAR_CALL ABI_FAR_CALL
-ABI_PLUGIN_DECLARE("AbiGarble")
-#endif
-
 class abiword_garble;
 
 class abiword_document {
 
 	private:
-		struct png_read_data {
-			void*	data;
-			size_t	size;
-			size_t	pos;
-		};
-		static void _png_read( png_structp png_ptr, png_bytep data, png_size_t length );
-		static void _png_write( png_structp png_ptr, png_bytep data, png_size_t length );
-
-	private:
 		string				mFilename;
 		xmlDocPtr			mDocument;
 		abiword_garble*		mAbiGarble;
@@ -73,6 +55,7 @@
 		void garble_image_node( xmlNodePtr node );
 		bool garble_png( void*& data, size_t& size );
 		bool garble_jpeg( void*& data, size_t& size );
+		void garble_image_line( char* line, size_t bytes );
 		char get_random_char();
 	public:
 		abiword_document( abiword_garble* abigarble, const string& filename );
Index: plugins/garble/xp/abiworld-garble-jpeg.cpp
===================================================================
--- plugins/garble/xp/abiworld-garble-jpeg.cpp	(revision 0)
+++ plugins/garble/xp/abiworld-garble-jpeg.cpp	(revision 0)
@@ -0,0 +1,124 @@
+/* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
+
+/* AbiSource
+ * 
+ * Copyright (C) 2009 Marc 'Foddex' Oude Kotte <foddex@foddex.net>
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * 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 Place - Suite 330, Boston, MA  
+ * 02111-1307, USA.
+ */
+
+#include "abiword-garble.h"
+
+extern "C" {
+	#include <jpeglib.h>
+}
+
+//-----------------------------------------------------------------------------
+typedef struct {
+	struct jpeg_destination_mgr pub;
+	JOCTET *buf;
+	size_t bufsize;
+	size_t jpegsize;
+} mem_destination_mgr, *mem_dest_ptr;
+
+//-----------------------------------------------------------------------------
+static void _jpeg_init_destination( j_compress_ptr cinfo )
+{
+    mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
+    dest->pub.next_output_byte = dest->buf;
+    dest->pub.free_in_buffer = dest->bufsize;
+    dest->jpegsize = 0;
+}
+
+//-----------------------------------------------------------------------------
+static boolean _jpeg_empty_output_buffer( j_compress_ptr cinfo )
+{
+    mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
+    dest->pub.next_output_byte = dest->buf;
+    dest->pub.free_in_buffer = dest->bufsize;
+    return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+static void _jpeg_term_destination( j_compress_ptr cinfo )
+{
+    mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
+    dest->jpegsize = dest->bufsize - dest->pub.free_in_buffer;
+}
+
+//-----------------------------------------------------------------------------
+bool abiword_document::garble_jpeg( void*& data, size_t& length ) {
+
+	// get dimensions
+	UT_ByteBuf bb;
+	bb.append( static_cast<UT_Byte*>( data), length );
+	UT_sint32 w, h;
+	UT_JPEG_getDimensions( &bb, w, h );
+
+	// create garbled image with given dimensions
+	size_t rowbytes = w * 3;
+	char** dib = (char**) malloc( sizeof(char*) * h );
+	for (int i=0; i<h; ++i) {
+		dib[i] = (char*) malloc( rowbytes );
+		garble_image_line( dib[i], rowbytes );
+	}
+
+	// free current data and reinit
+	free( data );
+	length = rowbytes * h;
+	data = (char*)malloc( length );
+
+	// rebuild jpeg data
+	jpeg_compress_struct cinfo;
+	jpeg_error_mgr jerr;
+	mem_dest_ptr dest;
+	memset( &cinfo, 0, sizeof(cinfo) );
+
+	// setup jpeg structure
+	jpeg_create_compress(&cinfo);
+	cinfo.err = jpeg_std_error(&jerr);
+	cinfo.in_color_space = JCS_RGB;
+	cinfo.input_components = 3;
+	cinfo.data_precision = 8;
+	cinfo.image_width = (JDIMENSION) w;
+	cinfo.image_height = (JDIMENSION) h;
+	jpeg_set_defaults (&cinfo);
+	jpeg_set_quality ( &cinfo, 50, TRUE );
+	cinfo.dest = (struct jpeg_destination_mgr *) (*cinfo.mem->alloc_small)((j_common_ptr)&cinfo, JPOOL_PERMANENT, sizeof(mem_destination_mgr));
+    dest = (mem_dest_ptr) cinfo.dest;
+    dest->pub.init_destination    = _jpeg_init_destination;
+    dest->pub.empty_output_buffer = _jpeg_empty_output_buffer;
+    dest->pub.term_destination    = _jpeg_term_destination;
+    dest->buf      = (JOCTET*)data;
+    dest->bufsize  = length;
+    dest->jpegsize = 0;
+	jpeg_start_compress (&cinfo, TRUE);
+
+	// write data
+	for (int i=0; i<h; ++i)
+		jpeg_write_scanlines( &cinfo, (JSAMPARRAY)&dib[i], 1 );
+
+	// finalize jpeg data
+	jpeg_finish_compress(&cinfo);
+	length = dest->jpegsize;
+	jpeg_destroy_compress(&cinfo);
+
+	// cleanup
+	for (int i=0; i<h; i++)
+		free( dib[i] );
+	free( dib );
+	return true;
+}
\ No newline at end of file