almost there

not unpacking correctly though
This commit is contained in:
John Cupitt 2016-02-11 08:35:29 +00:00
parent 9f2da7d0ee
commit d79407f285
5 changed files with 587 additions and 2 deletions

View File

@ -564,3 +564,123 @@ dnl |
dnl |Thomas:
dnl | I think that might be a good starting point (with the set of recommended
dnl | ifdef's and includes for AC_HEADER_DIRENT, of course).
dnl From FIND_MOTIF and ACX_PTHREAD, without much understanding
dnl
dnl FIND_GIFLIB[ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]
dnl ---------------------------------------------------
dnl
dnl Find GIFLIB libraries and headers
dnl
dnl Put compile stuff in GIFLIB_INCLUDES
dnl Put link stuff in GIFLIB_LIBS
dnl Define HAVE_GIFLIB if found.
dnl
AC_DEFUN([FIND_GIFLIB], [
AC_REQUIRE([AC_PATH_XTRA])
GIFLIB_INCLUDES=""
GIFLIB_LIBS=""
AC_ARG_WITH(giflib,
AS_HELP_STRING([--without-giflib], [build without giflib (default: test)]))
# Treat --without-giflib like --without-giflib-includes --without-giflib-libraries.
if test "$with_giflib" = "no"; then
GIFLIB_INCLUDES=no
GIFLIB_LIBS=no
fi
AC_ARG_WITH(giflib-includes,
AS_HELP_STRING([--with-giflib-includes=DIR], [giflib includes are in DIR]),
GIFLIB_INCLUDES="-I$withval")
AC_ARG_WITH(giflib-libraries,
AS_HELP_STRING([--with-giflib-libraries=DIR], [giflib libraries are in DIR]),
GIFLIB_LIBS="-L$withval -lgif")
AC_MSG_CHECKING(for giflib)
# Look for gif_lib.h
if test "$GIFLIB_INCLUDES" = ""; then
# Check the standard search path
AC_TRY_COMPILE([#include <gif_lib.h>],[int a;],[
GIFLIB_INCLUDES=""
], [
# gif_lib.h is not in the standard search path, try
# $prefix
giflib_save_INCLUDES="$INCLUDES"
INCLUDES="-I${prefix}/include $INCLUDES"
AC_TRY_COMPILE([#include <gif_lib.h>],[int a;],[
GIFLIB_INCLUDES="-I${prefix}/include"
], [
GIFLIB_INCLUDES="no"
])
INCLUDES=$giflib_save_INCLUDES
])
fi
# Now for the libraries
if test "$GIFLIB_LIBS" = ""; then
giflib_save_LIBS="$LIBS"
giflib_save_INCLUDES="$INCLUDES"
LIBS="-lgif $LIBS"
INCLUDES="$GIFLIB_INCLUDES $INCLUDES"
# Try the standard search path first
AC_TRY_LINK([#include <gif_lib.h>],[EGifSetGifVersion("")], [
GIFLIB_LIBS="-lgif"
], [
# giflib is not in the standard search path, try $prefix
LIBS="-L${prefix}/lib $LIBS"
AC_TRY_LINK([#include <gif_lib.h>],[EGifSetGifVersion("")], [
GIFLIB_LIBS="-L${prefix}/lib -lgif"
], [
GIFLIB_LIBS=no
])
])
LIBS="$giflib_save_LIBS"
INCLUDES="$giflib_save_INCLUDES"
fi
AC_SUBST(GIFLIB_LIBS)
AC_SUBST(GIFLIB_INCLUDES)
# Print a helpful message
giflib_libraries_result="$GIFLIB_LIBS"
giflib_includes_result="$GIFLIB_INCLUDES"
if test x"$giflib_libraries_result" = x""; then
giflib_libraries_result="in default path"
fi
if test x"$giflib_includes_result" = x""; then
giflib_includes_result="in default path"
fi
if test "$giflib_libraries_result" = "no"; then
giflib_libraries_result="(none)"
fi
if test "$giflib_includes_result" = "no"; then
giflib_includes_result="(none)"
fi
AC_MSG_RESULT([libraries $giflib_libraries_result, headers $giflib_includes_result])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test "$GIFLIB_INCLUDES" != "no" && test "$GIFLIB_LIBS" != "no"; then
AC_DEFINE(HAVE_GIFLIB,1,[Define if you have giflib libraries and header files.])
$1
else
GIFLIB_INCLUDES=""
GIFLIB_LIBS=""
$2
fi
])dnl

View File

@ -718,6 +718,14 @@ if test x"$with_tiff" != "xno"; then
])
fi
# giflib
FIND_GIFLIB([
with_giflib="yes (found by search)"
], [
AC_MSG_WARN([giflib not found; disabling direct GIF support])
with_giflib=no
])
# look for PNG with pkg-config ... fall back to our tester
AC_ARG_WITH([png],
AS_HELP_STRING([--without-png], [build without libpng (default: test)]))
@ -822,14 +830,14 @@ fi
# Gather all up for VIPS_CFLAGS, VIPS_INCLUDES, VIPS_LIBS
# sort includes to get longer, more specific dirs first
# helps, for example, selecting graphicsmagick over imagemagick
VIPS_CFLAGS=`for i in $VIPS_CFLAGS $GTHREAD_CFLAGS $REQUIRED_CFLAGS $PANGOFT2_CFLAGS $GSF_CFLAGS $FFTW_CFLAGS $MAGICK_CFLAGS $PNG_CFLAGS $EXIF_CFLAGS $MATIO_CFLAGS $CFITSIO_CFLAGS $LIBWEBP_CFLAGS $RSVG_CFLAGS $POPPLER_CFLAGS $OPENEXR_CFLAGS $OPENSLIDE_CFLAGS $ORC_CFLAGS $TIFF_CFLAGS $LCMS_CFLAGS
VIPS_CFLAGS=`for i in $VIPS_CFLAGS $GTHREAD_CFLAGS $REQUIRED_CFLAGS $PANGOFT2_CFLAGS $GSF_CFLAGS $FFTW_CFLAGS $MAGICK_CFLAGS $PNG_CFLAGS $EXIF_CFLAGS $MATIO_CFLAGS $CFITSIO_CFLAGS $LIBWEBP_CFLAGS $GIFLIB_INCLUDES $RSVG_CFLAGS $POPPLER_CFLAGS $OPENEXR_CFLAGS $OPENSLIDE_CFLAGS $ORC_CFLAGS $TIFF_CFLAGS $LCMS_CFLAGS
do
echo $i
done | sort -ru`
VIPS_CFLAGS=`echo $VIPS_CFLAGS`
VIPS_CFLAGS="$VIPS_DEBUG_FLAGS $VIPS_CFLAGS"
VIPS_INCLUDES="$PNG_INCLUDES $TIFF_INCLUDES $ZIP_INCLUDES $JPEG_INCLUDES"
VIPS_LIBS="$MAGICK_LIBS $PNG_LIBS $TIFF_LIBS $ZIP_LIBS $JPEG_LIBS $GTHREAD_LIBS $REQUIRED_LIBS $PANGOFT2_LIBS $GSF_LIBS $FFTW_LIBS $ORC_LIBS $LCMS_LIBS $RSVG_LIBS $POPPLER_LIBS $OPENEXR_LIBS $OPENSLIDE_LIBS $CFITSIO_LIBS $LIBWEBP_LIBS $MATIO_LIBS $EXIF_LIBS -lm"
VIPS_LIBS="$MAGICK_LIBS $PNG_LIBS $TIFF_LIBS $ZIP_LIBS $JPEG_LIBS $GTHREAD_LIBS $REQUIRED_LIBS $PANGOFT2_LIBS $GSF_LIBS $FFTW_LIBS $ORC_LIBS $LCMS_LIBS $GIFLIB_LIBS $RSVG_LIBS $POPPLER_LIBS $OPENEXR_LIBS $OPENSLIDE_LIBS $CFITSIO_LIBS $LIBWEBP_LIBS $MATIO_LIBS $EXIF_LIBS -lm"
AC_SUBST(VIPS_LIBDIR)
@ -925,6 +933,7 @@ text rendering with pangoft2: $with_pangoft2
file import/export with libpng: $with_png
(requires libpng-1.2.9 or later)
file import/export with libtiff: $with_tiff
file import/export with giflib: $with_giflib
file import/export with libjpeg: $with_jpeg
image pyramid export: $with_gsf
(requires libgsf-1 1.14.27 or later)

View File

@ -1,6 +1,7 @@
noinst_LTLIBRARIES = libforeign.la
libforeign_la_SOURCES = \
gifload.c \
pdfload.c \
svgload.c \
radiance.h \

View File

@ -1660,6 +1660,9 @@ vips_foreign_operation_init( void )
extern GType vips_foreign_load_svg_get_type( void );
extern GType vips_foreign_load_svg_file_get_type( void );
extern GType vips_foreign_load_svg_buffer_get_type( void );
extern GType vips_foreign_load_gif_get_type( void );
extern GType vips_foreign_load_gif_file_get_type( void );
extern GType vips_foreign_load_gif_buffer_get_type( void );
vips_foreign_load_rad_get_type();
vips_foreign_save_rad_get_type();
@ -1689,6 +1692,12 @@ vips_foreign_operation_init( void )
vips_foreign_load_svg_buffer_get_type();
#endif /*HAVE_RSVG*/
#ifdef HAVE_GIFLIB
vips_foreign_load_gif_get_type();
vips_foreign_load_gif_file_get_type();
vips_foreign_load_gif_buffer_get_type();
#endif /*HAVE_GIFLIB*/
#ifdef HAVE_GSF
vips_foreign_save_dz_get_type();
#endif /*HAVE_GSF*/

446
libvips/foreign/gifload.c Normal file
View File

@ -0,0 +1,446 @@
/* load a GIF with giflib
*
* 10/2/16
* - from svgload.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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 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>
#ifdef HAVE_GIFLIB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <vips/vips.h>
#include <vips/buf.h>
#include <vips/internal.h>
#include <gif_lib.h>
typedef struct _VipsForeignLoadGif {
VipsForeignLoad parent_object;
GifFileType *file;
/* The bitmap for the frame we fetch.
*/
unsigned char *RasterBits;
} VipsForeignLoadGif;
typedef VipsForeignLoadClass VipsForeignLoadGifClass;
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadGif, vips_foreign_load_gif,
VIPS_TYPE_FOREIGN_LOAD );
/* From gif-lib.h
#define D_GIF_ERR_OPEN_FAILED 101
#define D_GIF_ERR_READ_FAILED 102
#define D_GIF_ERR_NOT_GIF_FILE 103
#define D_GIF_ERR_NO_SCRN_DSCR 104
#define D_GIF_ERR_NO_IMAG_DSCR 105
#define D_GIF_ERR_NO_COLOR_MAP 106
#define D_GIF_ERR_WRONG_RECORD 107
#define D_GIF_ERR_DATA_TOO_BIG 108
#define D_GIF_ERR_NOT_ENOUGH_MEM 109
#define D_GIF_ERR_CLOSE_FAILED 110
#define D_GIF_ERR_NOT_READABLE 111
#define D_GIF_ERR_IMAGE_DEFECT 112
#define D_GIF_ERR_EOF_TOO_SOON 113
*/
static const char *
vips_foreign_load_gif_errstr( int error_code )
{
switch( error_code ) {
case D_GIF_ERR_OPEN_FAILED:
return( _( "Failed to open given file" ) );
case D_GIF_ERR_READ_FAILED:
return( _( "Failed to read from given file" ) );
case D_GIF_ERR_NOT_GIF_FILE:
return( _( "Data is not a GIF file" ) );
case D_GIF_ERR_NO_SCRN_DSCR:
return( _( "No screen descriptor detected" ) );
case D_GIF_ERR_NO_IMAG_DSCR:
return( _( "No image descriptor detected" ) );
case D_GIF_ERR_NO_COLOR_MAP:
return( _( "Neither global nor local color map" ) );
case D_GIF_ERR_WRONG_RECORD:
return( _( "Wrong record type detected" ) );
case D_GIF_ERR_DATA_TOO_BIG:
return( _( "Number of pixels bigger than width * height" ) );
case D_GIF_ERR_NOT_ENOUGH_MEM:
return( _( "Failed to allocate required memory" ) );
case D_GIF_ERR_CLOSE_FAILED:
return( _( "Failed to close given file" ) );
case D_GIF_ERR_NOT_READABLE:
return( _( "Given file was not opened for read" ) );
case D_GIF_ERR_IMAGE_DEFECT:
return( _( "Image is defective, decoding aborted" ) );
case D_GIF_ERR_EOF_TOO_SOON:
return( _( "Image EOF detected, before image complete" ) );
default:
return( _( "Unknown error" ) );
}
}
static void
vips_foreign_load_gif_dispose( GObject *gobject )
{
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) gobject;
VIPS_FREEF( EGifCloseFile, gif->file );
G_OBJECT_CLASS( vips_foreign_load_gif_parent_class )->
dispose( gobject );
}
static VipsForeignFlags
vips_foreign_load_gif_get_flags_filename( const char *filename )
{
/* We can render any part of the image on demand.
*/
return( VIPS_FOREIGN_PARTIAL );
}
static VipsForeignFlags
vips_foreign_load_gif_get_flags( VipsForeignLoad *load )
{
return( VIPS_FOREIGN_PARTIAL );
}
static gboolean
vips_foreign_load_gif_is_a_buffer( const void *buf, size_t len )
{
const guchar *str = (const guchar *) buf;
if( len >= 4 &&
str[0] == 'G' &&
str[1] == 'I' &&
str[2] == 'F' &&
str[3] == '8' )
return( 1 );
return( 0 );
}
static gboolean
vips_foreign_load_gif_is_a( const char *filename )
{
unsigned char buf[4];
if( vips__get_bytes( filename, buf, 4 ) &&
vips_foreign_load_gif_is_a_buffer( buf, 4 ) )
return( 1 );
return( 0 );
}
static void
vips_foreign_load_gif_parse( VipsForeignLoadGif *gif,
VipsImage *out )
{
vips_image_init_fields( out,
gif->file->SWidth, gif->file->SHeight,
4, VIPS_FORMAT_UCHAR,
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 );
/* We have the whole GIF in memory, so we can render any area.
*/
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_ANY, NULL );
}
static int
vips_foreign_load_gif_header( VipsForeignLoad *load )
{
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
if( DGifSlurp( gif->file ) != GIF_OK ) {
vips_error( class->nickname,
_( "unable to decode GIF file: %s" ),
vips_foreign_load_gif_errstr( GifLastError() ) );
return( -1 );
}
if( gif->file->SavedImages &&
gif->file->SavedImages->RasterBits )
gif->RasterBits = gif->file->SavedImages->RasterBits;
vips_foreign_load_gif_parse( gif, load->out );
return( 0 );
}
static int
vips_foreign_load_gif_generate( VipsRegion *or,
void *seq, void *a, void *b, gboolean *stop )
{
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) a;
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
VipsRect *r = &or->valid;
unsigned char *bits = gif->RasterBits;
ColorMapObject *map = gif->file->SColorMap;
int width = gif->file->Image.Width;
if( bits &&
map ) {
int count = map->ColorCount;
int x, y;
for( y = 0; y < r->height; y++ ) {
VipsPel * restrict p;
VipsPel * restrict q;
p = bits + r->left + (r->top + y) * width;
q = VIPS_REGION_ADDR( or, r->left, r->top + y );
for( x = 0; x < r->width; x++ ) {
if( p[x] < count &&
p[x] != gif->file->SBackGroundColor ) {
q[0] = map->Colors[p[x]].Red;
q[1] = map->Colors[p[x]].Green;
q[2] = map->Colors[p[x]].Blue;
q[3] = 255;
}
else {
q[0] = 0;
q[1] = 0;
q[2] = 0;
q[3] = 0;
}
q += 4;
}
}
}
return( 0 );
}
static int
vips_foreign_load_gif_load( VipsForeignLoad *load )
{
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
vips_foreign_load_gif_parse( gif, load->real );
if( vips_image_generate( load->real,
NULL, vips_foreign_load_gif_generate, NULL, gif, NULL ) )
return( -1 );
return( 0 );
}
static void
vips_foreign_load_gif_class_init( VipsForeignLoadGifClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->dispose = vips_foreign_load_gif_dispose;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "gifload";
object_class->description = _( "load GIF with giflib" );
load_class->get_flags_filename =
vips_foreign_load_gif_get_flags_filename;
load_class->get_flags = vips_foreign_load_gif_get_flags;
load_class->load = vips_foreign_load_gif_load;
}
static void
vips_foreign_load_gif_init( VipsForeignLoadGif *gif )
{
}
typedef struct _VipsForeignLoadGifFile {
VipsForeignLoadGif parent_object;
/* Filename for load.
*/
char *filename;
} VipsForeignLoadGifFile;
typedef VipsForeignLoadGifClass VipsForeignLoadGifFileClass;
G_DEFINE_TYPE( VipsForeignLoadGifFile, vips_foreign_load_gif_file,
vips_foreign_load_gif_get_type() );
static int
vips_foreign_load_gif_file_header( VipsForeignLoad *load )
{
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( load );
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
VipsForeignLoadGifFile *file = (VipsForeignLoadGifFile *) load;
if( !(gif->file = DGifOpenFileName( file->filename )) ) {
vips_error( class->nickname,
"%s", _( "unable to open GIF file" ) );
return( -1 );
}
return( vips_foreign_load_gif_header( load ) );
}
static const char *vips_foreign_gif_suffs[] = {
".gif",
NULL
};
static void
vips_foreign_load_gif_file_class_init(
VipsForeignLoadGifFileClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "gifload";
object_class->description = _( "load GIF with giflib" );
foreign_class->suffs = vips_foreign_gif_suffs;
load_class->is_a = vips_foreign_load_gif_is_a;
load_class->header = vips_foreign_load_gif_file_header;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadGifFile, filename ),
NULL );
}
static void
vips_foreign_load_gif_file_init( VipsForeignLoadGifFile *file )
{
}
typedef struct _VipsForeignLoadGifBuffer {
VipsForeignLoadGif parent_object;
/* Load from a buffer.
*/
VipsArea *buf;
} VipsForeignLoadGifBuffer;
typedef VipsForeignLoadGifClass VipsForeignLoadGifBufferClass;
G_DEFINE_TYPE( VipsForeignLoadGifBuffer, vips_foreign_load_gif_buffer,
vips_foreign_load_gif_get_type() );
static int
vips_foreign_load_gif_buffer_header( VipsForeignLoad *load )
{
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
VipsForeignLoadGifBuffer *buffer =
(VipsForeignLoadGifBuffer *) load;
/*
if( !(gif->page = rgif_handle_new_from_data(
buffer->buf->data, buffer->buf->length, &error )) ) {
vips_g_error( &error );
return( -1 );
}
*/
return( vips_foreign_load_gif_header( load ) );
}
static void
vips_foreign_load_gif_buffer_class_init(
VipsForeignLoadGifBufferClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "gifload_buffer";
object_class->description = _( "load GIF with giflib" );
load_class->is_a_buffer = vips_foreign_load_gif_is_a_buffer;
load_class->header = vips_foreign_load_gif_buffer_header;
VIPS_ARG_BOXED( class, "buffer", 1,
_( "Buffer" ),
_( "Buffer to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadGifBuffer, buf ),
VIPS_TYPE_BLOB );
}
static void
vips_foreign_load_gif_buffer_init( VipsForeignLoadGifBuffer *buffer )
{
}
#endif /*HAVE_RSVG*/