Start of support for writing files with ImageMagick.
This commit is contained in:
parent
19e2e2e208
commit
e22282a844
|
@ -32,6 +32,7 @@ libforeign_la_SOURCES = \
|
|||
magick2vips.c \
|
||||
magickload.c \
|
||||
magick7load.c \
|
||||
magicksave.c \
|
||||
pngload.c \
|
||||
pngsave.c \
|
||||
vipspng.c \
|
||||
|
|
|
@ -1775,6 +1775,7 @@ vips_foreign_operation_init( void )
|
|||
extern GType vips_foreign_load_magick_buffer_get_type( void );
|
||||
extern GType vips_foreign_load_magick7_file_get_type( void );
|
||||
extern GType vips_foreign_load_magick7_buffer_get_type( void );
|
||||
extern GType vips_foreign_save_magick_file_get_type( void );
|
||||
extern GType vips_foreign_save_dz_file_get_type( void );
|
||||
extern GType vips_foreign_save_dz_buffer_get_type( void );
|
||||
extern GType vips_foreign_load_webp_file_get_type( void );
|
||||
|
@ -1880,11 +1881,13 @@ vips_foreign_operation_init( void )
|
|||
#ifdef HAVE_MAGICK
|
||||
vips_foreign_load_magick_file_get_type();
|
||||
vips_foreign_load_magick_buffer_get_type();
|
||||
vips_foreign_save_magick_file_get_type();
|
||||
#endif /*HAVE_MAGICK*/
|
||||
|
||||
#ifdef HAVE_MAGICK7
|
||||
vips_foreign_load_magick7_file_get_type();
|
||||
vips_foreign_load_magick7_buffer_get_type();
|
||||
vips_foreign_save_magick_file_get_type();
|
||||
#endif /*HAVE_MAGICK7*/
|
||||
|
||||
#ifdef HAVE_CFITSIO
|
||||
|
|
|
@ -93,8 +93,6 @@
|
|||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#ifdef HAVE_MAGICK
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -102,14 +100,17 @@
|
|||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#include <magick/api.h>
|
||||
#if HAVE_MAGICK || HAVE_MAGICK7
|
||||
|
||||
#include "pforeign.h"
|
||||
|
||||
/* pre-float Magick used to call this MaxRGB.
|
||||
*/
|
||||
#if !defined(QuantumRange)
|
||||
# define QuantumRange MaxRGB
|
||||
#if HAVE_MAGICK
|
||||
#include <magick/api.h>
|
||||
/* pre-float Magick used to call this MaxRGB.
|
||||
*/
|
||||
#if !defined(QuantumRange)
|
||||
# define QuantumRange MaxRGB
|
||||
#endif
|
||||
#elif HAVE_MAGICK7
|
||||
#include <MagickCore/MagickCore.h>
|
||||
#endif
|
||||
|
||||
/* And this used to be UseHDRI.
|
||||
|
@ -118,6 +119,25 @@
|
|||
# define UseHDRI 1
|
||||
#endif
|
||||
|
||||
/* What we track during a write call.
|
||||
*/
|
||||
typedef struct _Write {
|
||||
char *filename;
|
||||
VipsImage *im;
|
||||
|
||||
Image *image;
|
||||
ImageInfo *image_info;
|
||||
ExceptionInfo *exception;
|
||||
|
||||
Image *current_image;
|
||||
char *map;
|
||||
StorageType storageType;
|
||||
} Write;
|
||||
|
||||
#if HAVE_MAGICK
|
||||
|
||||
#include "pforeign.h"
|
||||
|
||||
/* What we track during a read call.
|
||||
*/
|
||||
typedef struct _Read {
|
||||
|
@ -894,3 +914,222 @@ vips__magick_read_buffer_header( const void *buf, const size_t len,
|
|||
|
||||
#endif /*HAVE_MAGICK*/
|
||||
|
||||
/* Can be called many times.
|
||||
*/
|
||||
static void
|
||||
write_free( Write *write )
|
||||
{
|
||||
VIPS_FREE( write->filename );
|
||||
VIPS_FREE( write->map );
|
||||
VIPS_FREEF( DestroyImageList, write->image );
|
||||
VIPS_FREEF( DestroyImageInfo, write->image_info );
|
||||
VIPS_FREEF( DestroyExceptionInfo, write->exception );
|
||||
}
|
||||
|
||||
/* Can be called many times.
|
||||
*/
|
||||
static int
|
||||
write_close( VipsImage *im, Write *write )
|
||||
{
|
||||
write_free( write );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static Write *
|
||||
write_new( const char *filename, VipsImage *im)
|
||||
{
|
||||
Write *write;
|
||||
static int inited = 0;
|
||||
|
||||
if( !inited ) {
|
||||
MagickCoreGenesis( vips_get_argv0(), MagickFalse );
|
||||
inited = 1;
|
||||
}
|
||||
|
||||
if( !(write = VIPS_NEW( im, Write )) )
|
||||
return( NULL );
|
||||
write->filename = filename ? g_strdup( filename ) : NULL;
|
||||
write->im = im;
|
||||
write->image = NULL;
|
||||
|
||||
write->storageType = UndefinedPixel;
|
||||
switch( im->BandFmt ) {
|
||||
case VIPS_FORMAT_UCHAR:
|
||||
write->storageType = CharPixel;
|
||||
break;
|
||||
case VIPS_FORMAT_USHORT:
|
||||
write->storageType = ShortPixel;
|
||||
break;
|
||||
case VIPS_FORMAT_UINT:
|
||||
write->storageType = LongPixel;
|
||||
break;
|
||||
case VIPS_FORMAT_FLOAT:
|
||||
write->storageType = FloatPixel;
|
||||
break;
|
||||
case VIPS_FORMAT_DOUBLE:
|
||||
write->storageType = DoublePixel;
|
||||
break;
|
||||
|
||||
default:
|
||||
write_free(write);
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
write->map = NULL;
|
||||
switch( im->Bands ) {
|
||||
case 1:
|
||||
write->map = g_strdup("R");
|
||||
break;
|
||||
case 2:
|
||||
write->map = g_strdup("RA");
|
||||
break;
|
||||
case 3:
|
||||
write->map = g_strdup("RGB");
|
||||
break;
|
||||
case 4:
|
||||
if( im->Type == VIPS_INTERPRETATION_CMYK )
|
||||
write->map = g_strdup("CMYK");
|
||||
else
|
||||
write->map = g_strdup("RGBA");
|
||||
break;
|
||||
case 5:
|
||||
write->map = g_strdup("CMYKA");
|
||||
break;
|
||||
|
||||
default:
|
||||
write_free(write);
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
write->image_info = CloneImageInfo( NULL );
|
||||
if( !write->image_info) {
|
||||
write_free(write);
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
write->exception = AcquireExceptionInfo();
|
||||
if( !write->exception) {
|
||||
write_free(write);
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
g_signal_connect( im, "close", G_CALLBACK( write_close ), write );
|
||||
|
||||
return( write );
|
||||
}
|
||||
|
||||
#ifdef HAVE_MAGICK7
|
||||
|
||||
static int
|
||||
magick_write_block( VipsRegion *region, VipsRect *area, void *a )
|
||||
{
|
||||
Write *write = (Write *) a;
|
||||
MagickBooleanType status;
|
||||
void *p;
|
||||
|
||||
p = VIPS_REGION_ADDR(region, area->left, area->top);
|
||||
|
||||
status=ImportImagePixels( write->current_image, area->left, area->top,
|
||||
area->width, area->height, write->map, write->storageType, p,
|
||||
write->exception );
|
||||
|
||||
return( status == MagickFalse ? -1 : 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
magick_create_image( Write *write, VipsImage *im )
|
||||
{
|
||||
Image *image;
|
||||
|
||||
if( write->image == NULL ) {
|
||||
image = AcquireImage( write->image_info, write->exception );
|
||||
if( image == NULL )
|
||||
return( -1 );
|
||||
|
||||
write->image = image;
|
||||
}
|
||||
else {
|
||||
image=GetLastImageInList( write->image );
|
||||
AcquireNextImage( write->image_info, image, write->exception );
|
||||
if( GetNextImageInList( image ) == NULL )
|
||||
return( -1 );
|
||||
|
||||
image=SyncNextImageInList( image );
|
||||
}
|
||||
|
||||
if( !SetImageExtent( image, im->Xsize, im->Ysize, write->exception ) )
|
||||
return( -1 );
|
||||
|
||||
write->current_image=image;
|
||||
return( vips_sink_disc( im, magick_write_block, write ) );
|
||||
}
|
||||
|
||||
static int
|
||||
magick_create_images( Write *write )
|
||||
{
|
||||
int height;
|
||||
int count;
|
||||
int status;
|
||||
|
||||
height = 0;
|
||||
if( vips_image_get_int( write->im, VIPS_META_PAGE_HEIGHT, &height ) )
|
||||
return( magick_create_image( write, write->im ) );
|
||||
|
||||
for( int top=0; top < write->im->Ysize ; top+=height ) {
|
||||
VipsImage *im;
|
||||
|
||||
if( vips_crop( write->im, &im, 0, top, write->im->Xsize, height, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
status = magick_create_image( write, im );
|
||||
|
||||
g_object_unref( im );
|
||||
|
||||
if( status )
|
||||
break;
|
||||
}
|
||||
|
||||
return( status );
|
||||
}
|
||||
|
||||
static int
|
||||
magick_write_images( Write *write )
|
||||
{
|
||||
if( !WriteImages( write->image_info, write->image, write->filename, write->exception ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /*HAVE_MAGICK7 */
|
||||
|
||||
int
|
||||
vips__magick_write( VipsImage *im, const char *filename )
|
||||
{
|
||||
Write *write;
|
||||
|
||||
if( !(write = write_new( filename, im )) )
|
||||
return( -1 );
|
||||
|
||||
if ( magick_create_images( write ) ) {
|
||||
vips_error( "magick2vips", _( "unable to write file \"%s\"\n"
|
||||
"libMagick error: %s %s" ),
|
||||
filename,
|
||||
write->exception->reason, write->exception->description );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( magick_write_images( write ) ) {
|
||||
vips_error( "magick2vips", _( "unable to write file \"%s\"\n"
|
||||
"libMagick error: %s %s" ),
|
||||
filename,
|
||||
write->exception->reason, write->exception->description );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /*HAVE_MAGICK | HAVE_MAGICK7*/
|
||||
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/* save with libMagick
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#if HAVE_MAGICK || HAVE_MAGICK7
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#include "pforeign.h"
|
||||
|
||||
typedef struct _VipsForeignSaveMagick {
|
||||
VipsForeignSave parent_object;
|
||||
|
||||
} VipsForeignSaveMagick;
|
||||
|
||||
typedef VipsForeignSaveClass VipsForeignSaveMagickClass;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE( VipsForeignSaveMagick, vips_foreign_save_magick,
|
||||
VIPS_TYPE_FOREIGN_SAVE );
|
||||
|
||||
/* Save a bit of typing.
|
||||
*/
|
||||
#define UC VIPS_FORMAT_UCHAR
|
||||
#define US VIPS_FORMAT_USHORT
|
||||
#define UI VIPS_FORMAT_UINT
|
||||
#define F VIPS_FORMAT_FLOAT
|
||||
#define D VIPS_FORMAT_DOUBLE
|
||||
|
||||
static int bandfmt_magick[10] = {
|
||||
/* UC C US S UI I F X D DX */
|
||||
UC, UC, US, US, UI, UI, F, F, D, D
|
||||
};
|
||||
|
||||
static void
|
||||
vips_foreign_save_magick_class_init( VipsForeignSaveMagickClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||
VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "magicksave_base";
|
||||
object_class->description = _( "save with ImageMagick" );
|
||||
|
||||
/* We need to be well to the back of the queue since vips's
|
||||
* dedicated savers are usually preferable.
|
||||
*/
|
||||
foreign_class->priority = -100;
|
||||
|
||||
save_class->saveable = VIPS_SAVEABLE_ANY;
|
||||
save_class->format_table = bandfmt_magick;
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_save_magick_init( VipsForeignSaveMagick *magick )
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignSaveMagickFile {
|
||||
VipsForeignSaveMagick parent_object;
|
||||
|
||||
char *filename;
|
||||
|
||||
} VipsForeignSaveMagickFile;
|
||||
|
||||
typedef VipsForeignSaveMagickClass VipsForeignSaveMagickFileClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsForeignSaveMagickFile, vips_foreign_save_magick_file,
|
||||
vips_foreign_save_magick_get_type() );
|
||||
|
||||
static int
|
||||
vips_foreign_save_magick_file_build( VipsObject *object )
|
||||
{
|
||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||
VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) object;
|
||||
VipsForeignSaveMagickFile *magick_file = (VipsForeignSaveMagickFile *) object;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_magick_file_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips__magick_write( save->ready, magick_file->filename ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_save_magick_file_class_init(
|
||||
VipsForeignSaveMagickFileClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->nickname = "magicksave";
|
||||
object_class->description = _( "save file with ImageMagick" );
|
||||
object_class->build = vips_foreign_save_magick_file_build;
|
||||
|
||||
VIPS_ARG_STRING( class, "filename", 1,
|
||||
_( "Filename" ),
|
||||
_( "Filename to save to" ),
|
||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||
G_STRUCT_OFFSET( VipsForeignSaveMagickFile, filename ),
|
||||
NULL );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_foreign_save_magick_file_init( VipsForeignSaveMagickFile *file )
|
||||
{
|
||||
}
|
||||
|
||||
#endif /*HAVE_MAGICK || HAVE_MAGICK7*/
|
|
@ -132,6 +132,8 @@ int vips__magick_read_buffer( const void *buf, const size_t len,
|
|||
int vips__magick_read_buffer_header( const void *buf, const size_t len,
|
||||
VipsImage *out, const char *density, int page, int n );
|
||||
|
||||
int vips__magick_write( VipsImage *in, const char *filename);
|
||||
|
||||
extern const char *vips__mat_suffs[];
|
||||
|
||||
int vips__mat_load( const char *filename, VipsImage *out );
|
||||
|
|
Loading…
Reference in New Issue