From 19b3c7eeb2f2df5e0cf76ed94f03f799fbabb01f Mon Sep 17 00:00:00 2001
From: John Cupitt <jcupitt@gmail.com>
Date: Fri, 25 Nov 2011 14:55:43 +0000
Subject: [PATCH] add new-style vips load and save

---
 TODO                     |   7 ++-
 libvips/file/Makefile.am |   2 +
 libvips/file/file.c      |   4 ++
 libvips/file/jpegsave.c  |   7 ++-
 libvips/file/vipsload.c  | 118 +++++++++++++++++++++++++++++++++++++++
 libvips/file/vipssave.c  | 115 ++++++++++++++++++++++++++++++++++++++
 libvips/iofuncs/image.c  |   4 +-
 7 files changed, 253 insertions(+), 4 deletions(-)
 create mode 100644 libvips/file/vipsload.c
 create mode 100644 libvips/file/vipssave.c

diff --git a/TODO b/TODO
index 52587c28..707fb5f9 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,9 @@
-- get image.c using the new system for vips_image_new_from_file()
+- need vips load/save class, so we can detect vips files for native read /
+  write
+
+  jpeg load needs to set suffs
+
+  get image.c using the new system for vips_image_new_from_file()
 
   CLI stuff image->new_from_string() needs to use new system too, chcek this
 
diff --git a/libvips/file/Makefile.am b/libvips/file/Makefile.am
index 5ea4d150..25c792c7 100644
--- a/libvips/file/Makefile.am
+++ b/libvips/file/Makefile.am
@@ -5,6 +5,8 @@ libfile_la_SOURCES = \
 	jpeg.h \
 	jpegload.c \
 	jpegsave.c \
+	vipssave.c \
+	vipsload.c \
 	file.c 
 
 INCLUDES = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
diff --git a/libvips/file/file.c b/libvips/file/file.c
index 59056da1..f6816e4e 100644
--- a/libvips/file/file.c
+++ b/libvips/file/file.c
@@ -970,9 +970,13 @@ vips_file_operation_init( void )
 {
 	extern GType vips_file_load_jpeg_get_type( void ); 
 	extern GType vips_file_save_jpeg_get_type( void ); 
+	extern GType vips_file_load_vips_get_type( void ); 
+	extern GType vips_file_save_vips_get_type( void ); 
 
 #ifdef HAVE_JPEG
 	vips_file_load_jpeg_get_type(); 
 	vips_file_save_jpeg_get_type(); 
 #endif /*HAVE_JPEG*/
+	vips_file_load_vips_get_type(); 
+	vips_file_save_vips_get_type(); 
 }
diff --git a/libvips/file/jpegsave.c b/libvips/file/jpegsave.c
index ba17ada6..639bf888 100644
--- a/libvips/file/jpegsave.c
+++ b/libvips/file/jpegsave.c
@@ -815,11 +815,14 @@ static int bandfmt_jpeg[10] = {
    UC, UC, UC, UC, UC, UC, UC, UC, UC, UC
 };
 
+static const char *jpeg_suffs[] = { ".jpg", ".jpeg", ".jpe", NULL };
+
 static void
 vips_file_save_jpeg_class_init( VipsFileSaveJpegClass *class )
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
 	VipsObjectClass *object_class = (VipsObjectClass *) class;
+	VipsFileClass *file_class = (VipsFileClass *) class;
 	VipsFileSaveClass *save_class = (VipsFileSaveClass *) class;
 
 	gobject_class->dispose = vips_file_save_jpeg_dispose;
@@ -828,9 +831,11 @@ vips_file_save_jpeg_class_init( VipsFileSaveJpegClass *class )
 	gobject_class->get_property = vips_object_get_property;
 
 	object_class->nickname = "jpegsave";
-	object_class->description = _( "save jpeg to file" );
+	object_class->description = _( "save image to jpeg file" );
 	object_class->build = vips_file_save_jpeg_build;
 
+	file_class->suffs = jpeg_suffs;
+
 	save_class->saveable = VIPS_SAVEABLE_RGB_CMYK;
 	save_class->format_table = bandfmt_jpeg;
 
