Add basic framework for file type based filters during libarchive stage.
Add packJPG filter for Jpeg files (not active yet). Directory format changes for clarity.
This commit is contained in:
parent
a5f1624a33
commit
75dfa6a6fb
22 changed files with 13255 additions and 76 deletions
57
Makefile.in
57
Makefile.in
|
@ -28,11 +28,9 @@ LINKLIB=pcompress
|
||||||
LIBVER=1
|
LIBVER=1
|
||||||
MAINSRCS = utils/utils.c allocator.c lzma_compress.c ppmd_compress.c \
|
MAINSRCS = utils/utils.c allocator.c lzma_compress.c ppmd_compress.c \
|
||||||
adaptive_compress.c lzfx_compress.c lz4_compress.c none_compress.c \
|
adaptive_compress.c lzfx_compress.c lz4_compress.c none_compress.c \
|
||||||
utils/xxhash_base.c utils/heap.c utils/cpuid.c archive/pc_archive.c \
|
utils/xxhash_base.c utils/heap.c utils/cpuid.c pcompress.c
|
||||||
utils/phash/phash.c utils/phash/lookupa.c utils/phash/recycle.c pcompress.c
|
|
||||||
MAINHDRS = allocator.h pcompress.h utils/utils.h utils/xxhash.h utils/heap.h \
|
MAINHDRS = allocator.h pcompress.h utils/utils.h utils/xxhash.h utils/heap.h \
|
||||||
utils/cpuid.h utils/xxhash.h archive/pc_archive.h utils/phash/standard.h \
|
utils/cpuid.h utils/xxhash.h archive/pc_archive.h
|
||||||
utils/phash/lookupa.h utils/phash/recycle.h utils/phash/phash.h
|
|
||||||
MAINOBJS = $(MAINSRCS:.c=.o)
|
MAINOBJS = $(MAINSRCS:.c=.o)
|
||||||
|
|
||||||
PROGSRCS = main.c
|
PROGSRCS = main.c
|
||||||
|
@ -124,14 +122,26 @@ CRCHDRS = lzma/crc64_table_le.h lzma/crc64_table_be.h lzma/crc_macros.h \
|
||||||
lzma/crc32_table_le.h lzma/crc32_table_be.h lzma/lzma_crc.h
|
lzma/crc32_table_le.h lzma/crc32_table_be.h lzma/lzma_crc.h
|
||||||
CRCOBJS = $(CRCSRCS:.c=.o)
|
CRCOBJS = $(CRCSRCS:.c=.o)
|
||||||
|
|
||||||
LZPSRCS = lzp/lzp.c
|
LZPSRCS = filters/lzp/lzp.c
|
||||||
LZPHDRS = lzp/lzp.h
|
LZPHDRS = filters/lzp/lzp.h
|
||||||
LZPOBJS = $(LZPSRCS:.c=.o)
|
LZPOBJS = $(LZPSRCS:.c=.o)
|
||||||
|
|
||||||
DELTA2SRCS = delta2/delta2.c
|
DELTA2SRCS = filters/delta2/delta2.c
|
||||||
DELTA2HDRS = delta2/delta2.h
|
DELTA2HDRS = filters/delta2/delta2.h
|
||||||
DELTA2OBJS = $(DELTA2SRCS:.c=.o)
|
DELTA2OBJS = $(DELTA2SRCS:.c=.o)
|
||||||
|
|
||||||
|
ARCHIVESRCS = archive/pc_archive.c archive/pc_arc_filter.c utils/phash/phash.c \
|
||||||
|
utils/phash/lookupa.c utils/phash/recycle.c
|
||||||
|
ARCHIVEHDRS = pcompress.h utils/utils.h archive/pc_archive.h utils/phash/standard.h \
|
||||||
|
utils/phash/lookupa.h utils/phash/recycle.h utils/phash/phash.h archive/pc_arc_filter.h
|
||||||
|
ARCHIVEOBJS = $(ARCHIVESRCS:.c=.o)
|
||||||
|
|
||||||
|
PJPGSRCS = filters/packjpg/aricoder.cpp filters/packjpg/bitops.cpp filters/packjpg/packjpg.cpp \
|
||||||
|
archive/pjpg_helper.cpp
|
||||||
|
PJPGHDRS = filters/packjpg/aricoder.h filters/packjpg/bitops.h filters/packjpg/dct8x8.h \
|
||||||
|
filters/packjpg/packjpglib.h filters/packjpg/pjpgtbl.h
|
||||||
|
PJPGOBJS = $(PJPGSRCS:.cpp=.o)
|
||||||
|
|
||||||
SKEIN_BLOCK_C = crypto/skein/skein_block.c
|
SKEIN_BLOCK_C = crypto/skein/skein_block.c
|
||||||
SKEIN_BLOCK_ASM = crypto/skein/skein_block_x64.s
|
SKEIN_BLOCK_ASM = crypto/skein/skein_block_x64.s
|
||||||
SKEIN_BLOCK_SRC = @SKEIN_BLOCK@
|
SKEIN_BLOCK_SRC = @SKEIN_BLOCK@
|
||||||
|
@ -157,8 +167,8 @@ LIBBSCLIB = @LIBBSCLIB@
|
||||||
LIBBSCGEN_OPT = -fopenmp
|
LIBBSCGEN_OPT = -fopenmp
|
||||||
LIBBSCCPPFLAGS = -I$(LIBBSCDIR)/libbsc -DENABLE_PC_LIBBSC
|
LIBBSCCPPFLAGS = -I$(LIBBSCDIR)/libbsc -DENABLE_PC_LIBBSC
|
||||||
|
|
||||||
TRANSP_SRCS = transpose/transpose.c
|
TRANSP_SRCS = filters/transpose/transpose.c
|
||||||
TRANSP_HDRS = transpose/transpose.h
|
TRANSP_HDRS = filters/transpose/transpose.h
|
||||||
TRANSP_OBJS = $(TRANSP_SRCS:.c=.o)
|
TRANSP_OBJS = $(TRANSP_SRCS:.c=.o)
|
||||||
|
|
||||||
KECCAK_SRC_COMMON = crypto/keccak/genKAT.c crypto/keccak/KeccakDuplex.c \
|
KECCAK_SRC_COMMON = crypto/keccak/genKAT.c crypto/keccak/KeccakDuplex.c \
|
||||||
|
@ -182,21 +192,23 @@ KECCAK_HDRS = @KECCAK_HDRS@
|
||||||
KECCAK_OBJS = $(KECCAK_SRCS:.c=.o)
|
KECCAK_OBJS = $(KECCAK_SRCS:.c=.o)
|
||||||
KECCAK_OBJS_ASM = $(KECCAK_SRCS_ASM:.s=.o)
|
KECCAK_OBJS_ASM = $(KECCAK_SRCS_ASM:.s=.o)
|
||||||
|
|
||||||
BAKFILES = *~ lzma/*~ lzfx/*~ lz4/*~ rabin/*~ bsdiff/*~ lzp/*~ utils/*~ crypto/sha2/*~ \
|
BAKFILES = *~ lzma/*~ lzfx/*~ lz4/*~ rabin/*~ bsdiff/*~ filters/lzp/*~ utils/*~ crypto/sha2/*~ \
|
||||||
crypto/sha2/intel/*~ crypto/aes/*~ crypto/scrypt/*~ crypto/*~ rabin/global/*~ \
|
crypto/sha2/intel/*~ crypto/aes/*~ crypto/scrypt/*~ crypto/*~ rabin/global/*~ \
|
||||||
delta2/*~ crypto/keccak/*~ transpose/*~ crypto/skein/*~ crypto/keccak/*.o \
|
delta2/*~ crypto/keccak/*~ transpose/*~ crypto/skein/*~ crypto/keccak/*.o \
|
||||||
archive/*~
|
archive/*~ filters/delta2/*~ filters/packjpg/*~ filters/transpose/*~
|
||||||
|
|
||||||
RM = rm -f
|
RM = rm -f
|
||||||
RM_RF = rm -rf
|
RM_RF = rm -rf
|
||||||
COMMON_CPPFLAGS = -I. -I./lzma -I./lzfx -I./lz4 -I./rabin -I./bsdiff -DNODEFAULT_PROPS \
|
BASE_CPPFLAGS = -I. -I./lzma -I./lzfx -I./lz4 -I./rabin -I./bsdiff -DNODEFAULT_PROPS \
|
||||||
-DFILE_OFFSET_BITS=64 -D_REENTRANT -D__USE_SSE_INTRIN__ -D_LZMA_PROB32 \
|
-DFILE_OFFSET_BITS=64 -D_REENTRANT -D__USE_SSE_INTRIN__ -D_LZMA_PROB32 \
|
||||||
-I./lzp @LIBBSCCPPFLAGS@ -I./crypto/skein -I./utils -I./crypto/sha2 \
|
-I./filters/lzp @LIBBSCCPPFLAGS@ -I./crypto/skein -I./utils -I./crypto/sha2 \
|
||||||
-I./crypto/scrypt -I./crypto/aes -I./crypto @KEYLEN@ -I./rabin/global \
|
-I./crypto/scrypt -I./crypto/aes -I./crypto @KEYLEN@ -I./rabin/global \
|
||||||
-I./crypto/keccak -I./transpose -I./crypto/blake2 $(EXTRA_CPPFLAGS) \
|
-I./crypto/keccak -I./filters/transpose -I./crypto/blake2 $(EXTRA_CPPFLAGS) \
|
||||||
-I./crypto/xsalsa20 -I./archive -pedantic -Wall -std=gnu99 \
|
-I./crypto/xsalsa20 -I./archive -pedantic -Wall -I./filters -fno-strict-aliasing \
|
||||||
-fno-strict-aliasing -Wno-unused-but-set-variable -Wno-enum-compare \
|
-Wno-unused-but-set-variable -Wno-enum-compare \
|
||||||
@COMPAT_CPPFLAGS@ @XSALSA20_DEBUG@ -I@LIBARCHIVE_INC@
|
@COMPAT_CPPFLAGS@ @XSALSA20_DEBUG@ -I@LIBARCHIVE_INC@ -I./filters/packjpg
|
||||||
|
COMMON_CPPFLAGS = $(BASE_CPPFLAGS) -std=gnu99
|
||||||
|
COMMON_CPPFLAGS_cpp = $(BASE_CPPFLAGS)
|
||||||
COMMON_VEC_FLAGS = -ftree-vectorize
|
COMMON_VEC_FLAGS = -ftree-vectorize
|
||||||
COMMON_LOOP_OPTFLAGS = $(VEC_FLAGS) -floop-interchange -floop-block
|
COMMON_LOOP_OPTFLAGS = $(VEC_FLAGS) -floop-interchange -floop-block
|
||||||
LDLIBS = -ldl -L./buildtmp -Wl,-R@LIBBZ2_DIR@ -lbz2 -L./buildtmp -Wl,-R@LIBZ_DIR@ -lz -lm @LIBBSCLFLAGS@ \
|
LDLIBS = -ldl -L./buildtmp -Wl,-R@LIBBZ2_DIR@ -lbz2 -L./buildtmp -Wl,-R@LIBZ_DIR@ -lz -lm @LIBBSCLFLAGS@ \
|
||||||
|
@ -206,7 +218,7 @@ OBJS = $(MAINOBJS) $(LZMAOBJS) $(PPMDOBJS) $(LZFXOBJS) $(LZ4OBJS) $(CRCOBJS) \
|
||||||
$(RABINOBJS) $(BSDIFFOBJS) $(LZPOBJS) $(DELTA2OBJS) @LIBBSCWRAPOBJ@ $(SKEINOBJS) \
|
$(RABINOBJS) $(BSDIFFOBJS) $(LZPOBJS) $(DELTA2OBJS) @LIBBSCWRAPOBJ@ $(SKEINOBJS) \
|
||||||
$(SKEIN_BLOCK_OBJ) @SHA2ASM_OBJS@ @SHA2_OBJS@ $(KECCAK_OBJS) $(KECCAK_OBJS_ASM) \
|
$(SKEIN_BLOCK_OBJ) @SHA2ASM_OBJS@ @SHA2_OBJS@ $(KECCAK_OBJS) $(KECCAK_OBJS_ASM) \
|
||||||
$(TRANSP_OBJS) $(CRYPTO_OBJS) $(ZLIB_OBJS) $(BZLIB_OBJS) $(XXHASH_OBJS) $(BLAKE2_OBJS) \
|
$(TRANSP_OBJS) $(CRYPTO_OBJS) $(ZLIB_OBJS) $(BZLIB_OBJS) $(XXHASH_OBJS) $(BLAKE2_OBJS) \
|
||||||
@CRYPTO_COMPAT_OBJS@ $(CRYPTO_ASM_OBJS)
|
@CRYPTO_COMPAT_OBJS@ $(CRYPTO_ASM_OBJS) $(ARCHIVEOBJS) $(PJPGOBJS)
|
||||||
|
|
||||||
DEBUG_LINK = g++ -pthread @LIBBSCGEN_OPT@ @EXTRA_OPT_FLAGS@ -fopenmp -fPIC
|
DEBUG_LINK = g++ -pthread @LIBBSCGEN_OPT@ @EXTRA_OPT_FLAGS@ -fopenmp -fPIC
|
||||||
DEBUG_COMPILE = gcc -g -c @EXTRA_OPT_FLAGS@ -fPIC
|
DEBUG_COMPILE = gcc -g -c @EXTRA_OPT_FLAGS@ -fPIC
|
||||||
|
@ -277,6 +289,13 @@ $(LZPOBJS): $(LZPSRCS) $(LZPHDRS)
|
||||||
$(DELTA2OBJS): $(DELTA2SRCS) $(DELTA2HDRS)
|
$(DELTA2OBJS): $(DELTA2SRCS) $(DELTA2HDRS)
|
||||||
$(COMPILE) $(GEN_OPT) $(VEC_FLAGS) $(CPPFLAGS) $(@:.o=.c) -o $@
|
$(COMPILE) $(GEN_OPT) $(VEC_FLAGS) $(CPPFLAGS) $(@:.o=.c) -o $@
|
||||||
|
|
||||||
|
$(ARCHIVEOBJS): $(ARCHIVESRCS) $(ARCHIVEHDRS)
|
||||||
|
$(COMPILE) $(GEN_OPT) $(VEC_FLAGS) $(CPPFLAGS) $(@:.o=.c) -o $@
|
||||||
|
|
||||||
|
$(PJPGOBJS): $(PJPGSRCS) $(PJPGHDRS)
|
||||||
|
$(COMPILE_cpp) $(COMMON_VEC_FLAGS) @SSE_OPT_FLAGS@ -O2 -fsched-spec-load \
|
||||||
|
$(VEC_FLAGS) -DBUILD_LIB $(COMMON_CPPFLAGS_cpp) $(@:.o=.cpp) -o $@
|
||||||
|
|
||||||
$(SKEIN_BLOCK_OBJ): $(SKEIN_BLOCK_SRC)
|
$(SKEIN_BLOCK_OBJ): $(SKEIN_BLOCK_SRC)
|
||||||
$(COMPILE) $(SKEIN_FLAGS) $(SKEIN_BLOCK_SRC) -o $@
|
$(COMPILE) $(SKEIN_FLAGS) $(SKEIN_BLOCK_SRC) -o $@
|
||||||
|
|
||||||
|
|
130
archive/pc_arc_filter.c
Normal file
130
archive/pc_arc_filter.c
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* This file is a part of Pcompress, a chunked parallel multi-
|
||||||
|
* algorithm lossless compression and decompression program.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2013 Moinak Ghosh. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* moinakg@belenix.org, http://moinakg.wordpress.com/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <utils.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <archive.h>
|
||||||
|
#include <archive_entry.h>
|
||||||
|
#include "pc_arc_filter.h"
|
||||||
|
#include "pc_archive.h"
|
||||||
|
|
||||||
|
#define PACKJPG_DEF_BUFSIZ (512 * 1024)
|
||||||
|
#define JPG_SIZE_LIMIT (100 * 1024 * 1024)
|
||||||
|
|
||||||
|
struct packjpg_filter_data {
|
||||||
|
uchar_t *buff;
|
||||||
|
size_t bufflen;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern size_t packjpg_filter_process(uchar_t *in_buf, size_t len, uchar_t **out_buf);
|
||||||
|
|
||||||
|
int packjpg_filter(struct filter_info *fi, void *filter_private);
|
||||||
|
|
||||||
|
void
|
||||||
|
add_filters_by_ext()
|
||||||
|
{
|
||||||
|
struct packjpg_filter_data *pjdat;
|
||||||
|
|
||||||
|
pjdat = (struct packjpg_filter_data *)malloc(sizeof (struct packjpg_filter_data));
|
||||||
|
pjdat->buff = (uchar_t *)malloc(PACKJPG_DEF_BUFSIZ);
|
||||||
|
pjdat->bufflen = PACKJPG_DEF_BUFSIZ;
|
||||||
|
if (insert_filter_data(packjpg_filter, pjdat, "pjg") != 0) {
|
||||||
|
free(pjdat->buff);
|
||||||
|
free(pjdat);
|
||||||
|
log_msg(LOG_WARN, 0, "Failed to add filter module for packJPG.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* a short reminder about input/output stream types
|
||||||
|
for the pjglib_init_streams() function
|
||||||
|
|
||||||
|
if input is file
|
||||||
|
----------------
|
||||||
|
in_scr -> name of input file
|
||||||
|
in_type -> 0
|
||||||
|
in_size -> ignore
|
||||||
|
|
||||||
|
if input is memory
|
||||||
|
------------------
|
||||||
|
in_scr -> array containg data
|
||||||
|
in_type -> 1
|
||||||
|
in_size -> size of data array
|
||||||
|
|
||||||
|
if input is *FILE (f.e. stdin)
|
||||||
|
------------------------------
|
||||||
|
in_src -> stream pointer
|
||||||
|
in_type -> 2
|
||||||
|
in_size -> ignore
|
||||||
|
|
||||||
|
vice versa for output streams! */
|
||||||
|
|
||||||
|
int
|
||||||
|
packjpg_filter(struct filter_info *fi, void *filter_private)
|
||||||
|
{
|
||||||
|
struct packjpg_filter_data *pjdat = (struct packjpg_filter_data *)filter_private;
|
||||||
|
uchar_t *mapbuf, *out;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = archive_entry_size(fi->entry);
|
||||||
|
if (len > JPG_SIZE_LIMIT) // Bork on massive JPEGs
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
mapbuf = mmap(NULL, len, PROT_READ, MAP_SHARED, fi->fd, 0);
|
||||||
|
if (mapbuf == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
if (pjdat->bufflen < len) {
|
||||||
|
free(pjdat->buff);
|
||||||
|
pjdat->bufflen = len;
|
||||||
|
pjdat->buff = malloc(pjdat->bufflen);
|
||||||
|
if (pjdat->buff == NULL) {
|
||||||
|
log_msg(LOG_ERR, 1, "Out of memory.");
|
||||||
|
munmap(mapbuf, len);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper routine to bridge to packJPG C++ lib, without changing packJPG itself.
|
||||||
|
*/
|
||||||
|
out = pjdat->buff;
|
||||||
|
if ((len = packjpg_filter_process(mapbuf, len, &out)) == 0) {
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (archive_write_data(fi->target_arc, out, len));
|
||||||
|
}
|
||||||
|
|
53
archive/pc_arc_filter.h
Normal file
53
archive/pc_arc_filter.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* This file is a part of Pcompress, a chunked parallel multi-
|
||||||
|
* algorithm lossless compression and decompression program.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2013 Moinak Ghosh. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* moinakg@belenix.org, http://moinakg.wordpress.com/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PC_ARCHIVE_FILTER_H
|
||||||
|
#define _PC_ARCHIVE_FILTER_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <archive.h>
|
||||||
|
#include <archive_entry.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct filter_info {
|
||||||
|
struct archive *target_arc;
|
||||||
|
struct archive_entry *entry;
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*filter_func_ptr)(struct filter_info *fi, void *filter_private);
|
||||||
|
|
||||||
|
void add_filters_by_ext();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -28,7 +28,7 @@
|
||||||
* based on extension (or first 4 chars of name if no extension) and size. A simple
|
* based on extension (or first 4 chars of name if no extension) and size. A simple
|
||||||
* external merge sort is used. This sorting yields better compression ratio.
|
* external merge sort is used. This sorting yields better compression ratio.
|
||||||
*
|
*
|
||||||
* Sorting is enabled for compression levels greater than 2.
|
* Sorting is enabled for compression levels greater than 6.
|
||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -45,10 +45,10 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <archive.h>
|
#include <archive.h>
|
||||||
#include <archive_entry.h>
|
#include <archive_entry.h>
|
||||||
#include "pc_archive.h"
|
|
||||||
#include <phash/phash.h>
|
#include <phash/phash.h>
|
||||||
#include <phash/extensions.h>
|
#include <phash/extensions.h>
|
||||||
#include <phash/standard.h>
|
#include <phash/standard.h>
|
||||||
|
#include "pc_archive.h"
|
||||||
|
|
||||||
#undef _FEATURES_H
|
#undef _FEATURES_H
|
||||||
#define _XOPEN_SOURCE 700
|
#define _XOPEN_SOURCE 700
|
||||||
|
@ -60,6 +60,8 @@ pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static struct ext_hash_entry {
|
static struct ext_hash_entry {
|
||||||
uint64_t extnum;
|
uint64_t extnum;
|
||||||
int type;
|
int type;
|
||||||
|
void *filter_private;
|
||||||
|
filter_func_ptr filter_func;
|
||||||
} *exthtab = NULL;
|
} *exthtab = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -809,12 +811,11 @@ setup_extractor(pc_ctx_t *pctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routines to archive members and write the archive to pipe. Most of the following
|
* Routines to archive members and write the file data to the callback. Portions of
|
||||||
* code is adapted from some of the Libarchive bsdtar code.
|
* the following code is adapted from some of the Libarchive bsdtar code.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
copy_file_data(pc_ctx_t *pctx, struct archive *arc,
|
copy_file_data(pc_ctx_t *pctx, struct archive *arc, struct archive_entry *entry, int typ)
|
||||||
struct archive *in_arc, struct archive_entry *entry, int typ)
|
|
||||||
{
|
{
|
||||||
size_t sz, offset, len;
|
size_t sz, offset, len;
|
||||||
ssize_t bytes_to_write;
|
ssize_t bytes_to_write;
|
||||||
|
@ -833,6 +834,10 @@ copy_file_data(pc_ctx_t *pctx, struct archive *arc,
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use mmap for copying file data. Not necessarily for performance, but it saves on
|
||||||
|
* resident memory use.
|
||||||
|
*/
|
||||||
while (bytes_to_write > 0) {
|
while (bytes_to_write > 0) {
|
||||||
uchar_t *src;
|
uchar_t *src;
|
||||||
size_t wlen;
|
size_t wlen;
|
||||||
|
@ -843,6 +848,12 @@ copy_file_data(pc_ctx_t *pctx, struct archive *arc,
|
||||||
else
|
else
|
||||||
len = MMAP_SIZE;
|
len = MMAP_SIZE;
|
||||||
mapbuf = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, offset);
|
mapbuf = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, offset);
|
||||||
|
if (mapbuf == NULL) {
|
||||||
|
/* Mmap failed; this is bad. */
|
||||||
|
log_msg(LOG_ERR, 1, "Mmap failed for %s.", fpath);
|
||||||
|
rv = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
offset += len;
|
offset += len;
|
||||||
src = mapbuf;
|
src = mapbuf;
|
||||||
wlen = len;
|
wlen = len;
|
||||||
|
@ -852,7 +863,7 @@ copy_file_data(pc_ctx_t *pctx, struct archive *arc,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write the entire mmap-ed buffer. Since we are writing to the compressor
|
* Write the entire mmap-ed buffer. Since we are writing to the compressor
|
||||||
* stage pipe there is no need for blocking.
|
* stage there is no need for blocking.
|
||||||
*/
|
*/
|
||||||
wrtn = archive_write_data(arc, src, wlen);
|
wrtn = archive_write_data(arc, src, wlen);
|
||||||
if (wrtn < wlen) {
|
if (wrtn < wlen) {
|
||||||
|
@ -870,8 +881,7 @@ copy_file_data(pc_ctx_t *pctx, struct archive *arc,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
write_entry(pc_ctx_t *pctx, struct archive *arc, struct archive *in_arc,
|
write_entry(pc_ctx_t *pctx, struct archive *arc, struct archive_entry *entry, int typ)
|
||||||
struct archive_entry *entry, int typ)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
@ -888,7 +898,7 @@ write_entry(pc_ctx_t *pctx, struct archive *arc, struct archive *in_arc,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (archive_entry_size(entry) > 0) {
|
if (archive_entry_size(entry) > 0) {
|
||||||
return (copy_file_data(pctx, arc, in_arc, entry, typ));
|
return (copy_file_data(pctx, arc, entry, typ));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -999,7 +1009,7 @@ archiver_thread_func(void *dat) {
|
||||||
archive_entry_linkify(resolver, &entry, &spare_entry);
|
archive_entry_linkify(resolver, &entry, &spare_entry);
|
||||||
ent = entry;
|
ent = entry;
|
||||||
while (ent != NULL) {
|
while (ent != NULL) {
|
||||||
if (write_entry(pctx, arc, ard, ent, typ) != 0) {
|
if (write_entry(pctx, arc, ent, typ) != 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
ent = spare_entry;
|
ent = spare_entry;
|
||||||
|
@ -1037,58 +1047,58 @@ start_archiver(pc_ctx_t *pctx) {
|
||||||
static int
|
static int
|
||||||
copy_data_out(struct archive *ar, struct archive *aw)
|
copy_data_out(struct archive *ar, struct archive *aw)
|
||||||
{
|
{
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
const void *buff;
|
const void *buff;
|
||||||
size_t size;
|
size_t size;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
r = archive_read_data_block(ar, &buff, &size, &offset);
|
r = archive_read_data_block(ar, &buff, &size, &offset);
|
||||||
if (r == ARCHIVE_EOF)
|
if (r == ARCHIVE_EOF)
|
||||||
return (ARCHIVE_OK);
|
return (ARCHIVE_OK);
|
||||||
if (r != ARCHIVE_OK)
|
if (r != ARCHIVE_OK)
|
||||||
return (r);
|
return (r);
|
||||||
r = (int)archive_write_data_block(aw, buff, size, offset);
|
r = (int)archive_write_data_block(aw, buff, size, offset);
|
||||||
if (r < ARCHIVE_WARN)
|
if (r < ARCHIVE_WARN)
|
||||||
r = ARCHIVE_WARN;
|
r = ARCHIVE_WARN;
|
||||||
if (r != ARCHIVE_OK) {
|
if (r != ARCHIVE_OK) {
|
||||||
archive_set_error(ar, archive_errno(aw),
|
archive_set_error(ar, archive_errno(aw),
|
||||||
"%s", archive_error_string(aw));
|
"%s", archive_error_string(aw));
|
||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
archive_extract_entry(struct archive *a, struct archive_entry *entry,
|
archive_extract_entry(struct archive *a, struct archive_entry *entry,
|
||||||
struct archive *ad)
|
struct archive *ad)
|
||||||
{
|
{
|
||||||
int r, r2;
|
int r, r2;
|
||||||
|
|
||||||
r = archive_write_header(ad, entry);
|
r = archive_write_header(ad, entry);
|
||||||
if (r < ARCHIVE_WARN)
|
if (r < ARCHIVE_WARN)
|
||||||
r = ARCHIVE_WARN;
|
r = ARCHIVE_WARN;
|
||||||
if (r != ARCHIVE_OK)
|
if (r != ARCHIVE_OK)
|
||||||
/* If _write_header failed, copy the error. */
|
/* If _write_header failed, copy the error. */
|
||||||
archive_copy_error(a, ad);
|
archive_copy_error(a, ad);
|
||||||
else if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) > 0)
|
else if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) > 0)
|
||||||
/* Otherwise, pour data into the entry. */
|
/* Otherwise, pour data into the entry. */
|
||||||
r = copy_data_out(a, ad);
|
r = copy_data_out(a, ad);
|
||||||
r2 = archive_write_finish_entry(ad);
|
r2 = archive_write_finish_entry(ad);
|
||||||
if (r2 < ARCHIVE_WARN)
|
if (r2 < ARCHIVE_WARN)
|
||||||
r2 = ARCHIVE_WARN;
|
r2 = ARCHIVE_WARN;
|
||||||
/* Use the first message. */
|
/* Use the first message. */
|
||||||
if (r2 != ARCHIVE_OK && r == ARCHIVE_OK)
|
if (r2 != ARCHIVE_OK && r == ARCHIVE_OK)
|
||||||
archive_copy_error(a, ad);
|
archive_copy_error(a, ad);
|
||||||
/* Use the worst error return. */
|
/* Use the worst error return. */
|
||||||
if (r2 < r)
|
if (r2 < r)
|
||||||
r = r2;
|
r = r2;
|
||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract Thread function. Read an uncompressed archive from the pipe and extract
|
* Extract Thread function. Read an uncompressed archive from the decompressor stage
|
||||||
* members to disk. The decompressor writes to the other end of the pipe.
|
* and extract members to disk.
|
||||||
*/
|
*/
|
||||||
static void *
|
static void *
|
||||||
extractor_thread_func(void *dat) {
|
extractor_thread_func(void *dat) {
|
||||||
|
@ -1241,7 +1251,11 @@ init_archive_mod() {
|
||||||
extnum = (extnum << 1) | extlist[i].ext[j];
|
extnum = (extnum << 1) | extlist[i].ext[j];
|
||||||
exthtab[slot].extnum = extnum;
|
exthtab[slot].extnum = extnum;
|
||||||
exthtab[slot].type = extlist[i].type;
|
exthtab[slot].type = extlist[i].type;
|
||||||
|
exthtab[slot].filter_func = NULL;
|
||||||
|
exthtab[slot].filter_private = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_filters_by_ext();
|
||||||
inited = 1;
|
inited = 1;
|
||||||
} else {
|
} else {
|
||||||
rv = 1;
|
rv = 1;
|
||||||
|
@ -1270,7 +1284,7 @@ detect_type_by_ext(char *path, int pathlen)
|
||||||
if (len == 0) goto out; // If extension is empty give up
|
if (len == 0) goto out; // If extension is empty give up
|
||||||
ext = &path[i+1];
|
ext = &path[i+1];
|
||||||
slot = phash(ext, len);
|
slot = phash(ext, len);
|
||||||
if (slot > PHASHNKEYS) goto out; // Extension maps outside hash table range, give up
|
if (slot >= PHASHNKEYS) goto out; // Extension maps outside hash table range, give up
|
||||||
extnum = 0;
|
extnum = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1326,3 +1340,16 @@ detect_type_by_data(uchar_t *buf, size_t len)
|
||||||
|
|
||||||
return (TYPE_UNKNOWN);
|
return (TYPE_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
insert_filter_data(filter_func_ptr func, void *filter_private, const char *ext)
|
||||||
|
{
|
||||||
|
ub4 slot = phash(ext, strlen(ext));
|
||||||
|
if (slot >= PHASHNKEYS || slot < 0) {
|
||||||
|
log_msg(LOG_WARN, 0, "Cannot add filter for unknown extension: %s", ext);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
exthtab[slot].filter_func = func;
|
||||||
|
exthtab[slot].filter_private = filter_private;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
|
@ -23,13 +23,14 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _ARCHIVE_H
|
#ifndef _PC_ARCHIVE_H
|
||||||
#define _ARCHIVE_H
|
#define _PC_ARCHIVE_H
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pcompress.h>
|
#include <pcompress.h>
|
||||||
|
#include <pc_arc_filter.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -52,6 +53,7 @@ int64_t archiver_read(void *ctx, void *buf, uint64_t count);
|
||||||
int64_t archiver_write(void *ctx, void *buf, uint64_t count);
|
int64_t archiver_write(void *ctx, void *buf, uint64_t count);
|
||||||
int archiver_close(void *ctx);
|
int archiver_close(void *ctx);
|
||||||
int init_archive_mod();
|
int init_archive_mod();
|
||||||
|
int insert_filter_data(filter_func_ptr func, void *filter_private, const char *ext);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
58
archive/pjpg_helper.cpp
Normal file
58
archive/pjpg_helper.cpp
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* This file is a part of Pcompress, a chunked parallel multi-
|
||||||
|
* algorithm lossless compression and decompression program.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2013 Moinak Ghosh. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* moinakg@belenix.org, http://moinakg.wordpress.com/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <packjpglib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char uchar_t;
|
||||||
|
|
||||||
|
size_t
|
||||||
|
packjpg_filter_process(uchar_t *in_buf, size_t len, uchar_t **out_buf)
|
||||||
|
{
|
||||||
|
unsigned int len1;
|
||||||
|
|
||||||
|
pjglib_init_streams(in_buf, 1, len, *out_buf, 1);
|
||||||
|
len1 = len;
|
||||||
|
if (!pjglib_convert_stream2mem(out_buf, &len1, NULL))
|
||||||
|
return (0);
|
||||||
|
if (len1 == len)
|
||||||
|
return (0);
|
||||||
|
return (len1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
256
filters/packjpg/Readme.txt
Normal file
256
filters/packjpg/Readme.txt
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
packJPG v2.5g (09/14/2013)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
packJPG is a compression program specially designed for further
|
||||||
|
compression of JPEG images without causing any further loss. Typically
|
||||||
|
it reduces the file size of a JPEG file by 20%.
|
||||||
|
|
||||||
|
|
||||||
|
LGPL v3 license and special permissions
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
All programs in this package are free software; you can redistribute
|
||||||
|
them and/or modify them under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either version 3
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The package is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||||
|
General Public License for more details at
|
||||||
|
http://www.gnu.org/copyleft/lgpl.html.
|
||||||
|
|
||||||
|
If the LGPL v3 license is not compatible with your software project you
|
||||||
|
might contact us and ask for a special permission to use the packJPG
|
||||||
|
library under different conditions. In any case, usage of the packJPG
|
||||||
|
algorithm under the LGPL v3 or above is highly advised and special
|
||||||
|
permissions will only be given where necessary on a case by case basis.
|
||||||
|
This offer is aimed mainly at closed source freeware developers seeking
|
||||||
|
to add PJG support to their software projects.
|
||||||
|
|
||||||
|
Copyright 2006...2013 by HTW Aalen University and Matthias Stirner.
|
||||||
|
|
||||||
|
|
||||||
|
Usage of packJPG
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
JPEG files are compressed and PJG files are decompressed using this
|
||||||
|
command:
|
||||||
|
|
||||||
|
"packJPG [file(s)]"
|
||||||
|
|
||||||
|
packJPG recognizes file types on its own and decides whether to compress
|
||||||
|
(JPG) or decompress (PJG). For unrecognized file types no action is
|
||||||
|
taken. Files are recognized by content, not by extension.
|
||||||
|
|
||||||
|
packJPG supports wildcards like "*.*" and drag and drop of multiple
|
||||||
|
files. Filenames for output files are created automatically. In default
|
||||||
|
mode, files are never overwritten. If a filename is already in use,
|
||||||
|
packJPG creates a new filename by adding underscores.
|
||||||
|
|
||||||
|
If "-" is used as a filename input from stdin is assumed and output is
|
||||||
|
written to stdout. This can be useful for example if jpegtran is to be
|
||||||
|
used as a preprocessor.
|
||||||
|
|
||||||
|
Usage examples:
|
||||||
|
|
||||||
|
"packJPG *.pjg"
|
||||||
|
"packJPG lena.jpg"
|
||||||
|
"packJPG kodim??.jpg"
|
||||||
|
"packJPG - < sail.pjg > sail.jpg"
|
||||||
|
|
||||||
|
|
||||||
|
Command line switches
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
-ver verify files after processing
|
||||||
|
-v? level of verbosity; 0,1 or 2 is allowed (default 0)
|
||||||
|
-np no pause after processing files
|
||||||
|
-o overwrite existing files
|
||||||
|
-p proceed on warnings
|
||||||
|
-d discard meta-info
|
||||||
|
|
||||||
|
By default, compression is cancelled on warnings. If warnings are
|
||||||
|
skipped by using "-p", most files with warnings can also be compressed,
|
||||||
|
but JPEG files reconstructed from PJG files might not be bitwise
|
||||||
|
identical with the original JPEG files. There won't be any loss to
|
||||||
|
image data or quality however.
|
||||||
|
|
||||||
|
Unnecessary meta information can be discarded using "-d". This reduces
|
||||||
|
compressed files' sizes. Be warned though, reconstructed files won't be
|
||||||
|
bitwise identical with the original files and meta information will be
|
||||||
|
lost forever. As with "-p" there won't be any loss to image data or
|
||||||
|
quality.
|
||||||
|
|
||||||
|
There is no known case in which a file compressed by packJPG (without
|
||||||
|
the "-p" option, see above) couldn't be reconstructed to exactly the
|
||||||
|
state it was before. If you want an additional layer of safety you can
|
||||||
|
also use the verify option "-ver". In this mode, files are compressed,
|
||||||
|
then decompressed and the decompressed file compared to the original
|
||||||
|
file. If this test doesn't pass there will be an error message and the
|
||||||
|
compressed file won't be written to the drive.
|
||||||
|
|
||||||
|
Please note that the "-ver" option should never be used in conjunction
|
||||||
|
with the "-d" and/or "-p" options. As stated above, the "-p" and "-d"
|
||||||
|
options will most likely lead to reconstructed JPG files not being
|
||||||
|
bitwise identical to the original JPG files. In turn, the verification
|
||||||
|
process may fail on various files although nothing actually went wrong.
|
||||||
|
|
||||||
|
Usage examples:
|
||||||
|
|
||||||
|
"packJPG -v1 -o baboon.pjg"
|
||||||
|
"packJPG -ver lena.jpg"
|
||||||
|
"packJPG -d tiffany.jpg"
|
||||||
|
"packJPG -p *.jpg"
|
||||||
|
|
||||||
|
|
||||||
|
Known Limitations
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
packJPG is a compression program specially for JPEG files, so it doesn't
|
||||||
|
compress other file types.
|
||||||
|
|
||||||
|
packJPG has low error tolerance. JPEG files might not work with packJPG
|
||||||
|
even if they work perfectly with other image processing software. The
|
||||||
|
command line switch "-p" can be used to increase error tolerance and
|
||||||
|
compatibility.
|
||||||
|
|
||||||
|
If you try to drag and drop to many files at once, there might be a
|
||||||
|
windowed error message about missing privileges. In that case you can
|
||||||
|
try it again with less files or consider using the command prompt.
|
||||||
|
packJPG has been tested to work perfectly with thousands of files from
|
||||||
|
the command line. This issue also happens with drag and drop in other
|
||||||
|
applications, so it might not be a limitation of packJPG but a
|
||||||
|
limitation of Windows.
|
||||||
|
|
||||||
|
Compressed PJG files are not compatible between different packJPG
|
||||||
|
versions. You will get an error message if you try to decompress PJG
|
||||||
|
files with a different version than the one used for compression. You
|
||||||
|
may download older versions of packJPG from:
|
||||||
|
http://www.elektronik.htw-aalen.de/packJPG/binaries/old/
|
||||||
|
|
||||||
|
|
||||||
|
Open source release / developer info
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The packJPG source codes is found inside the "source" subdirectory.
|
||||||
|
Additional documents aimed to developers, containing detailed
|
||||||
|
instructions on compiling the source code and using special
|
||||||
|
functionality, are included in the "packJPG" subdirectory.
|
||||||
|
|
||||||
|
|
||||||
|
History
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
v1.9a (04/20/2007) (non public)
|
||||||
|
- first released version
|
||||||
|
- only for testing purposes
|
||||||
|
|
||||||
|
v2.0 (05/28/2007) (public)
|
||||||
|
- first public version of packJPG
|
||||||
|
- minor improvements to overall compression
|
||||||
|
- minor bugfixes
|
||||||
|
|
||||||
|
v2.2 (08/05/2007) (public)
|
||||||
|
- around 40% faster compression & decompression
|
||||||
|
- major improvements to overall compression (around 2% on average)
|
||||||
|
- reading from stdin, writing to stdout
|
||||||
|
- smaller executable
|
||||||
|
- minor bugfixes
|
||||||
|
- various minor improvements
|
||||||
|
|
||||||
|
v2.3 (09/18/2007) (public)
|
||||||
|
- compatibility with JPEG progressive mode
|
||||||
|
- compatibility with JPEG extended sequential mode
|
||||||
|
- compatibility with the CMYK color space
|
||||||
|
- compatibility with older CPUs
|
||||||
|
- around 15% faster compression & decompression
|
||||||
|
- new switch: [-d] (discard meta-info)
|
||||||
|
- various bugfixes
|
||||||
|
|
||||||
|
v2.3a (11/21/2007) (public)
|
||||||
|
- crash issue with certain images fixed
|
||||||
|
- compatibility with packJPG v2.3 maintained
|
||||||
|
|
||||||
|
v2.3b (12/20/2007) (public)
|
||||||
|
- some minor errors in the packJPG library fixed
|
||||||
|
- compatibility with packJPG v2.3 maintained
|
||||||
|
|
||||||
|
v2.4 (03/24/2010) (public)
|
||||||
|
- major improvements (1%...2%) to overall compression
|
||||||
|
- around 10% faster compression & decompression
|
||||||
|
- major improvements to JPG compatibility
|
||||||
|
- size of executable reduced to ~33%
|
||||||
|
- new switch: [-ver] (verify file after processing)
|
||||||
|
- new switch: [-np] (no pause after processing)
|
||||||
|
- new progress bar output mode
|
||||||
|
- arithmetic coding routines rewritten from scratch
|
||||||
|
- various smaller improvements to numerous to list here
|
||||||
|
- new SFX (self extracting) archive format
|
||||||
|
|
||||||
|
v2.5 (11/11/2011) (public)
|
||||||
|
- improvements (~0.5%) to overall compression
|
||||||
|
- several minor bugfixes
|
||||||
|
- major code cleanup
|
||||||
|
- removed packJPX from the package
|
||||||
|
- added packARC to the package
|
||||||
|
- packJPG is now open source!
|
||||||
|
|
||||||
|
v2.5a (11/21/11) (public)
|
||||||
|
- source code compatibility improvements (Gerhard Seelmann)
|
||||||
|
- avoid some compiler warnings (Gerhard Seelmann)
|
||||||
|
- source code clean up (Gerhard Seelmann)
|
||||||
|
|
||||||
|
v2.5b (01/27/12) (public)
|
||||||
|
- further removal of redundant code
|
||||||
|
- some fixes for the packJPG static library
|
||||||
|
- compiler fix for Mac OS (thanks to Sergio Lopez)
|
||||||
|
- improved compression ratio calculation
|
||||||
|
- eliminated the need for temp files
|
||||||
|
|
||||||
|
v2.5c (04/13/12) (public)
|
||||||
|
- various source code optimizations
|
||||||
|
|
||||||
|
v2.5d (07/03/12) (public)
|
||||||
|
- fixed a rare bug with progressive JPEG
|
||||||
|
|
||||||
|
v2.5e (07/03/12) (public)
|
||||||
|
- some minor source code optimizations
|
||||||
|
- changed packJPG licensing to LGPL
|
||||||
|
- moved packARC to a separate package
|
||||||
|
|
||||||
|
v2.5f (02/24/13) (public)
|
||||||
|
- fixed a minor bug in the JPG parser (thanks to Stephan Busch)
|
||||||
|
|
||||||
|
v2.5g (09/14/13) (public)
|
||||||
|
- fixed a rare crash bug with manipulated JPEG files
|
||||||
|
|
||||||
|
|
||||||
|
Acknowledgements
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
packJPG is the result of countless hours of research and development. It
|
||||||
|
is part of my final year project for Hochschule Aalen.
|
||||||
|
|
||||||
|
Prof. Dr. Gerhard Seelmann from Hochschule Aalen supported my
|
||||||
|
development of packJPG with his extensive knowledge in the field of data
|
||||||
|
compression. Without his advice, packJPG would not be possible.
|
||||||
|
|
||||||
|
The official homepage of packJPG is currently maintained by Hochschule
|
||||||
|
Aalen staff.
|
||||||
|
|
||||||
|
packJPG logo and icon are designed by Michael Kaufmann.
|
||||||
|
|
||||||
|
|
||||||
|
Contact
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
The official home of packJPG:
|
||||||
|
http://www.elektronik.htw-aalen.de/packjpg/
|
||||||
|
|
||||||
|
For questions and bug reports:
|
||||||
|
packjpg (at) htw-aalen.de
|
||||||
|
|
||||||
|
|
||||||
|
____________________________________
|
||||||
|
packJPG by Matthias Stirner, 09/2013
|
1044
filters/packjpg/aricoder.cpp
Normal file
1044
filters/packjpg/aricoder.cpp
Normal file
File diff suppressed because it is too large
Load diff
268
filters/packjpg/aricoder.h
Normal file
268
filters/packjpg/aricoder.h
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
// defines for coder
|
||||||
|
#define CODER_USE_BITS 31 // must never be above 31
|
||||||
|
#define CODER_LIMIT100 ( (unsigned int) ( 1 << CODER_USE_BITS ) )
|
||||||
|
#define CODER_LIMIT025 ( ( CODER_LIMIT100 / 4 ) * 1 )
|
||||||
|
#define CODER_LIMIT050 ( ( CODER_LIMIT100 / 4 ) * 2 )
|
||||||
|
#define CODER_LIMIT075 ( ( CODER_LIMIT100 / 4 ) * 3 )
|
||||||
|
#define CODER_MAXSCALE CODER_LIMIT025 - 1
|
||||||
|
#define ESCAPE_SYMBOL CODER_LIMIT025
|
||||||
|
|
||||||
|
|
||||||
|
// symbol struct, used in arithmetic coding
|
||||||
|
struct symbol {
|
||||||
|
unsigned int low_count;
|
||||||
|
unsigned int high_count;
|
||||||
|
unsigned int scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
// table struct, used in in statistical models,
|
||||||
|
// holding all info needed for one context
|
||||||
|
struct table {
|
||||||
|
// counts for each symbol contained in the table
|
||||||
|
unsigned short* counts;
|
||||||
|
// links to higher order contexts
|
||||||
|
struct table** links;
|
||||||
|
// link to lower order context
|
||||||
|
struct table* lesser;
|
||||||
|
// accumulated counts
|
||||||
|
unsigned int scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
// special table struct, used in in model_s,
|
||||||
|
// holding additional info for a speedier 'totalize_table'
|
||||||
|
struct table_s {
|
||||||
|
// counts for each symbol contained in the table
|
||||||
|
unsigned short* counts;
|
||||||
|
// links to higher order contexts
|
||||||
|
struct table_s** links;
|
||||||
|
// link to lower order context
|
||||||
|
struct table_s* lesser;
|
||||||
|
// speedup info
|
||||||
|
unsigned short max_count;
|
||||||
|
unsigned short max_symbol;
|
||||||
|
// unsigned short esc_prob;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
class for arithmetic coding of data to/from iostream
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
class aricoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
aricoder( iostream* stream, int iomode );
|
||||||
|
~aricoder( void );
|
||||||
|
void encode( symbol* s );
|
||||||
|
unsigned int decode_count( symbol* s );
|
||||||
|
void decode( symbol* s );
|
||||||
|
|
||||||
|
private:
|
||||||
|
// bitwise operations
|
||||||
|
void write_bit( unsigned char bit );
|
||||||
|
unsigned char read_bit( void );
|
||||||
|
|
||||||
|
// i/o variables
|
||||||
|
iostream* sptr;
|
||||||
|
int mode;
|
||||||
|
unsigned char bbyte;
|
||||||
|
unsigned char cbit;
|
||||||
|
|
||||||
|
// arithmetic coding variables
|
||||||
|
unsigned int ccode;
|
||||||
|
unsigned int clow;
|
||||||
|
unsigned int chigh;
|
||||||
|
unsigned int cstep;
|
||||||
|
unsigned int nrbits;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
universal statistical model for arithmetic coding
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
class model_s
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
model_s( int max_s, int max_c, int max_o, int c_lim );
|
||||||
|
~model_s( void );
|
||||||
|
|
||||||
|
void update_model( int symbol );
|
||||||
|
void shift_context( int c );
|
||||||
|
void flush_model( int scale_factor );
|
||||||
|
void exclude_symbols( char rule, int c );
|
||||||
|
|
||||||
|
int convert_int_to_symbol( int c, symbol *s );
|
||||||
|
void get_symbol_scale( symbol *s );
|
||||||
|
int convert_symbol_to_int( int count, symbol *s );
|
||||||
|
|
||||||
|
bool error;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// unsigned short* totals;
|
||||||
|
unsigned int* totals;
|
||||||
|
char* scoreboard;
|
||||||
|
int sb0_count;
|
||||||
|
table_s **contexts;
|
||||||
|
table_s **storage;
|
||||||
|
|
||||||
|
int max_symbol;
|
||||||
|
int max_context;
|
||||||
|
int current_order;
|
||||||
|
int max_order;
|
||||||
|
int max_count;
|
||||||
|
|
||||||
|
inline void totalize_table(table_s* context );
|
||||||
|
inline void rescale_table(table_s* context, int scale_factor );
|
||||||
|
inline void recursive_flush(table_s* context, int scale_factor );
|
||||||
|
inline void recursive_cleanup(table_s* context );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
binary statistical model for arithmetic coding
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
class model_b
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
model_b( int max_c, int max_o, int c_lim );
|
||||||
|
~model_b( void );
|
||||||
|
|
||||||
|
void update_model( int symbol );
|
||||||
|
void shift_context( int c );
|
||||||
|
void flush_model( int scale_factor );
|
||||||
|
|
||||||
|
int convert_int_to_symbol( int c, symbol *s );
|
||||||
|
void get_symbol_scale( symbol *s );
|
||||||
|
int convert_symbol_to_int( int count, symbol *s );
|
||||||
|
|
||||||
|
bool error;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
table **contexts;
|
||||||
|
table **storage;
|
||||||
|
|
||||||
|
int max_context;
|
||||||
|
int max_order;
|
||||||
|
int max_count;
|
||||||
|
|
||||||
|
inline void check_counts( table *context );
|
||||||
|
inline void rescale_table( table* context, int scale_factor );
|
||||||
|
inline void recursive_flush( table* context, int scale_factor );
|
||||||
|
inline void recursive_cleanup( table *context );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
shift context x2 model_s function
|
||||||
|
----------------------------------------------- */
|
||||||
|
static inline void shift_model( model_s* model, int ctx1, int ctx2 )
|
||||||
|
{
|
||||||
|
model->shift_context( ctx1 );
|
||||||
|
model->shift_context( ctx2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
shift context x3 model_s function
|
||||||
|
----------------------------------------------- */
|
||||||
|
static inline void shift_model( model_s* model, int ctx1, int ctx2, int ctx3 )
|
||||||
|
{
|
||||||
|
model->shift_context( ctx1 );
|
||||||
|
model->shift_context( ctx2 );
|
||||||
|
model->shift_context( ctx3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
shift context x2 model_b function
|
||||||
|
----------------------------------------------- */
|
||||||
|
static inline void shift_model( model_b* model, int ctx1, int ctx2 )
|
||||||
|
{
|
||||||
|
model->shift_context( ctx1 );
|
||||||
|
model->shift_context( ctx2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
shift context x3 model_b function
|
||||||
|
----------------------------------------------- */
|
||||||
|
static inline void shift_model( model_b* model, int ctx1, int ctx2, int ctx3 )
|
||||||
|
{
|
||||||
|
model->shift_context( ctx1 );
|
||||||
|
model->shift_context( ctx2 );
|
||||||
|
model->shift_context( ctx3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
generic model_s encoder function
|
||||||
|
----------------------------------------------- */
|
||||||
|
static inline void encode_ari( aricoder* encoder, model_s* model, int c )
|
||||||
|
{
|
||||||
|
static symbol s;
|
||||||
|
static int esc;
|
||||||
|
|
||||||
|
do {
|
||||||
|
esc = model->convert_int_to_symbol( c, &s );
|
||||||
|
encoder->encode( &s );
|
||||||
|
} while ( esc );
|
||||||
|
model->update_model( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
generic model_s decoder function
|
||||||
|
----------------------------------------------- */
|
||||||
|
static inline int decode_ari( aricoder* decoder, model_s* model )
|
||||||
|
{
|
||||||
|
static symbol s;
|
||||||
|
static unsigned int count;
|
||||||
|
static int c;
|
||||||
|
|
||||||
|
do{
|
||||||
|
model->get_symbol_scale( &s );
|
||||||
|
count = decoder->decode_count( &s );
|
||||||
|
c = model->convert_symbol_to_int( count, &s );
|
||||||
|
decoder->decode( &s );
|
||||||
|
} while ( c == ESCAPE_SYMBOL );
|
||||||
|
model->update_model( c );
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
generic model_b encoder function
|
||||||
|
----------------------------------------------- */
|
||||||
|
static inline void encode_ari( aricoder* encoder, model_b* model, int c )
|
||||||
|
{
|
||||||
|
static symbol s;
|
||||||
|
|
||||||
|
model->convert_int_to_symbol( c, &s );
|
||||||
|
encoder->encode( &s );
|
||||||
|
model->update_model( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
generic model_b decoder function
|
||||||
|
----------------------------------------------- */
|
||||||
|
static inline int decode_ari( aricoder* decoder, model_b* model )
|
||||||
|
{
|
||||||
|
static symbol s;
|
||||||
|
static unsigned int count;
|
||||||
|
static int c;
|
||||||
|
|
||||||
|
model->get_symbol_scale( &s );
|
||||||
|
count = decoder->decode_count( &s );
|
||||||
|
c = model->convert_symbol_to_int( count, &s );
|
||||||
|
decoder->decode( &s );
|
||||||
|
model->update_model( c );
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
910
filters/packjpg/bitops.cpp
Normal file
910
filters/packjpg/bitops.cpp
Normal file
|
@ -0,0 +1,910 @@
|
||||||
|
/*
|
||||||
|
This file contains special classes for bitwise
|
||||||
|
reading and writing of arrays
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include "bitops.h"
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 1024 * 1024
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
constructor for abitreader class
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
abitreader::abitreader( unsigned char* array, int size )
|
||||||
|
{
|
||||||
|
cbyte = 0;
|
||||||
|
cbit = 8;
|
||||||
|
peof = 0;
|
||||||
|
eof = false;
|
||||||
|
|
||||||
|
data = array;
|
||||||
|
lbyte = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
destructor for abitreader class
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
abitreader::~abitreader( void )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
reads n bits from abitreader
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
unsigned int abitreader::read( int nbits )
|
||||||
|
{
|
||||||
|
unsigned int retval = 0;
|
||||||
|
|
||||||
|
// safety check for eof
|
||||||
|
if ( eof ) {
|
||||||
|
peof += nbits;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( nbits >= cbit ) {
|
||||||
|
nbits -= cbit;
|
||||||
|
retval |= ( RBITS( data[cbyte], cbit ) << nbits );
|
||||||
|
cbit = 8;
|
||||||
|
if ( ++cbyte >= lbyte ) {
|
||||||
|
peof = nbits;
|
||||||
|
eof = true;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( nbits > 0 ) {
|
||||||
|
retval |= ( MBITS( data[cbyte], cbit, (cbit-nbits) ) );
|
||||||
|
cbit -= nbits;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
reads one bit from abitreader
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
unsigned char abitreader::read_bit( void )
|
||||||
|
{
|
||||||
|
unsigned char bit;
|
||||||
|
|
||||||
|
// safety check for eof
|
||||||
|
if (eof) {
|
||||||
|
peof++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read one bit
|
||||||
|
bit = BITN( data[cbyte], --cbit );
|
||||||
|
if ( cbit == 0 ) {
|
||||||
|
if ( ++cbyte == lbyte ) eof = true;
|
||||||
|
cbit = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
to skip padding from current byte
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
unsigned char abitreader::unpad( unsigned char fillbit )
|
||||||
|
{
|
||||||
|
if ( ( cbit == 8 ) || eof ) return fillbit;
|
||||||
|
else {
|
||||||
|
fillbit = read( 1 );
|
||||||
|
while ( cbit != 8 ) read( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return fillbit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
get current position in array
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int abitreader::getpos( void )
|
||||||
|
{
|
||||||
|
return cbyte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
get current bit position
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int abitreader::getbitp( void )
|
||||||
|
{
|
||||||
|
return cbit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
set byte and bit position
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void abitreader::setpos( int pbyte, int pbit )
|
||||||
|
{
|
||||||
|
if ( pbyte < lbyte ) {
|
||||||
|
// reset eof
|
||||||
|
eof = false;
|
||||||
|
// set positions
|
||||||
|
cbyte = pbyte;
|
||||||
|
cbit = pbit;
|
||||||
|
} else {
|
||||||
|
// set eof
|
||||||
|
eof = true;
|
||||||
|
// set positions
|
||||||
|
cbyte = lbyte;
|
||||||
|
cbit = 8;
|
||||||
|
peof = ( ( pbyte - lbyte ) * 8 ) + 8 - pbit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
rewind n bits
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void abitreader::rewind_bits( int nbits )
|
||||||
|
{
|
||||||
|
if ( eof ) {
|
||||||
|
if ( nbits > peof ) nbits -= peof;
|
||||||
|
else {
|
||||||
|
peof -= nbits;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eof = false;
|
||||||
|
}
|
||||||
|
for ( cbit += nbits; cbit > 8; cbyte--, cbit -= 8 );
|
||||||
|
if ( cbyte < 0 ) {
|
||||||
|
cbyte = 0;
|
||||||
|
cbit = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
constructor for abitwriter class
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
abitwriter::abitwriter( int size )
|
||||||
|
{
|
||||||
|
fillbit = 1;
|
||||||
|
adds = 65536;
|
||||||
|
cbyte = 0;
|
||||||
|
cbit = 8;
|
||||||
|
|
||||||
|
error = false;
|
||||||
|
fmem = true;
|
||||||
|
|
||||||
|
dsize = ( size > 0 ) ? size : adds;
|
||||||
|
data = ( unsigned char* ) malloc ( dsize );
|
||||||
|
if ( data == NULL ) {
|
||||||
|
error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill buffer with zeroes
|
||||||
|
memset( data, 0, dsize * sizeof( char ) );
|
||||||
|
// for ( int i = 0; i < dsize; i++ ) data[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
destructor for abitwriter class
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
abitwriter::~abitwriter( void )
|
||||||
|
{
|
||||||
|
// free memory if pointer was not given out
|
||||||
|
if ( fmem ) free( data );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
writes n bits to abitwriter
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void abitwriter::write( unsigned int val, int nbits )
|
||||||
|
{
|
||||||
|
// safety check for error
|
||||||
|
if ( error ) return;
|
||||||
|
|
||||||
|
// test if pointer beyond flush treshold
|
||||||
|
if ( cbyte > ( dsize - 5 ) ) {
|
||||||
|
dsize += adds;
|
||||||
|
data = (unsigned char*) realloc( data, dsize );
|
||||||
|
if ( data == NULL ) {
|
||||||
|
error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset( ( data + cbyte + 1 ), 0, ( dsize - ( cbyte + 1 ) ) * sizeof( char ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// write data
|
||||||
|
while ( nbits >= cbit ) {
|
||||||
|
data[cbyte] |= ( MBITS32(val, nbits, (nbits-cbit)) );
|
||||||
|
nbits -= cbit;
|
||||||
|
cbyte++;
|
||||||
|
cbit = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( nbits > 0 ) {
|
||||||
|
data[cbyte] |= ( (RBITS32(val, nbits)) << (cbit - nbits) );
|
||||||
|
cbit -= nbits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
writes one bit to abitwriter
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void abitwriter::write_bit( unsigned char bit )
|
||||||
|
{
|
||||||
|
// safety check for error
|
||||||
|
if ( error ) return;
|
||||||
|
|
||||||
|
// write data
|
||||||
|
if ( bit ) data[cbyte] |= 0x1 << (--cbit);
|
||||||
|
else --cbit;
|
||||||
|
if ( cbit == 0 ) {
|
||||||
|
// test if pointer beyond flush treshold
|
||||||
|
if ( ++cbyte > ( dsize - 5 ) ) {
|
||||||
|
dsize += adds;
|
||||||
|
data = (unsigned char*) realloc( data, dsize );
|
||||||
|
if ( data == NULL ) {
|
||||||
|
error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset( ( data + cbyte + 1 ), 0, ( dsize - ( cbyte + 1 ) ) * sizeof( char ) );
|
||||||
|
}
|
||||||
|
cbit = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
pads data using fillbit
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void abitwriter::pad( unsigned char fillbit )
|
||||||
|
{
|
||||||
|
while ( cbit < 8 )
|
||||||
|
write( fillbit, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
gets data array from abitwriter
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
unsigned char* abitwriter::getptr( void )
|
||||||
|
{
|
||||||
|
// data is padded here
|
||||||
|
pad( fillbit );
|
||||||
|
// forbid freeing memory
|
||||||
|
fmem = false;
|
||||||
|
// realloc data
|
||||||
|
data = (unsigned char*) realloc( data, cbyte );
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
gets size of data array from abitwriter
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int abitwriter::getpos( void )
|
||||||
|
{
|
||||||
|
return cbyte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
get current bit position
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int abitwriter::getbitp( void )
|
||||||
|
{
|
||||||
|
return cbit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
constructor for abytewriter class
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
abytereader::abytereader( unsigned char* array, int size )
|
||||||
|
{
|
||||||
|
cbyte = 0;
|
||||||
|
eof = false;
|
||||||
|
|
||||||
|
data = array;
|
||||||
|
lbyte = size;
|
||||||
|
|
||||||
|
if ( ( data == NULL ) || ( lbyte == 0 ) )
|
||||||
|
eof = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
destructor for abytewriter class
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
abytereader::~abytereader( void )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
reads 1 byte from abytereader
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int abytereader::read( unsigned char* byte )
|
||||||
|
{
|
||||||
|
if ( cbyte >= lbyte ) {
|
||||||
|
cbyte = lbyte;
|
||||||
|
eof = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*byte = data[ cbyte++ ];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
reads n bytes from abytereader
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int abytereader::read_n( unsigned char* byte, int n )
|
||||||
|
{
|
||||||
|
int nl = lbyte - cbyte;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( nl < n ) {
|
||||||
|
for ( i = 0; i < nl; i++ )
|
||||||
|
byte[ i ] = data[ cbyte + i ];
|
||||||
|
cbyte = lbyte;
|
||||||
|
eof = true;
|
||||||
|
return nl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for ( i = 0; i < n; i++ )
|
||||||
|
byte[ i ] = data[ cbyte + i ];
|
||||||
|
cbyte += n;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
go to position in data
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void abytereader::seek( int pos )
|
||||||
|
{
|
||||||
|
if ( pos >= lbyte ) {
|
||||||
|
cbyte = lbyte;
|
||||||
|
eof = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cbyte = pos;
|
||||||
|
eof = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
gets size of current data
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int abytereader::getsize( void )
|
||||||
|
{
|
||||||
|
return lbyte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
gets current position from abytereader
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int abytereader::getpos( void )
|
||||||
|
{
|
||||||
|
return cbyte;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
constructor for abytewriter class
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
abytewriter::abytewriter( int size )
|
||||||
|
{
|
||||||
|
adds = 65536;
|
||||||
|
cbyte = 0;
|
||||||
|
|
||||||
|
error = false;
|
||||||
|
fmem = true;
|
||||||
|
|
||||||
|
dsize = ( size > 0 ) ? size : adds;
|
||||||
|
data = (unsigned char*) malloc( dsize );
|
||||||
|
if ( data == NULL ) {
|
||||||
|
error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
destructor for abytewriter class
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
abytewriter::~abytewriter( void )
|
||||||
|
{
|
||||||
|
// free data if pointer is not read
|
||||||
|
if ( fmem ) free( data );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
writes 1 byte to abytewriter
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void abytewriter::write( unsigned char byte )
|
||||||
|
{
|
||||||
|
// safety check for error
|
||||||
|
if ( error ) return;
|
||||||
|
|
||||||
|
// test if pointer beyond flush threshold
|
||||||
|
if ( cbyte >= ( dsize - 2 ) ) {
|
||||||
|
dsize += adds;
|
||||||
|
data = (unsigned char*) realloc( data, dsize );
|
||||||
|
if ( data == NULL ) {
|
||||||
|
error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write data
|
||||||
|
data[ cbyte++ ] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
writes n byte to abytewriter
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void abytewriter::write_n( unsigned char* byte, int n )
|
||||||
|
{
|
||||||
|
// safety check for error
|
||||||
|
if ( error ) return;
|
||||||
|
|
||||||
|
// make sure that pointer doesn't get beyond flush threshold
|
||||||
|
while ( ( cbyte + n ) >= ( dsize - 2 ) ) {
|
||||||
|
dsize += adds;
|
||||||
|
data = (unsigned char*) realloc( data, dsize );
|
||||||
|
if ( data == NULL ) {
|
||||||
|
error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy data from array
|
||||||
|
while ( n-- > 0 )
|
||||||
|
data[ cbyte++ ] = *(byte++);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
gets data array from abytewriter
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
unsigned char* abytewriter::getptr( void )
|
||||||
|
{
|
||||||
|
// safety check for error
|
||||||
|
if ( error ) return NULL;
|
||||||
|
// forbid freeing memory
|
||||||
|
fmem = false;
|
||||||
|
// realloc data
|
||||||
|
data = (unsigned char*) realloc( data, cbyte );
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
peeks into data array from abytewriter
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
unsigned char* abytewriter::peekptr( void )
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
gets size of data array from abytewriter
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int abytewriter::getpos( void )
|
||||||
|
{
|
||||||
|
return cbyte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
reset without realloc
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void abytewriter::reset( void )
|
||||||
|
{
|
||||||
|
// set position of current byte
|
||||||
|
cbyte = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
constructor for iostream class
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
iostream::iostream( void* src, int srctype, int srcsize, int iomode )
|
||||||
|
{
|
||||||
|
// locally copy source, source type # and io mode #
|
||||||
|
source = src;
|
||||||
|
srct = srctype;
|
||||||
|
srcs = srcsize;
|
||||||
|
mode = iomode;
|
||||||
|
|
||||||
|
// don't free memory when reading - this will be useful if switching occurs
|
||||||
|
free_mem_sw = false;
|
||||||
|
|
||||||
|
// set binary mode for streams
|
||||||
|
#if defined( _WIN32 )
|
||||||
|
setmode( fileno( stdin ), O_BINARY );
|
||||||
|
setmode( fileno( stdout ), O_BINARY );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// open file/mem/stream
|
||||||
|
switch ( srct )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
open_file();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
open_mem();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
open_stream();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
destructor for iostream class
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
iostream::~iostream( void )
|
||||||
|
{
|
||||||
|
// if needed, write memory to stream or free memory from buffered stream
|
||||||
|
if ( srct == 2 ) {
|
||||||
|
if ( mode == 1 ) {
|
||||||
|
if ( !(mwrt->error) ) {
|
||||||
|
srcs = mwrt->getpos();
|
||||||
|
source = mwrt->getptr();
|
||||||
|
fwrite( source, sizeof( char ), srcs, stdout );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// free all buffers
|
||||||
|
if ( srct == 0 ) {
|
||||||
|
if ( fptr != NULL )
|
||||||
|
fclose( fptr );
|
||||||
|
}
|
||||||
|
else if ( mode == 0 ) {
|
||||||
|
if ( free_mem_sw )
|
||||||
|
free( source );
|
||||||
|
delete( mrdr );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
delete( mwrt );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
switches mode from reading to writing and vice versa
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void iostream::switch_mode( void )
|
||||||
|
{
|
||||||
|
// return immediately if there's an error
|
||||||
|
if ( chkerr() ) return;
|
||||||
|
|
||||||
|
|
||||||
|
if ( mode == 0 ) {
|
||||||
|
// WARNING: when switching from reading to writing, information might be lost forever
|
||||||
|
switch ( srct ) {
|
||||||
|
case 0:
|
||||||
|
fclose( fptr );
|
||||||
|
fptr = fopen( ( char* ) source, "wb" );
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
delete( mrdr );
|
||||||
|
if ( free_mem_sw )
|
||||||
|
free( source ); // see? I've told you so :-)
|
||||||
|
mwrt = new abytewriter( srcs );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mode = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// switching from writing to reading is a bit more complicated
|
||||||
|
switch ( srct ) {
|
||||||
|
case 0:
|
||||||
|
fclose( fptr );
|
||||||
|
fptr = fopen( ( char* ) source, "rb" );
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
source = mwrt->getptr();
|
||||||
|
srcs = mwrt->getpos();
|
||||||
|
delete( mwrt );
|
||||||
|
mrdr = new abytereader( ( unsigned char* ) source, srcs );
|
||||||
|
free_mem_sw = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
generic read function
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int iostream::read( void* to, int tpsize, int dtsize )
|
||||||
|
{
|
||||||
|
return ( srct == 0 ) ? read_file( to, tpsize, dtsize ) : read_mem( to, tpsize, dtsize );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
generic write function
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int iostream::write( void* from, int tpsize, int dtsize )
|
||||||
|
{
|
||||||
|
return ( srct == 0 ) ? write_file( from, tpsize, dtsize ) : write_mem( from, tpsize, dtsize );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
flush function
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int iostream::flush( void )
|
||||||
|
{
|
||||||
|
if ( srct == 0 )
|
||||||
|
fflush( fptr );
|
||||||
|
|
||||||
|
return getpos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
rewind to beginning of stream
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int iostream::rewind( void )
|
||||||
|
{
|
||||||
|
// WARNING: when writing, rewind might lose all your data
|
||||||
|
if ( srct == 0 )
|
||||||
|
fseek( fptr, 0, SEEK_SET );
|
||||||
|
else if ( mode == 0 )
|
||||||
|
mrdr->seek( 0 );
|
||||||
|
else
|
||||||
|
mwrt->reset();
|
||||||
|
|
||||||
|
return getpos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
get current position in stream
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int iostream::getpos( void )
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
if ( srct == 0 )
|
||||||
|
pos = ftell( fptr );
|
||||||
|
else if ( mode == 0 )
|
||||||
|
pos = mrdr->getpos();
|
||||||
|
else
|
||||||
|
pos = mwrt->getpos();
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
get size of file
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int iostream::getsize( void )
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
int siz;
|
||||||
|
|
||||||
|
if ( mode == 0 ) {
|
||||||
|
if ( srct == 0 ) {
|
||||||
|
pos = ftell( fptr );
|
||||||
|
fseek( fptr, 0, SEEK_END );
|
||||||
|
siz = ftell( fptr );
|
||||||
|
fseek( fptr, pos, SEEK_SET );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
siz = mrdr->getsize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
siz = getpos();
|
||||||
|
}
|
||||||
|
|
||||||
|
return siz;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
get data pointer (for mem io only)
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
unsigned char* iostream::getptr( void )
|
||||||
|
{
|
||||||
|
if ( srct == 1 )
|
||||||
|
return ( mode == 0 ) ? ( unsigned char* ) source : mwrt->getptr();
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
check for errors
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
bool iostream::chkerr( void )
|
||||||
|
{
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
|
// check for user input errors
|
||||||
|
if ( ( mode != 0 ) && ( mode != 1 ) )
|
||||||
|
error = true;
|
||||||
|
if ( ( srct != 0 ) && ( srct != 1 ) && ( srct != 2 ) )
|
||||||
|
error = true;
|
||||||
|
|
||||||
|
// check for io errors
|
||||||
|
if ( srct == 0 ) {
|
||||||
|
if ( fptr == NULL )
|
||||||
|
error = true;
|
||||||
|
else if ( ferror( fptr ) )
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
else if ( mode == 0 ) {
|
||||||
|
if ( mrdr == NULL )
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( mwrt == NULL )
|
||||||
|
error = true;
|
||||||
|
else if ( mwrt->error )
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
check for eof (read only)
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
bool iostream::chkeof( void )
|
||||||
|
{
|
||||||
|
if ( mode == 0 )
|
||||||
|
return ( srct == 0 ) ? feof( fptr ) : mrdr->eof;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
open function for files
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void iostream::open_file( void )
|
||||||
|
{
|
||||||
|
char* fn = (char*) source;
|
||||||
|
|
||||||
|
// open file for reading / writing
|
||||||
|
fptr = fopen( fn, ( mode == 0 ) ? "rb" : "wb" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
open function for memory
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void iostream::open_mem( void )
|
||||||
|
{
|
||||||
|
if ( mode == 0 )
|
||||||
|
mrdr = new abytereader( ( unsigned char* ) source, srcs );
|
||||||
|
else
|
||||||
|
mwrt = new abytewriter( srcs );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
open function for streams
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
void iostream::open_stream( void )
|
||||||
|
{
|
||||||
|
abytewriter* strwrt;
|
||||||
|
unsigned char* buffer;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( mode == 0 ) {
|
||||||
|
// read whole stream into memory buffer
|
||||||
|
strwrt = new abytewriter( 0 );
|
||||||
|
buffer = ( unsigned char* ) calloc( BUFFER_SIZE, sizeof( char ) );
|
||||||
|
if ( buffer != NULL ) {
|
||||||
|
while ( ( i = fread( buffer, sizeof( char ), BUFFER_SIZE, stdin ) ) > 0 )
|
||||||
|
strwrt->write_n( buffer, i );
|
||||||
|
}
|
||||||
|
if ( strwrt->error ) {
|
||||||
|
source = NULL;
|
||||||
|
srcs = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
source = strwrt->getptr();
|
||||||
|
srcs = strwrt->getpos();
|
||||||
|
}
|
||||||
|
delete ( strwrt );
|
||||||
|
free( buffer );
|
||||||
|
// free memory after done
|
||||||
|
free_mem_sw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for writing: simply open new stream in mem writer
|
||||||
|
// writing to stream will be done later
|
||||||
|
open_mem();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
write function for files
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int iostream::write_file( void* from, int tpsize, int dtsize )
|
||||||
|
{
|
||||||
|
return fwrite( from, tpsize, dtsize, fptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
read function for files
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int iostream::read_file( void* to, int tpsize, int dtsize )
|
||||||
|
{
|
||||||
|
return fread( to, tpsize, dtsize, fptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
write function for memory
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int iostream::write_mem( void* from, int tpsize, int dtsize )
|
||||||
|
{
|
||||||
|
int n = tpsize * dtsize;
|
||||||
|
|
||||||
|
mwrt->write_n( ( unsigned char* ) from, n );
|
||||||
|
|
||||||
|
return ( mwrt->error ) ? 0 : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
read function for memory
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
int iostream::read_mem( void* to, int tpsize, int dtsize )
|
||||||
|
{
|
||||||
|
int n = tpsize * dtsize;
|
||||||
|
|
||||||
|
return ( mrdr->read_n( ( unsigned char* ) to, n ) ) / tpsize;
|
||||||
|
}
|
169
filters/packjpg/bitops.h
Normal file
169
filters/packjpg/bitops.h
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
#define RBITS( c, n ) ( c & ( 0xFF >> (8 - n) ) )
|
||||||
|
#define LBITS( c, n ) ( c >> (8 - n) )
|
||||||
|
#define MBITS( c, l, r ) ( RBITS( c,l ) >> r )
|
||||||
|
#define RBITS16( c, n ) ( c & ( 0xFFFFFFFF >> (16 - n) ) )
|
||||||
|
#define LBITS16( c, n ) ( c >> (16 - n) )
|
||||||
|
#define MBITS16( c, l, r ) ( RBITS16( c,l ) >> r )
|
||||||
|
#define RBITS32( c, n ) ( c & ( 0xFFFFFFFF >> (32 - n) ) )
|
||||||
|
#define LBITS32( c, n ) ( c >> (32 - n) )
|
||||||
|
#define MBITS32( c, l, r ) ( RBITS32( c,l ) >> r )
|
||||||
|
#define BITN( c, n ) ( (c >> n) & 0x1 )
|
||||||
|
#define BITLEN( l, v ) for ( l = 0; ( v >> l ) > 0; l++ )
|
||||||
|
#define FDIV2( v, p ) ( ( v < 0 ) ? -( (-v) >> p ) : ( v >> p ) )
|
||||||
|
|
||||||
|
#define TYPE_FILE 0
|
||||||
|
#define TYPE_MEMORY 1
|
||||||
|
#define TYPE_STREAM 2
|
||||||
|
#define MODE_READ 0
|
||||||
|
#define MODE_WRITE 1
|
||||||
|
|
||||||
|
#define BTST_BUFF 1024 * 1024
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
class to read arrays bitwise
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
class abitreader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
abitreader( unsigned char* array, int size );
|
||||||
|
~abitreader( void );
|
||||||
|
unsigned int read( int nbits );
|
||||||
|
unsigned char read_bit( void );
|
||||||
|
unsigned char unpad( unsigned char fillbit );
|
||||||
|
int getpos( void );
|
||||||
|
int getbitp( void );
|
||||||
|
void setpos( int pbyte, int pbit );
|
||||||
|
void rewind_bits( int nbits );
|
||||||
|
bool eof;
|
||||||
|
int peof;
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned char* data;
|
||||||
|
int lbyte;
|
||||||
|
int cbyte;
|
||||||
|
int cbit;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
class to write arrays bitwise
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
class abitwriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
abitwriter( int size );
|
||||||
|
~abitwriter( void );
|
||||||
|
void write( unsigned int val, int nbits );
|
||||||
|
void write_bit( unsigned char bit );
|
||||||
|
void pad ( unsigned char fillbit );
|
||||||
|
unsigned char* getptr( void );
|
||||||
|
int getpos( void );
|
||||||
|
int getbitp( void );
|
||||||
|
bool error;
|
||||||
|
unsigned char fillbit;
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned char* data;
|
||||||
|
int dsize;
|
||||||
|
int adds;
|
||||||
|
int lbyte;
|
||||||
|
int cbyte;
|
||||||
|
int cbit;
|
||||||
|
bool fmem;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
class to read arrays bytewise
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
class abytereader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
abytereader( unsigned char* array, int size );
|
||||||
|
~abytereader( void );
|
||||||
|
int read( unsigned char* byte );
|
||||||
|
int read_n( unsigned char* byte, int n );
|
||||||
|
void seek( int pos );
|
||||||
|
int getsize( void );
|
||||||
|
int getpos( void );
|
||||||
|
bool eof;
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned char* data;
|
||||||
|
int lbyte;
|
||||||
|
int cbyte;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
class to write arrays bytewise
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
class abytewriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
abytewriter( int size );
|
||||||
|
~abytewriter( void );
|
||||||
|
void write( unsigned char byte );
|
||||||
|
void write_n( unsigned char* byte, int n );
|
||||||
|
unsigned char* getptr( void );
|
||||||
|
unsigned char* peekptr( void );
|
||||||
|
int getpos( void );
|
||||||
|
void reset( void );
|
||||||
|
bool error;
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned char* data;
|
||||||
|
int dsize;
|
||||||
|
int adds;
|
||||||
|
int lbyte;
|
||||||
|
int cbyte;
|
||||||
|
bool fmem;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
class for input and output from file or memory
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
class iostream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
iostream( void* src, int srctype, int srcsize, int iomode );
|
||||||
|
~iostream( void );
|
||||||
|
void switch_mode( void );
|
||||||
|
int read( void* to, int tpsize, int dtsize );
|
||||||
|
int write( void* from, int tpsize, int dtsize );
|
||||||
|
int flush( void );
|
||||||
|
int rewind( void );
|
||||||
|
int getpos( void );
|
||||||
|
int getsize( void );
|
||||||
|
unsigned char* getptr( void );
|
||||||
|
bool chkerr( void );
|
||||||
|
bool chkeof( void );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void open_file( void );
|
||||||
|
void open_mem( void );
|
||||||
|
void open_stream( void );
|
||||||
|
|
||||||
|
int write_file( void* from, int tpsize, int dtsize );
|
||||||
|
int read_file( void* to, int tpsize, int dtsize );
|
||||||
|
int write_mem( void* from, int tpsize, int dtsize );
|
||||||
|
int read_mem( void* to, int tpsize, int dtsize );
|
||||||
|
|
||||||
|
FILE* fptr;
|
||||||
|
abytewriter* mwrt;
|
||||||
|
abytereader* mrdr;
|
||||||
|
|
||||||
|
bool free_mem_sw;
|
||||||
|
void* source;
|
||||||
|
int mode;
|
||||||
|
int srct;
|
||||||
|
int srcs;
|
||||||
|
};
|
1166
filters/packjpg/dct8x8.h
Normal file
1166
filters/packjpg/dct8x8.h
Normal file
File diff suppressed because it is too large
Load diff
165
filters/packjpg/lgpl-3.0.txt
Normal file
165
filters/packjpg/lgpl-3.0.txt
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
7213
filters/packjpg/packjpg.cpp
Normal file
7213
filters/packjpg/packjpg.cpp
Normal file
File diff suppressed because it is too large
Load diff
40
filters/packjpg/packjpglib.h
Normal file
40
filters/packjpg/packjpglib.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// packJPGlib.h - function declarations for the packJPG library
|
||||||
|
#if defined BUILD_DLL
|
||||||
|
#define EXPORT __declspec( dllexport )
|
||||||
|
#else
|
||||||
|
#define EXPORT extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* -----------------------------------------------
|
||||||
|
function declarations: library only functions
|
||||||
|
----------------------------------------------- */
|
||||||
|
|
||||||
|
EXPORT bool pjglib_convert_stream2stream( char* msg );
|
||||||
|
EXPORT bool pjglib_convert_file2file( char* in, char* out, char* msg );
|
||||||
|
EXPORT bool pjglib_convert_stream2mem( unsigned char** out_file, unsigned int* out_size, char* msg );
|
||||||
|
EXPORT void pjglib_init_streams( void* in_src, int in_type, int in_size, void* out_dest, int out_type );
|
||||||
|
EXPORT const char* pjglib_version_info( void );
|
||||||
|
EXPORT const char* pjglib_short_name( void );
|
||||||
|
|
||||||
|
/* a short reminder about input/output stream types
|
||||||
|
for the pjglib_init_streams() function
|
||||||
|
|
||||||
|
if input is file
|
||||||
|
----------------
|
||||||
|
in_scr -> name of input file
|
||||||
|
in_type -> 0
|
||||||
|
in_size -> ignore
|
||||||
|
|
||||||
|
if input is memory
|
||||||
|
------------------
|
||||||
|
in_scr -> array containg data
|
||||||
|
in_type -> 1
|
||||||
|
in_size -> size of data array
|
||||||
|
|
||||||
|
if input is *FILE (f.e. stdin)
|
||||||
|
------------------------------
|
||||||
|
in_src -> stream pointer
|
||||||
|
in_type -> 2
|
||||||
|
in_size -> ignore
|
||||||
|
|
||||||
|
vice versa for output streams! */
|
1659
filters/packjpg/pjpgtbl.h
Normal file
1659
filters/packjpg/pjpgtbl.h
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue