Merge branch 'master' into region-shrink-method
This commit is contained in:
commit
b752d2e442
27
.travis.yml
27
.travis.yml
@ -14,27 +14,6 @@ matrix:
|
|||||||
- os: osx
|
- os: osx
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
include:
|
include:
|
||||||
- os: linux
|
|
||||||
sudo: required
|
|
||||||
dist: precise
|
|
||||||
env:
|
|
||||||
- JPEG=/usr
|
|
||||||
- JOBS=`nproc`
|
|
||||||
- LIBTOOLFLAGS=--quiet
|
|
||||||
cache: ccache
|
|
||||||
before_install:
|
|
||||||
- sudo apt-get update -qq
|
|
||||||
- sudo apt-get install -y
|
|
||||||
automake gtk-doc-tools
|
|
||||||
gobject-introspection
|
|
||||||
libfftw3-dev libjpeg-turbo8-dev
|
|
||||||
libpng12-dev libwebp-dev libtiff4-dev libexpat1-dev
|
|
||||||
swig libmagick++-dev bc
|
|
||||||
libcfitsio3-dev libgsl0-dev libmatio-dev
|
|
||||||
liborc-0.4-dev liblcms2-dev libpoppler-glib-dev
|
|
||||||
librsvg2-dev libgif-dev
|
|
||||||
libpango1.0-dev
|
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
sudo: required
|
sudo: required
|
||||||
dist: trusty
|
dist: trusty
|
||||||
@ -58,18 +37,14 @@ matrix:
|
|||||||
- os: osx
|
- os: osx
|
||||||
osx_image: xcode7.3
|
osx_image: xcode7.3
|
||||||
env:
|
env:
|
||||||
- JPEG=/usr/local/opt/mozjpeg
|
|
||||||
- JOBS="`sysctl -n hw.ncpu`"
|
- JOBS="`sysctl -n hw.ncpu`"
|
||||||
- PATH="/usr/local/opt/ccache/libexec:$PATH"
|
- PATH="/usr/local/opt/ccache/libexec:$PATH"
|
||||||
cache: ccache
|
cache: ccache
|
||||||
before_install:
|
before_install:
|
||||||
- brew tap homebrew/science
|
|
||||||
- brew update
|
- brew update
|
||||||
- brew install ccache
|
- brew install ccache
|
||||||
- brew install --ignore-dependencies gtk-doc
|
|
||||||
- brew install
|
- brew install
|
||||||
gobject-introspection
|
fftw libexif
|
||||||
fftw mozjpeg libexif
|
|
||||||
libpng webp
|
libpng webp
|
||||||
swig imagemagick
|
swig imagemagick
|
||||||
cfitsio libmatio
|
cfitsio libmatio
|
||||||
|
15
ChangeLog
15
ChangeLog
@ -9,9 +9,22 @@
|
|||||||
- add vips_rotate() ... a convenience method for vips_similarity()
|
- add vips_rotate() ... a convenience method for vips_similarity()
|
||||||
- svgload was missing is_a [lovell]
|
- svgload was missing is_a [lovell]
|
||||||
- better header sniffing for small files
|
- better header sniffing for small files
|
||||||
|
- drop incompatible ICC profiles before save
|
||||||
|
- better hasalpha rules
|
||||||
|
- create funcs always make MULTIBAND (ie. no alpha)
|
||||||
|
- use O_TMPFILE, if available [Alexander--]
|
||||||
|
- set "interlaced=1" for interlaced JPG and PNG images
|
||||||
|
- add PDFium PDF loader
|
||||||
|
- add @format option to magickload
|
||||||
|
- jpegload adds a jpeg-chroma-subsample field with eg. 4:4:4 for no
|
||||||
|
chrominance subsampling.
|
||||||
|
- tiffload, pdfload, magickload set VIPS_META_N_PAGES "n-pages" metadata item
|
||||||
|
- add fontfile option to vips_text() [fangqiao]
|
||||||
|
|
||||||
12/3/18 started 8.6.4
|
12/3/18 started 8.6.4
|
||||||
- better fitting of fonts with overhanging edges, thanks Adrià
|
- better fitting of fonts with overhanging edges [Adrià]
|
||||||
|
- revise C++ example [fangqiao]
|
||||||
|
- strict round down on jpeg shrink on load [davidwood]
|
||||||
|
|
||||||
12/2/18 started 8.6.3
|
12/2/18 started 8.6.3
|
||||||
- use pkg-config to find libjpeg, if we can
|
- use pkg-config to find libjpeg, if we can
|
||||||
|
@ -202,10 +202,17 @@ via imagemagick instead.
|
|||||||
The usual SVG loader. If this is not present, vips will try to load SVGs
|
The usual SVG loader. If this is not present, vips will try to load SVGs
|
||||||
via imagemagick instead.
|
via imagemagick instead.
|
||||||
|
|
||||||
|
### PDFium
|
||||||
|
|
||||||
|
If present, libvips will attempt to load PDFs via PDFium. This library must be
|
||||||
|
packaged by https://github.com/jcupitt/docker-builds/tree/master/pdfium
|
||||||
|
|
||||||
|
If PDFium is not detected, libvips will look for poppler-glib instead.
|
||||||
|
|
||||||
### libpoppler
|
### libpoppler
|
||||||
|
|
||||||
The usual PDF loader. If this is not present, vips will try to load PDFs
|
The usual PDF loader. If this is not present, vips will try to load PDFs
|
||||||
via imagemagick instead.
|
via imagemagick.
|
||||||
|
|
||||||
### libgsf-1
|
### libgsf-1
|
||||||
|
|
||||||
|
64
configure.ac
64
configure.ac
@ -482,7 +482,7 @@ PKG_CHECK_MODULES(TYPE_INIT, glib-2.0 < 2.36,
|
|||||||
)
|
)
|
||||||
|
|
||||||
# from 2.40 we have g_win32_get_command_line() on win
|
# from 2.40 we have g_win32_get_command_line() on win
|
||||||
PKG_CHECK_MODULES(TYPE_INIT, glib-2.0 >= 2.40,
|
PKG_CHECK_MODULES(WIN32_GET_COMMAND_LINE, glib-2.0 >= 2.40,
|
||||||
[if test x"$vips_os_win32" = x"yes"; then
|
[if test x"$vips_os_win32" = x"yes"; then
|
||||||
AC_DEFINE(HAVE_G_WIN32_GET_COMMAND_LINE,1,[define if your glib has g_win32_get_command_line().])
|
AC_DEFINE(HAVE_G_WIN32_GET_COMMAND_LINE,1,[define if your glib has g_win32_get_command_line().])
|
||||||
have_g_win32_get_command_line=yes
|
have_g_win32_get_command_line=yes
|
||||||
@ -670,6 +670,46 @@ if test x"$magick6" = x"yes"; then
|
|||||||
CFLAGS="$save_CFLAGS"
|
CFLAGS="$save_CFLAGS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test x"$magick6" = x"yes"; then
|
||||||
|
# more recent magick6s have AcquireImage rather than AllocateImage argh
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $MAGICK_LIBS"
|
||||||
|
AC_CHECK_FUNCS(AcquireImage,
|
||||||
|
AC_DEFINE(HAVE_ACQUIREIMAGE,1,
|
||||||
|
[define if your magick has AcquireImage.]))
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x"$magick6" = x"yes"; then
|
||||||
|
# more recent magick6s have SetImageExtent
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $MAGICK_LIBS"
|
||||||
|
AC_CHECK_FUNCS(SetImageExtent,
|
||||||
|
AC_DEFINE(HAVE_SETIMAGEEXTENT,1,
|
||||||
|
[define if your magick has SetImageExtent.]))
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x"$magick6" = x"yes"; then
|
||||||
|
# GM uses SetImageAttribute(), IM uses SetImageProperty()
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $MAGICK_LIBS"
|
||||||
|
AC_CHECK_FUNCS(SetImageProperty,
|
||||||
|
AC_DEFINE(HAVE_SETIMAGEPROPERTY,1,
|
||||||
|
[define if your magick has SetImageProperty.]))
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x"$magick6" = x"yes"; then
|
||||||
|
# GM is missing InheritException
|
||||||
|
save_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $MAGICK_LIBS"
|
||||||
|
AC_CHECK_FUNCS(InheritException,
|
||||||
|
AC_DEFINE(HAVE_INHERITEXCEPTION,1,
|
||||||
|
[define if your magick has InheritException.]))
|
||||||
|
LIBS="$save_LIBS"
|
||||||
|
fi
|
||||||
|
|
||||||
# have flags to turn load and save off independently ... some people will want
|
# have flags to turn load and save off independently ... some people will want
|
||||||
# save but not load, for example
|
# save but not load, for example
|
||||||
AC_ARG_ENABLE([magickload],
|
AC_ARG_ENABLE([magickload],
|
||||||
@ -751,6 +791,23 @@ if test x"$with_OpenEXR" != "xno"; then
|
|||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# pdfium
|
||||||
|
AC_ARG_WITH([pdfium],
|
||||||
|
AS_HELP_STRING([--without-pdfium], [build without pdfium (default: test)]))
|
||||||
|
|
||||||
|
if test x"$with_pdfium" != x"no"; then
|
||||||
|
FIND_PDFIUM([
|
||||||
|
if test x"$with_poppler" != x"no"; then
|
||||||
|
AC_MSG_WARN([PDFium found, disabling poppler])
|
||||||
|
with_poppler=no
|
||||||
|
fi
|
||||||
|
with_pdfium=yes
|
||||||
|
],[
|
||||||
|
with_pdfium=no
|
||||||
|
]
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
# poppler
|
# poppler
|
||||||
AC_ARG_WITH([poppler],
|
AC_ARG_WITH([poppler],
|
||||||
AS_HELP_STRING([--without-poppler], [build without poppler (default: test)]))
|
AS_HELP_STRING([--without-poppler], [build without poppler (default: test)]))
|
||||||
@ -1152,14 +1209,14 @@ fi
|
|||||||
# Gather all up for VIPS_CFLAGS, VIPS_INCLUDES, VIPS_LIBS
|
# Gather all up for VIPS_CFLAGS, VIPS_INCLUDES, VIPS_LIBS
|
||||||
# sort includes to get longer, more specific dirs first
|
# sort includes to get longer, more specific dirs first
|
||||||
# helps, for example, selecting graphicsmagick over imagemagick
|
# helps, for example, selecting graphicsmagick over imagemagick
|
||||||
VIPS_CFLAGS=`for i in $VIPS_CFLAGS $GTHREAD_CFLAGS $REQUIRED_CFLAGS $EXPAT_CFLAGS $ZLIB_CFLAGS $PANGOFT2_CFLAGS $GSF_CFLAGS $FFTW_CFLAGS $MAGICK_CFLAGS $PNG_CFLAGS $EXIF_CFLAGS $MATIO_CFLAGS $CFITSIO_CFLAGS $LIBWEBP_CFLAGS $LIBWEBPMUX_CFLAGS $GIFLIB_INCLUDES $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 $EXPAT_CFLAGS $ZLIB_CFLAGS $PANGOFT2_CFLAGS $GSF_CFLAGS $FFTW_CFLAGS $MAGICK_CFLAGS $PNG_CFLAGS $EXIF_CFLAGS $MATIO_CFLAGS $CFITSIO_CFLAGS $LIBWEBP_CFLAGS $LIBWEBPMUX_CFLAGS $GIFLIB_INCLUDES $RSVG_CFLAGS $PDFIUM_INCLUDES $POPPLER_CFLAGS $OPENEXR_CFLAGS $OPENSLIDE_CFLAGS $ORC_CFLAGS $TIFF_CFLAGS $LCMS_CFLAGS
|
||||||
do
|
do
|
||||||
echo $i
|
echo $i
|
||||||
done | sort -ru`
|
done | sort -ru`
|
||||||
VIPS_CFLAGS=`echo $VIPS_CFLAGS`
|
VIPS_CFLAGS=`echo $VIPS_CFLAGS`
|
||||||
VIPS_CFLAGS="$VIPS_DEBUG_FLAGS $VIPS_CFLAGS"
|
VIPS_CFLAGS="$VIPS_DEBUG_FLAGS $VIPS_CFLAGS"
|
||||||
VIPS_INCLUDES="$ZLIB_INCLUDES $PNG_INCLUDES $TIFF_INCLUDES $JPEG_INCLUDES"
|
VIPS_INCLUDES="$ZLIB_INCLUDES $PNG_INCLUDES $TIFF_INCLUDES $JPEG_INCLUDES"
|
||||||
VIPS_LIBS="$ZLIB_LIBS $MAGICK_LIBS $PNG_LIBS $TIFF_LIBS $JPEG_LIBS $GTHREAD_LIBS $REQUIRED_LIBS $EXPAT_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 $LIBWEBPMUX_LIBS $MATIO_LIBS $EXIF_LIBS -lm"
|
VIPS_LIBS="$ZLIB_LIBS $MAGICK_LIBS $PNG_LIBS $TIFF_LIBS $JPEG_LIBS $GTHREAD_LIBS $REQUIRED_LIBS $EXPAT_LIBS $PANGOFT2_LIBS $GSF_LIBS $FFTW_LIBS $ORC_LIBS $LCMS_LIBS $GIFLIB_LIBS $RSVG_LIBS $PDFIUM_LIBS $POPPLER_LIBS $OPENEXR_LIBS $OPENSLIDE_LIBS $CFITSIO_LIBS $LIBWEBP_LIBS $LIBWEBPMUX_LIBS $MATIO_LIBS $EXIF_LIBS -lm"
|
||||||
|
|
||||||
AC_SUBST(VIPS_LIBDIR)
|
AC_SUBST(VIPS_LIBDIR)
|
||||||
|
|
||||||
@ -1253,6 +1310,7 @@ file import with OpenEXR: $with_OpenEXR
|
|||||||
file import with OpenSlide: $with_openslide
|
file import with OpenSlide: $with_openslide
|
||||||
(requires openslide-3.3.0 or later)
|
(requires openslide-3.3.0 or later)
|
||||||
file import with matio: $with_matio
|
file import with matio: $with_matio
|
||||||
|
PDF import with PDFium $with_pdfium
|
||||||
PDF import with poppler-glib: $with_poppler
|
PDF import with poppler-glib: $with_poppler
|
||||||
(requires poppler-glib 0.16.0 or later)
|
(requires poppler-glib 0.16.0 or later)
|
||||||
SVG import with librsvg-2.0: $with_rsvg
|
SVG import with librsvg-2.0: $with_rsvg
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
<programlisting language="cpp">
|
<programlisting language="cpp">
|
||||||
/* compile with:
|
/* compile with:
|
||||||
* g++ -g -Wall try.cc `pkg-config vips-cpp --cflags --libs`
|
* g++ -g -Wall example.cc `pkg-config vips-cpp --cflags --libs`
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vips/vips8>
|
#include <vips/vips8>
|
||||||
@ -34,64 +34,47 @@
|
|||||||
using namespace vips;
|
using namespace vips;
|
||||||
|
|
||||||
int
|
int
|
||||||
main( int argc, char **argv )
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
GOptionContext *context;
|
if (VIPS_INIT (argv[0]))
|
||||||
GOptionGroup *main_group;
|
vips_error_exit (NULL);
|
||||||
GError *error = NULL;
|
|
||||||
|
if (argc != 3)
|
||||||
|
vips_error_exit ("usage: %s input-file output-file", argv[0]);
|
||||||
|
|
||||||
if( VIPS_INIT( argv[0] ) )
|
VImage in = VImage::new_from_file (argv[1],
|
||||||
vips_error_exit( NULL );
|
VImage::option ()->set ("access", VIPS_ACCESS_SEQUENTIAL));
|
||||||
|
|
||||||
context = g_option_context_new( "" );
|
double avg = in.avg ();
|
||||||
|
|
||||||
main_group = g_option_group_new( NULL, NULL, NULL, NULL, NULL );
|
printf ("avg = %g\n", avg);
|
||||||
g_option_context_set_main_group( context, main_group );
|
printf ("width = %d\n", in.width ());
|
||||||
g_option_context_add_group( context, vips_get_option_group() );
|
|
||||||
|
in = VImage::new_from_file (argv[1],
|
||||||
if( !g_option_context_parse( context, &argc, &argv, &error ) ) {
|
VImage::option ()->set ("access", VIPS_ACCESS_SEQUENTIAL));
|
||||||
if( error ) {
|
|
||||||
fprintf( stderr, "%s\n", error->message );
|
VImage out = in.embed (10, 10, 1000, 1000,
|
||||||
g_error_free( error );
|
VImage::option ()->
|
||||||
}
|
set ("extend", "background")->
|
||||||
|
set ("background", 128));
|
||||||
vips_error_exit( NULL );
|
|
||||||
}
|
out.write_to_file (argv[2]);
|
||||||
|
|
||||||
VImage in = VImage::new_from_file( argv[1],
|
vips_shutdown ();
|
||||||
VImage::option()->
|
|
||||||
set( "access", VIPS_ACCESS_SEQUENTIAL ) );
|
return (0);
|
||||||
|
|
||||||
double avg = in.avg();
|
|
||||||
|
|
||||||
printf( "avg = %g\n", avg );
|
|
||||||
printf( "width = %d\n", in.width() );
|
|
||||||
|
|
||||||
VImage in = VImage::new_from_file( argv[1],
|
|
||||||
VImage::option()->
|
|
||||||
set( "access", VIPS_ACCESS_SEQUENTIAL ) );
|
|
||||||
|
|
||||||
VImage out = in.embed( 10, 10, 1000, 1000,
|
|
||||||
VImage::option()->
|
|
||||||
set( "extend", "background" )->
|
|
||||||
set( "background", 128 ) );
|
|
||||||
|
|
||||||
out.write_to_file( argv[2] );
|
|
||||||
|
|
||||||
vips_shutdown();
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
}
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Everything before <code>VImage in = VImage::..</code> is exactly
|
Everything before <code>VImage in = VImage::..</code> is exactly
|
||||||
as the C API. This boilerplate gives the example a set of standard
|
as the C API. vips_error_exit() just prints the arguments plus the
|
||||||
command-line flags.
|
libvips error log and exits with an error code.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
This line is the C++ equivalent of vips_image_new_from_file(). It works
|
<code>VImage in = VImage::..</code> is the C++ equivalent of
|
||||||
|
vips_image_new_from_file(). It works
|
||||||
in the same way, the differences being:
|
in the same way, the differences being:
|
||||||
|
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
|
@ -1226,6 +1226,36 @@ vips_icc_ac2rc( VipsImage *in, VipsImage **out, const char *profile_filename )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TRUE if a profile is compatible with an image.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
vips_icc_is_compatible_profile( VipsImage *image,
|
||||||
|
void *data, size_t data_length )
|
||||||
|
{
|
||||||
|
cmsHPROFILE profile;
|
||||||
|
|
||||||
|
if( !(profile = cmsOpenProfileFromMem( data, data_length )) ) {
|
||||||
|
g_warning( "%s", _( "corrupt profile" ) );
|
||||||
|
return( FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vips_image_expected_bands( image ) !=
|
||||||
|
vips_icc_profile_needs_bands( profile ) ) {
|
||||||
|
VIPS_FREEF( cmsCloseProfile, profile );
|
||||||
|
g_warning( "%s",
|
||||||
|
_( "profile incompatible with image" ) );
|
||||||
|
return( FALSE );
|
||||||
|
}
|
||||||
|
if( vips_image_expected_sig( image ) != cmsGetColorSpace( profile ) ) {
|
||||||
|
VIPS_FREEF( cmsCloseProfile, profile );
|
||||||
|
g_warning( "%s",
|
||||||
|
_( "profile colourspace differs from image" ) );
|
||||||
|
return( FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
#else /*!HAVE_LCMS2*/
|
#else /*!HAVE_LCMS2*/
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
@ -1245,6 +1275,13 @@ vips_icc_ac2rc( VipsImage *in, VipsImage **out, const char *profile_filename )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
vips_icc_is_compatible_profile( VipsImage *image,
|
||||||
|
void *data, size_t data_length )
|
||||||
|
{
|
||||||
|
return( TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
#endif /*HAVE_LCMS*/
|
#endif /*HAVE_LCMS*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -499,9 +499,9 @@ vips_bandjoin_const1( VipsImage *in, VipsImage **out, double c, ... )
|
|||||||
return( result );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vips_addalpha:
|
/* vips_addalpha: (method)
|
||||||
* @in: input image
|
* @in: input image
|
||||||
* @out: output image
|
* @out: (out): output image
|
||||||
* @...: %NULL-terminated list of optional named arguments
|
* @...: %NULL-terminated list of optional named arguments
|
||||||
*
|
*
|
||||||
* Append an alpha channel.
|
* Append an alpha channel.
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
* - gtkdoc
|
* - gtkdoc
|
||||||
* 31/10/11
|
* 31/10/11
|
||||||
* - redo as a class
|
* - redo as a class
|
||||||
|
* 3/4/18
|
||||||
|
* - always write MULTIBAND, otherwise when we join up these things it'll
|
||||||
|
* look like we have an alpha
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -97,8 +100,7 @@ vips_black_build( VipsObject *object )
|
|||||||
vips_image_init_fields( create->out,
|
vips_image_init_fields( create->out,
|
||||||
black->width, black->height, black->bands,
|
black->width, black->height, black->bands,
|
||||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
|
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
|
||||||
black->bands == 1 ?
|
VIPS_INTERPRETATION_MULTIBAND,
|
||||||
VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_MULTIBAND,
|
|
||||||
1.0, 1.0 );
|
1.0, 1.0 );
|
||||||
vips_image_pipelinev( create->out,
|
vips_image_pipelinev( create->out,
|
||||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||||
|
@ -134,7 +134,8 @@ vips_gaussmat_build( VipsObject *object )
|
|||||||
|
|
||||||
vips_image_init_fields( create->out,
|
vips_image_init_fields( create->out,
|
||||||
width, height, 1,
|
width, height, 1,
|
||||||
VIPS_FORMAT_DOUBLE, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
|
VIPS_FORMAT_DOUBLE, VIPS_CODING_NONE,
|
||||||
|
VIPS_INTERPRETATION_MULTIBAND,
|
||||||
1.0, 1.0 );
|
1.0, 1.0 );
|
||||||
vips_image_pipelinev( create->out,
|
vips_image_pipelinev( create->out,
|
||||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||||
|
@ -134,7 +134,7 @@ vips_gaussnoise_build( VipsObject *object )
|
|||||||
vips_image_init_fields( create->out,
|
vips_image_init_fields( create->out,
|
||||||
gaussnoise->width, gaussnoise->height, 1,
|
gaussnoise->width, gaussnoise->height, 1,
|
||||||
VIPS_FORMAT_FLOAT, VIPS_CODING_NONE,
|
VIPS_FORMAT_FLOAT, VIPS_CODING_NONE,
|
||||||
VIPS_INTERPRETATION_B_W, 1.0, 1.0 );
|
VIPS_INTERPRETATION_MULTIBAND, 1.0, 1.0 );
|
||||||
vips_image_pipelinev( create->out,
|
vips_image_pipelinev( create->out,
|
||||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||||
|
|
||||||
|
@ -153,7 +153,8 @@ vips_logmat_build( VipsObject *object )
|
|||||||
|
|
||||||
vips_image_init_fields( create->out,
|
vips_image_init_fields( create->out,
|
||||||
width, height, 1,
|
width, height, 1,
|
||||||
VIPS_FORMAT_DOUBLE, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
|
VIPS_FORMAT_DOUBLE, VIPS_CODING_NONE,
|
||||||
|
VIPS_INTERPRETATION_MULTIBAND,
|
||||||
1.0, 1.0 );
|
1.0, 1.0 );
|
||||||
vips_image_pipelinev( create->out,
|
vips_image_pipelinev( create->out,
|
||||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||||
|
@ -249,7 +249,7 @@ vips_perlin_build( VipsObject *object )
|
|||||||
vips_image_init_fields( create->out,
|
vips_image_init_fields( create->out,
|
||||||
perlin->width, perlin->height, 1,
|
perlin->width, perlin->height, 1,
|
||||||
perlin->uchar ? VIPS_FORMAT_UCHAR : VIPS_FORMAT_FLOAT,
|
perlin->uchar ? VIPS_FORMAT_UCHAR : VIPS_FORMAT_FLOAT,
|
||||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
|
VIPS_CODING_NONE, VIPS_INTERPRETATION_MULTIBAND,
|
||||||
1.0, 1.0 );
|
1.0, 1.0 );
|
||||||
vips_image_pipelinev( create->out,
|
vips_image_pipelinev( create->out,
|
||||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||||
|
@ -109,10 +109,9 @@ vips_point_build( VipsObject *object )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
in = t[2];
|
in = t[2];
|
||||||
|
|
||||||
/* uchar mode always does B_W. We don't want FOURIER or
|
/* We don't want FOURIER or whatever in this case.
|
||||||
* whatever in this case.
|
|
||||||
*/
|
*/
|
||||||
in->Type = VIPS_INTERPRETATION_B_W;
|
in->Type = VIPS_INTERPRETATION_MULTIBAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( vips_image_write( in, create->out ) )
|
if( vips_image_write( in, create->out ) )
|
||||||
@ -137,7 +136,7 @@ vips_point_class_init( VipsPointClass *class )
|
|||||||
class->point = NULL;
|
class->point = NULL;
|
||||||
class->min = -1.0;
|
class->min = -1.0;
|
||||||
class->max = 1.0;
|
class->max = 1.0;
|
||||||
class->interpretation = VIPS_INTERPRETATION_B_W;
|
class->interpretation = VIPS_INTERPRETATION_MULTIBAND;
|
||||||
|
|
||||||
VIPS_ARG_INT( class, "width", 2,
|
VIPS_ARG_INT( class, "width", 2,
|
||||||
_( "Width" ),
|
_( "Width" ),
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
* - implement auto fitting of text inside bounds
|
* - implement auto fitting of text inside bounds
|
||||||
* 12/3/18
|
* 12/3/18
|
||||||
* - better fitting of fonts with overhanging edges, thanks Adrià
|
* - better fitting of fonts with overhanging edges, thanks Adrià
|
||||||
|
* 26/4/18 fangqiao
|
||||||
|
* - add fontfile option
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -80,6 +82,7 @@ typedef struct _VipsText {
|
|||||||
int spacing;
|
int spacing;
|
||||||
VipsAlign align;
|
VipsAlign align;
|
||||||
int dpi;
|
int dpi;
|
||||||
|
char *fontfile;
|
||||||
|
|
||||||
FT_Bitmap bitmap;
|
FT_Bitmap bitmap;
|
||||||
PangoContext *context;
|
PangoContext *context;
|
||||||
@ -337,6 +340,15 @@ vips_text_build( VipsObject *object )
|
|||||||
if( !vips_text_fontmap )
|
if( !vips_text_fontmap )
|
||||||
vips_text_fontmap = pango_ft2_font_map_new();
|
vips_text_fontmap = pango_ft2_font_map_new();
|
||||||
|
|
||||||
|
if( text->fontfile &&
|
||||||
|
!FcConfigAppFontAddFile( NULL,
|
||||||
|
(const FcChar8 *) text->fontfile ) ) {
|
||||||
|
vips_error( class->nickname,
|
||||||
|
_( "unable to load font \"%s\"" ), text->fontfile );
|
||||||
|
g_mutex_unlock( vips_text_lock );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
/* If our caller set height and not dpi, we adjust dpi until
|
/* If our caller set height and not dpi, we adjust dpi until
|
||||||
* we get a fit.
|
* we get a fit.
|
||||||
*/
|
*/
|
||||||
@ -379,7 +391,8 @@ vips_text_build( VipsObject *object )
|
|||||||
|
|
||||||
vips_image_init_fields( create->out,
|
vips_image_init_fields( create->out,
|
||||||
text->bitmap.width, text->bitmap.rows, 1,
|
text->bitmap.width, text->bitmap.rows, 1,
|
||||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
|
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
|
||||||
|
VIPS_INTERPRETATION_MULTIBAND,
|
||||||
1.0, 1.0 );
|
1.0, 1.0 );
|
||||||
vips_image_pipelinev( create->out,
|
vips_image_pipelinev( create->out,
|
||||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||||
@ -476,6 +489,13 @@ vips_text_class_init( VipsTextClass *class )
|
|||||||
G_STRUCT_OFFSET( VipsText, spacing ),
|
G_STRUCT_OFFSET( VipsText, spacing ),
|
||||||
0, 1000000, 0 );
|
0, 1000000, 0 );
|
||||||
|
|
||||||
|
VIPS_ARG_STRING( class, "fontfile", 12,
|
||||||
|
_( "Font file" ),
|
||||||
|
_( "Load this font file" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsText, fontfile ),
|
||||||
|
NULL );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -498,6 +518,7 @@ vips_text_init( VipsText *text )
|
|||||||
* Optional arguments:
|
* Optional arguments:
|
||||||
*
|
*
|
||||||
* * @font: %gchararray, font to render with
|
* * @font: %gchararray, font to render with
|
||||||
|
* * @fontfile: %gchararray, load this font file
|
||||||
* * @width: %gint, image should be no wider than this many pixels
|
* * @width: %gint, image should be no wider than this many pixels
|
||||||
* * @height: %gint, image should be no higher than this many pixels
|
* * @height: %gint, image should be no higher than this many pixels
|
||||||
* * @align: #VipsAlign, left/centre/right alignment
|
* * @align: #VipsAlign, left/centre/right alignment
|
||||||
@ -515,6 +536,9 @@ vips_text_init( VipsText *text )
|
|||||||
* @font is the font to render with, as a fontconfig name. Examples might be
|
* @font is the font to render with, as a fontconfig name. Examples might be
|
||||||
* "sans 12" or perhaps "bitstream charter bold 10".
|
* "sans 12" or perhaps "bitstream charter bold 10".
|
||||||
*
|
*
|
||||||
|
* You can specify a font to load with @fontfile. You'll need to also set the
|
||||||
|
* name of the font with @font.
|
||||||
|
*
|
||||||
* @width is the number of pixels to word-wrap at. Lines of text wider than
|
* @width is the number of pixels to word-wrap at. Lines of text wider than
|
||||||
* this will be broken at word bounaries.
|
* this will be broken at word bounaries.
|
||||||
* @align can be used to set the alignment style for multi-line
|
* @align can be used to set the alignment style for multi-line
|
||||||
@ -531,7 +555,7 @@ vips_text_init( VipsText *text )
|
|||||||
* @dpi sets the resolution to render at. "sans 12" at 72 dpi draws characters
|
* @dpi sets the resolution to render at. "sans 12" at 72 dpi draws characters
|
||||||
* approximately 12 pixels high.
|
* approximately 12 pixels high.
|
||||||
*
|
*
|
||||||
* @spacing sets the line spacing, in points. It would typicallly be something
|
* @spacing sets the line spacing, in points. It would typically be something
|
||||||
* like font size times 1.2.
|
* like font size times 1.2.
|
||||||
*
|
*
|
||||||
* See also: vips_xyz(), vips_text(), vips_gaussnoise().
|
* See also: vips_xyz(), vips_text(), vips_gaussnoise().
|
||||||
|
@ -281,7 +281,8 @@ vips_worley_build( VipsObject *object )
|
|||||||
|
|
||||||
vips_image_init_fields( create->out,
|
vips_image_init_fields( create->out,
|
||||||
worley->width, worley->height, 1,
|
worley->width, worley->height, 1,
|
||||||
VIPS_FORMAT_FLOAT, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W,
|
VIPS_FORMAT_FLOAT, VIPS_CODING_NONE,
|
||||||
|
VIPS_INTERPRETATION_MULTIBAND,
|
||||||
1.0, 1.0 );
|
1.0, 1.0 );
|
||||||
vips_image_pipelinev( create->out,
|
vips_image_pipelinev( create->out,
|
||||||
VIPS_DEMAND_STYLE_ANY, NULL );
|
VIPS_DEMAND_STYLE_ANY, NULL );
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
static int
|
static int
|
||||||
tiff2vips( const char *name, IMAGE *out, gboolean header_only )
|
tiff2vips( const char *name, IMAGE *out, gboolean header_only )
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_TIFF
|
||||||
char filename[FILENAME_MAX];
|
char filename[FILENAME_MAX];
|
||||||
char mode[FILENAME_MAX];
|
char mode[FILENAME_MAX];
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
@ -84,7 +85,6 @@ tiff2vips( const char *name, IMAGE *out, gboolean header_only )
|
|||||||
* malloc if all we are doing is looking at fields.
|
* malloc if all we are doing is looking at fields.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_TIFF
|
|
||||||
if( !header_only &&
|
if( !header_only &&
|
||||||
!seq &&
|
!seq &&
|
||||||
!vips__istifftiled( filename ) &&
|
!vips__istifftiled( filename ) &&
|
||||||
|
@ -6,6 +6,7 @@ libforeign_la_SOURCES = \
|
|||||||
gifload.c \
|
gifload.c \
|
||||||
cairo.c \
|
cairo.c \
|
||||||
pdfload.c \
|
pdfload.c \
|
||||||
|
pdfload_pdfium.c \
|
||||||
svgload.c \
|
svgload.c \
|
||||||
radiance.c \
|
radiance.c \
|
||||||
radload.c \
|
radload.c \
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
* - META_SEQ support moved here
|
* - META_SEQ support moved here
|
||||||
* 5/3/18
|
* 5/3/18
|
||||||
* - block _start if one start fails, see #893
|
* - block _start if one start fails, see #893
|
||||||
|
* 1/4/18
|
||||||
|
* - drop incompatible ICC profiles before save
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1504,6 +1506,21 @@ vips__foreign_convert_saveable( VipsImage *in, VipsImage **ready,
|
|||||||
in = out;
|
in = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Some format libraries, like libpng, will throw a hard error if the
|
||||||
|
* profile is inappropriate for this image type. With profiles inherited
|
||||||
|
* from a source image, this can happen all the time, so we
|
||||||
|
* want to just drop the profile in this case.
|
||||||
|
*/
|
||||||
|
if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) {
|
||||||
|
void *data;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
if( !vips_image_get_blob( in, VIPS_META_ICC_NAME,
|
||||||
|
&data, &length ) &&
|
||||||
|
!vips_icc_is_compatible_profile( in, data, length ) )
|
||||||
|
vips_image_remove( in, VIPS_META_ICC_NAME );
|
||||||
|
}
|
||||||
|
|
||||||
*ready = in;
|
*ready = in;
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -1849,6 +1866,12 @@ vips_foreign_operation_init( void )
|
|||||||
vips_foreign_load_pdf_buffer_get_type();
|
vips_foreign_load_pdf_buffer_get_type();
|
||||||
#endif /*HAVE_POPPLER*/
|
#endif /*HAVE_POPPLER*/
|
||||||
|
|
||||||
|
#ifdef HAVE_PDFIUM
|
||||||
|
vips_foreign_load_pdf_get_type();
|
||||||
|
vips_foreign_load_pdf_file_get_type();
|
||||||
|
vips_foreign_load_pdf_buffer_get_type();
|
||||||
|
#endif /*HAVE_PDFIUM*/
|
||||||
|
|
||||||
#ifdef HAVE_RSVG
|
#ifdef HAVE_RSVG
|
||||||
vips_foreign_load_svg_get_type();
|
vips_foreign_load_svg_get_type();
|
||||||
vips_foreign_load_svg_file_get_type();
|
vips_foreign_load_svg_file_get_type();
|
||||||
|
@ -94,6 +94,10 @@
|
|||||||
* - revert previous warning change: libvips reports serious corruption,
|
* - revert previous warning change: libvips reports serious corruption,
|
||||||
* like a truncated file, as a warning and we need to be able to catch
|
* like a truncated file, as a warning and we need to be able to catch
|
||||||
* that
|
* that
|
||||||
|
* 9/4/18
|
||||||
|
* - set interlaced=1 for interlaced images
|
||||||
|
* 10/4/18
|
||||||
|
* - strict round down on shrink-on-load
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -151,8 +155,6 @@
|
|||||||
/* Stuff we track during a read.
|
/* Stuff we track during a read.
|
||||||
*/
|
*/
|
||||||
typedef struct _ReadJpeg {
|
typedef struct _ReadJpeg {
|
||||||
VipsImage *out;
|
|
||||||
|
|
||||||
/* Shrink by this much during load. 1, 2, 4, 8.
|
/* Shrink by this much during load. 1, 2, 4, 8.
|
||||||
*/
|
*/
|
||||||
int shrink;
|
int shrink;
|
||||||
@ -177,6 +179,13 @@ typedef struct _ReadJpeg {
|
|||||||
* during load.
|
* during load.
|
||||||
*/
|
*/
|
||||||
gboolean autorotate;
|
gboolean autorotate;
|
||||||
|
|
||||||
|
/* cinfo->output_width and height can be larger than we want since
|
||||||
|
* libjpeg rounds up on shrink-on-load. This is the real size we will
|
||||||
|
* output, as opposed to the size we decompress to.
|
||||||
|
*/
|
||||||
|
int output_width;
|
||||||
|
int output_height;
|
||||||
} ReadJpeg;
|
} ReadJpeg;
|
||||||
|
|
||||||
/* This can be called many times.
|
/* This can be called many times.
|
||||||
@ -228,7 +237,6 @@ readjpeg_new( VipsImage *out, int shrink, gboolean fail, gboolean autorotate )
|
|||||||
if( !(jpeg = VIPS_NEW( out, ReadJpeg )) )
|
if( !(jpeg = VIPS_NEW( out, ReadJpeg )) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
jpeg->out = out;
|
|
||||||
jpeg->shrink = shrink;
|
jpeg->shrink = shrink;
|
||||||
jpeg->fail = fail;
|
jpeg->fail = fail;
|
||||||
jpeg->filename = NULL;
|
jpeg->filename = NULL;
|
||||||
@ -271,6 +279,25 @@ readjpeg_file( ReadJpeg *jpeg, const char *filename )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
find_chroma_subsample( struct jpeg_decompress_struct *cinfo )
|
||||||
|
{
|
||||||
|
gboolean has_subsample;
|
||||||
|
|
||||||
|
/* libjpeg only uses 4:4:4 and 4:2:0, confusingly.
|
||||||
|
*
|
||||||
|
* http://poynton.ca/PDFs/Chroma_subsampling_notation.pdf
|
||||||
|
*/
|
||||||
|
has_subsample = cinfo->max_h_samp_factor > 1 ||
|
||||||
|
cinfo->max_v_samp_factor > 1;
|
||||||
|
if( cinfo->num_components > 3 )
|
||||||
|
/* A cmyk image.
|
||||||
|
*/
|
||||||
|
return( has_subsample ? "4:2:0:4" : "4:4:4:4" );
|
||||||
|
else
|
||||||
|
return( has_subsample ? "4:2:0" : "4:4:4" );
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
attach_blob( VipsImage *im, const char *field, void *data, int data_length )
|
attach_blob( VipsImage *im, const char *field, void *data, int data_length )
|
||||||
{
|
{
|
||||||
@ -408,12 +435,32 @@ read_jpeg_header( ReadJpeg *jpeg, VipsImage *out )
|
|||||||
|
|
||||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
|
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
|
||||||
|
|
||||||
|
/* cinfo->output_width and cinfo->output_height round up with
|
||||||
|
* shrink-on-load. For example, if the image is 1801 pixels across and
|
||||||
|
* we shrink by 4, the output will be 450.25 pixels across,
|
||||||
|
* cinfo->output_width with be 451, and libjpeg will write a black
|
||||||
|
* column of pixels down the right.
|
||||||
|
*
|
||||||
|
* We must strictly round down, since we don't want fractional pixels
|
||||||
|
* along the bottom and right.
|
||||||
|
*/
|
||||||
|
jpeg->output_width = cinfo->image_width / jpeg->shrink;
|
||||||
|
jpeg->output_height = cinfo->image_height / jpeg->shrink;
|
||||||
|
|
||||||
/* Interlaced jpegs need lots of memory to read, so our caller needs
|
/* Interlaced jpegs need lots of memory to read, so our caller needs
|
||||||
* to know.
|
* to know.
|
||||||
*/
|
*/
|
||||||
(void) vips_image_set_int( out, "jpeg-multiscan",
|
(void) vips_image_set_int( out, "jpeg-multiscan",
|
||||||
jpeg_has_multiple_scans( cinfo ) );
|
jpeg_has_multiple_scans( cinfo ) );
|
||||||
|
|
||||||
|
/* 8.7 adds this for PNG as well, so we have a new format-neutral name.
|
||||||
|
*/
|
||||||
|
if( jpeg_has_multiple_scans( cinfo ) )
|
||||||
|
vips_image_set_int( out, "interlaced", 1 );
|
||||||
|
|
||||||
|
(void) vips_image_set_string( out, "jpeg-chroma-subsample",
|
||||||
|
find_chroma_subsample( cinfo ) );
|
||||||
|
|
||||||
/* Look for EXIF and ICC profile.
|
/* Look for EXIF and ICC profile.
|
||||||
*/
|
*/
|
||||||
for( p = cinfo->marker_list; p; p = p->next ) {
|
for( p = cinfo->marker_list; p; p = p->next ) {
|
||||||
@ -684,15 +731,20 @@ read_jpeg_image( ReadJpeg *jpeg, VipsImage *out )
|
|||||||
printf( "read_jpeg_image: starting decompress\n" );
|
printf( "read_jpeg_image: starting decompress\n" );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
/* We must crop after the seq, or our generate may not be asked for
|
||||||
|
* full lines of pixels and will attempt to write beyond the buffer.
|
||||||
|
*/
|
||||||
if( vips_image_generate( t[0],
|
if( vips_image_generate( t[0],
|
||||||
NULL, read_jpeg_generate, NULL,
|
NULL, read_jpeg_generate, NULL,
|
||||||
jpeg, NULL ) ||
|
jpeg, NULL ) ||
|
||||||
vips_sequential( t[0], &t[1],
|
vips_sequential( t[0], &t[1],
|
||||||
"tile_height", 8,
|
"tile_height", 8,
|
||||||
NULL ) )
|
NULL ) ||
|
||||||
|
vips_extract_area( t[1], &t[2],
|
||||||
|
0, 0, jpeg->output_width, jpeg->output_height, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
im = t[1];
|
im = t[2];
|
||||||
if( jpeg->autorotate )
|
if( jpeg->autorotate )
|
||||||
im = read_jpeg_rotate( VIPS_OBJECT( out ), im );
|
im = read_jpeg_rotate( VIPS_OBJECT( out ), im );
|
||||||
|
|
||||||
@ -731,6 +783,11 @@ vips__jpeg_read( ReadJpeg *jpeg, VipsImage *out, gboolean header_only )
|
|||||||
if( read_jpeg_header( jpeg, out ) )
|
if( read_jpeg_header( jpeg, out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
/* Patch in the correct size.
|
||||||
|
*/
|
||||||
|
out->Xsize = jpeg->output_width;
|
||||||
|
out->Ysize = jpeg->output_height;
|
||||||
|
|
||||||
/* Swap width and height if we're going to rotate this image.
|
/* Swap width and height if we're going to rotate this image.
|
||||||
*/
|
*/
|
||||||
if( jpeg->autorotate ) {
|
if( jpeg->autorotate ) {
|
||||||
|
@ -374,6 +374,11 @@ vips_foreign_load_jpeg_buffer_init( VipsForeignLoadJpegBuffer *buffer )
|
|||||||
* memory to load, so this field gives callers a chance to handle these
|
* memory to load, so this field gives callers a chance to handle these
|
||||||
* images differently.
|
* images differently.
|
||||||
*
|
*
|
||||||
|
* The string-valued field "jpeg-chroma-subsample" gives the chroma subsample
|
||||||
|
* in standard notation. 4:4:4 means no subsample, 4:2:0 means YCbCr with
|
||||||
|
* Cb and Cr subsampled horizontally and vertically, 4:4:4:4 means a CMYK
|
||||||
|
* image with no subsampling.
|
||||||
|
*
|
||||||
* The EXIF thumbnail, if present, is attached to the image as
|
* The EXIF thumbnail, if present, is attached to the image as
|
||||||
* "jpeg-thumbnail-data". See vips_image_get_blob().
|
* "jpeg-thumbnail-data". See vips_image_get_blob().
|
||||||
*
|
*
|
||||||
|
@ -82,13 +82,6 @@ magick_set_property( Image *image, const char *property, const char *value,
|
|||||||
(void) SetImageProperty( image, property, value, exception );
|
(void) SetImageProperty( image, property, value, exception );
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
magick_set_image_colorspace( Image *image, const ColorspaceType colorspace,
|
|
||||||
ExceptionInfo *exception)
|
|
||||||
{
|
|
||||||
return( SetImageColorspace( image, colorspace, exception ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
magick_inherit_exception( ExceptionInfo *exception, Image *image )
|
magick_inherit_exception( ExceptionInfo *exception, Image *image )
|
||||||
{
|
{
|
||||||
@ -104,7 +97,13 @@ Image*
|
|||||||
magick_acquire_image(const ImageInfo *image_info, ExceptionInfo *exception)
|
magick_acquire_image(const ImageInfo *image_info, ExceptionInfo *exception)
|
||||||
{
|
{
|
||||||
(void) exception;
|
(void) exception;
|
||||||
|
#ifdef HAVE_ACQUIREIMAGE
|
||||||
return( AcquireImage( image_info ) );
|
return( AcquireImage( image_info ) );
|
||||||
|
#else /*!HAVE_ACQUIREIMAGE*/
|
||||||
|
/* IM5-ish and GraphicsMagick use AllocateImage().
|
||||||
|
*/
|
||||||
|
return( AllocateImage( image_info ) );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -112,7 +111,13 @@ magick_acquire_next_image( const ImageInfo *image_info, Image *image,
|
|||||||
ExceptionInfo *exception )
|
ExceptionInfo *exception )
|
||||||
{
|
{
|
||||||
(void) exception;
|
(void) exception;
|
||||||
|
#ifdef HAVE_ACQUIREIMAGE
|
||||||
AcquireNextImage( image_info, image );
|
AcquireNextImage( image_info, image );
|
||||||
|
#else /*!HAVE_ACQUIREIMAGE*/
|
||||||
|
/* IM5-ish and GraphicsMagick use AllocateNextImage().
|
||||||
|
*/
|
||||||
|
AllocateNextImage( image_info, image );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -120,15 +125,38 @@ magick_set_image_size( Image *image, const size_t width, const size_t height,
|
|||||||
ExceptionInfo *exception )
|
ExceptionInfo *exception )
|
||||||
{
|
{
|
||||||
(void) exception;
|
(void) exception;
|
||||||
|
#ifdef HAVE_SETIMAGEEXTENT
|
||||||
return( SetImageExtent( image, width, height ) );
|
return( SetImageExtent( image, width, height ) );
|
||||||
|
#else /*!HAVE_SETIMAGEEXTENT*/
|
||||||
|
image->columns = width;
|
||||||
|
image->rows = height;
|
||||||
|
|
||||||
|
/* imagemagick does a SyncImagePixelCache() at the end of
|
||||||
|
* SetImageExtent(), but GM does not really have an equivalent. Just
|
||||||
|
* always return True.
|
||||||
|
*/
|
||||||
|
return( MagickTrue );
|
||||||
|
#endif /*HAVE_SETIMAGEEXTENT*/
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
magick_import_pixels( Image *image, const ssize_t x, const ssize_t y,
|
magick_import_pixels( Image *image, const ssize_t x, const ssize_t y,
|
||||||
const size_t width, const size_t height, const char *map,
|
const size_t width, const size_t height, const char *map,
|
||||||
const StorageType type,const void *pixels, ExceptionInfo *exception )
|
const StorageType type, const void *pixels, ExceptionInfo *exception )
|
||||||
{
|
{
|
||||||
(void) exception;
|
(void) exception;
|
||||||
|
|
||||||
|
/* GM does not seem to have a simple equivalent, unfortunately.
|
||||||
|
*
|
||||||
|
* Looks like we'd need to call
|
||||||
|
*
|
||||||
|
* extern MagickExport PixelPacket
|
||||||
|
* *SetImagePixels(Image *image,const long x,const long y,
|
||||||
|
* const unsigned long columns,const unsigned
|
||||||
|
* long rows);
|
||||||
|
*
|
||||||
|
* then repack pixels into that area using map and storage_type.
|
||||||
|
*/
|
||||||
return( ImportImagePixels( image, x, y, width, height, map,
|
return( ImportImagePixels( image, x, y, width, height, map,
|
||||||
type, pixels ) );
|
type, pixels ) );
|
||||||
}
|
}
|
||||||
@ -138,21 +166,19 @@ magick_set_property( Image *image, const char *property, const char *value,
|
|||||||
ExceptionInfo *exception )
|
ExceptionInfo *exception )
|
||||||
{
|
{
|
||||||
(void) exception;
|
(void) exception;
|
||||||
|
#ifdef HAVE_SETIMAGEPROPERTY
|
||||||
(void) SetImageProperty( image, property, value );
|
(void) SetImageProperty( image, property, value );
|
||||||
}
|
#else /*!HAVE_SETIMAGEPROPERTY*/
|
||||||
|
(void) SetImageAttribute( image, property, value );
|
||||||
int
|
#endif /*HAVE_SETIMAGEPROPERTY*/
|
||||||
magick_set_image_colorspace( Image *image, const ColorspaceType colorspace,
|
|
||||||
ExceptionInfo *exception )
|
|
||||||
{
|
|
||||||
(void) exception;
|
|
||||||
return( SetImageColorspace( image, colorspace ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
magick_inherit_exception( ExceptionInfo *exception, Image *image )
|
magick_inherit_exception( ExceptionInfo *exception, Image *image )
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_INHERITEXCEPTION
|
||||||
InheritException( exception, &image->exception );
|
InheritException( exception, &image->exception );
|
||||||
|
#endif /*HAVE_INHERITEXCEPTION*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*HAVE_MAGICK6*/
|
#endif /*HAVE_MAGICK6*/
|
||||||
@ -182,7 +208,7 @@ magick_genesis_cb( void *client )
|
|||||||
printf( "magick_genesis_cb:\n" );
|
printf( "magick_genesis_cb:\n" );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
#ifdef HAVE_MAGICKCOREGENESIS
|
#if defined(HAVE_MAGICKCOREGENESIS) || defined(HAVE_MAGICK7)
|
||||||
MagickCoreGenesis( vips_get_argv0(), MagickFalse );
|
MagickCoreGenesis( vips_get_argv0(), MagickFalse );
|
||||||
#else /*!HAVE_MAGICKCOREGENESIS*/
|
#else /*!HAVE_MAGICKCOREGENESIS*/
|
||||||
InitializeMagick( "" );
|
InitializeMagick( "" );
|
||||||
|
@ -46,8 +46,8 @@ Image *magick_acquire_image( const ImageInfo *image_info,
|
|||||||
ExceptionInfo *exception );
|
ExceptionInfo *exception );
|
||||||
void magick_acquire_next_image( const ImageInfo *image_info,
|
void magick_acquire_next_image( const ImageInfo *image_info,
|
||||||
Image *image, ExceptionInfo *exception );
|
Image *image, ExceptionInfo *exception );
|
||||||
int magick_set_image_size( Image *image, const size_t width, const size_t height,
|
int magick_set_image_size( Image *image,
|
||||||
ExceptionInfo *exception );
|
const size_t width, const size_t height, ExceptionInfo *exception );
|
||||||
int magick_import_pixels( Image *image, const ssize_t x, const ssize_t y,
|
int magick_import_pixels( Image *image, const ssize_t x, const ssize_t y,
|
||||||
const size_t width, const size_t height, const char *map,
|
const size_t width, const size_t height, const char *map,
|
||||||
const StorageType type,const void *pixels, ExceptionInfo *exception );
|
const StorageType type,const void *pixels, ExceptionInfo *exception );
|
||||||
|
@ -55,6 +55,8 @@
|
|||||||
* - remove @all_frames, add @n
|
* - remove @all_frames, add @n
|
||||||
* 23/2/17
|
* 23/2/17
|
||||||
* - try using GetImageChannelDepth() instead of ->depth
|
* - try using GetImageChannelDepth() instead of ->depth
|
||||||
|
* 24/4/18
|
||||||
|
* - add format hint
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -132,7 +134,14 @@ typedef struct _Read {
|
|||||||
ImageInfo *image_info;
|
ImageInfo *image_info;
|
||||||
ExceptionInfo exception;
|
ExceptionInfo exception;
|
||||||
|
|
||||||
|
/* Number of pages in image.
|
||||||
|
*/
|
||||||
|
int n_pages;
|
||||||
|
|
||||||
|
/* Number of pages we will read.
|
||||||
|
*/
|
||||||
int n_frames;
|
int n_frames;
|
||||||
|
|
||||||
Image **frames;
|
Image **frames;
|
||||||
int frame_height;
|
int frame_height;
|
||||||
|
|
||||||
@ -172,7 +181,7 @@ read_close( VipsImage *im, Read *read )
|
|||||||
|
|
||||||
static Read *
|
static Read *
|
||||||
read_new( const char *filename, VipsImage *im,
|
read_new( const char *filename, VipsImage *im,
|
||||||
const char *density, int page, int n )
|
const char *format, const char *density, int page, int n )
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
static int inited = 0;
|
static int inited = 0;
|
||||||
@ -201,6 +210,7 @@ read_new( const char *filename, VipsImage *im,
|
|||||||
read->image = NULL;
|
read->image = NULL;
|
||||||
read->image_info = CloneImageInfo( NULL );
|
read->image_info = CloneImageInfo( NULL );
|
||||||
GetExceptionInfo( &read->exception );
|
GetExceptionInfo( &read->exception );
|
||||||
|
read->n_pages = 0;
|
||||||
read->n_frames = 0;
|
read->n_frames = 0;
|
||||||
read->frames = NULL;
|
read->frames = NULL;
|
||||||
read->frame_height = 0;
|
read->frame_height = 0;
|
||||||
@ -215,6 +225,12 @@ read_new( const char *filename, VipsImage *im,
|
|||||||
vips_strncpy( read->image_info->filename,
|
vips_strncpy( read->image_info->filename,
|
||||||
filename, MaxTextExtent );
|
filename, MaxTextExtent );
|
||||||
|
|
||||||
|
/* The file format hint, eg. "ICO".
|
||||||
|
*/
|
||||||
|
if( format )
|
||||||
|
vips_strncpy( read->image_info->magick,
|
||||||
|
format, MaxTextExtent );
|
||||||
|
|
||||||
/* Canvas resolution for rendering vector formats like SVG.
|
/* Canvas resolution for rendering vector formats like SVG.
|
||||||
*/
|
*/
|
||||||
VIPS_SETSTR( read->image_info->density, density );
|
VIPS_SETSTR( read->image_info->density, density );
|
||||||
@ -480,11 +496,16 @@ parse_header( Read *read )
|
|||||||
which says this is a volumetric image
|
which says this is a volumetric image
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
read->n_pages = GetImageListLength( image );
|
||||||
read->n_frames = 0;
|
read->n_frames = 0;
|
||||||
for( p = image; p; (p = GetNextImageInList( p )) ) {
|
for( p = image; p; (p = GetNextImageInList( p )) ) {
|
||||||
|
int p_depth =
|
||||||
|
GetImageChannelDepth( p, AllChannels, &p->exception );
|
||||||
|
|
||||||
if( p->columns != (unsigned int) im->Xsize ||
|
if( p->columns != (unsigned int) im->Xsize ||
|
||||||
p->rows != (unsigned int) im->Ysize ||
|
p->rows != (unsigned int) im->Ysize ||
|
||||||
get_bands( p ) != im->Bands ) {
|
get_bands( p ) != im->Bands ||
|
||||||
|
p_depth != depth ) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "frame %d differs\n", read->n_frames );
|
printf( "frame %d differs\n", read->n_frames );
|
||||||
printf( "%zdx%zd, %d bands\n",
|
printf( "%zdx%zd, %d bands\n",
|
||||||
@ -504,7 +525,7 @@ parse_header( Read *read )
|
|||||||
read->n_frames = 1;
|
read->n_frames = 1;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "image has %d frames\n", read->n_frames );
|
printf( "will read %d frames\n", read->n_frames );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
if( read->n != -1 )
|
if( read->n != -1 )
|
||||||
@ -525,6 +546,8 @@ parse_header( Read *read )
|
|||||||
im->Ysize *= read->n_frames;
|
im->Ysize *= read->n_frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vips_image_set_int( im, VIPS_META_N_PAGES, read->n_pages );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,7 +766,8 @@ magick_fill_region( VipsRegion *out,
|
|||||||
|
|
||||||
int
|
int
|
||||||
vips__magick_read( const char *filename,
|
vips__magick_read( const char *filename,
|
||||||
VipsImage *out, const char *density, int page, int n )
|
VipsImage *out, const char *format, const char *density,
|
||||||
|
int page, int n )
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
@ -751,7 +775,7 @@ vips__magick_read( const char *filename,
|
|||||||
printf( "magick2vips: vips__magick_read: %s\n", filename );
|
printf( "magick2vips: vips__magick_read: %s\n", filename );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
if( !(read = read_new( filename, out, density, page, n )) )
|
if( !(read = read_new( filename, out, format, density, page, n )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -782,7 +806,8 @@ vips__magick_read( const char *filename,
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
vips__magick_read_header( const char *filename,
|
vips__magick_read_header( const char *filename,
|
||||||
VipsImage *out, const char *density, int page, int n )
|
VipsImage *out, const char *format, const char *density,
|
||||||
|
int page, int n )
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
@ -790,7 +815,7 @@ vips__magick_read_header( const char *filename,
|
|||||||
printf( "vips__magick_read_header: %s\n", filename );
|
printf( "vips__magick_read_header: %s\n", filename );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
if( !(read = read_new( filename, out, density, page, n )) )
|
if( !(read = read_new( filename, out, format, density, page, n )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -824,7 +849,8 @@ vips__magick_read_header( const char *filename,
|
|||||||
|
|
||||||
int
|
int
|
||||||
vips__magick_read_buffer( const void *buf, const size_t len,
|
vips__magick_read_buffer( const void *buf, const size_t len,
|
||||||
VipsImage *out, const char *density, int page, int n )
|
VipsImage *out, const char *format, const char *density,
|
||||||
|
int page, int n )
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
@ -832,7 +858,7 @@ vips__magick_read_buffer( const void *buf, const size_t len,
|
|||||||
printf( "magick2vips: vips__magick_read_buffer: %p %zu\n", buf, len );
|
printf( "magick2vips: vips__magick_read_buffer: %p %zu\n", buf, len );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
if( !(read = read_new( NULL, out, density, page, n )) )
|
if( !(read = read_new( NULL, out, format, density, page, n )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -859,7 +885,8 @@ vips__magick_read_buffer( const void *buf, const size_t len,
|
|||||||
|
|
||||||
int
|
int
|
||||||
vips__magick_read_buffer_header( const void *buf, const size_t len,
|
vips__magick_read_buffer_header( const void *buf, const size_t len,
|
||||||
VipsImage *out, const char *density, int page, int n )
|
VipsImage *out, const char *format, const char *density,
|
||||||
|
int page, int n )
|
||||||
{
|
{
|
||||||
Read *read;
|
Read *read;
|
||||||
|
|
||||||
@ -867,7 +894,7 @@ vips__magick_read_buffer_header( const void *buf, const size_t len,
|
|||||||
printf( "vips__magick_read_buffer_header: %p %zu\n", buf, len );
|
printf( "vips__magick_read_buffer_header: %p %zu\n", buf, len );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
if( !(read = read_new( NULL, out, density, page, n )) )
|
if( !(read = read_new( NULL, out, format, density, page, n )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
* - from magickload
|
* - from magickload
|
||||||
* 25/11/16
|
* 25/11/16
|
||||||
* - add @n, deprecate @all_frames (just sets n = -1)
|
* - add @n, deprecate @all_frames (just sets n = -1)
|
||||||
|
* 24/4/18
|
||||||
|
* - add format hint
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -56,6 +58,8 @@
|
|||||||
|
|
||||||
#include <MagickCore/MagickCore.h>
|
#include <MagickCore/MagickCore.h>
|
||||||
|
|
||||||
|
#include "magick.h"
|
||||||
|
|
||||||
typedef struct _VipsForeignLoadMagick7 {
|
typedef struct _VipsForeignLoadMagick7 {
|
||||||
VipsForeignLoad parent_object;
|
VipsForeignLoad parent_object;
|
||||||
|
|
||||||
@ -63,6 +67,7 @@ typedef struct _VipsForeignLoadMagick7 {
|
|||||||
*/
|
*/
|
||||||
gboolean all_frames;
|
gboolean all_frames;
|
||||||
|
|
||||||
|
char *format; /* Format hint */
|
||||||
char *density; /* Load at this resolution */
|
char *density; /* Load at this resolution */
|
||||||
int page; /* Load this page (frame) */
|
int page; /* Load this page (frame) */
|
||||||
int n; /* Load this many pages */
|
int n; /* Load this many pages */
|
||||||
@ -71,7 +76,11 @@ typedef struct _VipsForeignLoadMagick7 {
|
|||||||
ImageInfo *image_info;
|
ImageInfo *image_info;
|
||||||
ExceptionInfo *exception;
|
ExceptionInfo *exception;
|
||||||
|
|
||||||
int n_frames; /* Number of frames in file */
|
/* Number of pages in image.
|
||||||
|
*/
|
||||||
|
int n_pages;
|
||||||
|
|
||||||
|
int n_frames; /* Number of frames we will read */
|
||||||
Image **frames; /* An Image* for each frame */
|
Image **frames; /* An Image* for each frame */
|
||||||
CacheView **cache_view; /* A CacheView for each frame */
|
CacheView **cache_view; /* A CacheView for each frame */
|
||||||
int frame_height;
|
int frame_height;
|
||||||
@ -278,26 +287,6 @@ vips_foreign_load_magick7_dispose( GObject *gobject )
|
|||||||
dispose( gobject );
|
dispose( gobject );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
|
||||||
vips_foreign_load_magick7_genesis_cb( void *client )
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
printf( "vips_foreign_load_magick7_genesis:\n" );
|
|
||||||
#endif /*DEBUG*/
|
|
||||||
|
|
||||||
MagickCoreGenesis( vips_get_argv0(), MagickFalse );
|
|
||||||
|
|
||||||
return( NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
vips_foreign_load_magick7_genesis( void )
|
|
||||||
{
|
|
||||||
static GOnce once = G_ONCE_INIT;
|
|
||||||
|
|
||||||
VIPS_ONCE( &once, vips_foreign_load_magick7_genesis_cb, NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_foreign_load_magick7_build( VipsObject *object )
|
vips_foreign_load_magick7_build( VipsObject *object )
|
||||||
{
|
{
|
||||||
@ -307,7 +296,7 @@ vips_foreign_load_magick7_build( VipsObject *object )
|
|||||||
printf( "vips_foreign_load_magick7_build: %p\n", object );
|
printf( "vips_foreign_load_magick7_build: %p\n", object );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
vips_foreign_load_magick7_genesis();
|
magick_genesis();
|
||||||
|
|
||||||
magick7->image_info = CloneImageInfo( NULL );
|
magick7->image_info = CloneImageInfo( NULL );
|
||||||
magick7->exception = AcquireExceptionInfo();
|
magick7->exception = AcquireExceptionInfo();
|
||||||
@ -319,6 +308,12 @@ vips_foreign_load_magick7_build( VipsObject *object )
|
|||||||
if( magick7->all_frames )
|
if( magick7->all_frames )
|
||||||
magick7->n = -1;
|
magick7->n = -1;
|
||||||
|
|
||||||
|
/* The file format hint, eg. "ICO".
|
||||||
|
*/
|
||||||
|
if( magick7->format )
|
||||||
|
vips_strncpy( magick7->image_info->magick,
|
||||||
|
magick7->format, MaxTextExtent );
|
||||||
|
|
||||||
/* Canvas resolution for rendering vector formats like SVG.
|
/* Canvas resolution for rendering vector formats like SVG.
|
||||||
*/
|
*/
|
||||||
VIPS_SETSTR( magick7->image_info->density, magick7->density );
|
VIPS_SETSTR( magick7->image_info->density, magick7->density );
|
||||||
@ -377,12 +372,12 @@ vips_foreign_load_magick7_class_init( VipsForeignLoadMagick7Class *class )
|
|||||||
vips_foreign_load_magick7_get_flags_filename;
|
vips_foreign_load_magick7_get_flags_filename;
|
||||||
load_class->get_flags = vips_foreign_load_magick7_get_flags;
|
load_class->get_flags = vips_foreign_load_magick7_get_flags;
|
||||||
|
|
||||||
VIPS_ARG_BOOL( class, "all_frames", 3,
|
VIPS_ARG_STRING( class, "format", 3,
|
||||||
_( "all_frames" ),
|
_( "Format" ),
|
||||||
_( "Read all frames from an image" ),
|
_( "Image format hint" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignLoadMagick7, all_frames ),
|
G_STRUCT_OFFSET( VipsForeignLoadMagick7, format ),
|
||||||
FALSE );
|
NULL );
|
||||||
|
|
||||||
VIPS_ARG_STRING( class, "density", 4,
|
VIPS_ARG_STRING( class, "density", 4,
|
||||||
_( "Density" ),
|
_( "Density" ),
|
||||||
@ -405,6 +400,13 @@ vips_foreign_load_magick7_class_init( VipsForeignLoadMagick7Class *class )
|
|||||||
G_STRUCT_OFFSET( VipsForeignLoadMagick7, n ),
|
G_STRUCT_OFFSET( VipsForeignLoadMagick7, n ),
|
||||||
-1, 100000, 1 );
|
-1, 100000, 1 );
|
||||||
|
|
||||||
|
VIPS_ARG_BOOL( class, "all_frames", 7,
|
||||||
|
_( "all_frames" ),
|
||||||
|
_( "Read all frames from an image" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignLoadMagick7, all_frames ),
|
||||||
|
FALSE );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -423,6 +425,26 @@ vips_foreign_load_magick7_error( VipsForeignLoadMagick7 *magick7 )
|
|||||||
magick7->exception->description );
|
magick7->exception->description );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
magick7_get_bands( Image *image )
|
||||||
|
{
|
||||||
|
int bands;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* We skip all index channels. Lots of images can have these, it's not
|
||||||
|
* just the palette ones.
|
||||||
|
*/
|
||||||
|
bands = 0;
|
||||||
|
for( i = 0; i < GetPixelChannels( image ); i++ ) {
|
||||||
|
PixelChannel channel = GetPixelChannelChannel( image, i );
|
||||||
|
|
||||||
|
if( channel != IndexPixelChannel )
|
||||||
|
bands += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return( bands );
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7,
|
vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7,
|
||||||
Image *image, VipsImage *out )
|
Image *image, VipsImage *out )
|
||||||
@ -430,7 +452,7 @@ vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7,
|
|||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( magick7 );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( magick7 );
|
||||||
|
|
||||||
const char *key;
|
const char *key;
|
||||||
int i;
|
Image *p;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "image->depth = %zd\n", image->depth );
|
printf( "image->depth = %zd\n", image->depth );
|
||||||
@ -446,17 +468,7 @@ vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7,
|
|||||||
out->Xsize = image->columns;
|
out->Xsize = image->columns;
|
||||||
out->Ysize = image->rows;
|
out->Ysize = image->rows;
|
||||||
magick7->frame_height = image->rows;
|
magick7->frame_height = image->rows;
|
||||||
|
out->Bands = magick7_get_bands( image );
|
||||||
/* We skip all index channels. Lots of images can have these, it's not
|
|
||||||
* just the palette ones.
|
|
||||||
*/
|
|
||||||
out->Bands = 0;
|
|
||||||
for( i = 0; i < GetPixelChannels( image ); i++ ) {
|
|
||||||
PixelChannel channel = GetPixelChannelChannel( image, i );
|
|
||||||
|
|
||||||
if( channel != IndexPixelChannel )
|
|
||||||
out->Bands += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Depth can be 'fractional'. You'd think we should use
|
/* Depth can be 'fractional'. You'd think we should use
|
||||||
* GetImageDepth() but that seems to compute something very complex.
|
* GetImageDepth() but that seems to compute something very complex.
|
||||||
@ -554,16 +566,43 @@ vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7,
|
|||||||
vips_image_set_string( out, vips_buf_all( &name ), value );
|
vips_image_set_string( out, vips_buf_all( &name ), value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
magick7->n_pages = GetImageListLength( GetFirstImageInList( image ) );
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "image has %d pages\n", magick7->n_pages );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
/* Do we have a set of equal-sized frames? Append them.
|
/* Do we have a set of equal-sized frames? Append them.
|
||||||
|
|
||||||
FIXME ... there must be an attribute somewhere from dicom read
|
FIXME ... there must be an attribute somewhere from dicom read
|
||||||
which says this is a volumetric image
|
which says this is a volumetric image
|
||||||
|
|
||||||
*/
|
*/
|
||||||
magick7->n_frames = GetImageListLength( GetFirstImageInList( image ) );
|
magick7->n_frames = 0;
|
||||||
|
for( p = image; p; (p = GetNextImageInList( p )) ) {
|
||||||
|
if( p->columns != (unsigned int) out->Xsize ||
|
||||||
|
p->rows != (unsigned int) out->Ysize ||
|
||||||
|
magick7_get_bands( p ) != out->Bands ||
|
||||||
|
p->depth != image->depth ) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "frame %d differs\n", magick7->n_frames );
|
||||||
|
printf( "%zdx%zd, %d bands\n",
|
||||||
|
p->columns, p->rows, magick7_get_bands( p ) );
|
||||||
|
printf( "first frame is %dx%d, %d bands\n",
|
||||||
|
out->Xsize, out->Ysize, out->Bands );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
magick7->n_frames += 1;
|
||||||
|
}
|
||||||
|
if( p )
|
||||||
|
/* Nope ... just do the first image in the list.
|
||||||
|
*/
|
||||||
|
magick7->n_frames = 1;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "image has %d frames\n", magick7->n_frames );
|
printf( "will read %d frames\n", magick7->n_frames );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
if( magick7->n != -1 )
|
if( magick7->n != -1 )
|
||||||
@ -576,11 +615,13 @@ vips_foreign_load_magick7_parse( VipsForeignLoadMagick7 *magick7,
|
|||||||
out->Ysize *= magick7->n_frames;
|
out->Ysize *= magick7->n_frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vips_image_set_int( out, VIPS_META_N_PAGES, magick7->n_pages );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We don't bother with GetPixelReadMask((), assume it's everywhere. Don't
|
/* We don't bother with GetPixelReadMask(), assume it's everywhere. Don't
|
||||||
* bother with traits, assume taht's always update.
|
* bother with traits, assume that's always updated.
|
||||||
*
|
*
|
||||||
* We do skip index channels. Palette images add extra index channels
|
* We do skip index channels. Palette images add extra index channels
|
||||||
* containing the index value from the file before colourmap lookup.
|
* containing the index value from the file before colourmap lookup.
|
||||||
@ -681,7 +722,8 @@ vips_foreign_load_magick7_load( VipsForeignLoadMagick7 *magick7 )
|
|||||||
/* Record frame pointers.
|
/* Record frame pointers.
|
||||||
*/
|
*/
|
||||||
g_assert( !magick7->frames );
|
g_assert( !magick7->frames );
|
||||||
if( !(magick7->frames = VIPS_ARRAY( NULL, magick7->n_frames, Image * )) )
|
if( !(magick7->frames =
|
||||||
|
VIPS_ARRAY( NULL, magick7->n_frames, Image * )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
p = magick7->image;
|
p = magick7->image;
|
||||||
for( i = 0; i < magick7->n_frames; i++ ) {
|
for( i = 0; i < magick7->n_frames; i++ ) {
|
||||||
@ -735,7 +777,7 @@ ismagick7( const char *filename )
|
|||||||
ExceptionInfo *exception;
|
ExceptionInfo *exception;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
vips_foreign_load_magick7_genesis();
|
magick_genesis();
|
||||||
|
|
||||||
/* Horribly slow :-(
|
/* Horribly slow :-(
|
||||||
*/
|
*/
|
||||||
@ -835,7 +877,7 @@ vips_foreign_load_magick7_buffer_is_a_buffer( const void *buf, size_t len )
|
|||||||
ExceptionInfo *exception;
|
ExceptionInfo *exception;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
vips_foreign_load_magick7_genesis();
|
magick_genesis();
|
||||||
|
|
||||||
/* Horribly slow :-(
|
/* Horribly slow :-(
|
||||||
*/
|
*/
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
* - add @n, deprecate @all_frames (just sets n = -1)
|
* - add @n, deprecate @all_frames (just sets n = -1)
|
||||||
* 8/9/17
|
* 8/9/17
|
||||||
* - don't cache magickload
|
* - don't cache magickload
|
||||||
|
* 24/4/18
|
||||||
|
* - add format hint
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -72,6 +74,7 @@ typedef struct _VipsForeignLoadMagick {
|
|||||||
gboolean all_frames;
|
gboolean all_frames;
|
||||||
|
|
||||||
char *density; /* Load at this resolution */
|
char *density; /* Load at this resolution */
|
||||||
|
char *format; /* Load format hint */
|
||||||
int page; /* Load this page (frame) */
|
int page; /* Load this page (frame) */
|
||||||
int n; /* Load this many pages */
|
int n; /* Load this many pages */
|
||||||
|
|
||||||
@ -122,28 +125,35 @@ vips_foreign_load_magick_class_init( VipsForeignLoadMagickClass *class )
|
|||||||
vips_foreign_load_magick_get_flags_filename;
|
vips_foreign_load_magick_get_flags_filename;
|
||||||
load_class->get_flags = vips_foreign_load_magick_get_flags;
|
load_class->get_flags = vips_foreign_load_magick_get_flags;
|
||||||
|
|
||||||
VIPS_ARG_BOOL( class, "all_frames", 3,
|
VIPS_ARG_STRING( class, "format", 3,
|
||||||
|
_( "Format" ),
|
||||||
|
_( "Image format hint" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignLoadMagick, format ),
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
VIPS_ARG_BOOL( class, "all_frames", 4,
|
||||||
_( "all_frames" ),
|
_( "all_frames" ),
|
||||||
_( "Read all frames from an image" ),
|
_( "Read all frames from an image" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
|
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
|
||||||
G_STRUCT_OFFSET( VipsForeignLoadMagick, all_frames ),
|
G_STRUCT_OFFSET( VipsForeignLoadMagick, all_frames ),
|
||||||
FALSE );
|
FALSE );
|
||||||
|
|
||||||
VIPS_ARG_STRING( class, "density", 4,
|
VIPS_ARG_STRING( class, "density", 5,
|
||||||
_( "Density" ),
|
_( "Density" ),
|
||||||
_( "Canvas resolution for rendering vector formats like SVG" ),
|
_( "Canvas resolution for rendering vector formats like SVG" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignLoadMagick, density ),
|
G_STRUCT_OFFSET( VipsForeignLoadMagick, density ),
|
||||||
NULL );
|
NULL );
|
||||||
|
|
||||||
VIPS_ARG_INT( class, "page", 5,
|
VIPS_ARG_INT( class, "page", 6,
|
||||||
_( "Page" ),
|
_( "Page" ),
|
||||||
_( "Load this page from the file" ),
|
_( "Load this page from the file" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignLoadMagick, page ),
|
G_STRUCT_OFFSET( VipsForeignLoadMagick, page ),
|
||||||
0, 100000, 0 );
|
0, 100000, 0 );
|
||||||
|
|
||||||
VIPS_ARG_INT( class, "n", 6,
|
VIPS_ARG_INT( class, "n", 7,
|
||||||
_( "n" ),
|
_( "n" ),
|
||||||
_( "Load this many pages" ),
|
_( "Load this many pages" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
@ -177,7 +187,7 @@ ismagick( const char *filename )
|
|||||||
|
|
||||||
t = vips_image_new();
|
t = vips_image_new();
|
||||||
vips_error_freeze();
|
vips_error_freeze();
|
||||||
result = vips__magick_read_header( filename, t, NULL, 0, 1 );
|
result = vips__magick_read_header( filename, t, NULL, NULL, 0, 1 );
|
||||||
g_object_unref( t );
|
g_object_unref( t );
|
||||||
vips_error_thaw();
|
vips_error_thaw();
|
||||||
|
|
||||||
@ -202,7 +212,8 @@ vips_foreign_load_magick_file_header( VipsForeignLoad *load )
|
|||||||
magick->n = -1;
|
magick->n = -1;
|
||||||
|
|
||||||
if( vips__magick_read( magick_file->filename,
|
if( vips__magick_read( magick_file->filename,
|
||||||
load->out, magick->density, magick->page, magick->n ) )
|
load->out, magick->format, magick->density,
|
||||||
|
magick->page, magick->n ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
VIPS_SETSTR( load->out->filename, magick_file->filename );
|
VIPS_SETSTR( load->out->filename, magick_file->filename );
|
||||||
@ -262,7 +273,8 @@ vips_foreign_load_magick_buffer_is_a_buffer( const void *buf, size_t len )
|
|||||||
|
|
||||||
t = vips_image_new();
|
t = vips_image_new();
|
||||||
vips_error_freeze();
|
vips_error_freeze();
|
||||||
result = vips__magick_read_buffer_header( buf, len, t, NULL, 0, 1 );
|
result = vips__magick_read_buffer_header( buf, len, t,
|
||||||
|
NULL, NULL, 0, 1 );
|
||||||
g_object_unref( t );
|
g_object_unref( t );
|
||||||
vips_error_thaw();
|
vips_error_thaw();
|
||||||
|
|
||||||
@ -288,7 +300,8 @@ vips_foreign_load_magick_buffer_header( VipsForeignLoad *load )
|
|||||||
|
|
||||||
if( vips__magick_read_buffer(
|
if( vips__magick_read_buffer(
|
||||||
magick_buffer->buf->data, magick_buffer->buf->length,
|
magick_buffer->buf->data, magick_buffer->buf->length,
|
||||||
load->out, magick->density, magick->page, magick->n ) )
|
load->out, magick->format, magick->density, magick->page,
|
||||||
|
magick->n ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -338,6 +351,7 @@ vips_foreign_load_magick_buffer_init( VipsForeignLoadMagickBuffer *buffer )
|
|||||||
*
|
*
|
||||||
* Optional arguments:
|
* Optional arguments:
|
||||||
*
|
*
|
||||||
|
* * @format: string, format hint, eg. "JPG"
|
||||||
* * @page: %gint, load from this page
|
* * @page: %gint, load from this page
|
||||||
* * @n: %gint, load this many pages
|
* * @n: %gint, load this many pages
|
||||||
* * @density: string, canvas resolution for rendering vector formats like SVG
|
* * @density: string, canvas resolution for rendering vector formats like SVG
|
||||||
@ -352,6 +366,10 @@ vips_foreign_load_magick_buffer_init( VipsForeignLoadMagickBuffer *buffer )
|
|||||||
* The reader should also work with most versions of GraphicsMagick. See the
|
* The reader should also work with most versions of GraphicsMagick. See the
|
||||||
* "--with-magickpackage" configure option.
|
* "--with-magickpackage" configure option.
|
||||||
*
|
*
|
||||||
|
* The file format is usually guessed from the filename suffix. You can
|
||||||
|
* override this with @format -- for example `"ICO"` selects Windows icon
|
||||||
|
* format. See the ImageMagick documentation for a list of format names.
|
||||||
|
*
|
||||||
* Normally it will only load the first image in a many-image sequence (such
|
* Normally it will only load the first image in a many-image sequence (such
|
||||||
* as a GIF or a PDF). Use @page and @n to set the start page and number of
|
* as a GIF or a PDF). Use @page and @n to set the start page and number of
|
||||||
* pages to load. Set @n to -1 to load all pages from @page onwards.
|
* pages to load. Set @n to -1 to load all pages from @page onwards.
|
||||||
@ -387,6 +405,7 @@ vips_magickload( const char *filename, VipsImage **out, ... )
|
|||||||
*
|
*
|
||||||
* Optional arguments:
|
* Optional arguments:
|
||||||
*
|
*
|
||||||
|
* * @format: string, format hint, eg. "JPG"
|
||||||
* * @page: %gint, load from this page
|
* * @page: %gint, load from this page
|
||||||
* * @n: %gint, load this many pages
|
* * @n: %gint, load this many pages
|
||||||
* * @density: string, canvas resolution for rendering vector formats like SVG
|
* * @density: string, canvas resolution for rendering vector formats like SVG
|
||||||
@ -394,6 +413,12 @@ vips_magickload( const char *filename, VipsImage **out, ... )
|
|||||||
* Read an image memory block using libMagick into a VIPS image. Exactly as
|
* Read an image memory block using libMagick into a VIPS image. Exactly as
|
||||||
* vips_magickload(), but read from a memory source.
|
* vips_magickload(), but read from a memory source.
|
||||||
*
|
*
|
||||||
|
* The file format is usually guessed from the buffer contents, but this does
|
||||||
|
* not work for all image formats. You can
|
||||||
|
* set the format explicitly with @format -- for example `"ICO"` selects
|
||||||
|
* Windows icon
|
||||||
|
* format. See the ImageMagick documentation for a list of format names.
|
||||||
|
*
|
||||||
* You must not free the buffer while @out is active. The
|
* You must not free the buffer while @out is active. The
|
||||||
* #VipsObject::postclose signal on @out is a good place to free.
|
* #VipsObject::postclose signal on @out is a good place to free.
|
||||||
*
|
*
|
||||||
|
@ -55,6 +55,8 @@
|
|||||||
#include <vips/buf.h>
|
#include <vips/buf.h>
|
||||||
#include <vips/internal.h>
|
#include <vips/internal.h>
|
||||||
|
|
||||||
|
#include "pforeign.h"
|
||||||
|
|
||||||
#ifdef HAVE_POPPLER
|
#ifdef HAVE_POPPLER
|
||||||
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
@ -91,7 +93,7 @@ typedef struct _VipsForeignLoadPdf {
|
|||||||
*/
|
*/
|
||||||
int n_pages;
|
int n_pages;
|
||||||
|
|
||||||
/* We need to read out the side of each page we will render, and lay
|
/* We need to read out the size of each page we will render, and lay
|
||||||
* them out in the final image.
|
* them out in the final image.
|
||||||
*/
|
*/
|
||||||
VipsRect image;
|
VipsRect image;
|
||||||
@ -145,33 +147,6 @@ vips_foreign_load_pdf_get_flags( VipsForeignLoad *load )
|
|||||||
return( VIPS_FOREIGN_PARTIAL );
|
return( VIPS_FOREIGN_PARTIAL );
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
vips_foreign_load_pdf_is_a_buffer( const void *buf, size_t len )
|
|
||||||
{
|
|
||||||
const guchar *str = (const guchar *) buf;
|
|
||||||
|
|
||||||
if( len >= 4 &&
|
|
||||||
str[0] == '%' &&
|
|
||||||
str[1] == 'P' &&
|
|
||||||
str[2] == 'D' &&
|
|
||||||
str[3] == 'F' )
|
|
||||||
return( 1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
vips_foreign_load_pdf_is_a( const char *filename )
|
|
||||||
{
|
|
||||||
unsigned char buf[4];
|
|
||||||
|
|
||||||
if( vips__get_bytes( filename, buf, 4 ) == 4 &&
|
|
||||||
vips_foreign_load_pdf_is_a_buffer( buf, 4 ) )
|
|
||||||
return( 1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_foreign_load_pdf_get_page( VipsForeignLoadPdf *pdf, int page_no )
|
vips_foreign_load_pdf_get_page( VipsForeignLoadPdf *pdf, int page_no )
|
||||||
{
|
{
|
||||||
@ -229,9 +204,10 @@ vips_foreign_load_pdf_set_image( VipsForeignLoadPdf *pdf, VipsImage *out )
|
|||||||
*/
|
*/
|
||||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
|
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
|
||||||
|
|
||||||
/* Extract and attach metadata.
|
/* Extract and attach metadata. Set the old name too for compat.
|
||||||
*/
|
*/
|
||||||
vips_image_set_int( out, "pdf-n_pages", pdf->n_pages );
|
vips_image_set_int( out, "pdf-n_pages", pdf->n_pages );
|
||||||
|
vips_image_set_int( out, VIPS_META_N_PAGES, pdf->n_pages );
|
||||||
|
|
||||||
for( i = 0; i < n_metadata; i++ ) {
|
for( i = 0; i < n_metadata; i++ ) {
|
||||||
VipsForeignLoadPdfMetadata *metadata =
|
VipsForeignLoadPdfMetadata *metadata =
|
||||||
@ -429,7 +405,7 @@ vips_foreign_load_pdf_load( VipsForeignLoad *load )
|
|||||||
* (again) keep the number of calls to page_render low.
|
* (again) keep the number of calls to page_render low.
|
||||||
*/
|
*/
|
||||||
if( vips_linecache( t[0], &t[1],
|
if( vips_linecache( t[0], &t[1],
|
||||||
"tile_height", 5000,
|
"tile_height", VIPS_MIN( 5000, pdf->pages[0].height ),
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( vips_image_write( t[1], load->real ) )
|
if( vips_image_write( t[1], load->real ) )
|
||||||
@ -658,6 +634,37 @@ vips_foreign_load_pdf_buffer_init( VipsForeignLoadPdfBuffer *buffer )
|
|||||||
|
|
||||||
#endif /*HAVE_POPPLER*/
|
#endif /*HAVE_POPPLER*/
|
||||||
|
|
||||||
|
/* Also used by the pdfium loader.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
vips_foreign_load_pdf_is_a_buffer( const void *buf, size_t len )
|
||||||
|
{
|
||||||
|
const guchar *str = (const guchar *) buf;
|
||||||
|
|
||||||
|
if( len >= 4 &&
|
||||||
|
str[0] == '%' &&
|
||||||
|
str[1] == 'P' &&
|
||||||
|
str[2] == 'D' &&
|
||||||
|
str[3] == 'F' )
|
||||||
|
return( 1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Also used by the pdfium loader.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
vips_foreign_load_pdf_is_a( const char *filename )
|
||||||
|
{
|
||||||
|
unsigned char buf[4];
|
||||||
|
|
||||||
|
if( vips__get_bytes( filename, buf, 4 ) == 4 &&
|
||||||
|
vips_foreign_load_pdf_is_a_buffer( buf, 4 ) )
|
||||||
|
return( 1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_pdfload:
|
* vips_pdfload:
|
||||||
* @filename: file to load
|
* @filename: file to load
|
||||||
@ -678,18 +685,6 @@ vips_foreign_load_pdf_buffer_init( VipsForeignLoadPdfBuffer *buffer )
|
|||||||
* converted. If you need CMYK bitmaps, you should use vips_magickload()
|
* converted. If you need CMYK bitmaps, you should use vips_magickload()
|
||||||
* instead.
|
* instead.
|
||||||
*
|
*
|
||||||
* Rendering is progressive, that is, the image is rendered in strips equal in
|
|
||||||
* height to the tile height. If your PDF contains large image files and
|
|
||||||
* they span several strips in the output image, they will be decoded multiple
|
|
||||||
* times. To fix this, increase the the tile height, for example:
|
|
||||||
*
|
|
||||||
* |[
|
|
||||||
* vips copy huge.pdf x.png --vips-tile-height=1024
|
|
||||||
* ]|
|
|
||||||
*
|
|
||||||
* Will process images in 1024-pixel high strips, potentially much faster,
|
|
||||||
* though of course also using a lot more memory.
|
|
||||||
*
|
|
||||||
* Use @page to select a page to render, numbering from zero.
|
* Use @page to select a page to render, numbering from zero.
|
||||||
*
|
*
|
||||||
* Use @n to select the number of pages to render. The default is 1. Pages are
|
* Use @n to select the number of pages to render. The default is 1. Pages are
|
||||||
|
651
libvips/foreign/pdfload_pdfium.c
Normal file
651
libvips/foreign/pdfload_pdfium.c
Normal file
@ -0,0 +1,651 @@
|
|||||||
|
/* load PDF with PDFium
|
||||||
|
*
|
||||||
|
* 5/4/18
|
||||||
|
* - from pdfload.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
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO
|
||||||
|
*
|
||||||
|
* - what about filename encodings
|
||||||
|
* - need to test on Windows
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
#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 <errno.h>
|
||||||
|
|
||||||
|
#include <vips/vips.h>
|
||||||
|
#include <vips/buf.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
|
#include "pforeign.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_PDFIUM
|
||||||
|
|
||||||
|
#include <fpdfview.h>
|
||||||
|
#include <fpdf_doc.h>
|
||||||
|
|
||||||
|
typedef struct _VipsForeignLoadPdf {
|
||||||
|
VipsForeignLoad parent_object;
|
||||||
|
|
||||||
|
/* Load this page.
|
||||||
|
*/
|
||||||
|
int page_no;
|
||||||
|
|
||||||
|
/* Load this many pages.
|
||||||
|
*/
|
||||||
|
int n;
|
||||||
|
|
||||||
|
/* Render at this DPI.
|
||||||
|
*/
|
||||||
|
double dpi;
|
||||||
|
|
||||||
|
/* Calculate this from DPI. At 72 DPI, we render 1:1.
|
||||||
|
*/
|
||||||
|
double scale;
|
||||||
|
|
||||||
|
FPDF_DOCUMENT *doc;
|
||||||
|
FPDF_PAGE *page;
|
||||||
|
int current_page;
|
||||||
|
|
||||||
|
/* Doc has this many pages.
|
||||||
|
*/
|
||||||
|
int n_pages;
|
||||||
|
|
||||||
|
/* We need to read out the size of each page we will render, and lay
|
||||||
|
* them out in the final image.
|
||||||
|
*/
|
||||||
|
VipsRect image;
|
||||||
|
VipsRect *pages;
|
||||||
|
|
||||||
|
} VipsForeignLoadPdf;
|
||||||
|
|
||||||
|
typedef VipsForeignLoadClass VipsForeignLoadPdfClass;
|
||||||
|
|
||||||
|
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadPdf, vips_foreign_load_pdf,
|
||||||
|
VIPS_TYPE_FOREIGN_LOAD );
|
||||||
|
|
||||||
|
static char *vips_pdfium_errors[] = {
|
||||||
|
"no error",
|
||||||
|
"unknown error",
|
||||||
|
"file not found or could not be opened",
|
||||||
|
"file not in PDF format or corrupted",
|
||||||
|
"password required or incorrect password",
|
||||||
|
"unsupported security scheme",
|
||||||
|
"page not found or content error"
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_pdfium_error( void )
|
||||||
|
{
|
||||||
|
int err = FPDF_GetLastError();
|
||||||
|
|
||||||
|
if( err >= 0 &&
|
||||||
|
err < VIPS_NUMBER( vips_pdfium_errors ) )
|
||||||
|
vips_error( "pdfload", "%s", _( vips_pdfium_errors[err] ) );
|
||||||
|
else
|
||||||
|
vips_error( "pdfload", "%s", _( "unknown error" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_pdf_dispose( GObject *gobject )
|
||||||
|
{
|
||||||
|
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) gobject;
|
||||||
|
|
||||||
|
VIPS_FREEF( FPDF_ClosePage, pdf->page );
|
||||||
|
VIPS_FREEF( FPDF_CloseDocument, pdf->doc );
|
||||||
|
|
||||||
|
G_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )->dispose( gobject );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
vips_pdfium_init_cb( void *dummy )
|
||||||
|
{
|
||||||
|
FPDF_LIBRARY_CONFIG config;
|
||||||
|
|
||||||
|
config.version = 2;
|
||||||
|
config.m_pUserFontPaths = NULL;
|
||||||
|
config.m_pIsolate = NULL;
|
||||||
|
config.m_v8EmbedderSlot = 0;
|
||||||
|
|
||||||
|
FPDF_InitLibraryWithConfig( &config );
|
||||||
|
|
||||||
|
return( NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_pdf_build( VipsObject *object )
|
||||||
|
{
|
||||||
|
static GOnce once = G_ONCE_INIT;
|
||||||
|
|
||||||
|
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) object;
|
||||||
|
|
||||||
|
VIPS_ONCE( &once, vips_pdfium_init_cb, NULL );
|
||||||
|
|
||||||
|
if( !vips_object_argument_isset( object, "scale" ) )
|
||||||
|
pdf->scale = pdf->dpi / 72.0;
|
||||||
|
|
||||||
|
if( VIPS_OBJECT_CLASS( vips_foreign_load_pdf_parent_class )->
|
||||||
|
build( object ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static VipsForeignFlags
|
||||||
|
vips_foreign_load_pdf_get_flags_filename( const char *filename )
|
||||||
|
{
|
||||||
|
/* We can't render any part of the page on demand, but we can render
|
||||||
|
* separate pages. Might as well call ourselves partial.
|
||||||
|
*/
|
||||||
|
return( VIPS_FOREIGN_PARTIAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static VipsForeignFlags
|
||||||
|
vips_foreign_load_pdf_get_flags( VipsForeignLoad *load )
|
||||||
|
{
|
||||||
|
return( VIPS_FOREIGN_PARTIAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_pdf_get_page( VipsForeignLoadPdf *pdf, int page_no )
|
||||||
|
{
|
||||||
|
if( pdf->current_page != page_no ) {
|
||||||
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( pdf );
|
||||||
|
|
||||||
|
VIPS_FREEF( FPDF_ClosePage, pdf->page );
|
||||||
|
pdf->current_page = -1;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "vips_foreign_load_pdf_get_page: %d\n", page_no );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
if( !(pdf->page = FPDF_LoadPage( pdf->doc, page_no )) ) {
|
||||||
|
vips_pdfium_error();
|
||||||
|
vips_error( class->nickname,
|
||||||
|
_( "unable to load page %d" ), page_no );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
pdf->current_page = page_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* String-based metadata fields we extract.
|
||||||
|
*/
|
||||||
|
typedef struct _VipsForeignLoadPdfMetadata {
|
||||||
|
char *tag; /* as understood by PDFium */
|
||||||
|
char *field; /* as understood by libvips */
|
||||||
|
} VipsForeignLoadPdfMetadata;
|
||||||
|
|
||||||
|
static VipsForeignLoadPdfMetadata vips_foreign_load_pdf_metadata[] = {
|
||||||
|
{ "Title", "pdf-title" },
|
||||||
|
{ "Author", "pdf-author" },
|
||||||
|
{ "Subject", "pdf-subject" },
|
||||||
|
{ "Keywords", "pdf-keywords" },
|
||||||
|
{ "Creator", "pdf-creator" },
|
||||||
|
{ "Producer", "pdf-producer" },
|
||||||
|
/* poppler has "metadata" as well, but pdfium does not support this */
|
||||||
|
};
|
||||||
|
static int n_metadata = VIPS_NUMBER( vips_foreign_load_pdf_metadata );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_pdf_set_image( VipsForeignLoadPdf *pdf, VipsImage *out )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
double res;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "vips_foreign_load_pdf_set_image: %p\n", pdf );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
/* We render to a linecache, so fat strips work well.
|
||||||
|
*/
|
||||||
|
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
|
||||||
|
|
||||||
|
/* Extract and attach metadata. Set the old name too for compat.
|
||||||
|
*/
|
||||||
|
vips_image_set_int( out, "pdf-n_pages", pdf->n_pages );
|
||||||
|
vips_image_set_int( out, VIPS_META_N_PAGES, pdf->n_pages );
|
||||||
|
|
||||||
|
for( i = 0; i < n_metadata; i++ ) {
|
||||||
|
VipsForeignLoadPdfMetadata *metadata =
|
||||||
|
&vips_foreign_load_pdf_metadata[i];
|
||||||
|
|
||||||
|
char text[1024];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = FPDF_GetMetaText( pdf->doc, metadata->tag, text, 1024 );
|
||||||
|
if( len > 0 ) {
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
/* Silently ignore coding errors.
|
||||||
|
*/
|
||||||
|
if( (str = g_utf16_to_utf8( (gunichar2 *) text, len,
|
||||||
|
NULL, NULL, NULL )) ) {
|
||||||
|
vips_image_set_string( out,
|
||||||
|
metadata->field, str );
|
||||||
|
g_free( str );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need pixels/mm for vips.
|
||||||
|
*/
|
||||||
|
res = pdf->dpi / 25.4;
|
||||||
|
|
||||||
|
vips_image_init_fields( out,
|
||||||
|
pdf->image.width, pdf->image.height,
|
||||||
|
4, VIPS_FORMAT_UCHAR,
|
||||||
|
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, res, res );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_pdf_header( VipsForeignLoad *load )
|
||||||
|
{
|
||||||
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( load );
|
||||||
|
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load;
|
||||||
|
|
||||||
|
int top;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "vips_foreign_load_pdf_header: %p\n", pdf );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
pdf->n_pages = FPDF_GetPageCount( pdf->doc );
|
||||||
|
|
||||||
|
/* @n == -1 means until the end of the doc.
|
||||||
|
*/
|
||||||
|
if( pdf->n == -1 )
|
||||||
|
pdf->n = pdf->n_pages - pdf->page_no;
|
||||||
|
|
||||||
|
if( pdf->page_no + pdf->n > pdf->n_pages ||
|
||||||
|
pdf->page_no < 0 ||
|
||||||
|
pdf->n <= 0 ) {
|
||||||
|
vips_error( class->nickname, "%s", _( "pages out of range" ) );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lay out the pages in our output image.
|
||||||
|
*/
|
||||||
|
if( !(pdf->pages = VIPS_ARRAY( pdf, pdf->n, VipsRect )) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
top = 0;
|
||||||
|
pdf->image.left = 0;
|
||||||
|
pdf->image.top = 0;
|
||||||
|
pdf->image.width = 0;
|
||||||
|
pdf->image.height = 0;
|
||||||
|
for( i = 0; i < pdf->n; i++ ) {
|
||||||
|
if( vips_foreign_load_pdf_get_page( pdf, pdf->page_no + i ) )
|
||||||
|
return( -1 );
|
||||||
|
pdf->pages[i].left = 0;
|
||||||
|
pdf->pages[i].top = top;
|
||||||
|
pdf->pages[i].width =
|
||||||
|
FPDF_GetPageWidth( pdf->page ) * pdf->scale;
|
||||||
|
pdf->pages[i].height =
|
||||||
|
FPDF_GetPageHeight( pdf->page ) * pdf->scale;
|
||||||
|
|
||||||
|
if( pdf->pages[i].width > pdf->image.width )
|
||||||
|
pdf->image.width = pdf->pages[i].width;
|
||||||
|
pdf->image.height += pdf->pages[i].height;
|
||||||
|
|
||||||
|
top += pdf->pages[i].height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If all pages are the same size, we can tag this as a toilet roll
|
||||||
|
* image and tiffsave will be able to save it as a multipage tiff.
|
||||||
|
*/
|
||||||
|
for( i = 1; i < pdf->n; i++ )
|
||||||
|
if( pdf->pages[i].width != pdf->pages[0].width ||
|
||||||
|
pdf->pages[i].height != pdf->pages[0].height )
|
||||||
|
break;
|
||||||
|
if( i == pdf->n )
|
||||||
|
vips_image_set_int( load->out,
|
||||||
|
VIPS_META_PAGE_HEIGHT, pdf->pages[0].height );
|
||||||
|
|
||||||
|
vips_foreign_load_pdf_set_image( pdf, load->out );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_pdf_generate( VipsRegion *or,
|
||||||
|
void *seq, void *a, void *b, gboolean *stop )
|
||||||
|
{
|
||||||
|
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) a;
|
||||||
|
VipsRect *r = &or->valid;
|
||||||
|
|
||||||
|
int top;
|
||||||
|
int i;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
/*
|
||||||
|
printf( "vips_foreign_load_pdf_generate: "
|
||||||
|
"left = %d, top = %d, width = %d, height = %d\n",
|
||||||
|
r->left, r->top, r->width, r->height );
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Poppler won't always paint the background. Use 255 (white) for the
|
||||||
|
* bg, PDFs generally assume a paper backgrocund colour.
|
||||||
|
*/
|
||||||
|
vips_region_paint( or, r, 255 );
|
||||||
|
|
||||||
|
/* Search through the pages we are drawing for the first containing
|
||||||
|
* this rect. This could be quicker, perhaps a binary search, but who
|
||||||
|
* cares.
|
||||||
|
*/
|
||||||
|
for( i = 0; i < pdf->n; i++ )
|
||||||
|
if( VIPS_RECT_BOTTOM( &pdf->pages[i] ) > r->top )
|
||||||
|
break;
|
||||||
|
|
||||||
|
top = r->top;
|
||||||
|
while( top < VIPS_RECT_BOTTOM( r ) ) {
|
||||||
|
VipsRect rect;
|
||||||
|
FPDF_BITMAP bitmap;
|
||||||
|
|
||||||
|
vips_rect_intersectrect( r, &pdf->pages[i], &rect );
|
||||||
|
|
||||||
|
if( vips_foreign_load_pdf_get_page( pdf, pdf->page_no + i ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
/* 4 means RGBA.
|
||||||
|
*/
|
||||||
|
bitmap = FPDFBitmap_CreateEx( rect.width, rect.height, 4,
|
||||||
|
VIPS_REGION_ADDR( or, rect.left, rect.top ),
|
||||||
|
VIPS_REGION_LSKIP( or ) );
|
||||||
|
|
||||||
|
FPDF_RenderPageBitmap( bitmap, pdf->page,
|
||||||
|
0, 0, rect.width, rect.height,
|
||||||
|
0, 0 );
|
||||||
|
|
||||||
|
FPDFBitmap_Destroy( bitmap );
|
||||||
|
|
||||||
|
top += rect.height;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PDFium writes BRGA, we must swap.
|
||||||
|
*
|
||||||
|
* FIXME ... this is a bit slow.
|
||||||
|
*/
|
||||||
|
for( y = 0; y < r->height; y++ ) {
|
||||||
|
VipsPel *p;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
p = VIPS_REGION_ADDR( or, r->left, r->top + y );
|
||||||
|
for( x = 0; x < r->width; x++ ) {
|
||||||
|
VIPS_SWAP( VipsPel, p[0], p[2] );
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_pdf_load( VipsForeignLoad *load )
|
||||||
|
{
|
||||||
|
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load;
|
||||||
|
VipsImage **t = (VipsImage **)
|
||||||
|
vips_object_local_array( (VipsObject *) load, 2 );
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "vips_foreign_load_pdf_load: %p\n", pdf );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
/* Read to this image, then cache to out, see below.
|
||||||
|
*/
|
||||||
|
t[0] = vips_image_new();
|
||||||
|
|
||||||
|
vips_foreign_load_pdf_set_image( pdf, t[0] );
|
||||||
|
if( vips_image_generate( t[0],
|
||||||
|
NULL, vips_foreign_load_pdf_generate, NULL, pdf, NULL ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
/* PDFium does not like rendering parts of pages :-( always render
|
||||||
|
* complete ones.
|
||||||
|
*/
|
||||||
|
if( vips_linecache( t[0], &t[1],
|
||||||
|
"tile_height", pdf->pages[0].height,
|
||||||
|
NULL ) )
|
||||||
|
return( -1 );
|
||||||
|
if( vips_image_write( t[1], load->real ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_pdf_class_init( VipsForeignLoadPdfClass *class )
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||||
|
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||||
|
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||||
|
|
||||||
|
gobject_class->dispose = vips_foreign_load_pdf_dispose;
|
||||||
|
gobject_class->set_property = vips_object_set_property;
|
||||||
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
|
object_class->nickname = "pdfload_base";
|
||||||
|
object_class->description = _( "load PDF with libpoppler" );
|
||||||
|
object_class->build = vips_foreign_load_pdf_build;
|
||||||
|
|
||||||
|
load_class->get_flags_filename =
|
||||||
|
vips_foreign_load_pdf_get_flags_filename;
|
||||||
|
load_class->get_flags = vips_foreign_load_pdf_get_flags;
|
||||||
|
load_class->load = vips_foreign_load_pdf_load;
|
||||||
|
|
||||||
|
VIPS_ARG_INT( class, "page", 10,
|
||||||
|
_( "Page" ),
|
||||||
|
_( "Load this page from the file" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignLoadPdf, page_no ),
|
||||||
|
0, 100000, 0 );
|
||||||
|
|
||||||
|
VIPS_ARG_INT( class, "n", 11,
|
||||||
|
_( "n" ),
|
||||||
|
_( "Load this many pages" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignLoadPdf, n ),
|
||||||
|
-1, 100000, 1 );
|
||||||
|
|
||||||
|
VIPS_ARG_DOUBLE( class, "dpi", 12,
|
||||||
|
_( "DPI" ),
|
||||||
|
_( "Render at this DPI" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignLoadPdf, dpi ),
|
||||||
|
0.001, 100000.0, 72.0 );
|
||||||
|
|
||||||
|
VIPS_ARG_DOUBLE( class, "scale", 13,
|
||||||
|
_( "Scale" ),
|
||||||
|
_( "Scale output by this factor" ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignLoadPdf, scale ),
|
||||||
|
0.001, 100000.0, 1.0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_pdf_init( VipsForeignLoadPdf *pdf )
|
||||||
|
{
|
||||||
|
pdf->dpi = 72.0;
|
||||||
|
pdf->scale = 1.0;
|
||||||
|
pdf->n = 1;
|
||||||
|
pdf->current_page = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsForeignLoadPdfFile {
|
||||||
|
VipsForeignLoadPdf parent_object;
|
||||||
|
|
||||||
|
/* Filename for load.
|
||||||
|
*/
|
||||||
|
char *filename;
|
||||||
|
|
||||||
|
} VipsForeignLoadPdfFile;
|
||||||
|
|
||||||
|
typedef VipsForeignLoadPdfClass VipsForeignLoadPdfFileClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignLoadPdfFile, vips_foreign_load_pdf_file,
|
||||||
|
vips_foreign_load_pdf_get_type() );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_pdf_file_header( VipsForeignLoad *load )
|
||||||
|
{
|
||||||
|
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load;
|
||||||
|
VipsForeignLoadPdfFile *file = (VipsForeignLoadPdfFile *) load;
|
||||||
|
|
||||||
|
if( !(pdf->doc = FPDF_LoadDocument( file->filename, NULL )) ) {
|
||||||
|
vips_pdfium_error();
|
||||||
|
vips_error( "pdfload",
|
||||||
|
_( "unable to load \"%s\"" ), file->filename );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
VIPS_SETSTR( load->out->filename, file->filename );
|
||||||
|
|
||||||
|
return( vips_foreign_load_pdf_header( load ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *vips_foreign_pdf_suffs[] = {
|
||||||
|
".pdf",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_pdf_file_class_init(
|
||||||
|
VipsForeignLoadPdfFileClass *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 = "pdfload";
|
||||||
|
|
||||||
|
foreign_class->suffs = vips_foreign_pdf_suffs;
|
||||||
|
|
||||||
|
load_class->is_a = vips_foreign_load_pdf_is_a;
|
||||||
|
load_class->header = vips_foreign_load_pdf_file_header;
|
||||||
|
|
||||||
|
VIPS_ARG_STRING( class, "filename", 1,
|
||||||
|
_( "Filename" ),
|
||||||
|
_( "Filename to load from" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignLoadPdfFile, filename ),
|
||||||
|
NULL );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_pdf_file_init( VipsForeignLoadPdfFile *file )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsForeignLoadPdfBuffer {
|
||||||
|
VipsForeignLoadPdf parent_object;
|
||||||
|
|
||||||
|
/* Load from a buffer.
|
||||||
|
*/
|
||||||
|
VipsArea *buf;
|
||||||
|
|
||||||
|
} VipsForeignLoadPdfBuffer;
|
||||||
|
|
||||||
|
typedef VipsForeignLoadPdfClass VipsForeignLoadPdfBufferClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignLoadPdfBuffer, vips_foreign_load_pdf_buffer,
|
||||||
|
vips_foreign_load_pdf_get_type() );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_pdf_buffer_header( VipsForeignLoad *load )
|
||||||
|
{
|
||||||
|
VipsForeignLoadPdf *pdf = (VipsForeignLoadPdf *) load;
|
||||||
|
VipsForeignLoadPdfBuffer *buffer =
|
||||||
|
(VipsForeignLoadPdfBuffer *) load;
|
||||||
|
|
||||||
|
if( !(pdf->doc = FPDF_LoadMemDocument( buffer->buf->data,
|
||||||
|
buffer->buf->length, NULL )) ) {
|
||||||
|
vips_pdfium_error();
|
||||||
|
vips_error( "pdfload",
|
||||||
|
"%s", _( "unable to load from buffer" ) );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( vips_foreign_load_pdf_header( load ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_pdf_buffer_class_init(
|
||||||
|
VipsForeignLoadPdfBufferClass *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 = "pdfload_buffer";
|
||||||
|
|
||||||
|
load_class->is_a_buffer = vips_foreign_load_pdf_is_a_buffer;
|
||||||
|
load_class->header = vips_foreign_load_pdf_buffer_header;
|
||||||
|
|
||||||
|
VIPS_ARG_BOXED( class, "buffer", 1,
|
||||||
|
_( "Buffer" ),
|
||||||
|
_( "Buffer to load from" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignLoadPdfBuffer, buf ),
|
||||||
|
VIPS_TYPE_BLOB );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_pdf_buffer_init( VipsForeignLoadPdfBuffer *buffer )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*HAVE_PDFIUM*/
|
@ -123,14 +123,18 @@ int vips__fits_read( const char *filename, VipsImage *out );
|
|||||||
int vips__fits_write( VipsImage *in, const char *filename );
|
int vips__fits_write( VipsImage *in, const char *filename );
|
||||||
|
|
||||||
int vips__magick_read( const char *filename,
|
int vips__magick_read( const char *filename,
|
||||||
VipsImage *out, const char *density, int page, int n );
|
VipsImage *out, const char *format, const char *density,
|
||||||
|
int page, int n );
|
||||||
int vips__magick_read_header( const char *filename,
|
int vips__magick_read_header( const char *filename,
|
||||||
VipsImage *out, const char *density, int page, int n );
|
VipsImage *out, const char *format, const char *density,
|
||||||
|
int page, int n );
|
||||||
|
|
||||||
int vips__magick_read_buffer( const void *buf, const size_t len,
|
int vips__magick_read_buffer( const void *buf, const size_t len,
|
||||||
VipsImage *out, const char *density, int page, int n );
|
VipsImage *out, const char *format, const char *density,
|
||||||
|
int page, int n );
|
||||||
int vips__magick_read_buffer_header( 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 );
|
VipsImage *out, const char *format, const char *density,
|
||||||
|
int page, int n );
|
||||||
|
|
||||||
extern const char *vips__mat_suffs[];
|
extern const char *vips__mat_suffs[];
|
||||||
|
|
||||||
@ -162,12 +166,14 @@ int vips__jpeg_write_file( VipsImage *in,
|
|||||||
const char *filename, int Q, const char *profile,
|
const char *filename, int Q, const char *profile,
|
||||||
gboolean optimize_coding, gboolean progressive, gboolean strip,
|
gboolean optimize_coding, gboolean progressive, gboolean strip,
|
||||||
gboolean no_subsample, gboolean trellis_quant,
|
gboolean no_subsample, gboolean trellis_quant,
|
||||||
gboolean overshoot_deringing, gboolean optimize_scans, int quant_table );
|
gboolean overshoot_deringing, gboolean optimize_scans,
|
||||||
|
int quant_table );
|
||||||
int vips__jpeg_write_buffer( VipsImage *in,
|
int vips__jpeg_write_buffer( VipsImage *in,
|
||||||
void **obuf, size_t *olen, int Q, const char *profile,
|
void **obuf, size_t *olen, int Q, const char *profile,
|
||||||
gboolean optimize_coding, gboolean progressive, gboolean strip,
|
gboolean optimize_coding, gboolean progressive, gboolean strip,
|
||||||
gboolean no_subsample, gboolean trellis_quant,
|
gboolean no_subsample, gboolean trellis_quant,
|
||||||
gboolean overshoot_deringing, gboolean optimize_scans, int quant_table );
|
gboolean overshoot_deringing, gboolean optimize_scans,
|
||||||
|
int quant_table );
|
||||||
|
|
||||||
int vips__isjpeg_buffer( const void *buf, size_t len );
|
int vips__isjpeg_buffer( const void *buf, size_t len );
|
||||||
int vips__isjpeg( const char *filename );
|
int vips__isjpeg( const char *filename );
|
||||||
@ -239,6 +245,9 @@ int vips__openslide_read( const char *filename, VipsImage *out,
|
|||||||
int vips__openslide_read_associated( const char *filename, VipsImage *out,
|
int vips__openslide_read_associated( const char *filename, VipsImage *out,
|
||||||
const char *associated );
|
const char *associated );
|
||||||
|
|
||||||
|
gboolean vips_foreign_load_pdf_is_a_buffer( const void *buf, size_t len );
|
||||||
|
gboolean vips_foreign_load_pdf_is_a( const char *filename );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
* - add buffer save functions
|
* - add buffer save functions
|
||||||
* 28/2/17
|
* 28/2/17
|
||||||
* - use dbuf for buffer output
|
* - use dbuf for buffer output
|
||||||
|
* 4/4/17
|
||||||
|
* - reduce stack use to help musl
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -885,10 +887,12 @@ rle_scanline_write( COLR *scanline, int width,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a single scanline.
|
/* Write a single scanline. buffer is at least MAX_LINE bytes and is used to
|
||||||
|
* construct the RLE scanline. Don't allocate this on the stack so we don't
|
||||||
|
* die too horribly on small-stack libc.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
scanline_write( COLR *scanline, int width, FILE *fp )
|
scanline_write( unsigned char *buffer, COLR *scanline, int width, FILE *fp )
|
||||||
{
|
{
|
||||||
if( width < MINELEN ||
|
if( width < MINELEN ||
|
||||||
width > MAXELEN )
|
width > MAXELEN )
|
||||||
@ -898,11 +902,12 @@ scanline_write( COLR *scanline, int width, FILE *fp )
|
|||||||
else {
|
else {
|
||||||
/* An RLE scanline.
|
/* An RLE scanline.
|
||||||
*/
|
*/
|
||||||
unsigned char buffer[MAX_LINE];
|
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
rle_scanline_write( scanline, width, buffer, &length );
|
rle_scanline_write( scanline, width, buffer, &length );
|
||||||
|
|
||||||
|
g_assert( length <= MAX_LINE );
|
||||||
|
|
||||||
return( fwrite( buffer, 1, length, fp ) - length );
|
return( fwrite( buffer, 1, length, fp ) - length );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1290,12 +1295,23 @@ static int
|
|||||||
vips2rad_put_data_block( VipsRegion *region, VipsRect *area, void *a )
|
vips2rad_put_data_block( VipsRegion *region, VipsRect *area, void *a )
|
||||||
{
|
{
|
||||||
Write *write = (Write *) a;
|
Write *write = (Write *) a;
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
unsigned char *buffer;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* You have to seek back after a write.
|
||||||
|
*/
|
||||||
|
buffer = vips_dbuf_get_write( &write->dbuf, &size );
|
||||||
|
vips_dbuf_seek( &write->dbuf, 0, SEEK_SET );
|
||||||
|
|
||||||
|
g_assert( size >= MAX_LINE );
|
||||||
|
|
||||||
for( i = 0; i < area->height; i++ ) {
|
for( i = 0; i < area->height; i++ ) {
|
||||||
VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + i );
|
VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + i );
|
||||||
|
|
||||||
if( scanline_write( (COLR *) p, area->width, write->fout ) )
|
if( scanline_write( buffer,
|
||||||
|
(COLR *) p, area->width, write->fout ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1329,6 +1345,11 @@ vips__rad_save( VipsImage *in, const char *filename )
|
|||||||
write->filename = vips_strdup( NULL, filename );
|
write->filename = vips_strdup( NULL, filename );
|
||||||
write->fout = vips__file_open_write( filename, FALSE );
|
write->fout = vips__file_open_write( filename, FALSE );
|
||||||
|
|
||||||
|
/* scanline_write() needs a buffer to write compressed scanlines to.
|
||||||
|
* We use the dbuf ... why not.
|
||||||
|
*/
|
||||||
|
vips_dbuf_allocate( &write->dbuf, MAX_LINE );
|
||||||
|
|
||||||
if( !write->filename ||
|
if( !write->filename ||
|
||||||
!write->fout ||
|
!write->fout ||
|
||||||
vips2rad_put_header( write ) ||
|
vips2rad_put_header( write ) ||
|
||||||
|
@ -177,6 +177,8 @@
|
|||||||
* - remove missing res warning
|
* - remove missing res warning
|
||||||
* 19/5/17
|
* 19/5/17
|
||||||
* - page > 0 could break edge tiles or strips
|
* - page > 0 could break edge tiles or strips
|
||||||
|
* 26/4/18
|
||||||
|
* - add n-pages metadata item
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -283,6 +285,10 @@ typedef struct _Rtiff {
|
|||||||
*/
|
*/
|
||||||
TIFF *tiff;
|
TIFF *tiff;
|
||||||
|
|
||||||
|
/* Number of pages (directories) in image.
|
||||||
|
*/
|
||||||
|
int n_pages;
|
||||||
|
|
||||||
/* The current page we have set.
|
/* The current page we have set.
|
||||||
*/
|
*/
|
||||||
int current_page;
|
int current_page;
|
||||||
@ -1230,6 +1236,8 @@ rtiff_set_header( Rtiff *rtiff, VipsImage *out )
|
|||||||
vips_image_set_int( out,
|
vips_image_set_int( out,
|
||||||
VIPS_META_PAGE_HEIGHT, rtiff->header.height );
|
VIPS_META_PAGE_HEIGHT, rtiff->header.height );
|
||||||
|
|
||||||
|
vips_image_set_int( out, VIPS_META_N_PAGES, rtiff->n_pages );
|
||||||
|
|
||||||
/* Even though we could end up serving tiled data, always hint
|
/* Even though we could end up serving tiled data, always hint
|
||||||
* THINSTRIP, since we're quite happy doing that too, and it could need
|
* THINSTRIP, since we're quite happy doing that too, and it could need
|
||||||
* a lot less memory.
|
* a lot less memory.
|
||||||
@ -1984,6 +1992,7 @@ rtiff_new( VipsImage *out, int page, int n, gboolean autorotate )
|
|||||||
rtiff->n = n;
|
rtiff->n = n;
|
||||||
rtiff->autorotate = autorotate;
|
rtiff->autorotate = autorotate;
|
||||||
rtiff->tiff = NULL;
|
rtiff->tiff = NULL;
|
||||||
|
rtiff->n_pages = 0;
|
||||||
rtiff->current_page = -1;
|
rtiff->current_page = -1;
|
||||||
rtiff->sfn = NULL;
|
rtiff->sfn = NULL;
|
||||||
rtiff->client = NULL;
|
rtiff->client = NULL;
|
||||||
@ -2167,8 +2176,9 @@ rtiff_header_read_all( Rtiff *rtiff )
|
|||||||
|
|
||||||
/* -1 means "to the end".
|
/* -1 means "to the end".
|
||||||
*/
|
*/
|
||||||
|
rtiff->n_pages = rtiff_n_pages( rtiff );
|
||||||
if( rtiff->n == -1 )
|
if( rtiff->n == -1 )
|
||||||
rtiff->n = rtiff_n_pages( rtiff ) - rtiff->page;
|
rtiff->n = rtiff->n_pages - rtiff->page;
|
||||||
|
|
||||||
/* If we're to read many pages, verify that they are all identical.
|
/* If we're to read many pages, verify that they are all identical.
|
||||||
*/
|
*/
|
||||||
|
@ -65,6 +65,8 @@
|
|||||||
* - better behaviour for truncated png files, thanks Yury
|
* - better behaviour for truncated png files, thanks Yury
|
||||||
* 26/4/17
|
* 26/4/17
|
||||||
* - better @fail handling with truncated PNGs
|
* - better @fail handling with truncated PNGs
|
||||||
|
* 9/4/18
|
||||||
|
* - set interlaced=1 for interlaced images
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -438,6 +440,11 @@ png2vips_header( Read *read, VipsImage *out )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Let our caller know. These are very expensive to decode.
|
||||||
|
*/
|
||||||
|
if( interlace_type != PNG_INTERLACE_NONE )
|
||||||
|
vips_image_set_int( out, "interlaced", 1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -992,7 +999,8 @@ write_vips( Write *write,
|
|||||||
/* If we're an intel byte order CPU and this is a 16bit image, we need
|
/* If we're an intel byte order CPU and this is a 16bit image, we need
|
||||||
* to swap bytes.
|
* to swap bytes.
|
||||||
*/
|
*/
|
||||||
if( bit_depth > 8 && !vips_amiMSBfirst() )
|
if( bit_depth > 8 &&
|
||||||
|
!vips_amiMSBfirst() )
|
||||||
png_set_swap( write->pPng );
|
png_set_swap( write->pPng );
|
||||||
|
|
||||||
if( interlace )
|
if( interlace )
|
||||||
|
@ -177,6 +177,8 @@ int vips_icc_export( VipsImage *in, VipsImage **out, ... )
|
|||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
int vips_icc_ac2rc( VipsImage *in, VipsImage **out,
|
int vips_icc_ac2rc( VipsImage *in, VipsImage **out,
|
||||||
const char *profile_filename );
|
const char *profile_filename );
|
||||||
|
gboolean vips_icc_is_compatible_profile( VipsImage *image,
|
||||||
|
void *data, size_t data_length );
|
||||||
|
|
||||||
int vips_dE76( VipsImage *left, VipsImage *right, VipsImage **out, ... )
|
int vips_dE76( VipsImage *left, VipsImage *right, VipsImage **out, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
|
@ -5,6 +5,32 @@
|
|||||||
#define VIPS_ENUM_TYPES_H
|
#define VIPS_ENUM_TYPES_H
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
/* enumerations from "../../../libvips/include/vips/resample.h" */
|
||||||
|
GType vips_kernel_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_KERNEL (vips_kernel_get_type())
|
||||||
|
GType vips_size_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_SIZE (vips_size_get_type())
|
||||||
|
/* enumerations from "../../../libvips/include/vips/foreign.h" */
|
||||||
|
GType vips_foreign_flags_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_FOREIGN_FLAGS (vips_foreign_flags_get_type())
|
||||||
|
GType vips_saveable_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_SAVEABLE (vips_saveable_get_type())
|
||||||
|
GType vips_foreign_webp_preset_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_FOREIGN_WEBP_PRESET (vips_foreign_webp_preset_get_type())
|
||||||
|
GType vips_foreign_tiff_compression_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_FOREIGN_TIFF_COMPRESSION (vips_foreign_tiff_compression_get_type())
|
||||||
|
GType vips_foreign_tiff_predictor_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_FOREIGN_TIFF_PREDICTOR (vips_foreign_tiff_predictor_get_type())
|
||||||
|
GType vips_foreign_tiff_resunit_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_FOREIGN_TIFF_RESUNIT (vips_foreign_tiff_resunit_get_type())
|
||||||
|
GType vips_foreign_png_filter_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_FOREIGN_PNG_FILTER (vips_foreign_png_filter_get_type())
|
||||||
|
GType vips_foreign_dz_layout_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_FOREIGN_DZ_LAYOUT (vips_foreign_dz_layout_get_type())
|
||||||
|
GType vips_foreign_dz_depth_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_FOREIGN_DZ_DEPTH (vips_foreign_dz_depth_get_type())
|
||||||
|
GType vips_foreign_dz_container_get_type (void) G_GNUC_CONST;
|
||||||
|
#define VIPS_TYPE_FOREIGN_DZ_CONTAINER (vips_foreign_dz_container_get_type())
|
||||||
/* enumerations from "../../../libvips/include/vips/arithmetic.h" */
|
/* enumerations from "../../../libvips/include/vips/arithmetic.h" */
|
||||||
GType vips_operation_math_get_type (void) G_GNUC_CONST;
|
GType vips_operation_math_get_type (void) G_GNUC_CONST;
|
||||||
#define VIPS_TYPE_OPERATION_MATH (vips_operation_math_get_type())
|
#define VIPS_TYPE_OPERATION_MATH (vips_operation_math_get_type())
|
||||||
|
@ -143,6 +143,13 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define VIPS_META_PAGE_HEIGHT "page-height"
|
#define VIPS_META_PAGE_HEIGHT "page-height"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VIPS_META_N_PAGES:
|
||||||
|
*
|
||||||
|
* If set, the number of pages in the original file.
|
||||||
|
*/
|
||||||
|
#define VIPS_META_N_PAGES "n-pages"
|
||||||
|
|
||||||
guint64 vips_format_sizeof( VipsBandFormat format );
|
guint64 vips_format_sizeof( VipsBandFormat format );
|
||||||
guint64 vips_format_sizeof_unsafe( VipsBandFormat format );
|
guint64 vips_format_sizeof_unsafe( VipsBandFormat format );
|
||||||
|
|
||||||
|
@ -12,8 +12,10 @@
|
|||||||
* - vips_image_write() does not ref input for non-partial images
|
* - vips_image_write() does not ref input for non-partial images
|
||||||
* 29/10/16
|
* 29/10/16
|
||||||
* - add vips_image_hasalpha()
|
* - add vips_image_hasalpha()
|
||||||
* 11/10/1
|
* 11/10/17
|
||||||
* - more severing for vips_image_write()
|
* - more severing for vips_image_write()
|
||||||
|
* 3/4/18
|
||||||
|
* - better rules for hasalpha
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2449,9 +2451,6 @@ vips_get_disc_threshold( void )
|
|||||||
* will default to /tmp. On Windows, vips uses GetTempPath() to find the
|
* will default to /tmp. On Windows, vips uses GetTempPath() to find the
|
||||||
* temporary directory.
|
* temporary directory.
|
||||||
*
|
*
|
||||||
* vips uses g_mkstemp() to make the temporary filename. They generally look
|
|
||||||
* something like "vips-12-EJKJFGH.v".
|
|
||||||
*
|
|
||||||
* See also: vips_image_new().
|
* See also: vips_image_new().
|
||||||
*
|
*
|
||||||
* Returns: the new #VipsImage, or %NULL on error.
|
* Returns: the new #VipsImage, or %NULL on error.
|
||||||
@ -2658,7 +2657,7 @@ vips_image_write_to_buffer( VipsImage *in,
|
|||||||
*
|
*
|
||||||
* Writes @in to memory as a simple, unformatted C-style array.
|
* Writes @in to memory as a simple, unformatted C-style array.
|
||||||
*
|
*
|
||||||
* The caller is responsible for freeing this memory.
|
* The caller is responsible for freeing this memory with g_free().
|
||||||
*
|
*
|
||||||
* See also: vips_image_write_to_buffer().
|
* See also: vips_image_write_to_buffer().
|
||||||
*
|
*
|
||||||
@ -2866,18 +2865,47 @@ vips_image_ispartial( VipsImage *image )
|
|||||||
* vips_image_hasalpha: (method)
|
* vips_image_hasalpha: (method)
|
||||||
* @image: image to check
|
* @image: image to check
|
||||||
*
|
*
|
||||||
* libvips assumes an image has an alpha if it has two bands (ie. it is a
|
* Look at an image's interpretation and see if it has extra alpha bands. For
|
||||||
* monochrome image with an extra band), if it has four bands (unless it's been
|
* example, a 4-band #VIPS_INTERPRETATION_RGB would, but a six-band
|
||||||
* tagged as CMYK), or if it has more than four bands.
|
* #VIPS_INTERPRETATION_MULTIBAND would not.
|
||||||
*
|
*
|
||||||
* Return %TRUE if @image has an alpha channel.
|
* Return %TRUE if @image has an alpha channel.
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
vips_image_hasalpha( VipsImage *image )
|
vips_image_hasalpha( VipsImage *image )
|
||||||
{
|
{
|
||||||
return( image->Bands == 2 ||
|
/* The result of hasalpha is used to turn on things like
|
||||||
(image->Bands == 4 && image->Type != VIPS_INTERPRETATION_CMYK) ||
|
* premultiplication, so we are rather conservative about when we
|
||||||
image->Bands > 4 );
|
* signal this. We don't want to premultiply things that should not be
|
||||||
|
* premultiplied.
|
||||||
|
*/
|
||||||
|
switch( image->Type ) {
|
||||||
|
case VIPS_INTERPRETATION_B_W:
|
||||||
|
case VIPS_INTERPRETATION_GREY16:
|
||||||
|
return( image->Bands > 1 );
|
||||||
|
|
||||||
|
case VIPS_INTERPRETATION_RGB:
|
||||||
|
case VIPS_INTERPRETATION_CMC:
|
||||||
|
case VIPS_INTERPRETATION_LCH:
|
||||||
|
case VIPS_INTERPRETATION_LABS:
|
||||||
|
case VIPS_INTERPRETATION_sRGB:
|
||||||
|
case VIPS_INTERPRETATION_YXY:
|
||||||
|
case VIPS_INTERPRETATION_XYZ:
|
||||||
|
case VIPS_INTERPRETATION_LAB:
|
||||||
|
case VIPS_INTERPRETATION_RGB16:
|
||||||
|
case VIPS_INTERPRETATION_scRGB:
|
||||||
|
case VIPS_INTERPRETATION_HSV:
|
||||||
|
return( image->Bands > 3 );
|
||||||
|
|
||||||
|
case VIPS_INTERPRETATION_CMYK:
|
||||||
|
return( image->Bands > 4 );
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* We can't really infer anything about bands from things like
|
||||||
|
* HISTOGRAM or FOURIER.
|
||||||
|
*/
|
||||||
|
return( FALSE );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1118,9 +1118,9 @@ vips__ftruncate( int fd, gint64 pos )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test for file exists.
|
/* TRUE if file exists.
|
||||||
*/
|
*/
|
||||||
int
|
gboolean
|
||||||
vips_existsf( const char *name, ... )
|
vips_existsf( const char *name, ... )
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@ -1135,7 +1135,12 @@ vips_existsf( const char *name, ... )
|
|||||||
|
|
||||||
g_free( path );
|
g_free( path );
|
||||||
|
|
||||||
return( !result );
|
/* access() can fail for various reasons, especially under things
|
||||||
|
* like selinux. Only return FALSE if we are certain the file does not
|
||||||
|
* exist.
|
||||||
|
*/
|
||||||
|
return( result == 0 ||
|
||||||
|
errno != ENOENT );
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OS_WIN32
|
#ifdef OS_WIN32
|
||||||
@ -1624,32 +1629,30 @@ vips__temp_dir( void )
|
|||||||
/* Make a temporary file name. The format parameter is something like "%s.jpg"
|
/* Make a temporary file name. The format parameter is something like "%s.jpg"
|
||||||
* and will be expanded to something like "/tmp/vips-12-34587.jpg".
|
* and will be expanded to something like "/tmp/vips-12-34587.jpg".
|
||||||
*
|
*
|
||||||
* You need to free the result. A real file will also be created, though we
|
* You need to free the result.
|
||||||
* delete it for you.
|
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
vips__temp_name( const char *format )
|
vips__temp_name( const char *format )
|
||||||
{
|
{
|
||||||
static int serial = 1;
|
static int serial = 0;
|
||||||
|
|
||||||
char file[FILENAME_MAX];
|
char file[FILENAME_MAX];
|
||||||
char file2[FILENAME_MAX];
|
char file2[FILENAME_MAX];
|
||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
int fd;
|
|
||||||
|
|
||||||
vips_snprintf( file, FILENAME_MAX, "vips-%d-XXXXXX", serial++ );
|
vips_snprintf( file, FILENAME_MAX, "vips-%d-%u",
|
||||||
|
serial++, g_random_int() );
|
||||||
vips_snprintf( file2, FILENAME_MAX, format, file );
|
vips_snprintf( file2, FILENAME_MAX, format, file );
|
||||||
name = g_build_filename( vips__temp_dir(), file2, NULL );
|
name = g_build_filename( vips__temp_dir(), file2, NULL );
|
||||||
|
|
||||||
if( (fd = g_mkstemp( name )) == -1 ) {
|
/* We could use something like g_mkstemp() to guarantee uniqueness
|
||||||
vips_error( "tempfile",
|
* across processes, but the extra FS calls can be difficult for
|
||||||
_( "unable to make temporary file %s" ), name );
|
* selinux.
|
||||||
g_free( name );
|
*
|
||||||
return( NULL );
|
* g_random_int() should be safe enough -- it's seeded from time(), so
|
||||||
}
|
* it ought not to collide often -- and on linux at least we never
|
||||||
close( fd );
|
* actually use these filenames in the filesystem anyway.
|
||||||
g_unlink( name );
|
*/
|
||||||
|
|
||||||
return( name );
|
return( name );
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
* - use expat for xml read, printf for xml write
|
* - use expat for xml read, printf for xml write
|
||||||
* 16/8/17
|
* 16/8/17
|
||||||
* - validate strs as being utf-8 before we write
|
* - validate strs as being utf-8 before we write
|
||||||
|
* 9/4/18 Alexander--
|
||||||
|
* - use O_TMPFILE, if available
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -55,6 +57,10 @@
|
|||||||
#define DEBUG
|
#define DEBUG
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Enable linux extensions like O_TMPFILE, if available.
|
||||||
|
*/
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif /*HAVE_CONFIG_H*/
|
#endif /*HAVE_CONFIG_H*/
|
||||||
@ -69,12 +75,12 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#ifdef HAVE_SYS_FILE_H
|
#ifdef HAVE_SYS_FILE_H
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#endif /*HAVE_SYS_FILE_H*/
|
#endif /*HAVE_SYS_FILE_H*/
|
||||||
#include <sys/stat.h>
|
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif /*HAVE_UNISTD_H*/
|
#endif /*HAVE_UNISTD_H*/
|
||||||
@ -181,19 +187,37 @@ vips__open_image_write( const char *filename, gboolean temp )
|
|||||||
|
|
||||||
flags = MODE_WRITE;
|
flags = MODE_WRITE;
|
||||||
|
|
||||||
|
#ifdef O_TMPFILE
|
||||||
|
/* Linux-only extension creates an unlinked file. CREAT and TRUNC must
|
||||||
|
* be clear. The filename arg to open() must name a directory.
|
||||||
|
*/
|
||||||
|
if( temp ) {
|
||||||
|
char *dirname;
|
||||||
|
|
||||||
|
flags |= O_TMPFILE;
|
||||||
|
flags &= ~O_CREAT;
|
||||||
|
flags &= ~O_TRUNC;
|
||||||
|
|
||||||
|
dirname = g_path_get_dirname( filename );
|
||||||
|
fd = vips_tracked_open( dirname, flags, 0666 );
|
||||||
|
g_free( dirname );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fd = vips_tracked_open( filename, flags, 0666 );
|
||||||
|
#else /*!O_TMPFILE*/
|
||||||
#ifdef _O_TEMPORARY
|
#ifdef _O_TEMPORARY
|
||||||
/* On Windows, setting O_TEMP gets the file automatically
|
/* On Windows, setting _O_TEMPORARY gets the file automatically
|
||||||
* deleted on process exit, even if the processes crashes. See
|
* deleted on process exit, even if the processes crashes. See
|
||||||
* vips_image_rewind() for what we do to help on *nix.
|
* vips_image_rewind() for what we do to help on *nix.
|
||||||
*/
|
*/
|
||||||
if( temp )
|
if( temp )
|
||||||
flags |= _O_TEMPORARY;
|
flags |= _O_TEMPORARY;
|
||||||
#endif /*_O_TEMPORARY*/
|
#endif /*_O_TEMPORARY*/
|
||||||
|
#endif /*O_TMPFILE*/
|
||||||
|
|
||||||
if( (fd = vips_tracked_open( filename, flags, 0666 )) < 0 ) {
|
if( fd < 0 ) {
|
||||||
vips_error_system( errno, "VipsImage",
|
vips_error_system( errno, "VipsImage",
|
||||||
_( "unable to write to \"%s\"" ),
|
_( "unable to write to \"%s\"" ), filename );
|
||||||
filename );
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
143
m4/pdfium.m4
Normal file
143
m4/pdfium.m4
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
dnl From FIND_MOTIF and ACX_PTHREAD, without much understanding
|
||||||
|
dnl
|
||||||
|
dnl FIND_PDFIUM[ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]
|
||||||
|
dnl ---------------------------------------------------
|
||||||
|
dnl
|
||||||
|
dnl Find pdfium libraries and headers
|
||||||
|
dnl
|
||||||
|
dnl Put -I stuff in PDFIUM_INCLUDES
|
||||||
|
dnl Put PDFium objects in PDFIUM_LIBS (add this to the link line untouched!)
|
||||||
|
dnl Define HAVE_PDFIUM if found
|
||||||
|
dnl
|
||||||
|
AC_DEFUN([FIND_PDFIUM], [
|
||||||
|
AC_REQUIRE([AC_PATH_XTRA])
|
||||||
|
|
||||||
|
ZLIB_INCLUDES=""
|
||||||
|
ZLIB_LIBS=""
|
||||||
|
|
||||||
|
# PDFium has a set of object archives that must be linked firectly into your
|
||||||
|
# app, and a couple of true libraries. The objects must be linked in this
|
||||||
|
# order.
|
||||||
|
pdfium_objects="\
|
||||||
|
libpdfium.a \
|
||||||
|
libfpdfapi.a \
|
||||||
|
libfxge.a \
|
||||||
|
libfpdfdoc.a \
|
||||||
|
libfxcrt.a \
|
||||||
|
libfx_agg.a \
|
||||||
|
libfxcodec.a \
|
||||||
|
libfx_lpng.a \
|
||||||
|
libfx_libopenjpeg.a \
|
||||||
|
libfx_lcms2.a \
|
||||||
|
libfx_freetype.a \
|
||||||
|
libjpeg.a \
|
||||||
|
libfdrm.a \
|
||||||
|
libpwl.a \
|
||||||
|
libbigint.a \
|
||||||
|
libformfiller.a"
|
||||||
|
|
||||||
|
AC_ARG_WITH(pdfium,
|
||||||
|
AS_HELP_STRING([--without-pdfium], [build without pdfium (default: test)]))
|
||||||
|
# Treat --without-pdfium like --without-pdfium-includes
|
||||||
|
# --without-pdfium-libraries
|
||||||
|
if test "$with_pdfium" = "no"; then
|
||||||
|
PDFIUM_INCLUDES=no
|
||||||
|
PDFIUM_LIBS=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_ARG_WITH(pdfium-includes,
|
||||||
|
AS_HELP_STRING([--with-pdfium-includes=DIR], [pdfium includes are in DIR]),
|
||||||
|
PDFIUM_INCLUDES="-I$withval")
|
||||||
|
AC_ARG_WITH(pdfium-libraries,
|
||||||
|
AS_HELP_STRING([--with-pdfium-libraries=DIR], [pdfium libraries are in DIR]),
|
||||||
|
PDFIUM_LIBS="$withval")
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(for PDFIUM)
|
||||||
|
|
||||||
|
# Look for fpdfview.h ... this is a documented header, so it should be a good
|
||||||
|
# target
|
||||||
|
#
|
||||||
|
# it won't be in the standard search path, but try $PREFIX
|
||||||
|
if test "$PDFIUM_INCLUDES" = ""; then
|
||||||
|
pdfium_save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
|
||||||
|
CPPFLAGS="-I${prefix}/include $CPPFLAGS"
|
||||||
|
|
||||||
|
AC_TRY_COMPILE([#include <fpdfview.h>],[int a;],[
|
||||||
|
PDFIUM_INCLUDES="-I${prefix}/include"
|
||||||
|
], [
|
||||||
|
PDFIUM_INCLUDES="no"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
CPPFLAGS="$pdfium_save_CPPFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Now for the libraries ... if there's nothing set, try $PREFIX/lib
|
||||||
|
if test "$PDFIUM_LIBS" = ""; then
|
||||||
|
pdfium_save_LIBS="$LIBS"
|
||||||
|
pdfium_save_CPPFLAGS="$CPPFLAGS"
|
||||||
|
|
||||||
|
LIBS=""
|
||||||
|
for i in $pdfium_objects; do
|
||||||
|
LIBS="$LIBS $prefix/lib/pdfium-obj/$i"
|
||||||
|
done
|
||||||
|
LIBS="$LIBS -L$prefix/lib -lm -lpthread"
|
||||||
|
CPPFLAGS="$PDFIUM_INCLUDES $CPPFLAGS"
|
||||||
|
|
||||||
|
AC_TRY_LINK([#include <fpdfview.h>],
|
||||||
|
[FPDF_DOCUMENT doc; doc = FPDF_LoadDocument("", "")], [
|
||||||
|
PDFIUM_LIBS="${prefix}/lib"
|
||||||
|
], [
|
||||||
|
PDFIUM_LIBS=no
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
LIBS="$pdfium_save_LIBS"
|
||||||
|
CPPFLAGS="$pdfium_save_CPPFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Print a helpful message
|
||||||
|
pdfium_libraries_result="$PDFIUM_LIBS"
|
||||||
|
pdfium_includes_result="$PDFIUM_INCLUDES"
|
||||||
|
|
||||||
|
if test x"$pdfium_libraries_result" = x""; then
|
||||||
|
pdfium_libraries_result="in default path"
|
||||||
|
fi
|
||||||
|
if test x"$pdfium_includes_result" = x""; then
|
||||||
|
pdfium_includes_result="in default path"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "$pdfium_libraries_result" = "no"; then
|
||||||
|
pdfium_libraries_result="(none)"
|
||||||
|
fi
|
||||||
|
if test "$pdfium_includes_result" = "no"; then
|
||||||
|
pdfium_includes_result="(none)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_RESULT([libraries $pdfium_libraries_result, headers $pdfium_includes_result])
|
||||||
|
|
||||||
|
if test x"$PDFIUM_LIBS" != x"no"; then
|
||||||
|
dir="$PDFIUM_LIBS"
|
||||||
|
PDFIUM_LIBS=""
|
||||||
|
for i in $pdfium_objects; do
|
||||||
|
PDFIUM_LIBS="$PDFIUM_LIBS $prefix/lib/pdfium-obj/$i"
|
||||||
|
done
|
||||||
|
PDFIUM_LIBS="$PDFIUM_LIBS -L$dir -lm -lpthread"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_SUBST(PDFIUM_LIBS)
|
||||||
|
AC_SUBST(PDFIUM_INCLUDES)
|
||||||
|
|
||||||
|
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||||
|
if test "$PDFIUM_INCLUDES" != "no" && test "$PDFIUM_LIBS" != "no"; then
|
||||||
|
AC_DEFINE(HAVE_PDFIUM,1,
|
||||||
|
[Define if you have pdfium libraries and header files.])
|
||||||
|
$1
|
||||||
|
else
|
||||||
|
PDFIUM_INCLUDES=""
|
||||||
|
PDFIUM_LIBS=""
|
||||||
|
$2
|
||||||
|
fi
|
||||||
|
|
||||||
|
])dnl
|
Loading…
x
Reference in New Issue
Block a user