Merge branch 'zstd'
This commit is contained in:
commit
442fa64e41
@ -1,6 +1,6 @@
|
||||
image: ubuntu:16.04
|
||||
before_script:
|
||||
- apt-get update -qq && apt-get install -y -qq autoconf automake build-essential cmake libtool libjpeg8-dev libjbig-dev liblzma-dev ninja-build zlib1g-dev zip
|
||||
- apt-get update -qq && apt-get install -y -qq autoconf automake build-essential cmake libtool libjpeg8-dev libjbig-dev liblzma-dev ninja-build zlib1g-dev zip wget
|
||||
|
||||
stages:
|
||||
- build
|
||||
|
@ -522,6 +522,27 @@ if(LIBLZMA_FOUND)
|
||||
set(LZMA_SUPPORT 1)
|
||||
endif()
|
||||
|
||||
# libzstd
|
||||
option(zstd "use libzstd (required for ZSTD compression)" ON)
|
||||
if (zstd)
|
||||
find_path(ZSTD_INCLUDE_DIR zstd.h)
|
||||
find_library(ZSTD_LIBRARY NAMES zstd)
|
||||
if (ZSTD_INCLUDE_DIR AND ZSTD_LIBRARY)
|
||||
check_library_exists ("${ZSTD_LIBRARY}" ZSTD_decompressStream "" ZSTD_RECENT_ENOUGH)
|
||||
if (ZSTD_RECENT_ENOUGH)
|
||||
set(ZSTD_FOUND TRUE)
|
||||
set(ZSTD_LIBRARIES ${ZSTD_LIBRARY})
|
||||
message(STATUS "Found ZSTD library: ${ZSTD_LIBRARY}")
|
||||
else ()
|
||||
message(WARNING "Found ZSTD library, but not recent enough. Use zstd >= 1.0")
|
||||
endif ()
|
||||
endif ()
|
||||
endif()
|
||||
set(ZSTD_SUPPORT 0)
|
||||
if(ZSTD_FOUND)
|
||||
set(ZSTD_SUPPORT 1)
|
||||
endif()
|
||||
|
||||
# 8/12-bit jpeg mode
|
||||
option(jpeg12 "enable libjpeg 8/12-bit dual mode (requires separate
|
||||
12-bit libjpeg build)" ON)
|
||||
@ -632,6 +653,9 @@ endif()
|
||||
if(LIBLZMA_INCLUDE_DIRS)
|
||||
list(APPEND TIFF_INCLUDES ${LIBLZMA_INCLUDE_DIRS})
|
||||
endif()
|
||||
if(ZSTD_INCLUDE_DIR)
|
||||
list(APPEND TIFF_INCLUDES ${ZSTD_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
# Libraries required by libtiff
|
||||
set(TIFF_LIBRARY_DEPS)
|
||||
@ -653,6 +677,9 @@ endif()
|
||||
if(LIBLZMA_LIBRARIES)
|
||||
list(APPEND TIFF_LIBRARY_DEPS ${LIBLZMA_LIBRARIES})
|
||||
endif()
|
||||
if(ZSTD_LIBRARIES)
|
||||
list(APPEND TIFF_LIBRARY_DEPS ${ZSTD_LIBRARIES})
|
||||
endif()
|
||||
|
||||
#report_values(TIFF_INCLUDES TIFF_LIBRARY_DEPS)
|
||||
|
||||
@ -696,6 +723,7 @@ message(STATUS " Old JPEG support: ${old-jpeg} (requested) ${
|
||||
message(STATUS " JPEG 8/12 bit dual mode: ${jpeg12} (requested) ${JPEG12_FOUND} (availability)")
|
||||
message(STATUS " ISO JBIG support: ${jbig} (requested) ${JBIG_FOUND} (availability)")
|
||||
message(STATUS " LZMA2 support: ${lzma} (requested) ${LIBLZMA_FOUND} (availability)")
|
||||
message(STATUS " ZSTD support: ${zstd} (requested) ${ZSTD_FOUND} (availability)")
|
||||
message(STATUS "")
|
||||
message(STATUS " C++ support: ${cxx} (requested) ${CXX_SUPPORT} (availability)")
|
||||
message(STATUS "")
|
||||
|
@ -13,7 +13,7 @@ autoconf_build()
|
||||
mkdir autoconf-build
|
||||
cd autoconf-build
|
||||
echo "Running ../configure --prefix=$(pwd)/../autoconf-install) ${opts}"
|
||||
../configure --prefix=$(pwd)/../autoconf-install ${opts}
|
||||
../configure --prefix=$(pwd)/../autoconf-install --with-zstd-include-dir=/tmp/include --with-zstd-lib-dir=/tmp/lib ${opts}
|
||||
make
|
||||
make install
|
||||
make check
|
||||
@ -29,8 +29,8 @@ cmake_build()
|
||||
fi
|
||||
mkdir cmake-build
|
||||
cd cmake-build
|
||||
echo "Running cmake -G "$1" -DCMAKE_BUILD_TYPE="$2" -DCMAKE_INSTALL_PREFIX=../autoconf-install ${opts} .."
|
||||
cmake -G "$1" -DCMAKE_BUILD_TYPE="$2" -DCMAKE_INSTALL_PREFIX=../autoconf-install ${opts} ..
|
||||
echo "Running cmake -G "$1" -DCMAKE_BUILD_TYPE="$2" -DCMAKE_INSTALL_PREFIX=../autoconf-install -DZSTD_INCLUDE_DIR=/tmp/include -DZSTD_LIBRARY=/tmp/lib/libzstd.so ${opts} .."
|
||||
cmake -G "$1" -DCMAKE_BUILD_TYPE="$2" -DCMAKE_INSTALL_PREFIX=../autoconf-install -DZSTD_INCLUDE_DIR=/tmp/include -DZSTD_LIBRARY=/tmp/lib/libzstd.so ${opts} ..
|
||||
cmake --build .
|
||||
cmake --build . --target install
|
||||
ctest -V
|
||||
@ -39,6 +39,17 @@ cmake_build()
|
||||
build=$1
|
||||
shift
|
||||
|
||||
# Build zstd
|
||||
wget https://github.com/facebook/zstd/archive/v1.3.3.tar.gz
|
||||
tar xvzf v1.3.3.tar.gz
|
||||
cd zstd-1.3.3/lib
|
||||
# Faster build
|
||||
make -j3 PREFIX=/tmp ZSTD_LEGACY_SUPPORT=0 CFLAGS=-O1
|
||||
make install PREFIX=/tmp ZSTD_LEGACY_SUPPORT=0 CFLAGS=-O1
|
||||
cd ../..
|
||||
rm -rf zstd-1.3.3
|
||||
export LD_LIBRARY_PATH=/tmp/lib
|
||||
|
||||
case $build in
|
||||
autoconf)
|
||||
echo "Testing Autoconf build"
|
||||
|
55
configure.ac
55
configure.ac
@ -811,6 +811,60 @@ fi
|
||||
|
||||
AM_CONDITIONAL(HAVE_LZMA, test "$HAVE_LZMA" = 'yes')
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Check for libzstd.
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
HAVE_ZSTD=no
|
||||
|
||||
AC_ARG_ENABLE(zstd,
|
||||
AS_HELP_STRING([--disable-zstd],
|
||||
[disable libzstd usage (required for zstd compression, enabled by default)]),,)
|
||||
AC_ARG_WITH(zstd-include-dir,
|
||||
AS_HELP_STRING([--with-zstd-include-dir=DIR],
|
||||
[location of libzstd headers]),,)
|
||||
AC_ARG_WITH(zstd-lib-dir,
|
||||
AS_HELP_STRING([--with-zstd-lib-dir=DIR],
|
||||
[location of libzstd library binary]),,)
|
||||
|
||||
if test "x$enable_zstd" != "xno" ; then
|
||||
|
||||
if test "x$with_zstd_lib_dir" != "x" ; then
|
||||
LDFLAGS="-L$with_zstd_lib_dir $LDFLAGS"
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB(zstd, ZSTD_decompressStream, [zstd_lib=yes], [zstd_lib=no],)
|
||||
if test "$zstd_lib" = "no" -a "x$with_zstd_lib_dir" != "x"; then
|
||||
AC_MSG_ERROR([zstd library not found at $with_zstd_lib_dir])
|
||||
fi
|
||||
|
||||
if test "x$with_zstd_include_dir" != "x" ; then
|
||||
CPPFLAGS="-I$with_zstd_include_dir $CPPFLAGS"
|
||||
fi
|
||||
AC_CHECK_HEADER(zstd.h, [zstd_h=yes], [zstd_h=no])
|
||||
if test "$zstd_h" = "no" -a "x$with_zstd_include_dir" != "x" ; then
|
||||
AC_MSG_ERROR([Libzstd headers not found at $with_zstd_include_dir])
|
||||
fi
|
||||
|
||||
if test "$zstd_lib" = "yes" -a "$zstd_h" = "yes" ; then
|
||||
HAVE_ZSTD=yes
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if test "$HAVE_ZSTD" = "yes" ; then
|
||||
AC_DEFINE(ZSTD_SUPPORT,1,[Support zstd compression])
|
||||
LIBS="-lzstd $LIBS"
|
||||
tiff_libs_private="-lzstd ${tiff_libs_private}"
|
||||
|
||||
if test "$HAVE_RPATH" = "yes" -a "x$with_zstd_lib_dir" != "x" ; then
|
||||
LIBDIR="-R $with_zstd_lib_dir $LIBDIR"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(HAVE_ZSTD, test "$HAVE_ZSTD" = 'yes')
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Should 8/12 bit jpeg mode be enabled?
|
||||
dnl ---------------------------------------------------------------------------
|
||||
@ -1088,6 +1142,7 @@ LOC_MSG([ Old JPEG support: ${HAVE_OJPEG}])
|
||||
LOC_MSG([ JPEG 8/12 bit dual mode: ${HAVE_JPEG12}])
|
||||
LOC_MSG([ ISO JBIG support: ${HAVE_JBIG}])
|
||||
LOC_MSG([ LZMA2 support: ${HAVE_LZMA}])
|
||||
LOC_MSG([ ZSTD support: ${HAVE_ZSTD}])
|
||||
LOC_MSG()
|
||||
LOC_MSG([ C++ support: ${HAVE_CXX}])
|
||||
LOC_MSG()
|
||||
|
@ -94,7 +94,8 @@ set(tiff_SOURCES
|
||||
tif_version.c
|
||||
tif_warning.c
|
||||
tif_write.c
|
||||
tif_zip.c)
|
||||
tif_zip.c
|
||||
tif_zstd.c)
|
||||
|
||||
set(tiffxx_HEADERS
|
||||
tiffio.hxx)
|
||||
|
@ -99,7 +99,8 @@ libtiff_la_SOURCES = \
|
||||
tif_version.c \
|
||||
tif_warning.c \
|
||||
tif_write.c \
|
||||
tif_zip.c
|
||||
tif_zip.c \
|
||||
tif_zstd.c
|
||||
|
||||
libtiffxx_la_SOURCES = \
|
||||
tif_stream.cxx
|
||||
|
@ -70,6 +70,9 @@ static int NotConfigured(TIFF*, int);
|
||||
#ifndef LZMA_SUPPORT
|
||||
#define TIFFInitLZMA NotConfigured
|
||||
#endif
|
||||
#ifndef ZSTD_SUPPORT
|
||||
#define TIFFInitZSTD NotConfigured
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Compression schemes statically built into the library.
|
||||
@ -97,6 +100,7 @@ TIFFCodec _TIFFBuiltinCODECS[] = {
|
||||
{ "SGILog", COMPRESSION_SGILOG, TIFFInitSGILog },
|
||||
{ "SGILog24", COMPRESSION_SGILOG24, TIFFInitSGILog },
|
||||
{ "LZMA", COMPRESSION_LZMA, TIFFInitLZMA },
|
||||
{ "ZSTD", COMPRESSION_ZSTD, TIFFInitZSTD },
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -104,6 +104,9 @@
|
||||
/* Support LZMA2 compression */
|
||||
#cmakedefine LZMA_SUPPORT 1
|
||||
|
||||
/* Support ZSTD compression */
|
||||
#cmakedefine ZSTD_SUPPORT 1
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "@PACKAGE_NAME@"
|
||||
|
||||
|
@ -320,6 +320,9 @@
|
||||
/* Support Deflate compression */
|
||||
#undef ZIP_SUPPORT
|
||||
|
||||
/* Support zstd compression */
|
||||
#undef ZSTD_SUPPORT
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
|
@ -1052,6 +1052,10 @@ _TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag)
|
||||
if (tag == TIFFTAG_PREDICTOR)
|
||||
return 1;
|
||||
break;
|
||||
case COMPRESSION_ZSTD:
|
||||
if (tag == TIFFTAG_PREDICTOR)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
}
|
||||
return 0;
|
||||
|
442
libtiff/tif_zstd.c
Normal file
442
libtiff/tif_zstd.c
Normal file
@ -0,0 +1,442 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Planet Labs
|
||||
* Author: <even.rouault at spatialys.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "tiffiop.h"
|
||||
#ifdef ZSTD_SUPPORT
|
||||
/*
|
||||
* TIFF Library.
|
||||
*
|
||||
* ZSTD Compression Support
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tif_predict.h"
|
||||
#include "zstd.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* State block for each open TIFF file using ZSTD compression/decompression.
|
||||
*/
|
||||
typedef struct {
|
||||
TIFFPredictorState predict;
|
||||
ZSTD_DStream* dstream;
|
||||
ZSTD_CStream* cstream;
|
||||
int compression_level; /* compression level */
|
||||
ZSTD_outBuffer out_buffer;
|
||||
int state; /* state flags */
|
||||
#define LSTATE_INIT_DECODE 0x01
|
||||
#define LSTATE_INIT_ENCODE 0x02
|
||||
|
||||
TIFFVGetMethod vgetparent; /* super-class method */
|
||||
TIFFVSetMethod vsetparent; /* super-class method */
|
||||
} ZSTDState;
|
||||
|
||||
#define LState(tif) ((ZSTDState*) (tif)->tif_data)
|
||||
#define DecoderState(tif) LState(tif)
|
||||
#define EncoderState(tif) LState(tif)
|
||||
|
||||
static int ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
|
||||
static int ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s);
|
||||
|
||||
static int
|
||||
ZSTDFixupTags(TIFF* tif)
|
||||
{
|
||||
(void) tif;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ZSTDSetupDecode(TIFF* tif)
|
||||
{
|
||||
ZSTDState* sp = DecoderState(tif);
|
||||
|
||||
assert(sp != NULL);
|
||||
|
||||
/* if we were last encoding, terminate this mode */
|
||||
if (sp->state & LSTATE_INIT_ENCODE) {
|
||||
ZSTD_freeCStream(sp->cstream);
|
||||
sp->cstream = NULL;
|
||||
sp->state = 0;
|
||||
}
|
||||
|
||||
sp->state |= LSTATE_INIT_DECODE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup state for decoding a strip.
|
||||
*/
|
||||
static int
|
||||
ZSTDPreDecode(TIFF* tif, uint16 s)
|
||||
{
|
||||
static const char module[] = "ZSTDPreDecode";
|
||||
ZSTDState* sp = DecoderState(tif);
|
||||
size_t zstd_ret;
|
||||
|
||||
(void) s;
|
||||
assert(sp != NULL);
|
||||
|
||||
if( (sp->state & LSTATE_INIT_DECODE) == 0 )
|
||||
tif->tif_setupdecode(tif);
|
||||
|
||||
if( sp->dstream )
|
||||
{
|
||||
ZSTD_freeDStream(sp->dstream);
|
||||
sp->dstream = NULL;
|
||||
}
|
||||
|
||||
sp->dstream = ZSTD_createDStream();
|
||||
if( sp->dstream == NULL ) {
|
||||
TIFFErrorExt(tif->tif_clientdata, module,
|
||||
"Cannot allocate decompression stream");
|
||||
return 0;
|
||||
}
|
||||
zstd_ret = ZSTD_initDStream(sp->dstream);
|
||||
if( ZSTD_isError(zstd_ret) ) {
|
||||
TIFFErrorExt(tif->tif_clientdata, module,
|
||||
"Error in ZSTD_initDStream(): %s",
|
||||
ZSTD_getErrorName(zstd_ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ZSTDDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
|
||||
{
|
||||
static const char module[] = "ZSTDDecode";
|
||||
ZSTDState* sp = DecoderState(tif);
|
||||
ZSTD_inBuffer in_buffer;
|
||||
ZSTD_outBuffer out_buffer;
|
||||
size_t zstd_ret;
|
||||
|
||||
(void) s;
|
||||
assert(sp != NULL);
|
||||
assert(sp->state == LSTATE_INIT_DECODE);
|
||||
|
||||
in_buffer.src = tif->tif_rawcp;
|
||||
in_buffer.size = (size_t) tif->tif_rawcc;
|
||||
in_buffer.pos = 0;
|
||||
|
||||
out_buffer.dst = op;
|
||||
out_buffer.size = (size_t) occ;
|
||||
out_buffer.pos = 0;
|
||||
|
||||
do {
|
||||
zstd_ret = ZSTD_decompressStream(sp->dstream, &out_buffer,
|
||||
&in_buffer);
|
||||
if( ZSTD_isError(zstd_ret) ) {
|
||||
TIFFErrorExt(tif->tif_clientdata, module,
|
||||
"Error in ZSTD_decompressStream(): %s",
|
||||
ZSTD_getErrorName(zstd_ret));
|
||||
return 0;
|
||||
}
|
||||
} while( zstd_ret != 0 &&
|
||||
in_buffer.pos < in_buffer.size &&
|
||||
out_buffer.pos < out_buffer.size );
|
||||
|
||||
if (out_buffer.pos < (size_t)occ) {
|
||||
TIFFErrorExt(tif->tif_clientdata, module,
|
||||
"Not enough data at scanline %lu (short %lu bytes)",
|
||||
(unsigned long) tif->tif_row,
|
||||
(unsigned long) (size_t)occ - out_buffer.pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tif->tif_rawcp += in_buffer.pos;
|
||||
tif->tif_rawcc -= in_buffer.pos;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ZSTDSetupEncode(TIFF* tif)
|
||||
{
|
||||
ZSTDState* sp = EncoderState(tif);
|
||||
|
||||
assert(sp != NULL);
|
||||
if (sp->state & LSTATE_INIT_DECODE) {
|
||||
ZSTD_freeDStream(sp->dstream);
|
||||
sp->dstream = NULL;
|
||||
sp->state = 0;
|
||||
}
|
||||
|
||||
sp->state |= LSTATE_INIT_ENCODE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset encoding state at the start of a strip.
|
||||
*/
|
||||
static int
|
||||
ZSTDPreEncode(TIFF* tif, uint16 s)
|
||||
{
|
||||
static const char module[] = "ZSTDPreEncode";
|
||||
ZSTDState *sp = EncoderState(tif);
|
||||
size_t zstd_ret;
|
||||
|
||||
(void) s;
|
||||
assert(sp != NULL);
|
||||
if( sp->state != LSTATE_INIT_ENCODE )
|
||||
tif->tif_setupencode(tif);
|
||||
|
||||
if (sp->cstream) {
|
||||
ZSTD_freeCStream(sp->cstream);
|
||||
sp->cstream = NULL;
|
||||
}
|
||||
sp->cstream = ZSTD_createCStream();
|
||||
if( sp->cstream == NULL ) {
|
||||
TIFFErrorExt(tif->tif_clientdata, module,
|
||||
"Cannot allocate compression stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
zstd_ret = ZSTD_initCStream(sp->cstream, sp->compression_level);
|
||||
if( ZSTD_isError(zstd_ret) ) {
|
||||
TIFFErrorExt(tif->tif_clientdata, module,
|
||||
"Error in ZSTD_initCStream(): %s",
|
||||
ZSTD_getErrorName(zstd_ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp->out_buffer.dst = tif->tif_rawdata;
|
||||
sp->out_buffer.size = (size_t)tif->tif_rawdatasize;
|
||||
sp->out_buffer.pos = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a chunk of pixels.
|
||||
*/
|
||||
static int
|
||||
ZSTDEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
|
||||
{
|
||||
static const char module[] = "ZSTDEncode";
|
||||
ZSTDState *sp = EncoderState(tif);
|
||||
ZSTD_inBuffer in_buffer;
|
||||
size_t zstd_ret;
|
||||
|
||||
assert(sp != NULL);
|
||||
assert(sp->state == LSTATE_INIT_ENCODE);
|
||||
|
||||
(void) s;
|
||||
|
||||
in_buffer.src = bp;
|
||||
in_buffer.size = (size_t)cc;
|
||||
in_buffer.pos = 0;
|
||||
|
||||
do {
|
||||
zstd_ret = ZSTD_compressStream(sp->cstream, &sp->out_buffer,
|
||||
&in_buffer);
|
||||
if( ZSTD_isError(zstd_ret) ) {
|
||||
TIFFErrorExt(tif->tif_clientdata, module,
|
||||
"Error in ZSTD_compressStream(): %s",
|
||||
ZSTD_getErrorName(zstd_ret));
|
||||
return 0;
|
||||
}
|
||||
if( sp->out_buffer.pos == sp->out_buffer.size ) {
|
||||
tif->tif_rawcc = tif->tif_rawdatasize;
|
||||
TIFFFlushData1(tif);
|
||||
sp->out_buffer.dst = tif->tif_rawcp;
|
||||
sp->out_buffer.size = (size_t) tif->tif_rawcc;
|
||||
sp->out_buffer.pos = 0;
|
||||
}
|
||||
} while( in_buffer.pos < in_buffer.size );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish off an encoded strip by flushing it.
|
||||
*/
|
||||
static int
|
||||
ZSTDPostEncode(TIFF* tif)
|
||||
{
|
||||
static const char module[] = "ZSTDPostEncode";
|
||||
ZSTDState *sp = EncoderState(tif);
|
||||
size_t zstd_ret;
|
||||
|
||||
do {
|
||||
zstd_ret = ZSTD_endStream(sp->cstream, &sp->out_buffer);
|
||||
if( ZSTD_isError(zstd_ret) ) {
|
||||
TIFFErrorExt(tif->tif_clientdata, module,
|
||||
"Error in ZSTD_endStream(): %s",
|
||||
ZSTD_getErrorName(zstd_ret));
|
||||
return 0;
|
||||
}
|
||||
if( sp->out_buffer.pos > 0 ) {
|
||||
tif->tif_rawcc = sp->out_buffer.pos;
|
||||
TIFFFlushData1(tif);
|
||||
sp->out_buffer.dst = tif->tif_rawcp;
|
||||
sp->out_buffer.size = (size_t) tif->tif_rawcc;
|
||||
sp->out_buffer.pos = 0;
|
||||
}
|
||||
} while (zstd_ret != 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ZSTDCleanup(TIFF* tif)
|
||||
{
|
||||
ZSTDState* sp = LState(tif);
|
||||
|
||||
assert(sp != 0);
|
||||
|
||||
(void)TIFFPredictorCleanup(tif);
|
||||
|
||||
tif->tif_tagmethods.vgetfield = sp->vgetparent;
|
||||
tif->tif_tagmethods.vsetfield = sp->vsetparent;
|
||||
|
||||
if (sp->dstream) {
|
||||
ZSTD_freeDStream(sp->dstream);
|
||||
sp->dstream = NULL;
|
||||
}
|
||||
if (sp->cstream) {
|
||||
ZSTD_freeCStream(sp->cstream);
|
||||
sp->cstream = NULL;
|
||||
}
|
||||
_TIFFfree(sp);
|
||||
tif->tif_data = NULL;
|
||||
|
||||
_TIFFSetDefaultCompressionState(tif);
|
||||
}
|
||||
|
||||
static int
|
||||
ZSTDVSetField(TIFF* tif, uint32 tag, va_list ap)
|
||||
{
|
||||
static const char module[] = "ZSTDVSetField";
|
||||
ZSTDState* sp = LState(tif);
|
||||
|
||||
switch (tag) {
|
||||
case TIFFTAG_ZSTD_LEVEL:
|
||||
sp->compression_level = (int) va_arg(ap, int);
|
||||
if( sp->compression_level <= 0 ||
|
||||
sp->compression_level > ZSTD_maxCLevel() )
|
||||
{
|
||||
TIFFWarningExt(tif->tif_clientdata, module,
|
||||
"ZSTD_LEVEL should be between 1 and %d",
|
||||
ZSTD_maxCLevel());
|
||||
}
|
||||
return 1;
|
||||
default:
|
||||
return (*sp->vsetparent)(tif, tag, ap);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
static int
|
||||
ZSTDVGetField(TIFF* tif, uint32 tag, va_list ap)
|
||||
{
|
||||
ZSTDState* sp = LState(tif);
|
||||
|
||||
switch (tag) {
|
||||
case TIFFTAG_ZSTD_LEVEL:
|
||||
*va_arg(ap, int*) = sp->compression_level;
|
||||
break;
|
||||
default:
|
||||
return (*sp->vgetparent)(tif, tag, ap);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const TIFFField ZSTDFields[] = {
|
||||
{ TIFFTAG_ZSTD_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
|
||||
TIFF_SETGET_UNDEFINED,
|
||||
FIELD_PSEUDO, TRUE, FALSE, "ZSTD compression_level", NULL },
|
||||
};
|
||||
|
||||
int
|
||||
TIFFInitZSTD(TIFF* tif, int scheme)
|
||||
{
|
||||
static const char module[] = "TIFFInitZSTD";
|
||||
ZSTDState* sp;
|
||||
|
||||
assert( scheme == COMPRESSION_ZSTD );
|
||||
|
||||
/*
|
||||
* Merge codec-specific tag information.
|
||||
*/
|
||||
if (!_TIFFMergeFields(tif, ZSTDFields, TIFFArrayCount(ZSTDFields))) {
|
||||
TIFFErrorExt(tif->tif_clientdata, module,
|
||||
"Merging ZSTD codec-specific tags failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate state block so tag methods have storage to record values.
|
||||
*/
|
||||
tif->tif_data = (uint8*) _TIFFmalloc(sizeof(ZSTDState));
|
||||
if (tif->tif_data == NULL)
|
||||
goto bad;
|
||||
sp = LState(tif);
|
||||
|
||||
/*
|
||||
* Override parent get/set field methods.
|
||||
*/
|
||||
sp->vgetparent = tif->tif_tagmethods.vgetfield;
|
||||
tif->tif_tagmethods.vgetfield = ZSTDVGetField; /* hook for codec tags */
|
||||
sp->vsetparent = tif->tif_tagmethods.vsetfield;
|
||||
tif->tif_tagmethods.vsetfield = ZSTDVSetField; /* hook for codec tags */
|
||||
|
||||
/* Default values for codec-specific fields */
|
||||
sp->compression_level = 9; /* default comp. level */
|
||||
sp->state = 0;
|
||||
sp->dstream = 0;
|
||||
sp->cstream = 0;
|
||||
sp->out_buffer.dst = NULL;
|
||||
sp->out_buffer.size = 0;
|
||||
sp->out_buffer.pos = 0;
|
||||
|
||||
/*
|
||||
* Install codec methods.
|
||||
*/
|
||||
tif->tif_fixuptags = ZSTDFixupTags;
|
||||
tif->tif_setupdecode = ZSTDSetupDecode;
|
||||
tif->tif_predecode = ZSTDPreDecode;
|
||||
tif->tif_decoderow = ZSTDDecode;
|
||||
tif->tif_decodestrip = ZSTDDecode;
|
||||
tif->tif_decodetile = ZSTDDecode;
|
||||
tif->tif_setupencode = ZSTDSetupEncode;
|
||||
tif->tif_preencode = ZSTDPreEncode;
|
||||
tif->tif_postencode = ZSTDPostEncode;
|
||||
tif->tif_encoderow = ZSTDEncode;
|
||||
tif->tif_encodestrip = ZSTDEncode;
|
||||
tif->tif_encodetile = ZSTDEncode;
|
||||
tif->tif_cleanup = ZSTDCleanup;
|
||||
/*
|
||||
* Setup predictor setup.
|
||||
*/
|
||||
(void) TIFFPredictorInit(tif);
|
||||
return 1;
|
||||
bad:
|
||||
TIFFErrorExt(tif->tif_clientdata, module,
|
||||
"No space for ZSTD state block");
|
||||
return 0;
|
||||
}
|
||||
#endif /* ZSTD_SUPPORT */
|
||||
|
||||
/* vim: set ts=8 sts=8 sw=8 noet: */
|
@ -188,6 +188,7 @@ typedef enum {
|
||||
#define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */
|
||||
#define COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */
|
||||
#define COMPRESSION_LZMA 34925 /* LZMA2 */
|
||||
#define COMPRESSION_ZSTD 34926 /* ZSTD: WARNING not registerd in Adobe-maintained registry */
|
||||
#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */
|
||||
#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */
|
||||
#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */
|
||||
@ -601,6 +602,7 @@ typedef enum {
|
||||
#define TIFFTAG_PERSAMPLE 65563 /* interface for per sample tags */
|
||||
#define PERSAMPLE_MERGED 0 /* present as a single value */
|
||||
#define PERSAMPLE_MULTI 1 /* present as multiple values */
|
||||
#define TIFFTAG_ZSTD_LEVEL 65534 /* ZSTD compression level */
|
||||
|
||||
/*
|
||||
* EXIF tags
|
||||
|
@ -426,6 +426,9 @@ extern int TIFFInitSGILog(TIFF*, int);
|
||||
#ifdef LZMA_SUPPORT
|
||||
extern int TIFFInitLZMA(TIFF*, int);
|
||||
#endif
|
||||
#ifdef ZSTD_SUPPORT
|
||||
extern int TIFFInitZSTD(TIFF*, int);
|
||||
#endif
|
||||
#ifdef VMS
|
||||
extern const TIFFCodec _TIFFBuiltinCODECS[];
|
||||
#else
|
||||
|
@ -389,6 +389,9 @@ processCompressOptions(char* opt)
|
||||
} else if (strneq(opt, "lzma", 4)) {
|
||||
processZIPOptions(opt);
|
||||
defcompression = COMPRESSION_LZMA;
|
||||
} else if (strneq(opt, "zstd", 4)) {
|
||||
processZIPOptions(opt);
|
||||
defcompression = COMPRESSION_ZSTD;
|
||||
} else if (strneq(opt, "jbig", 4)) {
|
||||
defcompression = COMPRESSION_JBIG;
|
||||
} else if (strneq(opt, "sgilog", 6)) {
|
||||
@ -427,6 +430,7 @@ char* stuff[] = {
|
||||
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
|
||||
" -c zip[:opts] compress output with deflate encoding",
|
||||
" -c lzma[:opts] compress output with LZMA2 encoding",
|
||||
" -c zstd[:opts] compress output with ZSTD encoding",
|
||||
" -c jpeg[:opts] compress output with JPEG encoding",
|
||||
" -c jbig compress output with ISO JBIG encoding",
|
||||
" -c packbits compress output with packbits encoding",
|
||||
@ -446,7 +450,7 @@ char* stuff[] = {
|
||||
" r output color image as RGB rather than YCbCr",
|
||||
"For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
|
||||
"",
|
||||
"LZW, Deflate (ZIP) and LZMA2 options:",
|
||||
"LZW, Deflate (ZIP), LZMA2 and ZSTD options:",
|
||||
" # set predictor value",
|
||||
" p# set compression level (preset)",
|
||||
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing,",
|
||||
@ -731,6 +735,7 @@ tiffcp(TIFF* in, TIFF* out)
|
||||
case COMPRESSION_ADOBE_DEFLATE:
|
||||
case COMPRESSION_DEFLATE:
|
||||
case COMPRESSION_LZMA:
|
||||
case COMPRESSION_ZSTD:
|
||||
if (predictor != (uint16)-1)
|
||||
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
|
||||
else
|
||||
@ -741,6 +746,8 @@ tiffcp(TIFF* in, TIFF* out)
|
||||
TIFFSetField(out, TIFFTAG_ZIPQUALITY, preset);
|
||||
else if (compression == COMPRESSION_LZMA)
|
||||
TIFFSetField(out, TIFFTAG_LZMAPRESET, preset);
|
||||
else if (compression == COMPRESSION_ZSTD)
|
||||
TIFFSetField(out, TIFFTAG_ZSTD_LEVEL, preset);
|
||||
}
|
||||
break;
|
||||
case COMPRESSION_CCITTFAX3:
|
||||
|
Loading…
Reference in New Issue
Block a user