diff --git a/libvips/file/vipsload.c b/libvips/file/vipsload.c
new file mode 100644
index 00000000..60ff1a77
--- /dev/null
+++ b/libvips/file/vipsload.c
@@ -0,0 +1,118 @@
+/* load vips from a file
+ *
+ * 24/11/11
+ */
+
+/*
+
+    This file is part of VIPS.
+    
+    VIPS is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser 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
+
+ */
+
+/*
+
+    These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
+
+ */
+
+/*
+#define DEBUG
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /*HAVE_CONFIG_H*/
+#include <vips/intl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vips/vips.h>
+
+typedef VipsFileLoad VipsFileLoadVips;
+typedef VipsFileLoadClass VipsFileLoadVipsClass;
+
+G_DEFINE_TYPE( VipsFileLoadVips, vips_file_load_vips, VIPS_TYPE_FILE_SAVE );
+
+static int
+vips_file_load_vips_build( VipsObject *object )
+{
+	if( VIPS_OBJECT_CLASS( vips_file_load_vips_parent_class )->
+		build( object ) )
+		return( -1 );
+
+	return( 0 );
+}
+
+static int
+vips_file_load_vips_is_a( const char *filename )
+{
+	unsigned char buf[4];
+
+	if( vips__get_bytes( filename, buf, 4 ) ) {
+		if( buf[0] == 0x08 && buf[1] == 0xf2 &&
+			buf[2] == 0xa6 && buf[3] == 0xb6 )
+			/* SPARC-order VIPS image.
+			 */
+			return( 1 );
+		else if( buf[3] == 0x08 && buf[2] == 0xf2 &&
+			buf[1] == 0xa6 && buf[0] == 0xb6 )
+			/* INTEL-order VIPS image.
+			 */
+			return( 1 );
+	}
+
+	return( 0 );
+}
+
+static int
+vips_file_load_vips_header( VipsFileLoad *load )
+{
+}
+
+static int
+vips_file_load_vips_load( VipsFileLoad *load )
+{
+}
+
+static const char *vips_suffs[] = { ".v", NULL };
+
+static void
+vips_file_load_jpeg_class_init( VipsFileLoadJpegClass *class )
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
+	VipsObjectClass *object_class = (VipsObjectClass *) class;
+	VipsFileClass *file_class = (VipsLoadClass *) class;
+	VipsFileLoadClass *load_class = (VipsFileLoadClass *) class;
+
+	object_class->nickname = "vipsload";
+	object_class->description = _( "load vips from file" );
+	object_class->build = vips_file_load_vips_build;
+
+	file_class->suffs = vips_suffs;
+
+	load_class->is_a = vips_file_load_vips_is_a;
+	load_class->header = vips_file_load_vips_header;
+	load_class->load = vips_file_load_vips_load;
+
+}
+
+static void
+vips_file_load_vips_init( VipsFileLoadVips *vips )
+{
+}
+
diff --git a/libvips/file/vipssave.c b/libvips/file/vipssave.c
new file mode 100644
index 00000000..1f87efa0
--- /dev/null
+++ b/libvips/file/vipssave.c
@@ -0,0 +1,115 @@
+/* save to vips
+ *
+ * 24/11/11
+ */
+
+/*
+
+    This file is part of VIPS.
+    
+    VIPS is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser 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
+
+ */
+
+/*
+
+    These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
+
+ */
+
+/*
+#define DEBUG_VERBOSE
+#define DEBUG
+#define VIPS_DEBUG
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /*HAVE_CONFIG_H*/
+#include <vips/intl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vips/vips.h>
+
+typedef VipsFileSave VipsFileSaveVips;
+typedef VipsFileSaveClass VipsFileSaveVipsClass;
+
+G_DEFINE_TYPE( VipsFileSaveVips, vips_file_save_vips, VIPS_TYPE_FILE_SAVE );
+
+static int
+vips_file_save_vips_build( VipsObject *object )
+{
+	VipsFile *file = (VipsFile *) object;
+	VipsFileSave *save = (VipsFileSave *) object;
+
+	if( VIPS_OBJECT_CLASS( vips_file_save_vips_parent_class )->
+		build( object ) )
+		return( -1 );
+
+	if( vips_image_write_to_file( save->in, file->filename ) )
+		return( -1 );
+
+	return( 0 );
+}
+
+/* Save a bit of typing.
+ */
+#define UC VIPS_FORMAT_UCHAR
+#define C VIPS_FORMAT_CHAR
+#define US VIPS_FORMAT_USHORT
+#define S VIPS_FORMAT_SHORT
+#define UI VIPS_FORMAT_UINT
+#define I VIPS_FORMAT_INT
+#define F VIPS_FORMAT_FLOAT
+#define X VIPS_FORMAT_COMPLEX
+#define D VIPS_FORMAT_DOUBLE
+#define DX VIPS_FORMAT_DPCOMPLEX
+
+/* Type promotion for division. Sign and value preserving. Make sure 
+ * these match the case statement in complexform_buffer() above.
+ */
+static int vips_bandfmt_vips[10] = {
+/* UC  C   US  S   UI  I  F  X  D  DX */
+   UC, C,  US, S,  UI, I, F, X, D, DX
+};
+
+static const char *vips_suffs[] = { ".v", NULL };
+
+static void
+vips_file_save_vips_class_init( VipsFileSaveVipsClass *class )
+{
+	VipsObjectClass *object_class = (VipsObjectClass *) class;
+	VipsFileClass *file_class = (VipsFileClass *) class;
+	VipsFileSaveClass *save_class = (VipsFileSaveClass *) class;
+
+	object_class->nickname = "vipssave";
+	object_class->description = _( "save image to vips file" );
+	object_class->build = vips_file_save_vips_build;
+
+	file_class->suffs = vips_suffs;
+
+	save_class->saveable = VIPS_SAVEABLE_ANY;
+	save_class->format_table = vips_bandfmt_vips;
+
+}
+
+static void
+vips_file_save_vips_init( VipsFileSaveVips *vips )
+{
+}
+
diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c
index f9e3b26d..97bbc77b 100644
--- a/libvips/iofuncs/image.c
+++ b/libvips/iofuncs/image.c
@@ -756,7 +756,7 @@ vips_image_build( VipsObject *object )
 	const char *filename = image->filename;
 	const char *mode = image->mode;
 
-	VipsFormatClass *format;
+	const char *file_op;
 	size_t sizeof_image;
 
 	VIPS_DEBUG_MSG( "vips_image_build: %p\n", image );
@@ -768,7 +768,7 @@ vips_image_build( VipsObject *object )
 	 */
 	switch( mode[0] ) {
         case 'r':
-		if( !(format = vips_format_for_file( filename )) )
+		if( !(file_op = vips_file_find_load( filename )) )
 			return( -1 );
 
 		if( vips_format_is_vips( format ) ) {