This commit is contained in:
John Cupitt 2011-11-25 09:15:45 +00:00
parent 8e853b2857
commit 25d508ff3c
7 changed files with 406 additions and 64 deletions

View File

@ -1,6 +1,8 @@
noinst_LTLIBRARIES = libfile.la
libfile_la_SOURCES = \
jpeg.c \
jpeg.h \
jpegload.c \
file.c

View File

@ -611,14 +611,217 @@ vips_file_save_print_class( VipsObjectClass *object_class, VipsBuf *buf )
*/
}
/* Generate the saveable image.
*/
static int
vips_file_convert_saveable( VipsFileSave *save )
{
VipsFileSaveClass *class = VIPS_FILE_SAVE_GET_CLASS( save );
VipsImage *in = save->in;
/* If this is an VIPS_CODING_LABQ, we can go straight to RGB.
*/
if( in->Coding == VIPS_CODING_LABQ ) {
IMAGE *t = im_open_local( out, "conv:1", "p" );
static void *table = NULL;
/* Make sure fast LabQ2disp tables are built. 7 is sRGB.
*/
if( !table )
table = im_LabQ2disp_build_table( NULL,
im_col_displays( 7 ) );
if( !t || im_LabQ2disp_table( in, t, table ) ) {
im_close( out );
return( NULL );
}
in = t;
}
/* If this is an IM_CODING_RAD, we go to float RGB or XYZ. We should
* probably un-gamma-correct the RGB :(
*/
if( in->Coding == IM_CODING_RAD ) {
IMAGE *t;
if( !(t = im_open_local( out, "conv:1", "p" )) ||
im_rad2float( in, t ) ) {
im_close( out );
return( NULL );
}
in = t;
}
/* Get the bands right.
*/
if( in->Coding == IM_CODING_NONE ) {
if( in->Bands == 2 && saveable != IM__RGBA ) {
IMAGE *t = im_open_local( out, "conv:1", "p" );
if( !t || im_extract_band( in, t, 0 ) ) {
im_close( out );
return( NULL );
}
in = t;
}
else if( in->Bands > 3 && saveable == IM__RGB ) {
IMAGE *t = im_open_local( out, "conv:1", "p" );
if( !t ||
im_extract_bands( in, t, 0, 3 ) ) {
im_close( out );
return( NULL );
}
in = t;
}
else if( in->Bands > 4 &&
(saveable == IM__RGB_CMYK || saveable == IM__RGBA) ) {
IMAGE *t = im_open_local( out, "conv:1", "p" );
if( !t ||
im_extract_bands( in, t, 0, 4 ) ) {
im_close( out );
return( NULL );
}
in = t;
}
/* Else we have saveable IM__ANY and we don't chop bands down.
*/
}
/* Interpret the Type field for colorimetric images.
*/
if( in->Bands == 3 && in->BandFmt == IM_BANDFMT_SHORT &&
in->Type == IM_TYPE_LABS ) {
IMAGE *t = im_open_local( out, "conv:1", "p" );
if( !t || im_LabS2LabQ( in, t ) ) {
im_close( out );
return( NULL );
}
in = t;
}
if( in->Coding == IM_CODING_LABQ ) {
IMAGE *t = im_open_local( out, "conv:1", "p" );
if( !t || im_LabQ2Lab( in, t ) ) {
im_close( out );
return( NULL );
}
in = t;
}
if( in->Coding != IM_CODING_NONE ) {
im_close( out );
return( NULL );
}
if( in->Bands == 3 && in->Type == IM_TYPE_LCH ) {
IMAGE *t[2];
if( im_open_local_array( out, t, 2, "conv-1", "p" ) ||
im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ||
im_LCh2Lab( t[0], t[1] ) ) {
im_close( out );
return( NULL );
}
in = t[1];
}
if( in->Bands == 3 && in->Type == IM_TYPE_YXY ) {
IMAGE *t[2];
if( im_open_local_array( out, t, 2, "conv-1", "p" ) ||
im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ||
im_Yxy2XYZ( t[0], t[1] ) ) {
im_close( out );
return( NULL );
}
in = t[1];
}
if( in->Bands == 3 && in->Type == IM_TYPE_UCS ) {
IMAGE *t[2];
if( im_open_local_array( out, t, 2, "conv-1", "p" ) ||
im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ||
im_UCS2XYZ( t[0], t[1] ) ) {
im_close( out );
return( NULL );
}
in = t[1];
}
if( in->Bands == 3 && in->Type == IM_TYPE_LAB ) {
IMAGE *t[2];
if( im_open_local_array( out, t, 2, "conv-1", "p" ) ||
im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ||
im_Lab2XYZ( t[0], t[1] ) ) {
im_close( out );
return( NULL );
}
in = t[1];
}
if( in->Bands == 3 && in->Type == IM_TYPE_XYZ ) {
IMAGE *t[2];
if( im_open_local_array( out, t, 2, "conv-1", "p" ) ||
im_clip2fmt( in, t[0], IM_BANDFMT_FLOAT ) ||
im_XYZ2disp( t[0], t[1], im_col_displays( 7 ) ) ) {
im_close( out );
return( NULL );
}
in = t[1];
}
/* Cast to the output format.
*/
{
IMAGE *t = im_open_local( out, "conv:1", "p" );
if( !t || im_clip2fmt( in, t, format_table[in->BandFmt] ) ) {
im_close( out );
return( NULL );
}
in = t;
}
if( im_copy( in, out ) ) {
im_close( out );
return( NULL );
}
return( out );
}
static int
vips_file_save_build( VipsObject *object )
{
VipsFileSave *save = VIPS_FILE_SAVE( object );
/*
VipsFile *file = VIPS_FILE( object );
VipsFileSave *save = VIPS_FILE_SAVE( object );
*/
if( vips_file_convert_saveable( save ) )
return( -1 );
if( VIPS_OBJECT_CLASS( vips_file_save_parent_class )->
build( object ) )
return( -1 );
@ -766,4 +969,3 @@ vips_file_operation_init( void )
vips_file_load_jpeg_get_type();
#endif /*HAVE_JPEG*/
}

