diff --git a/ChangeLog b/ChangeLog index 72e16628..3a5fe3b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,12 +24,15 @@ 22/12/20 start 8.10.6 - don't seek on bad file descriptors [kleisauke] - check for null memory sources [kleisauke] -- revise ppmload, fixing a couple of small bugs -- signal error on EOF in jpegload more reliably [bozaro] -- better error detection in spngload [randy408] +- improve ppmload, fixing a couple of small bugs +- improve EOF detection in jpegload [bozaro] +- improve error detection in spngload [randy408] - fix includes of glib headers in C++ [lovell] - fix build with more modern librsvg [lovell] - fix a possible segv with very wide images [f1ac] +- fix issue thumbnailing RGBA images in linear mode [jjonesrs] +- improve vipsthumbnail profile handling +- fix tiff deflate predictor setting [Adios] 18/12/20 started 8.10.5 - fix potential /0 in animated webp load [lovell] diff --git a/configure.ac b/configure.ac index b3535d22..ba534ecb 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,12 @@ VIPS_MAJOR_VERSION=vips_major_version() VIPS_MINOR_VERSION=vips_minor_version() VIPS_MICRO_VERSION=vips_micro_version() VIPS_VERSION=vips_version() -VIPS_VERSION_STRING=$VIPS_VERSION-`date -u -r $srcdir/ChangeLog` +VIPS_VERSION_STRING="$VIPS_VERSION-$(date -u -r $srcdir/ChangeLog)" + +# packages add to these as we find them +VIPS_CFLAGS="" +VIPS_INCLUDES="" +VIPS_LIBS="" # libtool library versioning ... not user-visible (except as part of the # library file name) and does not correspond to major/minor/micro above @@ -74,31 +79,31 @@ done # add headers that form the public vips8 API .. don't do a find and exclude, # we end up excluding almost everything argh headers="\ - basic.h \ - vips.h \ - object.h \ - image.h \ - error.h \ - foreign.h \ - freqfilt.h \ - interpolate.h \ - header.h \ - histogram.h \ - operation.h \ - enumtypes.h \ - conversion.h \ - arithmetic.h \ - colour.h \ - convolution.h \ - create.h \ - draw.h \ - morphology.h \ - mosaicing.h \ - type.h \ - rect.h \ - resample.h \ - memory.h \ - region.h" + basic.h \ + vips.h \ + object.h \ + image.h \ + error.h \ + foreign.h \ + freqfilt.h \ + interpolate.h \ + header.h \ + histogram.h \ + operation.h \ + enumtypes.h \ + conversion.h \ + arithmetic.h \ + colour.h \ + convolution.h \ + create.h \ + draw.h \ + morphology.h \ + mosaicing.h \ + type.h \ + rect.h \ + resample.h \ + memory.h \ + region.h" for name in $headers; do vips_introspection_sources="$vips_introspection_sources include/vips/$name" @@ -141,69 +146,35 @@ AM_CONDITIONAL(ENABLE_DEPRECATED, [test x"$enable_deprecated" = x"yes"]) # this gets pasted into version.h as a #define AC_SUBST(VIPS_ENABLE_DEPRECATED) -AC_MSG_CHECKING([for native Win32]) -case "$host" in - *-*-mingw*) - vips_os_win32=yes - ;; - *) - vips_os_win32=no - ;; -esac -AC_MSG_RESULT([$vips_os_win32]) - -if test x"$vips_os_win32" = x"yes"; then - AC_DEFINE(OS_WIN32,1,[native win32]) - - # makes gcc use win native alignment - VIPS_CFLAGS="-mms-bitfields $VIPS_CFLAGS" -fi - -# CImg needs flags changed on win32 -AM_CONDITIONAL(OS_WIN32, [test x"$vips_os_win32" = x"yes"]) - -# Cygwin/mingw need binary open to avoid CR/LF madness -# ... should be a better way to test for this -AC_MSG_CHECKING([for binary open needed]) +AC_MSG_CHECKING([for -mms-bitfields support]) case "$host_os" in - cygwin* | mingw*) - vips_binary_open=yes + mingw*) + # makes gcc use win native alignment + # GCC >= 4.7 and Clang >= 11 does this automatically, see: + # https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1510#note_841637 + VIPS_CFLAGS="-mms-bitfields $VIPS_CFLAGS" + AC_MSG_RESULT([yes]) ;; *) - vips_binary_open=no + AC_MSG_RESULT([no]) ;; esac -AC_MSG_RESULT([$vips_binary_open]) -if test x"$vips_binary_open" = x"yes"; then - AC_DEFINE(BINARY_OPEN,1,[define to open non-text files in binary mode]) -fi - -AC_MSG_CHECKING([for Mac OS X]) -case "$host" in - *-*-darwin*) - vips_os_darwin=yes - ;; - *) - vips_os_darwin=no - ;; -esac -AC_MSG_RESULT([$vips_os_darwin]) - -if test x"$vips_os_darwin" = x"yes"; then - AC_DEFINE(VIPS_OS_DARWIN,1,[native Mac OS X]) -fi # set the default directory for ICC profiles -if test x"$vips_os_darwin" = x"yes"; then - profile_dir="/Library/ColorSync/Profiles" -elif test x"$vips_os_win32" = x"yes"; then - # need double escapes since this will get pasted into a #define in a C - # header ... the C:\Windows is usually overrwritten with the result of - # GetWindowsDirectoryW() - profile_dir="C:\\\\Windows\\\\System32\\\\spool\\\\drivers\\\\color" -else - profile_dir="/usr/share/color/icc" -fi +case "$host_os" in + darwin*) + profile_dir="/Library/ColorSync/Profiles" + ;; + mingw*) + # need double escapes since this will get pasted into a #define in a C + # header ... the C:\Windows is usually overwritten with the result of + # GetWindowsDirectoryW() + profile_dir="C:\\\\Windows\\\\System32\\\\spool\\\\drivers\\\\color" + ;; + *) + profile_dir="/usr/share/color/icc" + ;; +esac AC_DEFINE_UNQUOTED(VIPS_ICC_DIR,"$profile_dir",[default directory for ICC profiles]) # we want largefile support, if possible @@ -435,20 +406,23 @@ PACKAGES_USED="$PACKAGES_USED glib-2.0 gmodule-2.0 gobject-2.0 gio-2.0" # from 2.62 we have datetime PKG_CHECK_MODULES(DATE_TIME_FORMAT_ISO8601, glib-2.0 >= 2.62, [AC_DEFINE(HAVE_DATE_TIME_FORMAT_ISO8601,1, - [define if your glib has g_date_time_format_iso8601().] + [define if your glib has g_date_time_format_iso8601().] ) ], [: ] ) +VIPS_CFLAGS="$VIPS_CFLAGS $GIO_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $GIO_LIBS" + # if available, we use pthread_setattr_default_np() to raise the per-thread # stack size ... musl (libc on Alpine), for example, has a very small stack per # thread by default save_pthread_LIBS="$LIBS" save_pthread_CFLAGS="$CFLAGS" -LIBS="$LIBS $GTHREAD_LIBS" -CFLAGS="$CFLAGS $GTHREAD_CFLAGS" +LIBS="$LIBS $REQUIRED_LIBS" +CFLAGS="$CFLAGS $REQUIRED_CFLAGS" AC_CHECK_FUNC(pthread_setattr_default_np, [AC_DEFINE(HAVE_PTHREAD_DEFAULT_NP,1,[have pthread_setattr_default_np().]) ] @@ -456,11 +430,6 @@ AC_CHECK_FUNC(pthread_setattr_default_np, LIBS="$save_pthread_LIBS" CFLAGS="$save_pthread_CFLAGS" -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().]) - have_g_win32_get_command_line=yes -fi - # from 2.48 we have g_uint_checked_mul() etc. PKG_CHECK_MODULES(HAVE_CHECKED_MUL, glib-2.0 >= 2.48, [AC_DEFINE(HAVE_CHECKED_MUL,1,[define if your glib has checked multiply.]) @@ -486,6 +455,9 @@ if test x"$expat_found" = x"no"; then exit 1 fi +VIPS_CFLAGS="$VIPS_CFLAGS $EXPAT_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $EXPAT_LIBS" + # optional supporting libraries AC_ARG_WITH([gsf], @@ -510,13 +482,16 @@ if test x"$with_gsf" != x"no"; then PKG_CHECK_MODULES(GSF_ZIP64, libgsf-1 >= 1.14.31, [AC_DEFINE(HAVE_GSF_ZIP64,1,[define if your libgsf supports zip64.]) AC_DEFINE(HAVE_GSF_DEFLATE_LEVEL,1, - [define if your libgsf supports deflate-level.]) + [define if your libgsf supports deflate-level.]) ], [: ] ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $GSF_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $GSF_LIBS" + AC_ARG_WITH([fftw], AS_HELP_STRING([--without-fftw], [build without fftw (default: test)])) @@ -532,6 +507,9 @@ if test x"$with_fftw" != x"no"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $FFTW_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $FFTW_LIBS" + # ImageMagick AC_ARG_WITH([magick], AS_HELP_STRING([--without-magick], [build without libMagic (default: test)])) @@ -595,7 +573,7 @@ if test x"$magick6" = x"yes"; then CFLAGS="$CFLAGS $MAGICK_CFLAGS" AC_CHECK_MEMBER([struct _ImageInfo.number_scenes], AC_DEFINE(HAVE_NUMBER_SCENES,1, - [define if your magick has ImageInfo.number_scenes.]), + [define if your magick has ImageInfo.number_scenes.]), [], [#include ]) CFLAGS="$save_CFLAGS" @@ -653,11 +631,11 @@ fi # save but not load, for example AC_ARG_ENABLE([magickload], AS_HELP_STRING([--disable-magickload], - [disable libMagic load (default: enabled)])) + [disable libMagic load (default: enabled)])) AC_ARG_ENABLE([magicksave], AS_HELP_STRING([--disable-magicksave], - [disable libMagic save (default: enabled)])) + [disable libMagic save (default: enabled)])) if test x"$enable_magicksave" != x"yes"; then # we need ImportImagePixels ... GM is missing this sadly @@ -665,12 +643,12 @@ if test x"$enable_magicksave" != x"yes"; then LIBS="$LIBS $MAGICK_LIBS" AC_CHECK_FUNCS(ImportImagePixels,[ AC_DEFINE(HAVE_IMPORTIMAGEPIXELS,1, - [define if you have ImportImagePixels.]) + [define if you have ImportImagePixels.]) ],[] ) AC_CHECK_FUNCS(ImagesToBlob,[ AC_DEFINE(HAVE_IMAGESTOBLOB,1, - [define if you have ImagesToBlob.]) + [define if you have ImagesToBlob.]) ],[] ) LIBS="$save_LIBS" @@ -691,6 +669,9 @@ else enable_magicksave=no fi +VIPS_CFLAGS="$VIPS_CFLAGS $MAGICK_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $MAGICK_LIBS" + # orc AC_ARG_WITH([orc], AS_HELP_STRING([--without-orc], [build without orc (default: test)])) @@ -705,7 +686,7 @@ if test x"$with_orc" != x"no"; then LIBS="$LIBS $ORC_LIBS" AC_CHECK_FUNCS(orc_program_get_error, AC_DEFINE(HAVE_ORC_PROGRAM_GET_ERROR,1, - [define if your orc has orc_program_get_error.])) + [define if your orc has orc_program_get_error.])) LIBS="$save_LIBS" ], [AC_MSG_WARN([orc-0.4.11 or later not found; disabling orc support]) @@ -719,7 +700,7 @@ fi if test x"$with_orc" = x"yes"; then PKG_CHECK_MODULES(ORC_CF_PROTECTION, orc-0.4 >= 0.4.31, [AC_DEFINE(HAVE_ORC_CF_PROTECTION,1, - [define if your orc works with cf-protection.] + [define if your orc works with cf-protection.] ) ], [: @@ -727,6 +708,9 @@ if test x"$with_orc" = x"yes"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $ORC_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $ORC_LIBS" + # lcms ... refuse to use lcms1 AC_ARG_WITH([lcms], AS_HELP_STRING([--without-lcms], [build without lcms (default: test)])) @@ -747,6 +731,9 @@ fi # is detected AM_CONDITIONAL(ENABLE_LCMS, [test x"$with_lcms" != x"no"]) +VIPS_CFLAGS="$VIPS_CFLAGS $LCMS_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $LCMS_LIBS" + # OpenEXR AC_ARG_WITH([OpenEXR], AS_HELP_STRING([--without-OpenEXR], [build without OpenEXR (default: test)])) @@ -764,6 +751,9 @@ if test x"$with_OpenEXR" != x"no"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $OPENEXR_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $OPENEXR_LIBS" + # nifti AC_ARG_WITH([nifti], AS_HELP_STRING([--without-nifti], [build without nifti (default: test)])) @@ -777,6 +767,10 @@ if test x"$with_nifti" != x"no"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $NIFTI_CFLAGS" +VIPS_INCLUDES="$VIPS_INCLUDES $NIFTI_INCLUDES" +VIPS_LIBS="$VIPS_LIBS $NIFTI_LIBS" + # libheif AC_ARG_WITH([heif], AS_HELP_STRING([--without-heif], [build without libheif (default: test)])) @@ -790,13 +784,13 @@ if test x"$with_heif" != x"no"; then # this variable if test x"$have_h265_decoder" != x"no" -o x"$have_avif_decoder" = x"yes"; then AC_DEFINE(HAVE_HEIF_DECODER,1, - [define if your libheif has decode support.]) + [define if your libheif has decode support.]) fi have_h265_encoder=`$PKG_CONFIG libheif --variable builtin_h265_encoder` have_avif_encoder=`$PKG_CONFIG libheif --variable builtin_avif_encoder` if test x"$have_h265_encoder" != x"no" -o x"$have_avif_encoder" = x"yes"; then AC_DEFINE(HAVE_HEIF_ENCODER,1, - [define if your libheif has encode support.]) + [define if your libheif has encode support.]) fi PACKAGES_USED="$PACKAGES_USED libheif" ], @@ -817,7 +811,7 @@ if test x"$with_heif" = x"yes"; then LIBS="$LIBS $HEIF_LIBS" AC_CHECK_FUNCS(heif_image_handle_get_raw_color_profile,[ AC_DEFINE(HAVE_HEIF_COLOR_PROFILE,1, - [define if you have heif_image_handle_get_raw_color_profile.]) + [define if you have heif_image_handle_get_raw_color_profile.]) ],[] ) LIBS="$save_LIBS" @@ -838,12 +832,15 @@ if test x"$with_heif" = x"yes"; then CFLAGS="$CFLAGS $HEIF_CFLAGS" AC_CHECK_MEMBER([struct heif_decoding_options.convert_hdr_to_8bit],[ AC_DEFINE(HAVE_HEIF_DECODING_OPTIONS_CONVERT_HDR_TO_8BIT,1, - [define if you have heif_decoding_options.convert_hdr_to_8bit]) + [define if you have heif_decoding_options.convert_hdr_to_8bit]) ],[], [#include ]) CFLAGS="$save_CFLAGS" fi +VIPS_CFLAGS="$VIPS_CFLAGS $HEIF_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $HEIF_LIBS" + # pdfium AC_ARG_WITH([pdfium], AS_HELP_STRING([--without-pdfium], [build without pdfium (default: test)])) @@ -864,6 +861,9 @@ if test x"$with_pdfium" != x"no"; then ]) fi +VIPS_CFLAGS="$VIPS_CFLAGS $PDFIUM_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $PDFIUM_LIBS" + # poppler AC_ARG_WITH([poppler], AS_HELP_STRING([--without-poppler], [build without poppler (default: test)])) @@ -879,6 +879,9 @@ if test x"$with_poppler" != x"no"; then ]) fi +VIPS_CFLAGS="$VIPS_CFLAGS $POPPLER_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $POPPLER_LIBS" + # librsvg AC_ARG_WITH([rsvg], AS_HELP_STRING([--without-rsvg], [build without rsvg (default: test)])) @@ -895,6 +898,9 @@ if test x"$with_rsvg" != x"no"; then ]) fi +VIPS_CFLAGS="$VIPS_CFLAGS $RSVG_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $RSVG_LIBS" + # zlib # some platforms, like macosx, are missing the .pc files for zlib, so # we fall back to FIND_ZLIB @@ -918,6 +924,10 @@ if test x"$with_zlib" != x"no"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $ZLIB_CFLAGS" +VIPS_INCLUDES="$VIPS_INCLUDES $ZLIB_INCLUDES" +VIPS_LIBS="$VIPS_LIBS $ZLIB_LIBS" + # OpenSlide AC_ARG_WITH([openslide], AS_HELP_STRING([--without-openslide], @@ -945,6 +955,9 @@ if test x"$with_openslide" != x"no"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $OPENSLIDE_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $OPENSLIDE_LIBS" + # matio AC_ARG_WITH([matio], AS_HELP_STRING([--without-matio], [build without matio (default: test)])) @@ -961,6 +974,9 @@ if test x"$with_matio" != x"no"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $MATIO_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $MATIO_LIBS" + # not external libraries, but have options to disable them, helps to # reduce attack surface @@ -1014,6 +1030,9 @@ if test x"$with_cfitsio" != x"no"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $CFITSIO_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $CFITSIO_LIBS" + # libwebp ... target 0.6+ to reduce complication # webp has the stuff for handling metadata in two separate libraries -- we # insit on having all of them @@ -1032,6 +1051,9 @@ if test x"$with_libwebp" != x"no"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $LIBWEBP_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $LIBWEBP_LIBS" + # pangoft2 AC_ARG_WITH([pangoft2], AS_HELP_STRING([--without-pangoft2], @@ -1049,6 +1071,9 @@ if test x"$with_pangoft2" != x"no"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $PANGOFT2_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $PANGOFT2_LIBS" + # look for TIFF with pkg-config ... fall back to our tester # pkgconfig support for libtiff starts with libtiff-4 AC_ARG_WITH([tiff], @@ -1070,7 +1095,7 @@ if test x"$with_tiff" != x"no"; then ) fi -# WEBP in TIFF added in libtiff 4.0.10 +# ZSTD and WEBP in TIFF added in libtiff 4.0.10 if test x"$with_tiff" != x"no"; then save_INCLUDES="$INCLUDES" INCLUDES="$INCLUDES $TIFF_INCLUDES" @@ -1084,6 +1109,10 @@ if test x"$with_tiff" != x"no"; then INCLUDES="$save_INCLUDES" fi +VIPS_CFLAGS="$VIPS_CFLAGS $TIFF_CFLAGS" +VIPS_INCLUDES="$VIPS_INCLUDES $TIFF_INCLUDES" +VIPS_LIBS="$VIPS_LIBS $TIFF_LIBS" + # Look for libspng first # 0.6.1 uses "libspng.pc", git master libspng uses "spng.pc" AC_ARG_WITH([libspng], @@ -1107,6 +1136,9 @@ if test x"$with_libspng" != x"no"; then ) fi +VIPS_CFLAGS="$VIPS_CFLAGS $SPNG_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $SPNG_LIBS" + # look for PNG with pkg-config ... fall back to our tester # we can have both PNG and SPNG enabled, with SPNG for read and PNG for # write @@ -1137,11 +1169,15 @@ if test x"$with_png" != x"no"; then CFLAGS="$PNG_INCLUDES $CFLAGS" AC_CHECK_FUNCS(png_set_chunk_malloc_max, AC_DEFINE(HAVE_PNG_SET_CHUNK_MALLOC_MAX,1, - [define if your libpng has png_set_chunk_malloc_max.])) + [define if your libpng has png_set_chunk_malloc_max.])) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi +VIPS_CFLAGS="$VIPS_CFLAGS $PNG_CFLAGS" +VIPS_INCLUDES="$VIPS_INCLUDES $PNG_INCLUDES" +VIPS_LIBS="$VIPS_LIBS $PNG_LIBS" + # look for libimagequant with pkg-config (only if libpng is enabled) AC_ARG_WITH([imagequant], AS_HELP_STRING([--without-imagequant], [build without imagequant (default: test)])) @@ -1160,6 +1196,9 @@ else with_imagequant=no fi +VIPS_CFLAGS="$VIPS_CFLAGS $IMAGEQUANT_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $IMAGEQUANT_LIBS" + # look for libjpeg with pkg-config ... fall back to our tester AC_ARG_WITH([jpeg], AS_HELP_STRING([--without-jpeg], [build without libjpeg (default: test)])) @@ -1192,11 +1231,15 @@ if test x"$with_jpeg" != x"no"; then CFLAGS="$JPEG_INCLUDES $CFLAGS" AC_CHECK_FUNCS(jpeg_c_bool_param_supported, AC_DEFINE(HAVE_JPEG_EXT_PARAMS,1, - [define if your libjpeg has extension parameters.])) + [define if your libjpeg has extension parameters.])) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi +VIPS_CFLAGS="$VIPS_CFLAGS $JPEG_CFLAGS" +VIPS_INCLUDES="$VIPS_INCLUDES $JPEG_INCLUDES" +VIPS_LIBS="$VIPS_LIBS $JPEG_LIBS" + # libexif AC_ARG_WITH([libexif], AS_HELP_STRING([--without-libexif], [build without libexif (default: test)])) @@ -1224,6 +1267,9 @@ if test x"$with_libexif" != x"no"; then CPPFLAGS="$save_CPPFLAGS" fi +VIPS_CFLAGS="$VIPS_CFLAGS $EXIF_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $EXIF_LIBS" + # fuzzing AC_ARG_VAR([LIB_FUZZING_ENGINE], [fuzzing library, e.g. /path/to/libFuzzer.a]) @@ -1231,71 +1277,47 @@ if test x"$LIB_FUZZING_ENGINE" = x; then LIB_FUZZING_ENGINE="libstandaloneengine.a" fi -# Gather all up for VIPS_CFLAGS, VIPS_INCLUDES, VIPS_LIBS -VIPS_CFLAGS="$VIPS_CFLAGS \ - $GTHREAD_CFLAGS \ - $GIO_CFLAGS \ - $REQUIRED_CFLAGS \ - $EXPAT_CFLAGS \ - $ZLIB_CFLAGS \ - $PANGOFT2_CFLAGS \ - $GSF_CFLAGS \ - $FFTW_CFLAGS \ - $MAGICK_CFLAGS \ - $JPEG_CFLAGS \ - $SPNG_CFLAGS \ - $PNG_CFLAGS \ - $IMAGEQUANT_CFLAGS \ - $EXIF_CFLAGS \ - $MATIO_CFLAGS \ - $CFITSIO_CFLAGS \ - $LIBWEBP_CFLAGS \ - $LIBWEBPMUX_CFLAGS \ - $RSVG_CFLAGS \ - $PDFIUM_CFLAGS \ - $POPPLER_CFLAGS \ - $OPENEXR_CFLAGS \ - $OPENSLIDE_CFLAGS \ - $ORC_CFLAGS \ - $TIFF_CFLAGS \ - $LCMS_CFLAGS \ - $HEIF_CFLAGS" -VIPS_CFLAGS="$VIPS_DEBUG_FLAGS $VIPS_CFLAGS" - -VIPS_INCLUDES="$ZLIB_INCLUDES $PNG_INCLUDES $TIFF_INCLUDES $JPEG_INCLUDES $NIFTI_INCLUDES" -VIPS_LIBS="$ZLIB_LIBS \ - $HEIF_LIBS \ - $MAGICK_LIBS \ - $SPNG_LIBS \ - $PNG_LIBS \ - $IMAGEQUANT_LIBS \ - $TIFF_LIBS \ - $JPEG_LIBS \ - $GTHREAD_LIBS \ - $GIO_LIBS \ - $REQUIRED_LIBS \ - $EXPAT_LIBS \ - $PANGOFT2_LIBS \ - $GSF_LIBS \ - $FFTW_LIBS \ - $ORC_LIBS \ - $LCMS_LIBS \ - $RSVG_LIBS \ - $NIFTI_LIBS \ - $PDFIUM_LIBS \ - $POPPLER_LIBS \ - $OPENEXR_LIBS \ - $OPENSLIDE_LIBS \ - $CFITSIO_LIBS \ - $LIBWEBP_LIBS \ - $LIBWEBPMUX_LIBS \ - $MATIO_LIBS \ - $EXIF_LIBS \ - -lm" +VIPS_CFLAGS="$VIPS_CFLAGS $VIPS_DEBUG_FLAGS $REQUIRED_CFLAGS" +VIPS_LIBS="$VIPS_LIBS $REQUIRED_LIBS -lm" # autoconf hates multi-line AC_SUBST so we have to have another copy of this # thing -VIPS_CONFIG="native win32: $vips_os_win32, native OS X: $vips_os_darwin, open files in binary mode: $vips_binary_open, enable debug: $enable_debug, enable deprecated library components: $enable_deprecated, enable docs with gtkdoc: $enable_gtk_doc, gobject introspection: $found_introspection, enable radiance support: $with_radiance, enable analyze support: $with_analyze, enable PPM load/save: $with_ppm, enable GIF load: $with_nsgif, generate C++ docs: $with_doxygen, use fftw3 for FFT: $with_fftw, Magick package: $with_magickpackage, Magick API version: $magick_version, load with libMagick: $enable_magickload, save with libMagick: $enable_magicksave, accelerate loops with orc: $with_orc, ICC profile support with lcms: $with_lcms, NIfTI load/save with niftiio: $with_nifti, HEIC/AVIF load/save with libheif: $with_heif, EXR load/save with OpenEXR: $with_OpenEXR, slide load with OpenSlide: $with_openslide, Matlab load with matio: $with_matio, PDF load with PDFium: $with_pdfium, PDF load with poppler-glib: $with_poppler, SVG load with librsvg-2.0: $with_rsvg, zlib: $with_zlib, FITS load with cfitsio: $with_cfitsio, WebP load/save with libwebp: $with_libwebp, text rendering with pangoft2: $with_pangoft2, PNG load with libspng: $with_libspng, PNG load/save with libpng: $with_png, support 8bpp PNG quantisation: $with_imagequant, TIFF load/save with libtiff: $with_tiff, JPEG load/save with libjpeg: $with_jpeg, image pyramid export: $with_gsf, use libexif to load/save JPEG metadata: $with_libexif" +VIPS_CONFIG="\ +enable debug: $enable_debug, \ +enable deprecated library components: $enable_deprecated, \ +enable docs with gtkdoc: $enable_gtk_doc, \ +gobject introspection: $found_introspection, \ +RAD load/save: $with_radiance, \ +Analyze7 load/save: $with_analyze, \ +PPM load/save: $with_ppm, \ +GIF load: $with_nsgif, \ +generate C++ docs: $with_doxygen, \ +use fftw3 for FFT: $with_fftw, \ +accelerate loops with orc: $with_orc, \ +ICC profile support with lcms: $with_lcms, \ +zlib: $with_zlib, \ +text rendering with pangoft2: $with_pangoft2, \ +EXIF metadata support with libexif: $with_libexif, \ +JPEG load/save with libjpeg: $with_jpeg, \ +PNG load with libspng: $with_libspng, \ +PNG load/save with libpng: $with_png, \ +8bpp PNG quantisation: $with_imagequant, \ +TIFF load/save with libtiff: $with_tiff, \ +image pyramid save: $with_gsf, \ +HEIC/AVIF load/save with libheif: $with_heif, \ +WebP load/save with libwebp: $with_libwebp, \ +PDF load with PDFium: $with_pdfium, \ +PDF load with poppler-glib: $with_poppler, \ +SVG load with librsvg-2.0: $with_rsvg, \ +EXR load with OpenEXR: $with_OpenEXR, \ +slide load with OpenSlide: $with_openslide, \ +Matlab load with matio: $with_matio, \ +NIfTI load/save with niftiio: $with_nifti, \ +FITS load/save with cfitsio: $with_cfitsio, \ +Magick package: $with_magickpackage, \ +Magick API version: $magick_version, \ +load with libMagickCore: $enable_magickload, \ +save with libMagickCore: $enable_magicksave" AC_SUBST(VIPS_LIBDIR) @@ -1312,109 +1334,99 @@ TOP_SRCDIR=$ac_pwd AC_SUBST(TOP_SRCDIR) AC_CONFIG_FILES([ - vips.pc - vips-cpp.pc - Makefile - $srcdir/libvips/include/vips/version.h - libvips/include/Makefile - libvips/include/vips/Makefile - libvips/Makefile - libvips/arithmetic/Makefile - libvips/colour/Makefile - libvips/colour/profiles/Makefile - libvips/conversion/Makefile - libvips/convolution/Makefile - libvips/deprecated/Makefile - libvips/foreign/Makefile - libvips/foreign/libnsgif/Makefile - libvips/freqfilt/Makefile - libvips/histogram/Makefile - libvips/draw/Makefile - libvips/iofuncs/Makefile - libvips/morphology/Makefile - libvips/mosaicing/Makefile - libvips/create/Makefile - libvips/resample/Makefile - cplusplus/Doxyfile - cplusplus/include/Makefile - cplusplus/include/vips/Makefile - cplusplus/Makefile - tools/Makefile - tools/batch_crop - tools/batch_image_convert - tools/batch_rubber_sheet - tools/light_correct - tools/shrink_width - test/Makefile - test/variables.sh - test/test-suite/Makefile - test/test-suite/helpers/Makefile - man/Makefile - doc/Makefile - doc/libvips-docs.xml - po/Makefile.in - fuzz/Makefile + vips.pc + vips-cpp.pc + Makefile + $srcdir/libvips/include/vips/version.h + libvips/include/Makefile + libvips/include/vips/Makefile + libvips/Makefile + libvips/arithmetic/Makefile + libvips/colour/Makefile + libvips/colour/profiles/Makefile + libvips/conversion/Makefile + libvips/convolution/Makefile + libvips/deprecated/Makefile + libvips/foreign/Makefile + libvips/freqfilt/Makefile + libvips/histogram/Makefile + libvips/draw/Makefile + libvips/iofuncs/Makefile + libvips/morphology/Makefile + libvips/mosaicing/Makefile + libvips/create/Makefile + libvips/resample/Makefile + cplusplus/Doxyfile + cplusplus/include/Makefile + cplusplus/include/vips/Makefile + cplusplus/Makefile + tools/Makefile + tools/batch_crop + tools/batch_image_convert + tools/batch_rubber_sheet + tools/light_correct + tools/shrink_width + test/Makefile + test/variables.sh + test/test-suite/Makefile + test/test-suite/helpers/Makefile + man/Makefile + doc/Makefile + doc/libvips-docs.xml + po/Makefile.in + fuzz/Makefile ]) AC_OUTPUT # also add any new items to VIPS_CONFIG above AC_MSG_RESULT([dnl -* build options -native win32: $vips_os_win32 -native OS X: $vips_os_darwin -open files in binary mode: $vips_binary_open -enable debug: $enable_debug -enable deprecated library components: $enable_deprecated -enable docs with gtkdoc: $enable_gtk_doc -gobject introspection: $found_introspection -enable radiance load/save: $with_radiance -enable analyze load/save: $with_analyze -enable PPM load/save: $with_ppm -enable GIF load: $with_nsgif +## Build options +enable debug: $enable_debug +enable deprecated library components: $enable_deprecated +enable docs with gtkdoc: $enable_gtk_doc +gobject introspection: $found_introspection +RAD load/save: $with_radiance +Analyze7 load/save: $with_analyze +PPM load/save: $with_ppm +GIF load: $with_nsgif generate C++ docs: $with_doxygen -* optional dependencies -use fftw3 for FFT: $with_fftw -Magick package: $with_magickpackage -Magick API version: $magick_version -load with libMagick: $enable_magickload -save with libMagick: $enable_magicksave -accelerate loops with orc: $with_orc - (requires orc-0.4.11 or later) -ICC profile support with lcms: $with_lcms -NIfTI load/save with niftiio: $with_nifti -HEIC/AVIF load/save with libheif: $with_heif -EXR load/save with OpenEXR: $with_OpenEXR -slide load with OpenSlide: $with_openslide - (requires openslide-3.3.0 or later) -Matlab load with matio: $with_matio -PDF load with PDFium: $with_pdfium -PDF load with poppler-glib: $with_poppler - (requires poppler-glib 0.16.0 or later) -SVG load with librsvg-2.0: $with_rsvg - (requires librsvg-2.0 2.34.0 or later) -zlib: $with_zlib -FITS load/save with cfitsio: $with_cfitsio -WebP load/save with libwebp: $with_libwebp - (requires libwebp, libwebpmux, libwebpdemux 0.6.0 or later) -text rendering with pangoft2: $with_pangoft2 -PNG load with libspng: $with_libspng - (requires libspng-0.6 or later) -PNG load/save with libpng: $with_png - (requires libpng-1.2.9 or later) -support 8bpp PNG quantisation: $with_imagequant - (requires libimagequant) -TIFF load/save with libtiff: $with_tiff -JPEG load/save with libjpeg: $with_jpeg -image pyramid export: $with_gsf - (requires libgsf-1 1.14.26 or later) -use libexif to load/save JPEG metadata: $with_libexif -]) +## Optional dependencies +use fftw3 for FFT: $with_fftw +accelerate loops with orc: $with_orc + (requires orc-0.4.11 or later) +ICC profile support with lcms: $with_lcms +zlib: $with_zlib +text rendering with pangoft2: $with_pangoft2 +EXIF metadata support with libexif: $with_libexif -if test x"$vips_os_win32" = x"yes"; then - if test x"$have_g_win32_get_command_line" != x"yes"; then - AC_MSG_RESULT([dnl -Your glib is too old, vips will not support unicode command-line arguments. - ]) - fi -fi +## File format support +JPEG load/save with libjpeg: $with_jpeg +PNG load with libspng: $with_libspng + (requires libspng-0.6 or later) +PNG load/save with libpng: $with_png + (requires libpng-1.2.9 or later) +8bpp PNG quantisation: $with_imagequant + (requires libimagequant) +TIFF load/save with libtiff: $with_tiff +image pyramid save: $with_gsf + (requires libgsf-1 1.14.26 or later) +HEIC/AVIF load/save with libheif: $with_heif +WebP load/save with libwebp: $with_libwebp + (requires libwebp, libwebpmux, libwebpdemux 0.6.0 or later) +PDF load with PDFium: $with_pdfium +PDF load with poppler-glib: $with_poppler + (requires poppler-glib 0.16.0 or later) +SVG load with librsvg-2.0: $with_rsvg + (requires librsvg-2.0 2.34.0 or later) +EXR load with OpenEXR: $with_OpenEXR +slide load with OpenSlide: $with_openslide + (requires openslide-3.3.0 or later) +Matlab load with matio: $with_matio +NIfTI load/save with niftiio: $with_nifti +FITS load/save with cfitsio: $with_cfitsio +Magick package: $with_magickpackage +Magick API version: $magick_version +load with libMagickCore: $enable_magickload +save with libMagickCore: $enable_magicksave +]) diff --git a/doc/Makefile.am b/doc/Makefile.am index 6987b91e..82a516a7 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -127,7 +127,7 @@ HTML_IMAGES = \ # we have some files in markdown ... convert to docbook for gtk-doc # pandoc makes section headers, we want refsect3 for gtk-doc .md.xml: - pandoc -s --template="$(realpath pandoc-docbook-template.docbook)" --wrap=none -V title="$<" -f markdown+smart -t docbook-smart -o $@ $< + pandoc -s --template="$(realpath pandoc-docbook-template.docbook)" --wrap=none -V title="$<" -f markdown+smart -t docbook -o $@ $< sed -e s/section/refsect3/g < $@ > x && mv x $@ # Our markdown source files diff --git a/doc/binding.xml b/doc/binding.xml index 956b0101..24e30f7b 100644 --- a/doc/binding.xml +++ b/doc/binding.xml @@ -19,10 +19,35 @@ Donā€™t bind the top-level C API - The libvips C API (vips_add() and so on) is very inconvenient and dangerous to use from other languages due to its heavy use of varargs. + The libvips C API (vips_add() and so on) was designed to be easy for humans to write. It is inconvenient and dangerous to use from other languages due to its heavy use of varargs. - Itā€™s much better to use the layer below. This lower layer is structured as create operator, set parameters, execute, extract results. For example, you can execute vips_invert() like this: + Itā€™s much better to use the layer below. This lower layer is structured as: + + + + + Create operator. You can use vips_operation_new() to make a new VipsOperation object from an operator nickname, like "add". + + + + + Set parameters. You can loop over the operation with vips_argument_map() to get the name and type of each input argument. For each argument, you need to get the value from your language, convert to a GValue, then use g_object_set_property() to set that value on the operator. + + + + + Execute with vips_cache_operation_build(). + + + + + Extract results. Again, you loop over the operator arguments with vips_argument_map(), but instead of inputs, this time you look for output arguments. You extract their value with g_object_get_property(), and pass the value back to your language. + + + + + For example, you can execute vips_invert() like this: /* compile with @@ -111,17 +136,11 @@ main( int argc, char **argv ) return( 0 ); } - - libvips has a couple of extra things to let you examine the arguments and types of an operator at runtime. Use vips_argument_map() to loop over all the arguments of an operator, and vips_object_get_argument() to fetch the type and flags of a specific argument. - - - Use vips_operation_get_flags() to get general information about an operator. - Compiled language which can call C - The C++ binding uses this lower layer to define a function called VImage::call() which can call any libvips operator with a not-varargs set of variable arguments. + The C++ binding uses this lower layer to define a function called VImage::call() which can call any libvips operator with a set of variable arguments. A small Python program walks the set of all libvips operators and generates a set of static bindings. For example: @@ -139,7 +158,7 @@ VImage VImage::invert( VOption *options ) } - So from C++ you can call any libvips operator (though without type-safety) with VImage::call(), or use the member functions on VImage to get type-safe calls for at least the required operator arguments. + So from C++ you can call any libvips operator (though without static typechecking) with VImage::call(), or use the member functions on VImage to get type-checked calls for at least the required operator arguments. The VImage class also adds automatic reference counting, constant expansion, operator overloads, and various other useful features. @@ -151,13 +170,13 @@ VImage VImage::invert( VOption *options ) Languages like Ruby, Python, JavaScript and LuaJIT canā€™t call C directly, but they do support FFI. The bindings for these languages work rather like C++, but use FFI to call into libvips and run operations. - Since these languages are dynamic, they can add another trick: they intercept the method-missing hook and attempt to run any method calls not implemented by the Image class as libvips operators. This makes these bindings self-writing: they only contain a small amount of code and just expose everything they find in the libvips class hierarchy. + Since these languages are dynamic, they can add another trick: they intercept the method-missing hook and attempt to run any method calls not implemented by the Image class as libvips operators. In effect, the binding is generated at runtime. Dynamic langauge without FFI - PHP does not have FFI, unfortunately, so for this language a small native module implements the general vips_call() function for PHP language types, and a larger pure PHP layer makes it convenient to use. + PHP does not have a useful FFI, unfortunately, so for this language a small C module implements the general vips_call() function for PHP language types, and a larger pure PHP layer makes it convenient to use. diff --git a/libvips/conversion/flatten.c b/libvips/conversion/flatten.c index 912644c9..7c9f3527 100644 --- a/libvips/conversion/flatten.c +++ b/libvips/conversion/flatten.c @@ -67,7 +67,7 @@ typedef struct _VipsFlatten { */ VipsArrayDouble *background; - /* The [double] converted to the input image format. + /* The [double] background converted to the input image format. */ VipsPel *ink; diff --git a/libvips/conversion/unpremultiply.c b/libvips/conversion/unpremultiply.c index 219fac28..88bbbed2 100644 --- a/libvips/conversion/unpremultiply.c +++ b/libvips/conversion/unpremultiply.c @@ -7,6 +7,8 @@ * - max_alpha defaults to 65535 for RGB16/GREY16 * 24/11/17 lovell * - match normalised alpha to output type + * 27/2/21 jjonesrs + * - revise range clipping and 1/x, again */ /* @@ -70,7 +72,8 @@ typedef VipsConversionClass VipsUnpremultiplyClass; G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION ); -/* Unpremultiply an N-band image. +/* Unpremultiply an N-band image. Don't use clip_alpha to calculate factor: we + * want over and undershoots on alpha and RGB to cancel. */ #define UNPRE_MANY( IN, OUT ) { \ IN * restrict p = (IN *) in; \ @@ -78,18 +81,11 @@ G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION ); \ for( x = 0; x < width; x++ ) { \ IN alpha = p[alpha_band]; \ + OUT factor = alpha == 0 ? 0 : max_alpha / alpha; \ \ - if( alpha != 0 ) { \ - OUT factor = max_alpha / alpha; \ - \ - for( i = 0; i < alpha_band; i++ ) \ - q[i] = factor * p[i]; \ - q[alpha_band] = alpha; \ - } \ - else \ - for( i = 0; i < alpha_band + 1; i++ ) \ - q[i] = 0; \ - \ + for( i = 0; i < alpha_band; i++ ) \ + q[i] = factor * p[i]; \ + q[alpha_band] = VIPS_CLIP( 0, alpha, max_alpha ); \ for( i = alpha_band + 1; i < bands; i++ ) \ q[i] = p[i]; \ \ @@ -106,21 +102,12 @@ G_DEFINE_TYPE( VipsUnpremultiply, vips_unpremultiply, VIPS_TYPE_CONVERSION ); \ for( x = 0; x < width; x++ ) { \ IN alpha = p[3]; \ + OUT factor = alpha == 0 ? 0 : max_alpha / alpha; \ \ - if( alpha != 0 ) { \ - OUT factor = max_alpha / alpha; \ - \ - q[0] = factor * p[0]; \ - q[1] = factor * p[1]; \ - q[2] = factor * p[2]; \ - q[3] = alpha; \ - } \ - else { \ - q[0] = 0; \ - q[1] = 0; \ - q[2] = 0; \ - q[3] = 0; \ - } \ + q[0] = factor * p[0]; \ + q[1] = factor * p[1]; \ + q[2] = factor * p[2]; \ + q[3] = VIPS_CLIP( 0, alpha, max_alpha ); \ \ p += 4; \ q += 4; \ diff --git a/libvips/foreign/tiff.c b/libvips/foreign/tiff.c index 82fc78d9..744ac6d3 100644 --- a/libvips/foreign/tiff.c +++ b/libvips/foreign/tiff.c @@ -104,7 +104,7 @@ vips__tiff_openout( const char *path, gboolean bigtiff ) /* Need the utf-16 version on Windows. */ -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 { GError *error = NULL; wchar_t *path16; @@ -119,9 +119,9 @@ vips__tiff_openout( const char *path, gboolean bigtiff ) g_free( path16 ); } -#else /*!OS_WIN32*/ +#else /*!G_OS_WIN32*/ tif = TIFFOpen( path, mode ); -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ if( !tif ) { vips_error( "tiff", diff --git a/libvips/foreign/tiffsave.c b/libvips/foreign/tiffsave.c index c0565c59..57eda43b 100644 --- a/libvips/foreign/tiffsave.c +++ b/libvips/foreign/tiffsave.c @@ -590,8 +590,8 @@ vips_foreign_save_tiff_buffer_init( VipsForeignSaveTiffBuffer *buffer ) * User @level to set the ZSTD compression level. Use @lossless to * set WEBP lossless mode on. Use @Q to set the WEBP compression level. * - * Use @predictor to set the predictor for lzw and deflate compression. It - * defaults to #VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL, meaning horizontal + * Use @predictor to set the predictor for lzw, deflate and zstd compression. + * It defaults to #VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL, meaning horizontal * differencing. Please refer to the libtiff * specifications for further discussion of various predictors. * diff --git a/libvips/foreign/vips2tiff.c b/libvips/foreign/vips2tiff.c index 1ea73895..626b36ba 100644 --- a/libvips/foreign/vips2tiff.c +++ b/libvips/foreign/vips2tiff.c @@ -333,9 +333,9 @@ struct _Wtiff { VipsPel *tbuf; /* TIFF output buffer */ int tls; /* Tile line size */ - int compression; /* Compression type */ + int compression; /* libtiff compression type */ int Q; /* JPEG q-factor, webp level */ - int predictor; /* Predictor value */ + int predictor; /* libtiff predictor type */ int tile; /* Tile or not */ int tilew, tileh; /* Tile size */ int pyramid; /* Wtiff pyramid */ @@ -659,12 +659,16 @@ wtiff_write_header( Wtiff *wtiff, Layer *layer ) TIFFSetField( tif, TIFFTAG_WEBP_LEVEL, wtiff->Q ); TIFFSetField( tif, TIFFTAG_WEBP_LOSSLESS, wtiff->lossless ); } - if( wtiff->compression == COMPRESSION_ZSTD ) + if( wtiff->compression == COMPRESSION_ZSTD ) { TIFFSetField( tif, TIFFTAG_ZSTD_LEVEL, wtiff->level ); + if( wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE ) + TIFFSetField( tif, + TIFFTAG_PREDICTOR, wtiff->predictor ); + } #endif /*HAVE_TIFF_COMPRESSION_WEBP*/ - if( (wtiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_DEFLATE || - wtiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_LZW) && + if( (wtiff->compression == COMPRESSION_ADOBE_DEFLATE || + wtiff->compression == COMPRESSION_LZW) && wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE ) TIFFSetField( tif, TIFFTAG_PREDICTOR, wtiff->predictor ); @@ -1862,10 +1866,19 @@ wtiff_copy_tiff( Wtiff *wtiff, TIFF *out, TIFF *in ) TIFFSetField( out, TIFFTAG_WEBP_LEVEL, wtiff->Q ); TIFFSetField( out, TIFFTAG_WEBP_LOSSLESS, wtiff->lossless ); } - if( wtiff->compression == COMPRESSION_ZSTD ) + if( wtiff->compression == COMPRESSION_ZSTD ) { TIFFSetField( out, TIFFTAG_ZSTD_LEVEL, wtiff->level ); + if( wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE ) + TIFFSetField( out, + TIFFTAG_PREDICTOR, wtiff->predictor ); + } #endif /*HAVE_TIFF_COMPRESSION_WEBP*/ + if( (wtiff->compression == COMPRESSION_ADOBE_DEFLATE || + wtiff->compression == COMPRESSION_LZW) && + wtiff->predictor != VIPS_FOREIGN_TIFF_PREDICTOR_NONE ) + TIFFSetField( out, TIFFTAG_PREDICTOR, wtiff->predictor ); + /* We can't copy profiles or xmp :( Set again from wtiff. */ if( !wtiff->strip ) diff --git a/libvips/include/vips/object.h b/libvips/include/vips/object.h index 5cda33d3..14369e86 100644 --- a/libvips/include/vips/object.h +++ b/libvips/include/vips/object.h @@ -365,7 +365,6 @@ int vips_object_get_argument_priority( VipsObject *object, const char *name ); VIPS_ARGUMENT_COLLECT_END */ -#if GLIB_CHECK_VERSION( 2, 24, 0 ) #define VIPS_ARGUMENT_COLLECT_SET( PSPEC, ARG_CLASS, AP ) \ if( (ARG_CLASS->flags & VIPS_ARGUMENT_INPUT) ) { \ GValue value = { 0, }; \ @@ -383,25 +382,6 @@ int vips_object_get_argument_priority( VipsObject *object, const char *name ); VIPS_DEBUG_MSG( "VIPS_OBJECT_COLLECT_SET: err\n" ); \ g_free( error ); \ } -#else -#define VIPS_ARGUMENT_COLLECT_SET( PSPEC, ARG_CLASS, AP ) \ - if( (ARG_CLASS->flags & VIPS_ARGUMENT_INPUT) ) { \ - GValue value = { 0, }; \ - gchar *error = NULL; \ - \ - /* Input args are given inline, eg. ("factor", 12.0) \ - * and must be collected. \ - */ \ - g_value_init( &value, G_PARAM_SPEC_VALUE_TYPE( PSPEC ) ); \ - G_VALUE_COLLECT( &value, AP, 0, &error ); \ - \ - /* Don't bother with the error message. \ - */ \ - if( error ) { \ - VIPS_DEBUG_MSG( "VIPS_OBJECT_COLLECT_SET: err\n" ); \ - g_free( error ); \ - } -#endif #define VIPS_ARGUMENT_COLLECT_GET( PSPEC, ARG_CLASS, AP ) \ g_value_unset( &value ); \ diff --git a/libvips/iofuncs/error.c b/libvips/iofuncs/error.c index cbb44162..7125396a 100644 --- a/libvips/iofuncs/error.c +++ b/libvips/iofuncs/error.c @@ -65,10 +65,10 @@ #include #include -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 #include #include -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ /** * SECTION: errors @@ -294,7 +294,7 @@ vips_verror_system( int err, const char *domain, const char *fmt, va_list ap ) { vips_verror( domain, fmt, ap ); -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 { char *buf; @@ -310,7 +310,7 @@ vips_verror_system( int err, const char *domain, const char *fmt, va_list ap ) LocalFree( buf ); } } -#else /*OS_WIN32*/ +#else /*!G_OS_WIN32*/ { char *buf; @@ -318,7 +318,7 @@ vips_verror_system( int err, const char *domain, const char *fmt, va_list ap ) vips_error( _( "unix error" ), "%s", buf ); g_free( buf ); } -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ } /** diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index ce2303e8..db2c6595 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -1676,14 +1676,7 @@ vips_image_temp_name( char *name, int size ) { static int global_serial = 0; - /* Old glibs named this differently. - */ - int serial = -#if GLIB_CHECK_VERSION( 2, 30, 0 ) - g_atomic_int_add( &global_serial, 1 ); -#else - g_atomic_int_exchange_and_add( &global_serial, 1 ); -#endif + int serial = g_atomic_int_add( &global_serial, 1 ); vips_snprintf( name, size, "temp-%d", serial ); } diff --git a/libvips/iofuncs/init.c b/libvips/iofuncs/init.c index 8cc41a06..07836b15 100644 --- a/libvips/iofuncs/init.c +++ b/libvips/iofuncs/init.c @@ -290,24 +290,6 @@ empty_log_handler( const gchar *log_domain, GLogLevelFlags log_level, { } -#if !GLIB_CHECK_VERSION( 2, 31, 0 ) -static void -default_log_handler( const gchar *log_domain, GLogLevelFlags log_level, - const gchar *message, gpointer user_data ) -{ - if( log_level & (G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO) ) { - const char *domains = g_getenv( "G_MESSAGES_DEBUG" ); - - if( !domains || - (!g_str_equal( domains, "all" ) && - !g_strrstr( domains, log_domain )) ) - return; - } - - g_log_default_handler( log_domain, log_level, message, user_data ); -} -#endif /*!GLIB_CHECK_VERSION( 2, 31, 0 )*/ - /* Attempt to set a minimum stacksize. This can be important on systems with a * very low default, like musl. */ @@ -407,7 +389,7 @@ vips_init( const char *argv0 ) return( 0 ); started = TRUE; -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 /* Windows has a limit of 512 files open at once for the fopen() family * of functions, and 2048 for the _open() family. This raises the limit * of fopen() to the same level as _open(). @@ -415,7 +397,7 @@ vips_init( const char *argv0 ) * It will not go any higher than this, unfortunately. */ (void) _setmaxstdio( 2048 ); -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ vips__threadpool_init(); vips__buffer_init(); @@ -595,18 +577,6 @@ vips_init( const char *argv0 ) g_log_set_handler( G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, empty_log_handler, NULL ); -#if !GLIB_CHECK_VERSION( 2, 31, 0 ) - /* Older glibs can sometimes show G_LOG_LEVEL_{INFO,DEBUG} messages. - * Block them ourselves. We test the env var inside the handler since - * vips_verbose() can be toggled at runtime. - * - * Again, we should not call g_log_set_handler(), but this is the only - * convenient way to fix this behaviour. - */ - g_log_set_handler( G_LOG_DOMAIN, G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG, - default_log_handler, NULL ); -#endif /*!GLIB_CHECK_VERSION( 2, 31, 0 )*/ - /* Set a minimum stacksize, if we can. */ if( (vips_min_stack_size = g_getenv( "VIPS_MIN_STACK_SIZE" )) ) @@ -1057,7 +1027,7 @@ find_file( const char *name ) printf( "vips_guess_prefix: g_getenv( \"PATH\" ) == \"%s\"\n", path ); #endif /*DEBUG*/ -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 { char *dir; @@ -1068,9 +1038,9 @@ find_file( const char *name ) "%s" G_SEARCHPATH_SEPARATOR_S "%s", dir, path ); g_free( dir ); } -#else /*!OS_WIN32*/ +#else /*!G_OS_WIN32*/ vips_strncpy( full_path, path, VIPS_PATH_MAX ); -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ if( (prefix = scan_path( full_path, name )) ) return( prefix ); @@ -1177,9 +1147,9 @@ vips_guess_prefix( const char *argv0, const char *env_name ) return( prefix ); } -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 prefix = vips__windows_prefix(); -#else +#else /*!G_OS_WIN32*/ { char *basename; @@ -1187,7 +1157,7 @@ vips_guess_prefix( const char *argv0, const char *env_name ) prefix = guess_prefix( argv0, basename ); g_free( basename ); } -#endif +#endif /*G_OS_WIN32*/ g_setenv( env_name, prefix, TRUE ); diff --git a/libvips/iofuncs/mapfile.c b/libvips/iofuncs/mapfile.c index 8dda21e6..3c16c0b7 100644 --- a/libvips/iofuncs/mapfile.c +++ b/libvips/iofuncs/mapfile.c @@ -77,18 +77,16 @@ #ifdef HAVE_UNISTD_H #include #endif /*HAVE_UNISTD_H*/ -#ifdef OS_WIN32 -#ifndef S_ISREG -#define S_ISREG(m) (!!(m & _S_IFREG)) -#endif -#endif /*OS_WIN32*/ #include -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 +#ifndef S_ISREG +#define S_ISREG(m) (!!(m & _S_IFREG)) +#endif #include #include -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ /* Does this fd support mmap. Pipes won't, for example. */ @@ -99,7 +97,7 @@ vips__mmap_supported( int fd ) size_t length = 4096; off_t offset = 0; -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 { HANDLE hFile = (HANDLE) _get_osfhandle( fd ); @@ -128,7 +126,7 @@ vips__mmap_supported( int fd ) CloseHandle( hMMFile ); UnmapViewOfFile( baseaddr ); } -#else /*!OS_WIN32*/ +#else /*!G_OS_WIN32*/ { int prot = PROT_READ; int flags = MAP_SHARED; @@ -138,7 +136,7 @@ vips__mmap_supported( int fd ) return( FALSE ); munmap( baseaddr, length ); } -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ return( TRUE ); } @@ -153,7 +151,7 @@ vips__mmap( int fd, int writeable, size_t length, gint64 offset ) length, offset ); #endif /*DEBUG*/ -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 { HANDLE hFile = (HANDLE) _get_osfhandle( fd ); @@ -203,7 +201,7 @@ vips__mmap( int fd, int writeable, size_t length, gint64 offset ) */ CloseHandle( hMMFile ); } -#else /*!OS_WIN32*/ +#else /*!G_OS_WIN32*/ { int prot; int flags; @@ -237,7 +235,7 @@ vips__mmap( int fd, int writeable, size_t length, gint64 offset ) return( NULL ); } } -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ return( baseaddr ); } @@ -245,19 +243,19 @@ vips__mmap( int fd, int writeable, size_t length, gint64 offset ) int vips__munmap( const void *start, size_t length ) { -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 if( !UnmapViewOfFile( (void *) start ) ) { vips_error_system( GetLastError(), "vips_mapfile", "%s", _( "unable to UnmapViewOfFile" ) ); return( -1 ); } -#else /*!OS_WIN32*/ +#else /*!G_OS_WIN32*/ if( munmap( (void *) start, length ) < 0 ) { vips_error_system( errno, "vips_mapfile", "%s", _( "unable to munmap file" ) ); return( -1 ); } -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ return( 0 ); } @@ -345,7 +343,7 @@ vips_remapfilerw( VipsImage *image ) printf( "vips_remapfilerw:\n" ); #endif /*DEBUG*/ -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 { HANDLE hFile = (HANDLE) _get_osfhandle( image->fd ); HANDLE hMMFile; @@ -377,7 +375,7 @@ vips_remapfilerw( VipsImage *image ) */ CloseHandle( hMMFile ); } -#else /*!OS_WIN32*/ +#else /*!G_OS_WIN32*/ { assert( image->dtype == VIPS_IMAGE_MMAPIN ); @@ -390,7 +388,7 @@ vips_remapfilerw( VipsImage *image ) return( -1 ); } } -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ image->dtype = VIPS_IMAGE_MMAPINRW; diff --git a/libvips/iofuncs/source.c b/libvips/iofuncs/source.c index deabac72..25ea18fe 100644 --- a/libvips/iofuncs/source.c +++ b/libvips/iofuncs/source.c @@ -65,23 +65,24 @@ #include #include #include -#ifdef OS_WIN32 -#include -#endif /*OS_WIN32*/ #include #include #include +#ifdef G_OS_WIN32 +#include +#endif /*G_OS_WIN32*/ + /* Try to make an O_BINARY ... sometimes need the leading '_'. */ -#ifdef BINARY_OPEN +#ifdef G_PLATFORM_WIN32 #ifndef O_BINARY #ifdef _O_BINARY #define O_BINARY _O_BINARY #endif /*_O_BINARY*/ #endif /*!O_BINARY*/ -#endif /*BINARY_OPEN*/ +#endif /*G_PLATFORM_WIN32*/ /* If we have O_BINARY, add it to a mode flags set. */ @@ -307,12 +308,12 @@ vips_source_build( VipsObject *object ) connection->descriptor = dup( connection->descriptor ); connection->close_descriptor = connection->descriptor; -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 /* Windows will create eg. stdin and stdout in text mode. * We always read in binary mode. */ _setmode( connection->descriptor, _O_BINARY ); -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ } if( vips_object_argument_isset( object, "blob" ) ) { diff --git a/libvips/iofuncs/target.c b/libvips/iofuncs/target.c index 01b3339c..667edff1 100644 --- a/libvips/iofuncs/target.c +++ b/libvips/iofuncs/target.c @@ -55,23 +55,24 @@ #include #include #include -#ifdef OS_WIN32 -#include -#endif /*OS_WIN32*/ #include #include #include +#ifdef G_OS_WIN32 +#include +#endif /*G_OS_WIN32*/ + /* Try to make an O_BINARY ... sometimes need the leading '_'. */ -#ifdef BINARY_OPEN +#ifdef G_PLATFORM_WIN32 #ifndef O_BINARY #ifdef _O_BINARY #define O_BINARY _O_BINARY #endif /*_O_BINARY*/ #endif /*!O_BINARY*/ -#endif /*BINARY_OPEN*/ +#endif /*G_PLATFORM_WIN32*/ /* If we have O_BINARY, add it to a mode flags set. */ @@ -143,12 +144,12 @@ vips_target_build( VipsObject *object ) connection->descriptor = dup( connection->descriptor ); connection->close_descriptor = connection->descriptor; -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 /* Windows will create eg. stdin and stdout in text mode. * We always write in binary mode. */ _setmode( connection->descriptor, _O_BINARY ); -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ } else if( target->memory ) target->memory_buffer = g_byte_array_new(); diff --git a/libvips/iofuncs/threadpool.c b/libvips/iofuncs/threadpool.c index 14774587..2b4fc779 100644 --- a/libvips/iofuncs/threadpool.c +++ b/libvips/iofuncs/threadpool.c @@ -75,9 +75,9 @@ #include #include -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 #include -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ /** * SECTION: threadpool @@ -338,7 +338,7 @@ get_num_processors( void ) #endif /*G_OS_UNIX*/ -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 { /* Count the CPUs currently available to this process. */ @@ -365,7 +365,7 @@ get_num_processors( void ) nproc = af_count; } } -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ return( nproc ); #endif /*!GLIB_CHECK_VERSION( 2, 48, 1 )*/ diff --git a/libvips/iofuncs/util.c b/libvips/iofuncs/util.c index c3658893..ae697097 100644 --- a/libvips/iofuncs/util.c +++ b/libvips/iofuncs/util.c @@ -53,27 +53,27 @@ #endif /*HAVE_IO_H*/ #include -#ifdef OS_WIN32 -#include -#endif /*OS_WIN32*/ - #include #include #include +#ifdef G_OS_WIN32 +#include +#endif /*G_OS_WIN32*/ + /* Temp buffer for snprintf() layer on old systems. */ #define MAX_BUF (100000) /* Try to make an O_BINARY ... sometimes need the leading '_'. */ -#ifdef BINARY_OPEN +#ifdef G_PLATFORM_WIN32 #ifndef O_BINARY #ifdef _O_BINARY #define O_BINARY _O_BINARY #endif /*_O_BINARY*/ #endif /*!O_BINARY*/ -#endif /*BINARY_OPEN*/ +#endif /*G_PLATFORM_WIN32*/ /* If we have O_BINARY, add it to a mode flags set. */ @@ -562,15 +562,15 @@ vips_filename_suffix_match( const char *path, const char *suffixes[] ) gint64 vips_file_length( int fd ) { -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 struct _stati64 st; if( _fstati64( fd, &st ) == -1 ) { -#else /*!OS_WIN32*/ +#else /*!G_OS_WIN32*/ struct stat st; if( fstat( fd, &st ) == -1 ) { -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ vips_error_system( errno, "vips_file_length", "%s", _( "unable to get file stats" ) ); return( -1 ); @@ -600,7 +600,7 @@ vips__write( int fd, const void *buf, size_t count ) return( 0 ); } -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 /* Set the create date on a file. On Windows, the create date may be copied * over from an existing file of the same name, unless you reset it. * @@ -619,7 +619,7 @@ vips__set_create_time( int fd ) SystemTimeToFileTime( &st, &ft ); SetFileTime( handle, &ft, &ft, &ft ); } -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ /* open() with a utf8 filename, setting errno. */ @@ -638,10 +638,10 @@ vips__open( const char *filename, int flags, int mode ) fd = g_open( filename, flags, mode ); -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 if( mode & O_CREAT ) vips__set_create_time( fd ); -#endif +#endif /*G_OS_WIN32*/ return( fd ); } @@ -661,10 +661,10 @@ vips__fopen( const char *filename, const char *mode ) fp = g_fopen( filename, mode ); -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 if( mode[0] == 'w' ) vips__set_create_time( _fileno( fp ) ); -#endif +#endif /*G_OS_WIN32*/ return( fp ); } @@ -698,14 +698,14 @@ vips__file_open_read( const char *filename, const char *fallback_dir, char *mode; FILE *fp; -#ifdef BINARY_OPEN +#ifdef G_PLATFORM_WIN32 if( text_mode ) mode = "r"; else mode = "rb"; -#else /*BINARY_OPEN*/ +#else /*!G_PLATFORM_WIN32*/ mode = "r"; -#endif /*BINARY_OPEN*/ +#endif /*G_PLATFORM_WIN32*/ if( (fp = vips__fopen( filename, mode )) ) return( fp ); @@ -734,14 +734,14 @@ vips__file_open_write( const char *filename, gboolean text_mode ) char *mode; FILE *fp; -#ifdef BINARY_OPEN +#ifdef G_PLATFORM_WIN32 if( text_mode ) mode = "w"; else mode = "wb"; -#else /*BINARY_OPEN*/ +#else /*!G_PLATFORM_WIN32*/ mode = "w"; -#endif /*BINARY_OPEN*/ +#endif /*G_PLATFORM_WIN32*/ if( !(fp = vips__fopen( filename, mode )) ) { vips_error_system( errno, "vips__file_open_write", @@ -1089,15 +1089,15 @@ vips__seek_no_error( int fd, gint64 pos, int whence ) { gint64 new_pos; -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 new_pos = _lseeki64( fd, pos, whence ); -#else /*!OS_WIN32*/ +#else /*!G_OS_WIN32*/ /* On error, eg. opening a directory and seeking to the end, lseek() * on linux seems to return 9223372036854775807 ((1 << 63) - 1) * rather than (off_t) -1 for reasons I don't understand. */ new_pos = lseek( fd, pos, whence ); -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ return( new_pos ); } @@ -1128,7 +1128,7 @@ vips__seek( int fd, gint64 pos, int whence ) int vips__ftruncate( int fd, gint64 pos ) { -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 { HANDLE hFile = (HANDLE) _get_osfhandle( fd ); @@ -1140,13 +1140,13 @@ vips__ftruncate( int fd, gint64 pos ) return( -1 ); } } -#else /*!OS_WIN32*/ +#else /*!G_OS_WIN32*/ if( ftruncate( fd, pos ) ) { vips_error_system( errno, "vips__ftruncate", "%s", _( "unable to truncate" ) ); return( -1 ); } -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ return( 0 ); } @@ -1620,7 +1620,7 @@ vips__temp_dir( void ) const char *tmpd; if( !(tmpd = g_getenv( "TMPDIR" )) ) { -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 static gboolean done = FALSE; static char buf[256]; @@ -1629,9 +1629,9 @@ vips__temp_dir( void ) strcpy( buf, "C:\\temp" ); } tmpd = buf; -#else /*!OS_WIN32*/ +#else /*!G_OS_WIN32*/ tmpd = "/tmp"; -#endif /*!OS_WIN32*/ +#endif /*!G_OS_WIN32*/ } return( tmpd ); @@ -1651,14 +1651,7 @@ vips__temp_name( const char *format ) char file2[FILENAME_MAX]; char *name; - /* Old glibs named this differently. - */ - int serial = -#if GLIB_CHECK_VERSION( 2, 30, 0 ) - g_atomic_int_add( &global_serial, 1 ); -#else - g_atomic_int_exchange_and_add( &global_serial, 1 ); -#endif + int serial = g_atomic_int_add( &global_serial, 1 ); vips_snprintf( file, FILENAME_MAX, "vips-%d-%u", serial, g_random_int() ); @@ -1961,7 +1954,7 @@ vips__random_add( guint32 seed, int value ) static void * vips_icc_dir_once( void *null ) { -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 /* From glib get_windows_directory_root() */ wchar_t wwindowsdir[MAX_PATH]; @@ -1983,7 +1976,7 @@ vips_icc_dir_once( void *null ) return( (void *) full_path ); } } -#endif +#endif /*G_OS_WIN32*/ return( (void *) VIPS_ICC_DIR ); } @@ -1997,7 +1990,7 @@ vips__icc_dir( void ) vips_icc_dir_once, NULL ) ); } -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 static HMODULE vips__dll = NULL; #ifdef DLL_EXPORT BOOL WINAPI @@ -2009,19 +2002,19 @@ DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) return( TRUE ); } #endif -#endif +#endif /*G_OS_WIN32*/ static void * vips__windows_prefix_once( void *null ) { char *prefix; -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 prefix = g_win32_get_package_installation_directory_of_module( vips__dll ); -#else +#else /*!G_OS_WIN32*/ prefix = (char *) g_getenv( "VIPSHOME" ); -#endif +#endif /*G_OS_WIN32*/ return( (void *) prefix ); } diff --git a/libvips/iofuncs/vips.c b/libvips/iofuncs/vips.c index 81530277..74362084 100644 --- a/libvips/iofuncs/vips.c +++ b/libvips/iofuncs/vips.c @@ -115,13 +115,13 @@ /* Try to make an O_BINARY ... sometimes need the leading '_'. */ -#ifdef BINARY_OPEN +#ifdef G_PLATFORM_WIN32 #ifndef O_BINARY #ifdef _O_BINARY #define O_BINARY _O_BINARY #endif /*_O_BINARY*/ #endif /*!O_BINARY*/ -#endif /*BINARY_OPEN*/ +#endif /*G_PLATFORM_WIN32*/ /* If we have O_BINARY, add it to a mode flags set. */ diff --git a/libvips/iofuncs/window.c b/libvips/iofuncs/window.c index 875c895e..72b7a7ad 100644 --- a/libvips/iofuncs/window.c +++ b/libvips/iofuncs/window.c @@ -58,9 +58,9 @@ #include #include -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 #include -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ /* Sanity checking ... write to this during read tests to make sure we don't * get optimized out. @@ -189,15 +189,15 @@ vips_getpagesize( void ) static int pagesize = 0; if( !pagesize ) { -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 SYSTEM_INFO si; GetSystemInfo( &si ); pagesize = si.dwAllocationGranularity; -#else /*OS_WIN32*/ +#else /*!G_OS_WIN32*/ pagesize = getpagesize(); -#endif /*OS_WIN32*/ +#endif /*G_OS_WIN32*/ #ifdef DEBUG_TOTAL printf( "vips_getpagesize: 0x%x\n", pagesize ); diff --git a/libvips/mosaicing/lrmerge.c b/libvips/mosaicing/lrmerge.c index ff481c4c..73863123 100644 --- a/libvips/mosaicing/lrmerge.c +++ b/libvips/mosaicing/lrmerge.c @@ -1123,16 +1123,9 @@ vips__add_mosaic_name( VipsImage *image ) { static int global_serial = 0; - /* Old glibs named this differently. - * - * TODO(kleisauke): Could we call vips_image_temp_name instead? + /* TODO(kleisauke): Could we call vips_image_temp_name instead? */ - int serial = -#if GLIB_CHECK_VERSION( 2, 30, 0 ) - g_atomic_int_add( &global_serial, 1 ); -#else - g_atomic_int_exchange_and_add( &global_serial, 1 ); -#endif + int serial = g_atomic_int_add( &global_serial, 1 ); char name[256]; diff --git a/libvips/resample/thumbnail.c b/libvips/resample/thumbnail.c index aaee14fb..61830750 100644 --- a/libvips/resample/thumbnail.c +++ b/libvips/resample/thumbnail.c @@ -30,6 +30,9 @@ * - add thumbnail_source * 2/6/20 * - add subifd pyr support + * 27/2/21 + * - simplify rules re. processing space, colour management and linear + * mode */ /* @@ -624,16 +627,19 @@ vips_thumbnail_build( VipsObject *object ) int preshrunk_page_height; double hshrink; double vshrink; - VipsInterpretation interpretation; /* TRUE if we've done the import of an ICC transform and still need to * export. */ gboolean have_imported; - /* TRUE if we've premultiplied and need to unpremultiply. + /* If we shrink in linear space, we need to return to the input + * colourspace after the shrink. + */ + VipsInterpretation input_interpretation; + + /* The format we need to revert to after unpremultiply. */ - gboolean have_premultiplied; VipsBandFormat unpremultiplied_format; #ifdef DEBUG @@ -679,60 +685,78 @@ vips_thumbnail_build( VipsObject *object ) in = t[12]; } - /* In linear mode, we import right at the start. - * - * We also have to import the whole image if it's CMYK, since - * vips_colourspace() (see below) doesn't let you specify the fallback - * profile. - * - * This is only going to work for images in device space. If you have - * an image in PCS which also has an attached profile, strange things - * will happen. + /* In linear mode, we need to transform to a linear space before + * vips_resize(). */ have_imported = FALSE; - if( thumbnail->linear && - in->Coding == VIPS_CODING_NONE && - (in->BandFmt == VIPS_FORMAT_UCHAR || - in->BandFmt == VIPS_FORMAT_USHORT) && - (vips_image_get_typeof( in, VIPS_META_ICC_NAME ) || - thumbnail->import_profile) ) { - g_info( "importing to XYZ PCS" ); - if( thumbnail->import_profile ) - g_info( "fallback input profile %s", - thumbnail->import_profile ); + if( thumbnail->linear ) { + /* If we are doing colour management (there's an import + * profile), then we can use XYZ PCS as the resize space. + */ + if( in->Coding == VIPS_CODING_NONE && + (in->BandFmt == VIPS_FORMAT_UCHAR || + in->BandFmt == VIPS_FORMAT_USHORT) && + (vips_image_get_typeof( in, VIPS_META_ICC_NAME ) || + thumbnail->import_profile) ) { + g_info( "importing to XYZ PCS" ); + if( thumbnail->import_profile ) + g_info( "fallback input profile %s", + thumbnail->import_profile ); - if( vips_icc_import( in, &t[1], - "input_profile", thumbnail->import_profile, - "embedded", TRUE, - "intent", thumbnail->intent, - "pcs", VIPS_PCS_XYZ, - NULL ) ) - return( -1 ); + if( vips_icc_import( in, &t[1], + "input_profile", thumbnail->import_profile, + "embedded", TRUE, + "intent", thumbnail->intent, + "pcs", VIPS_PCS_XYZ, + NULL ) ) + return( -1 ); + in = t[1]; - in = t[1]; + have_imported = TRUE; + } + else { + /* Otherwise, use scRGB or GREY16 for linear shrink. + */ + VipsInterpretation interpretation; - have_imported = TRUE; + /* Note the interpretation we will revert to after + * linear. + */ + input_interpretation = in->Type; + + if( in->Bands < 3 ) + interpretation = VIPS_INTERPRETATION_GREY16; + else + interpretation = VIPS_INTERPRETATION_scRGB; + + g_info( "converting to processing space %s", + vips_enum_nick( VIPS_TYPE_INTERPRETATION, + interpretation ) ); + if( vips_colourspace( in, &t[2], interpretation, + NULL ) ) + return( -1 ); + in = t[2]; + } } + else { + /* In non-linear mode, use sRGB or B_W as the processing + * space. + */ + VipsInterpretation interpretation; - /* To the processing colourspace. This will unpack LABQ, import CMYK, - * etc. - * - * If this is a CMYK image, we need to set have_imported since we only - * want to export at the end. - */ - if( in->Type == VIPS_INTERPRETATION_CMYK ) - have_imported = TRUE; - if( thumbnail->linear ) - interpretation = VIPS_INTERPRETATION_scRGB; - else if( in->Bands < 3 ) - interpretation = VIPS_INTERPRETATION_B_W; - else - interpretation = VIPS_INTERPRETATION_sRGB; - g_info( "converting to processing space %s", - vips_enum_nick( VIPS_TYPE_INTERPRETATION, interpretation ) ); - if( vips_colourspace( in, &t[2], interpretation, NULL ) ) - return( -1 ); - in = t[2]; + if( in->Bands < 3 ) + interpretation = VIPS_INTERPRETATION_B_W; + else + interpretation = VIPS_INTERPRETATION_sRGB; + + g_info( "converting to processing space %s", + vips_enum_nick( VIPS_TYPE_INTERPRETATION, + interpretation ) ); + if( vips_colourspace( in, &t[2], interpretation, + NULL ) ) + return( -1 ); + in = t[2]; + } /* Shrink to preshrunk_page_height, so we work for multi-page images. */ @@ -751,23 +775,23 @@ vips_thumbnail_build( VipsObject *object ) vshrink = (double) in->Ysize / target_image_height; } + /* vips_premultiply() makes a float image, so when we unpremultiply + * below we must cast back to the original format. Use NOTSET to + * meran no pre/unmultiply. + */ + unpremultiplied_format = VIPS_FORMAT_NOTSET; + /* If there's an alpha, we have to premultiply before shrinking. See * https://github.com/libvips/libvips/issues/291 */ - have_premultiplied = FALSE; if( vips_image_hasalpha( in ) && hshrink != 1.0 && vshrink != 1.0 ) { g_info( "premultiplying alpha" ); + unpremultiplied_format = in->BandFmt; + if( vips_premultiply( in, &t[3], NULL ) ) return( -1 ); - have_premultiplied = TRUE; - - /* vips_premultiply() makes a float image. When we - * vips_unpremultiply() below, we need to cast back to the - * pre-premultiply format. - */ - unpremultiplied_format = in->BandFmt; in = t[3]; } @@ -777,6 +801,14 @@ vips_thumbnail_build( VipsObject *object ) return( -1 ); in = t[4]; + if( unpremultiplied_format != VIPS_FORMAT_NOTSET ) { + g_info( "unpremultiplying alpha" ); + if( vips_unpremultiply( in, &t[5], NULL ) || + vips_cast( t[5], &t[6], unpremultiplied_format, NULL ) ) + return( -1 ); + in = t[6]; + } + /* Only set page-height if we have more than one page, or this could * accidentally turn into an animated image later. */ @@ -792,21 +824,12 @@ vips_thumbnail_build( VipsObject *object ) VIPS_META_PAGE_HEIGHT, output_page_height ); } - if( have_premultiplied ) { - g_info( "unpremultiplying alpha" ); - if( vips_unpremultiply( in, &t[5], NULL ) || - vips_cast( t[5], &t[6], unpremultiplied_format, NULL ) ) - return( -1 ); - in = t[6]; - } - /* Colour management. - * - * If we've already imported, just export. Otherwise, we're in - * device space and we need a combined import/export to transform to - * the target space. */ if( have_imported ) { + /* We've already imported, just export. Go to sRGB if there's + * no export profile. + */ if( thumbnail->export_profile || vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) { g_info( "exporting to device space with a profile" ); @@ -825,21 +848,54 @@ vips_thumbnail_build( VipsObject *object ) in = t[7]; } } - else if( thumbnail->export_profile && - (vips_image_get_typeof( in, VIPS_META_ICC_NAME ) || - thumbnail->import_profile) ) { + else if( thumbnail->export_profile ) { + /* Not imported, but we are doing colour management. Transform + * to the output space. + */ g_info( "transforming to %s", thumbnail->export_profile ); - if( thumbnail->import_profile ) - g_info( "fallback input profile %s", - thumbnail->import_profile ); - if( vips_icc_transform( in, &t[7], - thumbnail->export_profile, - "input_profile", thumbnail->import_profile, - "intent", thumbnail->intent, - "embedded", TRUE, - NULL ) ) - return( -1 ); + /* If there's some kind of import profile, we can transform to + * the output. Otherwise we have to convert to PCS and then + * export. + */ + if( thumbnail->import_profile || + (vips_image_get_typeof( in, VIPS_META_ICC_NAME ) || + thumbnail->import_profile) ) { + g_info( "transforming with supplied profiles" ); + if( vips_icc_transform( in, &t[7], + thumbnail->export_profile, + "input_profile", thumbnail->import_profile, + "intent", thumbnail->intent, + "embedded", TRUE, + NULL ) ) + return( -1 ); + + in = t[7]; + } + else { + g_info( "exporting with %s", + thumbnail->export_profile ); + if( vips_colourspace( in, &t[7], + VIPS_INTERPRETATION_XYZ, NULL ) || + vips_icc_export( t[7], &t[10], + "output_profile", + thumbnail->export_profile, + "intent", thumbnail->intent, + NULL ) ) + return( -1 ); + in = t[10]; + } + } + else if( thumbnail->linear ) { + /* Linear mode, no colour management. We went to scRGB for + * processing, so we now revert to the input colourspace. + */ + g_info( "reverting to input space %s", + vips_enum_nick( VIPS_TYPE_INTERPRETATION, + input_interpretation ) ); + if( vips_colourspace( in, &t[7], + input_interpretation, NULL ) ) + return( -1 ); in = t[7]; } @@ -1368,7 +1424,7 @@ vips_thumbnail_buffer_init( VipsThumbnailBuffer *buffer ) * * @intent: #VipsIntent, rendering intent * * @option_string: %gchararray, extra loader options * - * Exacty as vips_thumbnail(), but read from a memory buffer. One extra + * Exactly as vips_thumbnail(), but read from a memory buffer. One extra * optional argument, @option_string, lets you pass options to the underlying * loader. * @@ -1564,7 +1620,7 @@ vips_thumbnail_source_init( VipsThumbnailSource *source ) * * @intent: #VipsIntent, rendering intent * * @option_string: %gchararray, extra loader options * - * Exacty as vips_thumbnail(), but read from a source. One extra + * Exactly as vips_thumbnail(), but read from a source. One extra * optional argument, @option_string, lets you pass options to the underlying * loader. * @@ -1671,7 +1727,7 @@ vips_thumbnail_image_init( VipsThumbnailImage *image ) * * @export_profile: %gchararray, export ICC profile * * @intent: #VipsIntent, rendering intent * - * Exacty as vips_thumbnail(), but read from an existing image. + * Exactly as vips_thumbnail(), but read from an existing image. * * This operation * is not able to exploit shrink-on-load features of image load libraries, so diff --git a/test/test-suite/helpers/helpers.py b/test/test-suite/helpers/helpers.py index c062d436..bac50248 100644 --- a/test/test-suite/helpers/helpers.py +++ b/test/test-suite/helpers/helpers.py @@ -42,6 +42,9 @@ BMP_FILE = os.path.join(IMAGES, "MARBLES.BMP") NIFTI_FILE = os.path.join(IMAGES, "avg152T1_LR_nifti.nii.gz") ICO_FILE = os.path.join(IMAGES, "favicon.ico") AVIF_FILE = os.path.join(IMAGES, "avif-orientation-6.avif") +HEIC_FILE = os.path.join(IMAGES, "heic-orientation-6.heic") +RGBA_FILE = os.path.join(IMAGES, "rgba.png") +RGBA_CORRECT_FILE = os.path.join(IMAGES, "rgba-correct.ppm") MOSAIC_FILES = [os.path.join(IMAGES, "cd1.1.jpg"), os.path.join(IMAGES, "cd1.2.jpg"), os.path.join(IMAGES, "cd2.1.jpg"), os.path.join(IMAGES, "cd2.2.jpg"), os.path.join(IMAGES, "cd3.1.jpg"), os.path.join(IMAGES, "cd3.2.jpg"), diff --git a/test/test-suite/images/rgba-correct.ppm b/test/test-suite/images/rgba-correct.ppm new file mode 100644 index 00000000..b83fdce9 --- /dev/null +++ b/test/test-suite/images/rgba-correct.ppm @@ -0,0 +1,5 @@ +P6 +#vips2ppm - 2021-02-27T15:39:39.437028Z +64 64 +255 +’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’žžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’žžžžžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ééėöö÷’’’’’’’’’’’’’’’žžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’¶³¼¾»ĀÉĒĶŻÜąźźģųųł’’’’’’’’’’’’žžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’³®µ¶²¹»“½Į»Ć¾¹æĄ»ĆĶĖŃįįäńņóżżż’’’’’’’’’žžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’Ŗ¦«¬§­°«²“­³ŗ²¹°§Æŗ“»³°·»¹ĀĖŹŃŽŽāņóō’’’’’’’’’žžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’­ŖÆ­©Æؤ©­©®²­“±Ŗ±°«±“®“±¬²µ²ŗø¶¾¹¹ĀŠŠ×čéģüüż’’’’’’žžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’Æ©ÆŖ„Ŗ££­Ø­±®²­Ø®§¢Ø²­²ÆŖÆŖ¤Ŗ°«±¬¦®°­²»¹ĀĖĒŃāāēūūü’’’’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’®§­­§­Ŗ„Ŗ«§­ÆŖ²¦Ÿ„«¦­“°¶“Æ“°Ŗ°³­“ÆØ®¢œ ¬¤Ŗ·±¹ŗ¶ĄĒÅĶäåčżżż’’’žžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’“®³§¢§Ŗ¦¬®Ŗ°§Ÿ¦©¢Ø©£©«§­«¦­Ŗ£«ÆØ°­§¬”›ŸŖ£Ŗ“­“²«±µ±¶¶³¹ÅĀĖééģ’’’’’’žžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’Ŗ¤Ø„Ÿ„©£«¦”§„ž¤®Ø®®ŖÆ£ž£ž—Ŗ„«Ŗ„«ž—¢›”„Ÿ„©¢Ŗ®¦­¤¢©¢§²«²²°øČŹŠńńó’’’’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’³­²°ŖƧ¢©š•›„ ¦±¬²¦”§§”§££­Ŗ®²®“­ŖÆŖ¦ŖŖ„Ŗ¦”§©£Ø¦Ÿ„ž™Ÿ­©­­§¬µ°¹µ³½ÕŌŁüüü’’’žžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’«¦«®§¬„ §©£Ŗ¤Ÿ¤™Ÿ¤Ÿ¦Ŗ„Ŗ¤£££©¤Ŗ¬ŖƧ¤Ŗ£ž£©„Ŗ§”§Ŗ£ŖŖ„«§£Ŗ¬§­“¬±­¦«²­“¾¼Äźźģ’’’’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’§”§ÆØ­Ŗ„«§”§Ÿ›Ÿ¢ž£¦¢§žšž£ž£Ŗ¤©§£Ŗœ˜ž¢£”™ „Ÿ¤£ž¤£ž¤¦”§Ø£©Ø£§²«Æ®Ø«”œ ©£Ŗ·³»ÕŌŁśśū’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’§Ÿ§²­²§”§¦”¦ž›Ÿ¢ž£žšžš”šŖ¤Ŗ©£Ø©„«§¢§Ÿ—žØ¢Ø££¦Ÿ¦­Ø°°Ŗ±°Ø®Ÿšžž™””¦£Ŗž›Ÿ§ ¦®©Æŗ¹Įķķļ’’’’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’£œ£„Ÿ¤”› Ø£Ø›•›£Ÿ¤£Ÿ¤š”šØ¢§§”¦ ›¢„”§¤Ÿ„ؤŖ„ ¦Ø Ø¬¤­²­“©£Ø›–›”œ¢”¢”Ÿ„§£Ø£”أثحŖ©°ŪŪą’’’’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’¦ „¢”¢ž£„ž£ŸšŸ¢Ÿ¤­ŖƦŸ£¦ž£®Ø­£ž„ž˜ŸŖ¤Ŗ£ž£©£©›•œ™’˜œš­Ø­ž™«§¬Æ«Æ˜”›£Ÿ„§”¦ž˜”œ ”œŸ¬Ø±ĘĘĪųłś’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’¬¦¬Ÿ›ŸŸ›Ÿ”› „Ÿ„Ÿ› ¬Ø®­¦­«£ØÆØ® ›”£Ÿ¤ÆŖ®Ÿ™œŸ› Ÿ™Ÿš“š›„ ¤Ø£§©£Ø§”§“Ž•¢ž¤§£Ø££¤ž£œ–œ ™ž£ Ø±±¹ģģļ’’’’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’˜§£§§£§–œ˜£Ÿ¤Ø£©¢›”§”§££Ø£©ž™Ÿ¤ž¤¤ž£—›£ž£—™”š££—”–š’— ™Ÿ™Ÿ£ ¦Ŗ¦«¬§¬˜›•šžšž œŸ¢£Ŗ§±āįę’’’’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’”¢¤ ¦„ §”•›•›—œ¤”¤Ÿ›žž˜¢œ”–”˜š”›˜’™ž™Ÿž™ŸšŸŸ› ’Œ’˜”™š•›œ•œ£Ÿ„š–›ž™Ÿ”› ””—“˜ œ”—”˜ŸšŸš”š°¬¶ŻŻć’’’’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’§£§ ›¢—’œž˜Ÿ™”™¤Ÿ£Ŗ¦©£ž”¦Ÿ„££™”š„Ÿ„˜ž‹’›”œ ˜Ÿœ•œŸ™Ÿ£ž¤Ŗ¦¬Ÿ› ”Ž”££Ÿš ˜“˜£›¢˜“˜ ›”˜’š™Ÿ›•›—›”šÆ«¶ŽŻä’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’£Ÿ„¦Ÿ§žšŸ˜“™™“™”œ”§”¦›”š–•ž™ŸŸ›Ÿ«§¬˜•™ž™Ÿ—‘—£›£Ÿš ›ŸŸ›¢§£«™Ÿ—’—™Ÿ„ §›—œ”Ž”›—œ‘‘Ž“£Ÿ„¢£ž–™“˜†Œ­Ø“ąąå’’’żżž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’¤ž„£ž£¦ ¤˜“›˜‘™“”‹›—’“„”§Ø„Ŗž› ”Ž”˜“™ŸšŸ˜’–ž™ž™Ÿ‘Œ‰„ˆ°ŖÆ„ž£——“˜Ÿšž””ŒˆŒ‘Œ›—›–œ”Œ“–Ž”•”Ž‰Ž§„Æźźķ’’’żżż’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’›–œ£ž£—’›œ—Ÿ££š•œ›˜Ÿ™”›—“™•––‘˜Ÿ™”–‘˜Œ’ž™–›„Ÿ£˜“™—›”Ž’™’— šŸœ•›””•“Ÿ›Ÿ“”Ÿ› ™•›Ÿš “Ž”š’˜œ–›™”™”œ ‰‘Ø©±ņóõ’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’”’Œ”š”œŒ”›—ž¦”§¢£–‘˜’Œ“Ÿ™ ž–žŖ”Ŗ’Ž”•”˜œ™ž œ ›–›™žš•›œ—˜’˜˜œ”™Ÿ•–‰…ŠŠ…‹™Ÿ˜”›“”—”™Ÿ› ˜”˜‡„ˆŸ› ›•›“Š‘“—²²½śśū’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ ›Ÿ™‘”£›”ŽˆŽ˜“›žš”‘‰Ž£›Ÿ©£Ŗ˜‘™£œ¢œ˜œ‘Œ“—“™Š†ŒŽ‰„ ¦™”š‘’‹…‹“Š‘˜”˜’‹‘’‹“‰’~xŒ‡‰„‹‹†Œ“Œ’“Ž“š•šŠ…‰›•œ••”Œ““”–•ÅÄĖ’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’Ŗ¤© ›ž›”—Ž‰œ—Ÿ”–ž–œ£¢”Ž“”•–‘˜—”š™”›’”“Ž”“Ž•ž™ŸŖ£Ŗ”›¢–˜‘–•”–‘•›–ž”€|‚„†–’˜“”•”Œ‘Œ‡Œ•‘•‡ŽŽˆ“Œ““Œ’‹’š˜ ŪŪß’’’żżž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’œ–•‘–‹†Š”•„”Ø¢£—’–z€Š‘ ›¢–”™–“™Ÿ›£”–”™Œ‰žš š•›”¢Ÿ˜ž™”™‰…ŠŽ‰ŽŽ‰Ž‰Š…Œ’Œ“Š‘ŽŠ‘Œ‘…€†’“‰‰‘Œ†ƒ}ƒŒ†Œ‡„ˆ¢ Ŗķķļ’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’••‘–ˆ‡ƒ‰‹‘“–•—Š†Œš•œ”•’•”’—~ƒ”“—ŽŠ‘†…‰“‘–Š‡•’–›•›‹†‹—’˜‘‹“˜“›‰…‹““Š†ŒŽ‰ŠŒ”Œ’‘’‡ƒ‰„†’Œ”‰„ŠŠ„‹‘‹‘‹„Šˆƒ‹°®øūūü’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’Ž‰‘Š‘•’—‰…Š’–”––‘—‹‡Ž‰™•›Š†ŒˆŽ‘‰’”Œ“™–—‘–’”™”›“‘–‹‡€}ƒ…Š‘”‘šŠ‘š”™””…†’“”–ˆ„ŠŠ…‹Š†‹„†”–“Ž”‹‘†‹ƒ‰~‚•’œĘĘĶ’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’—˜Žˆ”•‘‹š—œš–œ„ƒ–—”Ž”›—Œ†Œ‹‘ž—ž”˜ž–Œ“œ”œœ–ž‹…‹‘‹’˜‘—”“‡‚‡ˆŽ””™•›€{‚‹‡Ž‰†Œ‹†Œ‹‘xsw‰…Šœ˜žŒ†”–ˆ„…Ž‡Œ…Œ‡‚†Š…Š—˜¢įāå’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’œ–ž“Ž“š”˜’‹•‘”˜“˜“Šœ”›š”›™”œ›—Ÿ”—”‘—Š‡€ˆš’šŸ˜Ÿ–•”Œ“˜‘—˜’——’•„€†˜”™‹†Œxrzyt}ŒˆŽ‡‚ˆ‘Œ‘…€†ƒ€ƒ’ŒˆŽ‰‡„‚ˆ{z€€z€‡‚††€„‡ƒ‹««³÷÷ł’’’žžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’ˆ„ŠŽ‰Žš”š‡ŒŠ¢œ”›“—‡~ƒ‡…‚ˆŒŠ‘Ž‹‘ˆ„‰‘Œ“‰Ž‡”Œ”›”œ‰„Š†‚‰“”Ž‹…‚ˆ‘‰—‘—ˆƒŠˆƒ‹‚~ƒ…€…ŽˆŽŠ‘„ƒ‚~‚}ƒwt{~„€~„}‚…†ƒ~ƒ‹…Œz‰“ĘÅĪ’’’žžžžžžžžžžžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’”Ž”–ž¢œ¤‡‚ˆ‹‡›–›““€x~”“’Ž”‘•‘”’Œ“‘Š‰„‰€z€Œ†Ž‡Ž‡Ž‹“„…Œ‰…‡’‰‘”Ž”ŠƒŠ™“˜ˆŽ‰„Š‰ŽŠ‹ƒ„~z€‚~„zv}ƒ€‡‘•‹ˆ‚}„„€‡{‚„…£ «āćč’’’’’’’’’’’’’’’’’’’’’’’’žžžžžž’’’’’’’’’’’’’’’’’’’’’’’’’’’ŽŠ‘“—•’™ŽŠ‰‡‹‡˜“™‡‚ˆ‰„‰Š…‹–”˜‘“Œ‡Œ‰ƒˆŒ‡‹›˜ŒˆŒŽ†˜“™{x{{~…‚‰‰…‹–‘•…€‡…€ˆ‘‹‘–‘–‹’‚ƒ~yŠ†Œ€|‚€z}xzv~†ƒŠ‡„‹„‡|ƒ…€‡}y{€‰„Œ©§±ģģńõõųšļņššņóóōüüü’’’’’’’’’’’’’’’žžžžžž’’’’’’’’’’’’’’’’’’{zƒ„€ˆŠˆ‹“‹ŠŽŒ“Œ†Ž‡‚ˆ‹‰…ƒ‡‚|ŽŠ‰†‹€}ƒŠ…}zƒ””‘Œ“†‡xtx‡ƒˆ‹‡Ž…€‡ˆŽ‹…Œ…†y€ŽˆŽ“”sosxsx‰ƒŠˆ‚‰yu{…€†‚}ƒ‚}ƒ…€‡‹†ŒŠ†Œˆ„‰…€……}‚‡~…ŒƒÅĆĪééóčęļéēīźčīšīóéēķåäéīķņļīšųųų’’’’’’žžžžžž’’’’’’’’’’’’Œ”Š††‚ˆŒ‡–“™Œ‘ˆ†Œyw}‡„‰Š‡ˆ‰z‚‚…‰„‹…‚‰ur{‚~„‹‡‡‚ˆš”š‰…Š}y„†‹‘”˜“Ž–€z~w~‹†Œzwsyƒ~„‰„‹ˆƒ‹„}…‰ƒ‹y€†€‡ˆƒ‰‡ƒˆ††‡€†ˆ‡ŒƒŠ…Ž œØēęńńļųóš÷õółöōūöōūöóūōńśķźóćąéźčķõõö’’’’’’žžž’’’’’’’’’•’—‰†Œˆ…ŠŒ†ˆ‡˜’—~‚{z~Š‰ˆ‚‰ˆ„ŠŒ‰““ˆˆ‰|ƒƒ…‘’”Ž”•”…}„}w’ŽŠ‘€|ƒ‚…‚}ƒ‹…‹†ˆƒŠ{v|{v}€{‚‡‰‡‰Š…Œ}w~„~…vov‚z€‰‚ˆz•–™”§ ÆąŻźģźņōń÷óš÷šīöńīöńīöīģõģéóšģöōńłįŽēįąå÷÷÷’’’žžžžžž’’’|Œ‡Ž’Ž”€|ƒ‚~…’”Š…‰‰†‰‹…ŒŒˆŽ‚ƒuty†„Š’Š‡|…‡~ˆ‹…€z‚††xrv‹…‹Ž†‚~…ƒ†‹†Ž€y€Œ†Œx~††‡ƒˆƒ}ƒzv|xty|v}ˆ‚‰ƒ~„”•…„rlrysxƒ}‚x€…}†•š¹“æßŪęīģõšķõņńųńīöņļ÷ņš÷ļģōģéņģéņėčńźęļęįėćßźŻŪćīīš’’’’’’žžž‘Ž“xsy‰Žƒ„|z~Š†‚}ƒ…€ˆˆ‚|x‚‚„€~„ˆ†Œ…‹‘‰€}‚‚}„Š„‹†‚}€‰„‰’•‡‚‡ˆ„‰Ž‰‘mfn|v|ˆ‚ˆ‰„Šzw{~x~}y~ƒ}‚~w~{uzw}Š„Š„~„„}‚~x~tms…~…ššĖÄŠėčńöōśóńųņļ÷ņš÷ńīöšīöńīöīģōģčńīėóéęīęćģćŻčęāėčęļŚŲćāįå’’’’’’‰…‹Œ’Ž‹Ž”’}w|ƒ~„ws|y‚Šƒ‹‹…‡ƒ‰|‚‚…‚„tnsqps~zˆ‰‚‰|w|wqwƒ†~x}}vzw}}uz|wzx„~„ƒ„zv||w}}x}z†‡umstnu~xy€y‚——¹°»ŲÓŻńīųõóśõņųņļ÷ņļ÷ōņłņļ÷īėōļķõļķõģéóčåļēćķāŻčāŻēēćķāŽčÓĻŚÕŃÜŲׯśūś‚~ƒ•‘—y}‡ˆ†‚ˆvrx~ƒ€|€ˆƒ‹€}…xr{zv|‚~ƒ……yvzxu{yv}{v}x~|v}}x€””€yˆ€†Œ‡Œ‰ƒ‡’‹‡ƒ‡xsxvqv|uz}u{wpuwqwqjqmgm™˜»“¾ČĮĶÜÕāģēņöóūöōśōóųōņųóńųšīöšķöńīöļķõļīöķźņęćķéåšģčńąŪęåąėćßźŲÕßĪŹÕÖŃÜÖŃŪŁŲŽƒ‡„€‡…‡‡†ˆ‡Ž‹…Œˆ„Š€|‚„€†ƒ…ˆ}x‰…‰•”|w}yu||x~xsxŽˆŒtpv…†”Ž”†€…ˆˆ‡Ž€y‹„‹‰Ž{wz…~ƒŒ„‹ƒ|nhnqin–‘˜·³»ŅĢÖŲÓßåąėńī÷óšųóńųõółšīöšīöņš÷īģōļėōńīöčäīēćīéēļäąėäßźčäīÜ×湌åŪÕߊŹÕ×ŌŽŪ×āĻČÓĢÉՄ†“•‹†|Š‰…‹~z€|ƒ}…‰„Œ‹Ž€z„€‡‚€†…‚†Š‘y‚…†‚}ƒtqvrpw~y€“Ž’‹…‹|v}‚}„„…vow}ƒ€{umstmux– Ą·ĀŌĪŲ×ÓŽßÜčķźōõōśōółńļöóńųņš÷ļģõļīöļķõļėōėēšéćīēāķźęļźēńćßźāŽéÜŲäŅĖ×ßŪęßŪꊏÕŪ×āŅĪŁ¼¶Į¼¶Ć‡ƒ‰––‡ƒ‰†ƒˆ„~„z€}}wqjs‹‡ˆ„‹|x€€}ƒ}yˆ†‹‚~ƒ}xˆƒŠ‡ˆ}xvsxysxxryyt{wrxyt{rnvyu~qls{s{™’šĖÄĪŪÕąćŻéēćīīėōōņłõóśņļ÷šīöņļ÷óņłńīöļģōńīöķéņēäīėēńčćīģčņ掟Ż×äÜ×ćąÜēŪ×āŚÕąŽŚåŚ×āÉÄŠŹĘŅŗ¶Ā°Ŗø¹“Ā†ƒ‰„€„ƒ‡‚}†~yzv~Œ†z~w|„~„†„‡}„‚}„Œˆ‰„‰‰†‹wrwpkr~x€ˆ‚‰„…xsytmt…~…€zyvyysw‹„Š‚y€ —žČĀŹäŽčåąėčäīóńłöōūóņųōņųóņųńīöńīöļģõšķöńīöķéóķéōķźóēäīéåļéåļßŪēŻŲåŽŚę掟äßźßŪꎌåŠĖÖľŹ¼“ĀĒĮĪÄĄĶĄ¼ĖÉÅŅƒ„}x‡ƒ‹…ˆ|w~y‚†‡Œ…Š’‡’‰ƒ}xuyxqz†ƒˆ‰†‹„‚‰„~„€xxsy‚z‚ƒ}ƒ~xz‚‰ƒ‰‡…‰Œˆ£˜Ÿæ¶¾ŁŅŚåßčéćķńīöóńłöōūōņųņļöóńųńļ÷ļģõńīöļģōšķöļģõķźóķéóėēņźēńźęšßŚęąŪč×ŌßąŻčäßģŻŚåÕŠŪĪÉŌČĆĪĀ¾ŹĄŗÅ·±¾ÄæĢŗ“Į½¹ĒĮ¾Ė˜”šws|Š‡Šˆvrxƒ††‚‰zu}{v}„~„ƒ}ƒ}ƒzw~tqx‡ƒŠ‹ˆŽ|sy~u|‰€ˆ…Žzvmrshn‹‚ˆ“­µŹÄĶŽÖąäßźōńłņšųōšųóš÷ōņųņļöóļ÷ņīöīźņšķõšķõīģōėēóźęńéęļåąėźēńėčńŽŚę掟ŽŚåąÜéåąģąÜ莌ęĶČÕÅĄĪĻŹÖĪÉÕĄ»ÉĀ¾ĖĒĮĪÄĄĢ”œŖŖ§“Ŗ§“{vqow~|‚€{|w~~x~†‡tqx|w~‡‰‚}†qoujinxu|‚‡~y‚wrww‡~†„|ƒˆ~†§ §Ā¼ĀŲŅÜŽŁćźåļļķöņšųōņųōńųńīöńļöņšųšīöķźóšķõļģõīźņģēšéåļēäļėēńėēńčäīęįģÜÖāŚÕįäßģāŻéąŻčŻŁåŃĢŲĶČÖĘĮŠĖĘŌÖŃŻĻŹ×ŹÅŅĶĒŌÄĄĶ¤£²œ›Ŗ¦£²§£°…†ƒ†zƒxqw‚|‚ƒ~„x…}„†€†ytz~x€…€†~y€|x}wrx„€…limƒ}„„~…ÆØÆęąéģźōäßģīźõšīöõóśóńųņš÷šīöóņųšīöšķõńīöģéņīėōėčńģéņģčńćŻčėēńéęļęāķāßźŚÖāŽŲåŚŅŽßŪęāŽź×ŅŻŌĪŁĒĀĪľĖĢĒŌĶŹ×ŠĢŁĖČÓ²­ŗ¹³ĄĆæĖØ¢±œšØœ›«Ŗض©§µ„~ƒ€zrjs~w…€„y}w~ˆ€ˆzƒplq~x}€x~ˆ…‹onsrlq~v|—Š”ČĮĖÖŅÜčäļķźōņšųīėõņļųōņłóń÷ńļöšīöńīöņš÷ņļųėčńėēńīģōźēšćßźėēšéåīßŪåęäīäāģßŪęŻŪęßÜēäąģąÜčŪÖćÓĪŪČĀĶĻŹÕŹÄŃŠĖŁŌŃŽČĒÓŹČÕ»¶Ä”›Ŗø“Ā«©µ‘Œ›„”ÆŖ¦“Ŗ§“››Ŗ}u}‹„Š†€…~x…‡wsw„…x€‡€‡„€…}v|{s{ysy†Žø±¹ĪČŃ׊ÜāŻźŻ×åīėõóńųöōśõółńļöņļųōóśńļöīźóņš÷īģõėēńļīõėéņģčóīėóęāķčåļįŻéŽŚåčęļŻŚåŁÕąÜ×äßŪēŁ×įĪŹÕŹĀŠÅĄĪÅĮĻŠĢŲĻĖ×ĪŹ×½¼ĒŖ©¶¦„³§¤²­Ø·²®½£Ÿ­ž›Ŗ§¢°ÆŖø”œ«›˜Ø„‡ŽˆŽ€y~umu†€ˆoin}w}~xuqwjekŽ†š”™Į¹Ąęąéķčńņīųźčóņšųōņśóńųōółōņłšīöļģõóńłńļ÷ļķõļķöļķöļīöźęńźęšäąźäßėąÜēŻŲäÜŚęŌĻÜŁŌßŌĻŚĪĒÓÖŠÜŅĢŲŹÄŃÄæĖČĀĻĪČÕČÄŃĒĆŃĖČÕ¹µĀ­§µ¢ž­£ŸÆ”­›©¦£±¢ž­˜•¦£ °£ Æ››©—•£œŖŒ†‰„Šuns|t|}urjsgbj~y~•—Æ«²ŚÕŽęāėóļų÷öżņšųõņłõółōółōņųńļöšīöņšųļģõńļ÷ņšųšīöėčóėéóģźōāŽźäąģŪŲåŽŪęęāķęāģäąźćąģÕŅŽŽÜēÕŅŻŃĢ×ÖŅŽÖŅŽŃĶŚĢČÖĪĖŁĖČÕČĘŅÄĀĻ»¹Ē­Ø¶Ŗ¤µŖ§¶­Ŗŗ°­¾²Æ½¦£±–”¤›«¤ °–”””“ ”“ŸŖ‚}…ˆ„‰yvxxuyqls~w|§£ØŹÅĢćŽčćßģģéóöóūńī÷ōółōółņš÷ļīöņšųōņłļīöļīöóńųīģõķėōķėōčäļźčņäįģėčņęāķęćīźēņęćķćßėŚÕßŌĪŚĪĒŌĶČŌŌŃÜŹÅÓŠĖ×ŌŃŻŹĒŅĶŹÕĒĆŠĒĀŠ½¹ĘÆ­¹Ø¤²”ž­Ŗ¦“ø³Ć±®¾Æ­½©§¶Ø¦³ ž­”“”Ÿœ¬ ž­˜•£–”¢˜–£š›§†‰pjp{u|‘Š·±øŁŌÜčäīéåļšī÷ģéņņš÷õōśņńųņńųóńłšīöńļöńī÷ļķöšī÷ėéóļīöķėōźēńīģöėźóģźóéēńęāķęāīßŪčćąėßŪēĶČÕĻŹ×ĻÉÖĪČÕÖŅŻŲŌßĘĄĢĆ½ŹĄ½É³°½µ²æ®§³Ŗ£±ŸœŖ¤”ƤŸ®¤”°©§“¬Øø”ÆŸœ­”“”™˜¦””£š™§¢ Æœš©›š§ Ÿ­›Ŗ£¤² \ No newline at end of file diff --git a/test/test-suite/images/rgba.png b/test/test-suite/images/rgba.png new file mode 100644 index 00000000..50fd86f2 Binary files /dev/null and b/test/test-suite/images/rgba.png differ diff --git a/test/test-suite/test_resample.py b/test/test-suite/test_resample.py index 1756b581..a840718f 100644 --- a/test/test-suite/test_resample.py +++ b/test/test-suite/test_resample.py @@ -2,7 +2,8 @@ import pytest import pyvips -from helpers import JPEG_FILE, OME_FILE, AVIF_FILE, TIF_FILE, all_formats, have +from helpers import JPEG_FILE, OME_FILE, HEIC_FILE, TIF_FILE, all_formats, \ + have, RGBA_FILE, RGBA_CORRECT_FILE, AVIF_FILE # Run a function expecting a complex image on a two-band image @@ -193,6 +194,11 @@ class TestResample: im2 = pyvips.Image.thumbnail_buffer(buf, 100) assert abs(im1.avg() - im2.avg()) < 1 + # linear shrink should work on rgba images + im1 = pyvips.Image.thumbnail(RGBA_FILE, 64, linear=True) + im2 = pyvips.Image.new_from_file(RGBA_CORRECT_FILE) + assert abs(im1.flatten(background=255).avg() - im2.avg()) < 1 + if have("heifload"): # this image is orientation 6 ... thumbnail should flip it im = pyvips.Image.new_from_file(AVIF_FILE) diff --git a/tools/vips.c b/tools/vips.c index 38f0e787..35552352 100644 --- a/tools/vips.c +++ b/tools/vips.c @@ -101,9 +101,9 @@ #include #endif -#ifdef OS_WIN32 +#ifdef G_OS_WIN32 #define strcasecmp(a,b) _stricmp(a,b) -#endif +#endif /*G_OS_WIN32*/ static char *main_option_plugin = NULL; static gboolean main_option_version; @@ -458,11 +458,11 @@ parse_options( GOptionContext *context, int *argc, char **argv ) "OPER", _( "execute vips operation OPER" ) ); g_option_context_set_summary( context, vips_buf_all( &buf ) ); -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 if( !g_option_context_parse_strv( context, &argv, &error ) ) -#else /*!HAVE_G_WIN32_GET_COMMAND_LINE*/ +#else /*!G_OS_WIN32*/ if( !g_option_context_parse( context, argc, &argv, &error ) ) -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ { if( error ) { fprintf( stderr, "%s\n", error->message ); @@ -531,9 +531,9 @@ main( int argc, char **argv ) /* On Windows, argv is ascii-only .. use this to get a utf-8 version of * the args. */ -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 argv = g_win32_get_command_line(); -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ #ifdef DEBUG_FATAL /* Set masks for debugging ... stop on any problem. @@ -582,11 +582,11 @@ main( int argc, char **argv ) */ g_option_context_set_help_enabled( context, FALSE ); -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 if( !g_option_context_parse_strv( context, &argv, &error ) ) -#else /*!HAVE_G_WIN32_GET_COMMAND_LINE*/ +#else /*!G_OS_WIN32*/ if( !g_option_context_parse( context, &argc, &argv, &error ) ) -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ { if( error ) { fprintf( stderr, "%s\n", error->message ); @@ -753,9 +753,9 @@ main( int argc, char **argv ) g_option_context_free( context ); -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 g_strfreev( argv ); -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ vips_shutdown(); diff --git a/tools/vipsedit.c b/tools/vipsedit.c index 93c07a0c..218e8dd7 100644 --- a/tools/vipsedit.c +++ b/tools/vipsedit.c @@ -141,9 +141,9 @@ main( int argc, char **argv ) /* On Windows, argv is ascii-only .. use this to get a utf-8 version of * the args. */ -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 argv = g_win32_get_command_line(); -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ context = g_option_context_new( _( "vipsedit - edit vips file header" ) ); @@ -153,11 +153,11 @@ main( int argc, char **argv ) g_option_group_set_translation_domain( main_group, GETTEXT_PACKAGE ); g_option_context_set_main_group( context, main_group ); -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 if( !g_option_context_parse_strv( context, &argv, &error ) ) -#else /*!HAVE_G_WIN32_GET_COMMAND_LINE*/ +#else /*!G_OS_WIN32*/ if( !g_option_context_parse( context, &argc, &argv, &error ) ) -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ { vips_g_error( &error ); @@ -272,9 +272,9 @@ main( int argc, char **argv ) g_option_context_free( context ); -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 g_strfreev( argv ); -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ vips_shutdown(); diff --git a/tools/vipsheader.c b/tools/vipsheader.c index a984079a..e634ccef 100644 --- a/tools/vipsheader.c +++ b/tools/vipsheader.c @@ -180,9 +180,9 @@ main( int argc, char *argv[] ) /* On Windows, argv is ascii-only .. use this to get a utf-8 version of * the args. */ -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 argv = g_win32_get_command_line(); -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ context = g_option_context_new( _( "- print image header" ) ); main_group = g_option_group_new( NULL, NULL, NULL, NULL, NULL ); @@ -191,11 +191,11 @@ main( int argc, char *argv[] ) g_option_group_set_translation_domain( main_group, GETTEXT_PACKAGE ); g_option_context_set_main_group( context, main_group ); -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 if( !g_option_context_parse_strv( context, &argv, &error ) ) -#else /*!HAVE_G_WIN32_GET_COMMAND_LINE*/ +#else /*!G_OS_WIN32*/ if( !g_option_context_parse( context, &argc, &argv, &error ) ) -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ { if( error ) { fprintf( stderr, "%s\n", error->message ); @@ -247,9 +247,9 @@ main( int argc, char *argv[] ) /* We don't free this on error exit, sadly. */ -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 g_strfreev( argv ); -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ vips_shutdown(); diff --git a/tools/vipsthumbnail.c b/tools/vipsthumbnail.c index e7cc223d..ef23fc5a 100644 --- a/tools/vipsthumbnail.c +++ b/tools/vipsthumbnail.c @@ -500,9 +500,9 @@ main( int argc, char **argv ) /* On Windows, argv is ascii-only .. use this to get a utf-8 version of * the args. */ -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 argv = g_win32_get_command_line(); -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ context = g_option_context_new( _( "- thumbnail generator" ) ); @@ -512,11 +512,11 @@ main( int argc, char **argv ) g_option_group_set_translation_domain( main_group, GETTEXT_PACKAGE ); g_option_context_set_main_group( context, main_group ); -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 if( !g_option_context_parse_strv( context, &argv, &error ) ) -#else /*!HAVE_G_WIN32_GET_COMMAND_LINE*/ +#else /*!G_OS_WIN32*/ if( !g_option_context_parse( context, &argc, &argv, &error ) ) -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ { if( error ) { fprintf( stderr, "%s\n", error->message ); @@ -563,9 +563,9 @@ main( int argc, char **argv ) /* We don't free this on error exit, sadly. */ -#ifdef HAVE_G_WIN32_GET_COMMAND_LINE +#ifdef G_OS_WIN32 g_strfreev( argv ); -#endif /*HAVE_G_WIN32_GET_COMMAND_LINE*/ +#endif /*G_OS_WIN32*/ vips_shutdown();