102
libvips/file/jpeg.c Normal file
View File

@ -0,0 +1,102 @@
/* common jpeg definitions
*
* 24/11/11
* - from im_vips2jpeg.c
*/
/*
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 <string.h>
#include <setjmp.h>
#include <vips/vips.h>
/* jpeglib includes jconfig.h, which can define HAVE_STDLIB_H ... which we
* also define. Make sure it's turned off.
*/
#ifdef HAVE_STDLIB_H
#undef HAVE_STDLIB_H
#endif /*HAVE_STDLIB_H*/
#include <jpeglib.h>
#include <jerror.h>
#include "jpeg.h"
/* New output message method - send to VIPS.
*/
void
vips__new_output_message( j_common_ptr cinfo )
{
char buffer[JMSG_LENGTH_MAX];
(*cinfo->err->format_message)( cinfo, buffer );
vips_error( "VipsFile*Jpeg", _( "%s" ), buffer );
#ifdef DEBUG
printf( "jpeg.c: new_output_message: \"%s\"\n", buffer );
#endif /*DEBUG*/
}
/* New error_exit handler.
*/
void
vips__new_error_exit( j_common_ptr cinfo )
{
ErrorManager *eman = (ErrorManager *) cinfo->err;
#ifdef DEBUG
printf( "jpeg.c: new_error_exit\n" );
#endif /*DEBUG*/
/* Close the fp if necessary.
*/
if( eman->fp ) {
(void) fclose( eman->fp );
eman->fp = NULL;
}
/* Send the error message to VIPS. This method is overridden above.
*/
(*cinfo->err->output_message)( cinfo );
/* Jump back.
*/
longjmp( eman->jmp, 1 );
}

57
libvips/file/jpeg.h Normal file
View File

@ -0,0 +1,57 @@
/* common defs for jpeg read/write
*/
/*
Copyright (C) 1991-2005 The National Gallery
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
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifndef VIPS_JPEG_H
#define VIPS_JPEG_H
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus*/
/* Define a new error handler for when we bomb out.
*/
typedef struct {
/* Public fields.
*/
struct jpeg_error_mgr pub;
/* Private stuff for us.
*/
jmp_buf jmp; /* longjmp() here to get back to VIPS */
FILE *fp; /* fclose() if non-NULL */
} ErrorManager;
void vips__new_output_message( j_common_ptr cinfo );
void vips__new_error_exit( j_common_ptr cinfo );
#ifdef __cplusplus
}
#endif /*__cplusplus*/
#endif /*VIPS_JPEG_H*/

View File

@ -112,6 +112,8 @@
#include <jpeglib.h>
#include <jerror.h>
#include "jpeg.h"
typedef struct _VipsFileLoadJpeg {
VipsFileLoad parent_object;
@ -166,61 +168,6 @@ vips_file_load_jpeg_is_a( const char *filename )
return( FALSE );
}
/* Define a new error handler for when we bomb out.
*/
typedef struct {
/* Public fields.
*/
struct jpeg_error_mgr pub;
/* Private stuff for us.
*/
jmp_buf jmp; /* longjmp() here to get back to VIPS */
FILE *fp; /* fclose() if non-NULL */
} ErrorManager;
/* New output message method - send to VIPS.
*/
METHODDEF(void)
new_output_message( j_common_ptr cinfo )
{
char buffer[JMSG_LENGTH_MAX];
(*cinfo->err->format_message)( cinfo, buffer );
im_error( "VipsFileLoadJpeg", _( "%s" ), buffer );
#ifdef DEBUG
printf( "VipsFileLoadJpeg: new_output_message: \"%s\"\n", buffer );
#endif /*DEBUG*/
}
/* New error_exit handler.
*/
METHODDEF(void)
new_error_exit( j_common_ptr cinfo )
{
ErrorManager *eman = (ErrorManager *) cinfo->err;
#ifdef DEBUG
printf( "VipsFileLoadJpeg: new_error_exit\n" );
#endif /*DEBUG*/
/* Close the fp if necessary.
*/
if( eman->fp ) {
(void) fclose( eman->fp );
eman->fp = NULL;
}
/* Send the error message to VIPS. This method is overridden above.
*/
(*cinfo->err->output_message)( cinfo );
/* Jump back.
*/
longjmp( eman->jmp, 1 );
}
/* Read a cinfo to a VIPS image. Set invert_pels if the pixel reader needs to
* do 255-pel.
*/
@ -801,11 +748,11 @@ vips_file_load_jpeg_header( VipsFileLoad *load )
/* Make jpeg dcompression object.
*/
cinfo.err = jpeg_std_error( &eman.pub );
eman.pub.error_exit = new_error_exit;
eman.pub.output_message = new_output_message;
eman.pub.error_exit = vips__new_error_exit;
eman.pub.output_message = vips__new_output_message;
eman.fp = NULL;
if( setjmp( eman.jmp ) ) {
/* Here for longjmp() from new_error_exit().
/* Here for longjmp() from vips__new_error_exit().
*/
jpeg_destroy_decompress( &cinfo );
@ -904,11 +851,11 @@ vips_file_load_jpeg_load( VipsFileLoad *load )
/* Make jpeg dcompression object.
*/
cinfo.err = jpeg_std_error( &eman.pub );
eman.pub.error_exit = new_error_exit;
eman.pub.output_message = new_output_message;
eman.pub.error_exit = vips__new_error_exit;
eman.pub.output_message = vips__new_output_message;
eman.fp = NULL;
if( setjmp( eman.jmp ) ) {
/* Here for longjmp() from new_error_exit().
/* Here for longjmp() from vips__new_error_exit().
*/
jpeg_destroy_decompress( &cinfo );

View File

@ -79,6 +79,7 @@
/*
#define DEBUG_VERBOSE
#define DEBUG
#define VIPS_DEBUG
*/
#ifdef HAVE_CONFIG_H
@ -106,8 +107,9 @@
#endif /*HAVE_EXIF*/
#include <vips/vips.h>
#include <vips/buf.h>
#include <vips/internal.h>
#include <vips/debug.h>
#include <vips/buf.h>
/* jpeglib includes jconfig.h, which can define HAVE_STDLIB_H ... which we
* also define. Make sure it's turned off.
@ -119,6 +121,8 @@
#include <jpeglib.h>
#include <jerror.h>
#include "jpeg.h"
typedef struct _VipsFileSaveJpeg {
VipsFileSave parent_object;

View File

@ -174,6 +174,23 @@ const char *vips_file_find_load( const char *filename );
(G_TYPE_INSTANCE_GET_CLASS( (obj), \
VIPS_TYPE_FILE_SAVE, VipsFileSaveClass ))
/**
* VipsSaveable:
* @VIPS_SAVEABLE_RGB: 1 or 3 bands (eg. PPM)
* @VIPS_SAVEABLE_RGBA: 1, 2, 3 or 4 bands (eg. PNG)
* @VIPS_SAVEABLE_RGB_CMYK: 1, 3 or 4 bands (eg. JPEG)
* @VIPS_SAVEABLE_ANY: any number of bands (eg. TIFF)
*
* See also: #VipsFileSave.
*/
typedef enum {
VIPS_SAVEABLE_RGB,
VIPS_SAVEABLE_RGBA,
VIPS_SAVEABLE_RGB_CMYK,
VIPS_SAVEABLE_ANY,
VIPS_SAVEABLE_LAST
} VipsSaveable;
typedef struct _VipsFileSave {
VipsFile parent_object;
/*< public >*/
@ -182,6 +199,10 @@ typedef struct _VipsFileSave {
*/
VipsImage *in;
/* The image converted to a saveable format (eg. 8-bit RGB).
*/
VipsImage *in;
} VipsFileSave;
typedef struct _VipsFileSaveClass {
@ -189,6 +210,13 @@ typedef struct _VipsFileSaveClass {
/*< public >*/
/* How this format treats bands.
*/
VipsSaveable saveable;
/* How this format treats band formats.
*/
VipsBandFormat format_table[VIPS_FORMAT_LAST];
} VipsFileSaveClass;
GType vips_file_save_get_type( void );