Initial import
git-svn-id: http://moon:8086/svn/software/trunk/libsrc/libtiff_2007@1 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
Executable
+259
@@ -0,0 +1,259 @@
|
||||
# $Header: /home/cvsroot/libtiff/tools/Makefile.in,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $
|
||||
#
|
||||
# @WARNING@
|
||||
#
|
||||
# TIFF Library Tools
|
||||
#
|
||||
# Copyright (c) 1988-1997 Sam Leffler
|
||||
# Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and
|
||||
# its documentation for any purpose is hereby granted without fee, provided
|
||||
# that (i) the above copyright notices and this permission notice appear in
|
||||
# all copies of the software and related documentation, and (ii) the names of
|
||||
# Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
# publicity relating to the software without the specific, prior written
|
||||
# permission of Stanford and Silicon Graphics.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
DEPTH = ..
|
||||
|
||||
SRCDIR = @RELSRCDIR@/tools
|
||||
LIBDIR = @RELSRCDIR@/libtiff
|
||||
|
||||
#
|
||||
# VERSION: @VERSION@
|
||||
# DATE: @DATE@
|
||||
# TARGET: @TARGET@
|
||||
# CCOMPILER: @CCOMPILER@
|
||||
#
|
||||
SHELL = @SCRIPT_SH@
|
||||
NULL =
|
||||
CC = @CCOMPILER@
|
||||
INSTALL = @INSTALL@
|
||||
#
|
||||
COPTS = @GCOPTS@
|
||||
OPTIMIZER=-O
|
||||
IPATH = -I. -I${SRCDIR} -I${LIBDIR}
|
||||
CFLAGS = @ENVOPTS@ ${COPTS} ${OPTIMIZER} ${IPATH}
|
||||
#
|
||||
TIFFLIB = ${DEPTH}/libtiff/libtiff.@DSOSUF@
|
||||
LIBJPEG = @LIBJPEG@
|
||||
LIBGZ = @LIBGZ@
|
||||
LIBTIFF = @TIFFLIBREF@
|
||||
LIBPORT = @LIBPORT@
|
||||
MACHLIBS= @MACHDEPLIBS@
|
||||
LIBS = ${LIBTIFF} ${LIBJPEG} ${LIBGZ} ${LIBPORT} ${MACHLIBS}
|
||||
#
|
||||
OBJS= \
|
||||
fax2tiff.o \
|
||||
fax2ps.o \
|
||||
gif2tiff.o \
|
||||
pal2rgb.o \
|
||||
ppm2tiff.o \
|
||||
rgb2ycbcr.o \
|
||||
ras2tiff.o \
|
||||
thumbnail.o \
|
||||
tiff2bw.o \
|
||||
tiff2rgba.o \
|
||||
tiff2ps.o \
|
||||
tiffcmp.o \
|
||||
tiffcp.o \
|
||||
tiffdither.o \
|
||||
tiffdump.o \
|
||||
tiffinfo.o \
|
||||
tiffmedian.o \
|
||||
tiffsplit.o \
|
||||
${NULL}
|
||||
TARGETS =\
|
||||
fax2tiff \
|
||||
fax2ps \
|
||||
gif2tiff \
|
||||
pal2rgb \
|
||||
ppm2tiff \
|
||||
rgb2ycbcr \
|
||||
thumbnail \
|
||||
ras2tiff \
|
||||
tiff2bw \
|
||||
tiff2rgba \
|
||||
tiff2ps \
|
||||
tiffcmp \
|
||||
tiffcp \
|
||||
tiffdither \
|
||||
tiffdump \
|
||||
tiffinfo \
|
||||
tiffmedian \
|
||||
tiffsplit \
|
||||
${NULL}
|
||||
|
||||
all: ${TARGETS}
|
||||
@if [ "@LIBIMAGE@" = yes ]; then \
|
||||
${MAKE} sgi2tiff; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
@if [ "@LIBGL@" = yes ]; then \
|
||||
${MAKE} tiffgt tiffsv; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
install: all
|
||||
${INSTALL} -idb nostrip tiff.sw.tools -m 755 -dir @DIR_BIN@
|
||||
${INSTALL} -idb nostrip tiff.sw.tools -m 755 -F @DIR_BIN@ -O ${TARGETS}
|
||||
@if [ "@LIBIMAGE@" = yes ]; then \
|
||||
${INSTALL} -idb tiff.sw.tools -m 755 -F @DIR_BIN@ -O sgi2tiff; \
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
@if [ "@LIBGL@" = yes ]; then \
|
||||
${INSTALL} -idb tiff.sw.tools -m 755 -F @DIR_BIN@ -O tiffgt tiffsv;\
|
||||
else \
|
||||
true; \
|
||||
fi
|
||||
clean:
|
||||
rm -f ${TARGETS} ${OBJS} sgigt.o tiffgt sgisv.o tiffsv \
|
||||
sgi2tiff.o sgi2tiff core a.out ycbcr
|
||||
|
||||
#
|
||||
# System-independent tools
|
||||
#
|
||||
|
||||
tiffinfo: tiffinfo.o ${TIFFLIB}
|
||||
${CC} -o tiffinfo ${CFLAGS} tiffinfo.o ${LIBS}
|
||||
tiffinfo.o: ${SRCDIR}/tiffinfo.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/tiffinfo.c
|
||||
|
||||
tiffcmp:tiffcmp.o ${TIFFLIB}
|
||||
${CC} -o tiffcmp ${CFLAGS} tiffcmp.o ${LIBS}
|
||||
tiffcmp.o: ${SRCDIR}/tiffcmp.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/tiffcmp.c
|
||||
|
||||
tiffcp: tiffcp.o ${TIFFLIB}
|
||||
${CC} -o tiffcp ${CFLAGS} tiffcp.o ${LIBS}
|
||||
tiffcp.o: ${SRCDIR}/tiffcp.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/tiffcp.c
|
||||
|
||||
tiffdump: tiffdump.o
|
||||
${CC} -o tiffdump ${CFLAGS} tiffdump.o ${LIBS}
|
||||
tiffdump.o: ${SRCDIR}/tiffdump.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/tiffdump.c
|
||||
|
||||
tiffmedian: tiffmedian.o ${TIFFLIB}
|
||||
${CC} -o tiffmedian ${CFLAGS} tiffmedian.o ${LIBS}
|
||||
tiffmedian.o: ${SRCDIR}/tiffmedian.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/tiffmedian.c
|
||||
|
||||
tiffsplit: tiffsplit.o ${TIFFLIB}
|
||||
${CC} -o tiffsplit ${CFLAGS} tiffsplit.o ${LIBS}
|
||||
tiffsplit.o: ${SRCDIR}/tiffsplit.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/tiffsplit.c
|
||||
|
||||
tiff2ps: tiff2ps.o ${TIFFLIB}
|
||||
${CC} -o tiff2ps ${CFLAGS} tiff2ps.o ${LIBS}
|
||||
tiff2ps.o: ${SRCDIR}/tiff2ps.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/tiff2ps.c
|
||||
|
||||
#
|
||||
# Junky stuff... programs that are more examples of how
|
||||
# to use the library than full-blown useful tools.
|
||||
#
|
||||
|
||||
# convert RGB image to B&W
|
||||
tiff2bw: tiff2bw.o ${TIFFLIB}
|
||||
${CC} -o tiff2bw ${CFLAGS} tiff2bw.o ${LIBS}
|
||||
tiff2bw.o: ${SRCDIR}/tiff2bw.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/tiff2bw.c
|
||||
|
||||
# convert anything to RGBA.
|
||||
tiff2rgba: tiff2rgba.o ${TIFFLIB}
|
||||
${CC} -o tiff2rgba ${CFLAGS} tiff2rgba.o ${LIBS}
|
||||
tiff2rgba.o: ${SRCDIR}/tiff2rgba.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/tiff2rgba.c
|
||||
|
||||
# convert B&W image to bilevel w/ FS dithering
|
||||
tiffdither: tiffdither.o ${TIFFLIB}
|
||||
${CC} -o tiffdither ${CFLAGS} tiffdither.o ${LIBS}
|
||||
tiffdither.o: ${SRCDIR}/tiffdither.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/tiffdither.c
|
||||
|
||||
# simple Sun rasterfile converter
|
||||
ras2tiff: ras2tiff.o ${TIFFLIB}
|
||||
${CC} -o ras2tiff ${CFLAGS} ras2tiff.o ${LIBS}
|
||||
ras2tiff.o: ${SRCDIR}/ras2tiff.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/ras2tiff.c
|
||||
|
||||
# simple GIF converter
|
||||
gif2tiff: gif2tiff.o ${TIFFLIB}
|
||||
${CC} -o gif2tiff ${CFLAGS} gif2tiff.o ${LIBS}
|
||||
gif2tiff.o: ${SRCDIR}/gif2tiff.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/gif2tiff.c
|
||||
|
||||
# very limited PBM converter
|
||||
ppm2tiff: ppm2tiff.o ${TIFFLIB}
|
||||
${CC} -o ppm2tiff ${CFLAGS} ppm2tiff.o ${LIBS}
|
||||
ppm2tiff.o: ${SRCDIR}/ppm2tiff.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/ppm2tiff.c
|
||||
|
||||
# Group 3/4 FAX file converter
|
||||
fax2tiff: fax2tiff.o ${TIFFLIB}
|
||||
${CC} -o fax2tiff ${CFLAGS} fax2tiff.o ${LIBS}
|
||||
fax2tiff.o: ${SRCDIR}/fax2tiff.c
|
||||
${CC} -c -I${LIBDIR} -I${DEPTH}/libtiff ${CFLAGS} ${SRCDIR}/fax2tiff.c
|
||||
|
||||
# Group 3/4 FAX to encoded PS converter
|
||||
fax2ps: fax2ps.o ${TIFFLIB}
|
||||
${CC} -o fax2ps ${CFLAGS} fax2ps.o ${LIBS}
|
||||
fax2ps.o: ${SRCDIR}/fax2ps.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/fax2ps.c
|
||||
|
||||
# convert Palette image to RGB
|
||||
pal2rgb: pal2rgb.o ${TIFFLIB}
|
||||
${CC} -o pal2rgb ${CFLAGS} pal2rgb.o ${LIBS}
|
||||
pal2rgb.o: ${SRCDIR}/pal2rgb.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/pal2rgb.c
|
||||
|
||||
# convert RGB image to YCbCr
|
||||
rgb2ycbcr: rgb2ycbcr.o ${TIFFLIB}
|
||||
${CC} -o rgb2ycbcr ${CFLAGS} rgb2ycbcr.o ${LIBS}
|
||||
rgb2ycbcr.o: ${SRCDIR}/rgb2ycbcr.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/rgb2ycbcr.c
|
||||
|
||||
# generate thumbnail images from fax (example of SubIFD usage)
|
||||
thumbnail: thumbnail.o ${TIFFLIB}
|
||||
${CC} -o thumbnail ${CFLAGS} thumbnail.o ${LIBS}
|
||||
thumbnail.o: ${SRCDIR}/thumbnail.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/thumbnail.c
|
||||
|
||||
#
|
||||
# System-specific tools.
|
||||
#
|
||||
|
||||
#
|
||||
# sgi2tiff converts SGI RGB images to TIFF; it requires
|
||||
# the SGI image library -limage.
|
||||
#
|
||||
sgi2tiff: sgi2tiff.o ${TIFFLIB}
|
||||
${CC} -o sgi2tiff ${CFLAGS} sgi2tiff.o -limage ${LIBS}
|
||||
sgi2tiff.o: ${SRCDIR}/sgi2tiff.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/sgi2tiff.c
|
||||
|
||||
# SGI versions of tiffgt & tiffsv that require -lgl
|
||||
tiffgt: sgigt.o ${TIFFLIB}
|
||||
${CC} -o tiffgt ${CFLAGS} sgigt.o -lgutil -lgl ${LIBS}
|
||||
sgigt.o: ${SRCDIR}/sgigt.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/sgigt.c
|
||||
|
||||
tiffsv: sgisv.o ${TIFFLIB}
|
||||
${CC} -o tiffsv ${CFLAGS} sgisv.o -lgutil -lgl ${LIBS}
|
||||
sgisv.o: ${SRCDIR}/sgisv.c
|
||||
${CC} -c ${CFLAGS} ${SRCDIR}/sgisv.c
|
||||
Executable
+137
@@ -0,0 +1,137 @@
|
||||
# $Header: /home/cvsroot/libtiff/tools/Makefile.lcc,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $
|
||||
#
|
||||
# TIFF Library Tools
|
||||
#
|
||||
# Copyright (c) 1988-1997 Sam Leffler
|
||||
# Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and
|
||||
# its documentation for any purpose is hereby granted without fee, provided
|
||||
# that (i) the above copyright notices and this permission notice appear in
|
||||
# all copies of the software and related documentation, and (ii) the names of
|
||||
# Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
# publicity relating to the software without the specific, prior written
|
||||
# permission of Stanford and Silicon Graphics.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
NULL=
|
||||
IPATH= -I..\libtiff
|
||||
#
|
||||
# If you don't want the public domain getopt code, then
|
||||
# simply null this out and you'll get whatever is in your
|
||||
# libc (or similar).
|
||||
#
|
||||
GETOPT= getopt.o
|
||||
#
|
||||
# Library-wide configuration defines:
|
||||
# Note that if you change the library-wide configuration, you'll
|
||||
# need to manual force a full rebuild.
|
||||
#
|
||||
CONF_LIBRARY=\
|
||||
${NULL}
|
||||
COPTS= -Oloop -cwagshf -d1 -b0 -v -DNDEBUG -rr -j135i
|
||||
CFLAGS= ${COPTS} ${IPATH} -DBINMODE='"b"'
|
||||
#
|
||||
LIBTIFF=..\libtiff\tiffrnb.lib
|
||||
LIBS= -l${LIBTIFF} -lm
|
||||
MACHALL=ras2tiff.ttp
|
||||
OBJS=\
|
||||
fax2tiff.o \
|
||||
gif2tiff.o \
|
||||
pal2rgb.o \
|
||||
ppm2tiff.o \
|
||||
rgb2ycbcr.o \
|
||||
tiff2bw.o \
|
||||
tiff2rgba.o \
|
||||
tiff2ps.o \
|
||||
tiffcmp.o \
|
||||
tiffcp.o \
|
||||
tiffdither.o \
|
||||
tiffdump.o \
|
||||
tiffinfo.o \
|
||||
tiffmedian.o \
|
||||
tiffsplit.o \
|
||||
ras2tiff.o \
|
||||
${GETOPT} \
|
||||
${NULL}
|
||||
ALL=\
|
||||
fax2tiff.ttp \
|
||||
gif2tiff.ttp \
|
||||
pal2rgb.ttp \
|
||||
ppm2tiff.ttp \
|
||||
rgb2ycbcr.ttp \
|
||||
tiff2bw.ttp \
|
||||
tiff2rgba.ttp \
|
||||
tiff2ps.ttp \
|
||||
tiffcmp.ttp \
|
||||
tiffcp.ttp \
|
||||
tiffdither.ttp \
|
||||
tiffdump.ttp \
|
||||
tiffinfo.ttp \
|
||||
tiffmedian.ttp \
|
||||
tiffsplit.ttp \
|
||||
${MACHALL} \
|
||||
${NULL}
|
||||
|
||||
all: ${ALL}
|
||||
|
||||
tiffinfo.ttp: tiffinfo.c ${GETOPT} ${LIBTIFF}
|
||||
${CC} -o tiffinfo.ttp ${CFLAGS} tiffinfo.c ${GETOPT} ${LIBS}
|
||||
tiffcmp.ttp: tiffcmp.c ${GETOPT} ${LIBTIFF}
|
||||
${CC} -o tiffcmp.ttp ${CFLAGS} tiffcmp.c ${GETOPT} ${LIBS}
|
||||
tiffcp.ttp: tiffcp.c ${LIBTIFF}
|
||||
${CC} -o tiffcp.ttp ${CFLAGS} tiffcp.c ${LIBS}
|
||||
tiffdump.ttp: tiffdump.c
|
||||
${CC} -o tiffdump.ttp ${CFLAGS} tiffdump.c -lm ${LIBS}
|
||||
tiffmedian.ttp: tiffmedian.c ${LIBTIFF}
|
||||
${CC} -o tiffmedian.ttp ${CFLAGS} tiffmedian.c ${LIBS}
|
||||
tiffsplit.ttp: tiffsplit.c ${LIBTIFF}
|
||||
${CC} -o tiffsplit.ttp ${CFLAGS} tiffsplit.c ${LIBS}
|
||||
tiff2ps.ttp: tiff2ps.c ${LIBTIFF}
|
||||
${CC} -o tiff2ps.ttp ${CFLAGS} tiff2ps.c ${LIBS}
|
||||
# junky stuff...
|
||||
# convert RGB image to B&W
|
||||
tiff2bw.ttp: tiff2bw.c ${GETOPT} ${LIBTIFF}
|
||||
${CC} -o tiff2bw.ttp ${CFLAGS} tiff2bw.c ${GETOPT} ${LIBS}
|
||||
# convert anything to RGBA
|
||||
tiff2rgba.ttp: tiff2rgba.c ${GETOPT} ${LIBTIFF}
|
||||
${CC} -o tiff2rgba.ttp ${CFLAGS} tiff2rgba.c ${GETOPT} ${LIBS}
|
||||
# convert B&W image to bilevel w/ FS dithering
|
||||
tiffdither.ttp: tiffdither.c ${LIBTIFF}
|
||||
${CC} -o tiffdither.ttp ${CFLAGS} tiffdither.c ${LIBS}
|
||||
# Group 3 FAX file converter
|
||||
fax2tiff.ttp: fax2tiff.c ${GETOPT} ${LIBTIFF}
|
||||
${CC} -o fax2tiff.ttp ${CFLAGS} ${CONF_LIBRARY} fax2tiff.c ${GETOPT} ${LIBS}
|
||||
# convert Palette image to RGB
|
||||
pal2rgb.ttp: pal2rgb.c ${LIBTIFF}
|
||||
${CC} -o pal2rgb.ttp ${CFLAGS} pal2rgb.c ${LIBS}
|
||||
# convert RGB image to YCbCr
|
||||
rgb2ycbcr.ttp: rgb2ycbcr.c ${GETOPT} ${LIBTIFF}
|
||||
${CC} -o rgb2ycbcr.ttp ${CFLAGS} rgb2ycbcr.c ${GETOPT} ${LIBS}
|
||||
# GIF converter
|
||||
gif2tiff.ttp: gif2tiff.c ${LIBTIFF}
|
||||
${CC} -o gif2tiff.ttp ${CFLAGS} gif2tiff.c ${LIBS}
|
||||
# PBM converter
|
||||
ppm2tiff.ttp: ppm2tiff.c ${LIBTIFF}
|
||||
${CC} -o ppm2tiff.ttp ${CFLAGS} ppm2tiff.c ${LIBS}
|
||||
# Sun rasterfile converter
|
||||
ras2tiff.ttp: ras2tiff.c ${LIBTIFF}
|
||||
${CC} -o ras2tiff.ttp ${CFLAGS} ras2tiff.c ${LIBS}
|
||||
# generate thumbnail images from fax
|
||||
thumbnail: thumbnail.c ${LIBTIFF}
|
||||
${CC} -o thumbnail ${CFLAGS} thumbnail.c ${LIBS} -lm
|
||||
|
||||
install: all
|
||||
|
||||
clean:
|
||||
rm -f ${ALL} ${OBJS} ycbcr.ttp
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# Simple MS VC++ Makefile
|
||||
#
|
||||
# To build:
|
||||
# C:\libtiff\tools> nmake /f makefile.vc
|
||||
#
|
||||
TARGETS = tiffcp.exe tiffinfo.exe tiffdump.exe fax2tiff.exe \
|
||||
fax2ps.exe gif2tiff.exe pal2rgb.exe ppm2tiff.exe \
|
||||
rgb2ycbcr.exe thumbnail.exe ras2tiff.exe tiff2bw.exe \
|
||||
tiff2rgba.exe tiff2ps.exe tiffcmp.exe tiffdither.exe \
|
||||
tiffmedian.exe tiffsplit.exe
|
||||
|
||||
EXTRA_OBJ = strcasecmp.obj getopt.obj
|
||||
|
||||
LIBS = ..\libtiff\libtiff.lib
|
||||
|
||||
CFLAGS = /nologo -I..\libtiff /D_WINDOWS
|
||||
|
||||
default: $(EXTRA_OBJ) $(TARGETS)
|
||||
|
||||
.c.exe:
|
||||
$(CC) $(CFLAGS) $*.c $(EXTRA_OBJ) $(LIBS)
|
||||
|
||||
getopt.obj: ..\port\getopt.c
|
||||
$(CC) /c $(CFLAGS) ..\port\getopt.c
|
||||
|
||||
strcasecmp.obj: ..\port\strcasecmp.c
|
||||
$(CC) /c $(CFLAGS) ..\port\strcasecmp.c
|
||||
|
||||
clean:
|
||||
del *.obj *.exe
|
||||
Executable
+437
@@ -0,0 +1,437 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/fax2ps.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $" */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(VMS)
|
||||
#include <unixio.h>
|
||||
#elif defined(_WINDOWS)
|
||||
#include <io.h>
|
||||
#define off_t toff_t
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
float defxres = 204.; /* default x resolution (pixels/inch) */
|
||||
float defyres = 98.; /* default y resolution (lines/inch) */
|
||||
const float basePageWidth = 8.5;
|
||||
const float basePageHeight = 11.0;
|
||||
const float half = 0.5;
|
||||
const float points = 72.0;
|
||||
float pageWidth = 8.5; /* image page width (inches) */
|
||||
float pageHeight = 11.0; /* image page length (inches) */
|
||||
int scaleToPage = 0; /* if true, scale raster to page dimensions */
|
||||
int totalPages = 0; /* total # pages printed */
|
||||
int row; /* current output row */
|
||||
int maxline = 512; /* max output line of PostScript */
|
||||
|
||||
/*
|
||||
* Turn a bit-mapped scanline into the appropriate sequence
|
||||
* of PostScript characters to be rendered.
|
||||
*
|
||||
* Original version written by Bret D. Whissel,
|
||||
* Florida State University Meteorology Department
|
||||
* March 13-15, 1995.
|
||||
*/
|
||||
static void
|
||||
printruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
|
||||
{
|
||||
static struct {
|
||||
char white, black;
|
||||
short width;
|
||||
} WBarr[] = {
|
||||
{ 'd', 'n', 512 }, { 'e', 'o', 256 }, { 'f', 'p', 128 },
|
||||
{ 'g', 'q', 64 }, { 'h', 'r', 32 }, { 'i', 's', 16 },
|
||||
{ 'j', 't', 8 }, { 'k', 'u', 4 }, { 'l', 'v', 2 },
|
||||
{ 'm', 'w', 1 }
|
||||
};
|
||||
static char* svalue =
|
||||
" !\"#$&'*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abc";
|
||||
int colormode = 1; /* 0 for white, 1 for black */
|
||||
int runlength = 0;
|
||||
int n = maxline;
|
||||
int x = 0;
|
||||
int l;
|
||||
|
||||
(void) buf;
|
||||
printf("%d m(", row++);
|
||||
while (runs < erun) {
|
||||
if (!runlength) {
|
||||
colormode ^= 1;
|
||||
runlength = *runs++;
|
||||
if (x+runlength > lastx)
|
||||
runlength = runs[-1] = lastx-x;
|
||||
x += runlength;
|
||||
if (!colormode && runs == erun)
|
||||
break; /* don't bother printing the final white run */
|
||||
}
|
||||
/*
|
||||
* If a runlength is greater than 6 pixels, then spit out
|
||||
* black or white characters until the runlength drops to
|
||||
* 6 or less. Once a runlength is <= 6, then combine black
|
||||
* and white runlengths until a 6-pixel pattern is obtained.
|
||||
* Then write out the special character. Six-pixel patterns
|
||||
* were selected since 64 patterns is the largest power of
|
||||
* two less than the 92 "easily printable" PostScript
|
||||
* characters (i.e., no escape codes or octal chars).
|
||||
*/
|
||||
l = 0;
|
||||
while (runlength > 6) { /* Run is greater than six... */
|
||||
if (runlength >= WBarr[l].width) {
|
||||
if (n == 0) {
|
||||
putchar('\n');
|
||||
n = maxline;
|
||||
}
|
||||
putchar(colormode ? WBarr[l].black : WBarr[l].white), n--;
|
||||
runlength -= WBarr[l].width;
|
||||
} else
|
||||
l++;
|
||||
}
|
||||
while (runlength > 0 && runlength <= 6) {
|
||||
int bitsleft = 6;
|
||||
int t = 0;
|
||||
while (bitsleft) {
|
||||
if (runlength <= bitsleft) {
|
||||
if (colormode)
|
||||
t |= ((1 << runlength)-1) << (bitsleft-runlength);
|
||||
bitsleft -= runlength;
|
||||
runlength = 0;
|
||||
if (bitsleft) {
|
||||
if (runs >= erun)
|
||||
break;
|
||||
colormode ^= 1;
|
||||
runlength = *runs++;
|
||||
if (x+runlength > lastx)
|
||||
runlength = runs[-1] = lastx-x;
|
||||
x += runlength;
|
||||
}
|
||||
} else { /* runlength exceeds bits left */
|
||||
if (colormode)
|
||||
t |= ((1 << bitsleft)-1);
|
||||
runlength -= bitsleft;
|
||||
bitsleft = 0;
|
||||
}
|
||||
}
|
||||
if (n == 0) {
|
||||
putchar('\n');
|
||||
n = maxline;
|
||||
}
|
||||
putchar(svalue[t]), n--;
|
||||
}
|
||||
}
|
||||
printf(")s\n");
|
||||
}
|
||||
|
||||
void
|
||||
printTIF(TIFF* tif, int pageNumber)
|
||||
{
|
||||
uint32 w, h;
|
||||
uint16 unit;
|
||||
float xres, yres;
|
||||
tstrip_t s, ns;
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
|
||||
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
|
||||
if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres)) {
|
||||
TIFFWarning(TIFFFileName(tif),
|
||||
"No x-resolution, assuming %g dpi", defxres);
|
||||
xres = defxres;
|
||||
}
|
||||
if (!TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres)) {
|
||||
TIFFWarning(TIFFFileName(tif),
|
||||
"No y-resolution, assuming %g lpi", defyres);
|
||||
yres = defyres; /* XXX */
|
||||
}
|
||||
if (TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &unit) &&
|
||||
unit == RESUNIT_CENTIMETER) {
|
||||
xres *= 25.4;
|
||||
yres *= 25.4;
|
||||
}
|
||||
|
||||
printf("%%%%Page: \"%d\" %d\n", pageNumber, pageNumber);
|
||||
printf("/$pageTop save def gsave\n");
|
||||
if (scaleToPage) {
|
||||
float yscale = pageHeight / (h/yres);
|
||||
float xscale = pageWidth / (w/xres);
|
||||
printf("%d %d translate\n",
|
||||
(int) (((basePageWidth - pageWidth) * points) * half),
|
||||
(int)((yscale*(h/yres)*points) +
|
||||
(basePageHeight - pageHeight) * points * half) );
|
||||
printf("%g %g scale\n", (72.*xscale)/xres, -(72.*yscale)/yres);
|
||||
} else {
|
||||
printf("%d %d translate\n",
|
||||
(int) ((basePageWidth - pageWidth) * points * half),
|
||||
(int)((72.*h/yres) +
|
||||
(basePageHeight - pageHeight) * points * half) );
|
||||
printf("%g %g scale\n", 72./xres, -72./yres);
|
||||
}
|
||||
printf("0 setgray\n");
|
||||
TIFFSetField(tif, TIFFTAG_FAXFILLFUNC, printruns);
|
||||
ns = TIFFNumberOfStrips(tif);
|
||||
row = 0;
|
||||
for (s = 0; s < ns; s++)
|
||||
(void) TIFFReadEncodedStrip(tif, s, (tdata_t) NULL, (tsize_t) -1);
|
||||
printf("p\n");
|
||||
printf("grestore $pageTop restore\n");
|
||||
totalPages++;
|
||||
}
|
||||
|
||||
#define GetPageNumber(tif) \
|
||||
TIFFGetField(tif, TIFFTAG_PAGENUMBER, &pn, &ptotal)
|
||||
|
||||
int
|
||||
findPage(TIFF* tif, int pageNumber)
|
||||
{
|
||||
uint16 pn = (uint16) -1;
|
||||
uint16 ptotal = (uint16) -1;
|
||||
if (GetPageNumber(tif)) {
|
||||
while (pn != pageNumber && TIFFReadDirectory(tif) && GetPageNumber(tif))
|
||||
;
|
||||
return (pn == pageNumber);
|
||||
} else
|
||||
return (TIFFSetDirectory(tif, pageNumber-1));
|
||||
}
|
||||
|
||||
void
|
||||
fax2ps(TIFF* tif, int npages, int* pages, char* filename)
|
||||
{
|
||||
if (npages > 0) {
|
||||
uint16 pn, ptotal;
|
||||
int i;
|
||||
|
||||
if (!GetPageNumber(tif))
|
||||
fprintf(stderr, "%s: No page numbers, counting directories.\n",
|
||||
filename);
|
||||
for (i = 0; i < npages; i++) {
|
||||
if (findPage(tif, pages[i]))
|
||||
printTIF(tif, pages[i]);
|
||||
else
|
||||
fprintf(stderr, "%s: No page number %d\n", filename, pages[i]);
|
||||
}
|
||||
} else {
|
||||
int pageNumber = 1;
|
||||
do
|
||||
printTIF(tif, pageNumber++);
|
||||
while (TIFFReadDirectory(tif));
|
||||
}
|
||||
}
|
||||
|
||||
#undef GetPageNumber
|
||||
|
||||
/*
|
||||
* Create a special PostScript font for printing FAX documents. By taking
|
||||
* advantage of the font-cacheing mechanism, a substantial speed-up in
|
||||
* rendering time is realized.
|
||||
*/
|
||||
static void
|
||||
emitFont(FILE* fd)
|
||||
{
|
||||
static const char* fontPrologue[] = {
|
||||
"/newfont 10 dict def newfont begin /FontType 3 def /FontMatrix [1",
|
||||
"0 0 1 0 0] def /FontBBox [0 0 512 1] def /Encoding 256 array def",
|
||||
"0 1 31{Encoding exch /255 put}for 120 1 255{Encoding exch /255",
|
||||
"put}for Encoding 37 /255 put Encoding 40 /255 put Encoding 41 /255",
|
||||
"put Encoding 92 /255 put /count 0 def /ls{Encoding exch count 3",
|
||||
"string cvs cvn put /count count 1 add def}def 32 1 36{ls}for",
|
||||
"38 1 39{ls}for 42 1 91{ls}for 93 1 99{ls}for /count 100",
|
||||
"def 100 1 119{ls}for /CharDict 5 dict def CharDict begin /white",
|
||||
"{dup 255 eq{pop}{1 dict begin 100 sub neg 512 exch bitshift",
|
||||
"/cw exch def cw 0 0 0 cw 1 setcachedevice end}ifelse}def /black",
|
||||
"{dup 255 eq{pop}{1 dict begin 110 sub neg 512 exch bitshift",
|
||||
"/cw exch def cw 0 0 0 cw 1 setcachedevice 0 0 moveto cw 0 rlineto",
|
||||
"0 1 rlineto cw neg 0 rlineto closepath fill end}ifelse}def /numbuild",
|
||||
"{dup 255 eq{pop}{6 0 0 0 6 1 setcachedevice 0 1 5{0 moveto",
|
||||
"dup 32 and 32 eq{1 0 rlineto 0 1 rlineto -1 0 rlineto closepath",
|
||||
"fill newpath}if 1 bitshift}for pop}ifelse}def /.notdef {}",
|
||||
"def /255 {}def end /BuildChar{exch begin dup 110 ge{Encoding",
|
||||
"exch get 3 string cvs cvi CharDict /black get}{dup 100 ge {Encoding",
|
||||
"exch get 3 string cvs cvi CharDict /white get}{Encoding exch get",
|
||||
"3 string cvs cvi CharDict /numbuild get}ifelse}ifelse exec end",
|
||||
"}def end /Bitfont newfont definefont 1 scalefont setfont",
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
for (i = 0; fontPrologue[i] != NULL; i++)
|
||||
fprintf(fd, "%s\n", fontPrologue[i]);
|
||||
}
|
||||
|
||||
static int
|
||||
pcompar(const void* va, const void* vb)
|
||||
{
|
||||
const int* pa = (const int*) va;
|
||||
const int* pb = (const int*) vb;
|
||||
return (*pa - *pb);
|
||||
}
|
||||
|
||||
static void usage(int code);
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
int c, pageNumber;
|
||||
int* pages = 0, npages = 0;
|
||||
int dowarnings = 0; /* if 1, enable library warnings */
|
||||
time_t t;
|
||||
TIFF* tif;
|
||||
|
||||
while ((c = getopt(argc, argv, "l:p:x:y:W:H:wS")) != -1)
|
||||
switch (c) {
|
||||
case 'H': /* page height */
|
||||
pageHeight = atof(optarg);
|
||||
break;
|
||||
case 'S': /* scale to page */
|
||||
scaleToPage = 1;
|
||||
break;
|
||||
case 'W': /* page width */
|
||||
pageWidth = atof(optarg);
|
||||
break;
|
||||
case 'p': /* print specific page */
|
||||
pageNumber = atoi(optarg);
|
||||
if (pageNumber < 1) {
|
||||
fprintf(stderr, "%s: Invalid page number (must be > 0).\n",
|
||||
optarg);
|
||||
usage(-1);
|
||||
}
|
||||
if (pages)
|
||||
pages = (int*) realloc((char*) pages, (npages+1)*sizeof (int));
|
||||
else
|
||||
pages = (int*) malloc(sizeof (int));
|
||||
pages[npages++] = pageNumber;
|
||||
break;
|
||||
case 'w':
|
||||
dowarnings = 1;
|
||||
break;
|
||||
case 'x':
|
||||
defxres = atof(optarg);
|
||||
break;
|
||||
case 'y':
|
||||
defyres = atof(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
maxline = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
usage(-1);
|
||||
}
|
||||
if (npages > 0)
|
||||
qsort(pages, npages, sizeof (int), pcompar);
|
||||
if (!dowarnings)
|
||||
TIFFSetWarningHandler(0);
|
||||
printf("%%!PS-Adobe-3.0\n");
|
||||
printf("%%%%Creator: fax2ps\n");
|
||||
#ifdef notdef
|
||||
printf("%%%%Title: %s\n", file);
|
||||
#endif
|
||||
t = time(0);
|
||||
printf("%%%%CreationDate: %s", ctime(&t));
|
||||
printf("%%%%Origin: 0 0\n");
|
||||
printf("%%%%BoundingBox: 0 0 %u %u\n",
|
||||
(int)(pageWidth*72), (int)(pageHeight*72)); /* XXX */
|
||||
printf("%%%%Pages: (atend)\n");
|
||||
printf("%%%%EndComments\n");
|
||||
printf("%%%%BeginProlog\n");
|
||||
emitFont(stdout);
|
||||
printf("/d{bind def}def\n"); /* bind and def proc */
|
||||
printf("/m{0 exch moveto}d\n");
|
||||
printf("/s{show}d\n");
|
||||
printf("/p{showpage}d \n"); /* end page */
|
||||
printf("%%%%EndProlog\n");
|
||||
if (optind < argc) {
|
||||
do {
|
||||
tif = TIFFOpen(argv[optind], "r");
|
||||
if (tif) {
|
||||
fax2ps(tif, npages, pages, argv[optind]);
|
||||
TIFFClose(tif);
|
||||
} else
|
||||
fprintf(stderr, "%s: Can not open, or not a TIFF file.\n",
|
||||
argv[optind]);
|
||||
} while (++optind < argc);
|
||||
} else {
|
||||
int n;
|
||||
FILE* fd;
|
||||
char temp[1024], buf[16*1024];
|
||||
|
||||
strcpy(temp, "/tmp/fax2psXXXXXX");
|
||||
(void) mktemp(temp);
|
||||
fd = fopen(temp, "w");
|
||||
if (fd == NULL) {
|
||||
fprintf(stderr, "Could not create temp file \"%s\"\n", temp);
|
||||
exit(-2);
|
||||
}
|
||||
while ((n = read(fileno(stdin), buf, sizeof (buf))) > 0)
|
||||
write(fileno(fd), buf, n);
|
||||
tif = TIFFOpen(temp, "r");
|
||||
#ifndef VMS
|
||||
unlink(temp);
|
||||
#else
|
||||
remove(temp);
|
||||
#endif
|
||||
if (tif) {
|
||||
fax2ps(tif, npages, pages, "<stdin>");
|
||||
TIFFClose(tif);
|
||||
} else
|
||||
fprintf(stderr, "%s: Can not open, or not a TIFF file.\n", temp);
|
||||
fclose(fd);
|
||||
}
|
||||
printf("%%%%Trailer\n");
|
||||
printf("%%%%Pages: %u\n", totalPages);
|
||||
printf("%%%%EOF\n");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: fax2ps [options] [input.tif ...]",
|
||||
"where options are:",
|
||||
" -w suppress warning messages",
|
||||
" -l chars set maximum output line length for generated PostScript",
|
||||
" -p page# select page to print (can use multiple times)",
|
||||
" -x xres set default horizontal resolution of input data (dpi)",
|
||||
" -y yres set default vertical resolution of input data (lpi)",
|
||||
" -S scale output to page size",
|
||||
" -W width set output page width (inches), default is 8.5",
|
||||
" -H height set output page height (inchest), default is 11",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(int code)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(code);
|
||||
}
|
||||
Executable
+359
@@ -0,0 +1,359 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/fax2tiff.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert a CCITT Group 3 FAX file to TIFF Group 3 format.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* should have atof & getopt */
|
||||
#include "tiffiop.h"
|
||||
|
||||
#ifndef BINMODE
|
||||
#define BINMODE
|
||||
#endif
|
||||
|
||||
#ifndef EXIT_SUCCESS
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif
|
||||
#ifndef EXIT_FAILURE
|
||||
#define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
TIFF *faxTIFF;
|
||||
#define XSIZE 1728
|
||||
char rowbuf[TIFFhowmany(XSIZE,8)];
|
||||
char refbuf[TIFFhowmany(XSIZE,8)];
|
||||
|
||||
int verbose;
|
||||
int stretch;
|
||||
uint16 badfaxrun;
|
||||
uint32 badfaxlines;
|
||||
|
||||
int copyFaxFile(TIFF* tifin, TIFF* tifout);
|
||||
static void usage(void);
|
||||
|
||||
static tsize_t
|
||||
DummyReadProc(thandle_t fd, tdata_t buf, tsize_t size)
|
||||
{
|
||||
(void) fd; (void) buf; (void) size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static tsize_t
|
||||
DummyWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
|
||||
{
|
||||
(void) fd; (void) buf; (void) size;
|
||||
return (size);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
FILE *in;
|
||||
TIFF *out = NULL;
|
||||
TIFFErrorHandler whandler;
|
||||
int compression = COMPRESSION_CCITTFAX3;
|
||||
int fillorder = FILLORDER_LSB2MSB;
|
||||
uint32 group3options = GROUP3OPT_FILLBITS|GROUP3OPT_2DENCODING;
|
||||
int photometric = PHOTOMETRIC_MINISWHITE;
|
||||
int mode = FAXMODE_CLASSF;
|
||||
int rows;
|
||||
int c;
|
||||
int pn, npages;
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
|
||||
/* smuggle a descriptor out of the library */
|
||||
faxTIFF = TIFFClientOpen("(FakeInput)", "w", (thandle_t) -1,
|
||||
DummyReadProc, DummyWriteProc,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
if (faxTIFF == NULL)
|
||||
return (EXIT_FAILURE);
|
||||
faxTIFF->tif_mode = O_RDONLY;
|
||||
|
||||
TIFFSetField(faxTIFF, TIFFTAG_IMAGEWIDTH, XSIZE);
|
||||
TIFFSetField(faxTIFF, TIFFTAG_SAMPLESPERPIXEL, 1);
|
||||
TIFFSetField(faxTIFF, TIFFTAG_BITSPERSAMPLE, 1);
|
||||
TIFFSetField(faxTIFF, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
|
||||
TIFFSetField(faxTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(faxTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
|
||||
TIFFSetField(faxTIFF, TIFFTAG_YRESOLUTION, 196.);
|
||||
TIFFSetField(faxTIFF, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
|
||||
/* NB: this is normally setup when a directory is read */
|
||||
faxTIFF->tif_scanlinesize = TIFFScanlineSize(faxTIFF);
|
||||
|
||||
while ((c = getopt(argc, argv, "R:o:2BLMW14cflmpsvwz")) != -1)
|
||||
switch (c) {
|
||||
/* input-related options */
|
||||
case '2': /* input is 2d-encoded */
|
||||
TIFFSetField(faxTIFF,
|
||||
TIFFTAG_GROUP3OPTIONS, GROUP3OPT_2DENCODING);
|
||||
break;
|
||||
case 'B': /* input has 0 mean black */
|
||||
TIFFSetField(faxTIFF,
|
||||
TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
|
||||
break;
|
||||
case 'L': /* input has lsb-to-msb fillorder */
|
||||
TIFFSetField(faxTIFF,
|
||||
TIFFTAG_FILLORDER, FILLORDER_LSB2MSB);
|
||||
break;
|
||||
case 'M': /* input has msb-to-lsb fillorder */
|
||||
TIFFSetField(faxTIFF,
|
||||
TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
|
||||
break;
|
||||
case 'R': /* input resolution */
|
||||
TIFFSetField(faxTIFF,
|
||||
TIFFTAG_YRESOLUTION, atof(optarg));
|
||||
break;
|
||||
case 'W': /* input has 0 mean white */
|
||||
TIFFSetField(faxTIFF,
|
||||
TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
|
||||
break;
|
||||
|
||||
/* output-related options */
|
||||
case '1': /* generate 1d-encoded output */
|
||||
group3options &= ~GROUP3OPT_2DENCODING;
|
||||
break;
|
||||
case '4': /* generate g4-encoded output */
|
||||
compression = COMPRESSION_CCITTFAX4;
|
||||
break;
|
||||
case 'c': /* generate "classic" g3 format */
|
||||
mode = FAXMODE_CLASSIC;
|
||||
break;
|
||||
case 'f': /* generate Class F format */
|
||||
mode = FAXMODE_CLASSF;
|
||||
break;
|
||||
case 'm': /* output's fillorder is msb-to-lsb */
|
||||
fillorder = FILLORDER_MSB2LSB;
|
||||
break;
|
||||
case 'o':
|
||||
out = TIFFOpen(optarg, "w");
|
||||
if (out == NULL)
|
||||
return EXIT_FAILURE;
|
||||
break;
|
||||
case 'p': /* zero pad output scanline EOLs */
|
||||
group3options &= ~GROUP3OPT_FILLBITS;
|
||||
break;
|
||||
case 's': /* stretch image by dup'ng scanlines */
|
||||
stretch = 1;
|
||||
break;
|
||||
case 'w': /* undocumented -- for testing */
|
||||
photometric = PHOTOMETRIC_MINISBLACK;
|
||||
break;
|
||||
|
||||
case 'z': /* undocumented -- for testing */
|
||||
compression = COMPRESSION_LZW;
|
||||
break;
|
||||
|
||||
case 'v': /* -v for info */
|
||||
verbose++;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (out == NULL) {
|
||||
out = TIFFOpen("fax.tif", "w");
|
||||
if (out == NULL)
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
faxTIFF->tif_readproc = out->tif_readproc; /* XXX */
|
||||
faxTIFF->tif_writeproc = out->tif_writeproc; /* XXX */
|
||||
faxTIFF->tif_seekproc = out->tif_seekproc; /* XXX */
|
||||
faxTIFF->tif_closeproc = out->tif_closeproc; /* XXX */
|
||||
faxTIFF->tif_sizeproc = out->tif_sizeproc; /* XXX */
|
||||
faxTIFF->tif_mapproc = out->tif_mapproc; /* XXX */
|
||||
faxTIFF->tif_unmapproc = out->tif_unmapproc; /* XXX */
|
||||
|
||||
npages = argc - optind;
|
||||
if (npages < 1)
|
||||
usage();
|
||||
|
||||
/* NB: this must be done after directory info is setup */
|
||||
TIFFSetField(faxTIFF, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX3);
|
||||
for (pn = 0; optind < argc; pn++, optind++) {
|
||||
in = fopen(argv[optind], "r" BINMODE);
|
||||
if (in == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: %s: Can not open\n", argv[0], argv[optind]);
|
||||
continue;
|
||||
}
|
||||
faxTIFF->tif_fd = fileno(in);
|
||||
faxTIFF->tif_clientdata = (thandle_t) faxTIFF->tif_fd;
|
||||
faxTIFF->tif_name = argv[optind];
|
||||
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, XSIZE);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1);
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
|
||||
if (compression == COMPRESSION_CCITTFAX3) {
|
||||
TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, group3options);
|
||||
TIFFSetField(out, TIFFTAG_FAXMODE, mode);
|
||||
}
|
||||
if (compression == COMPRESSION_CCITTFAX3 ||
|
||||
compression == COMPRESSION_CCITTFAX4)
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, -1L);
|
||||
else
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
|
||||
TIFFDefaultStripSize(out, 0));
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
|
||||
TIFFSetField(out, TIFFTAG_SOFTWARE, "fax2tiff");
|
||||
TIFFSetField(out, TIFFTAG_XRESOLUTION, 204.0);
|
||||
if (!stretch) {
|
||||
float yres;
|
||||
TIFFGetField(faxTIFF, TIFFTAG_YRESOLUTION, &yres);
|
||||
TIFFSetField(out, TIFFTAG_YRESOLUTION, yres);
|
||||
} else
|
||||
TIFFSetField(out, TIFFTAG_YRESOLUTION, 196.);
|
||||
TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
|
||||
TIFFSetField(out, TIFFTAG_PAGENUMBER, pn+1, npages);
|
||||
|
||||
if (!verbose)
|
||||
whandler = TIFFSetWarningHandler(NULL);
|
||||
rows = copyFaxFile(faxTIFF, out);
|
||||
fclose(in);
|
||||
if (!verbose)
|
||||
(void) TIFFSetWarningHandler(whandler);
|
||||
|
||||
TIFFSetField(out, TIFFTAG_IMAGELENGTH, rows);
|
||||
|
||||
if (verbose) {
|
||||
fprintf(stderr, "%s:\n", argv[optind]);
|
||||
fprintf(stderr, "%d rows in input\n", rows);
|
||||
fprintf(stderr, "%ld total bad rows\n",
|
||||
(long) badfaxlines);
|
||||
fprintf(stderr, "%d max consecutive bad rows\n", badfaxrun);
|
||||
}
|
||||
if (compression == COMPRESSION_CCITTFAX3 &&
|
||||
mode == FAXMODE_CLASSF) {
|
||||
TIFFSetField(out, TIFFTAG_BADFAXLINES, badfaxlines);
|
||||
TIFFSetField(out, TIFFTAG_CLEANFAXDATA, badfaxlines ?
|
||||
CLEANFAXDATA_REGENERATED : CLEANFAXDATA_CLEAN);
|
||||
TIFFSetField(out, TIFFTAG_CONSECUTIVEBADFAXLINES, badfaxrun);
|
||||
}
|
||||
TIFFWriteDirectory(out);
|
||||
}
|
||||
TIFFClose(out);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
int
|
||||
copyFaxFile(TIFF* tifin, TIFF* tifout)
|
||||
{
|
||||
uint32 row;
|
||||
uint16 badrun;
|
||||
int ok;
|
||||
|
||||
tifin->tif_rawdatasize = TIFFGetFileSize(tifin);
|
||||
tifin->tif_rawdata = _TIFFmalloc(tifin->tif_rawdatasize);
|
||||
if (!ReadOK(tifin, tifin->tif_rawdata, tifin->tif_rawdatasize)) {
|
||||
TIFFError(tifin->tif_name, "%s: Read error at scanline 0");
|
||||
return (0);
|
||||
}
|
||||
tifin->tif_rawcp = tifin->tif_rawdata;
|
||||
tifin->tif_rawcc = tifin->tif_rawdatasize;
|
||||
|
||||
(*tifin->tif_setupdecode)(tifin);
|
||||
(*tifin->tif_predecode)(tifin, (tsample_t) 0);
|
||||
tifin->tif_row = 0;
|
||||
badfaxlines = 0;
|
||||
badfaxrun = 0;
|
||||
|
||||
_TIFFmemset(refbuf, 0, sizeof (refbuf));
|
||||
row = 0;
|
||||
badrun = 0; /* current run of bad lines */
|
||||
while (tifin->tif_rawcc > 0) {
|
||||
ok = (*tifin->tif_decoderow)(tifin, (tdata_t) rowbuf,
|
||||
sizeof (rowbuf), 0);
|
||||
if (!ok) {
|
||||
badfaxlines++;
|
||||
badrun++;
|
||||
/* regenerate line from previous good line */
|
||||
_TIFFmemcpy(rowbuf, refbuf, sizeof (rowbuf));
|
||||
} else {
|
||||
if (badrun > badfaxrun)
|
||||
badfaxrun = badrun;
|
||||
badrun = 0;
|
||||
_TIFFmemcpy(refbuf, rowbuf, sizeof (rowbuf));
|
||||
}
|
||||
tifin->tif_row++;
|
||||
|
||||
if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) {
|
||||
fprintf(stderr, "%s: Write error at row %ld.\n",
|
||||
tifout->tif_name, (long) row);
|
||||
break;
|
||||
}
|
||||
row++;
|
||||
if (stretch) {
|
||||
if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) {
|
||||
fprintf(stderr, "%s: Write error at row %ld.\n",
|
||||
tifout->tif_name, (long) row);
|
||||
break;
|
||||
}
|
||||
row++;
|
||||
}
|
||||
}
|
||||
if (badrun > badfaxrun)
|
||||
badfaxrun = badrun;
|
||||
_TIFFfree(tifin->tif_rawdata);
|
||||
return (row);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: fax2tiff [options] input.g3...",
|
||||
"where options are:",
|
||||
" -2 input data is 2d encoded",
|
||||
" -B input data has min 0 means black",
|
||||
" -L input data has LSB2MSB bit order (default)",
|
||||
" -M input data has MSB2LSB bit order",
|
||||
" -W input data has min 0 means white (default)",
|
||||
" -R # input data has # resolution (lines/inch) (default is 196)",
|
||||
"",
|
||||
" -o out.tif write output to out.tif",
|
||||
" -1 generate 1d-encoded output (default is G3 2d)",
|
||||
" -4 generate G4-encoded output (default is G3 2D)",
|
||||
" -c generate \"classic\" TIFF format (default is TIFF/F)",
|
||||
" -f generate TIFF Class F (TIFF/F) format (default)",
|
||||
" -m output fill order is MSB2LSB (default is LSB2MSB)",
|
||||
" -p do not byte-align EOL codes in output (default is byte-align)",
|
||||
" -s stretch image by duplicating scanlines",
|
||||
" -v print information about conversion work",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
Executable
+513
@@ -0,0 +1,513 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/gif2tiff.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* convert a GIF file into a TIFF file.
|
||||
* based on Paul Haeberli's fromgif program which in turn is
|
||||
* based on a GIF file reader by Marcel J.E. Mol March 23 1989
|
||||
*
|
||||
* if input is 320 by 200 pixel aspect is probably 1.2
|
||||
* if input is 640 350 pixel aspect is probably 1.37
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#if defined(_WINDOWS) || defined(MSDOS)
|
||||
#define BINMODE "b"
|
||||
#else
|
||||
#define BINMODE
|
||||
#endif
|
||||
|
||||
#define GIFGAMMA (1.5) /* smaller makes output img brighter */
|
||||
#define IMAX 0xffff /* max intensity value */
|
||||
#define EXTRAFUDGE 128 /* some people write BAD .gif files */
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define strneq(a,b,n) (strncmp(a,b,n) == 0)
|
||||
|
||||
unsigned short gamtab[256];
|
||||
|
||||
void
|
||||
makegamtab(float gam)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<256; i++)
|
||||
gamtab[i] = IMAX*pow(i/255.0,gam)+0.5;
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: gif2tiff [options] input.gif output.tif",
|
||||
"where options are:",
|
||||
" -r # make each strip have no more than # rows",
|
||||
"",
|
||||
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
|
||||
" (no longer supported by default due to Unisys patent enforcement)",
|
||||
" -c zip[:opts] compress output with deflate encoding",
|
||||
" -c packbits compress output with packbits encoding",
|
||||
" -c none use no compression algorithm on output",
|
||||
"",
|
||||
"LZW and deflate options:",
|
||||
" # set predictor value",
|
||||
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#define COLSIZE 256
|
||||
|
||||
unsigned char *stackp;
|
||||
unsigned int prefix[4096];
|
||||
unsigned char suffix[4096];
|
||||
unsigned char stack[4096];
|
||||
int datasize,codesize,codemask; /* Decoder working variables */
|
||||
int clear,eoi; /* Special code values */
|
||||
int avail, oldcode;
|
||||
|
||||
FILE *infile;
|
||||
int global; /* Is there a global color map? */
|
||||
int globalbits; /* Number of bits of global colors */
|
||||
unsigned char globalmap[COLSIZE][3];/* RGB values for global color map */
|
||||
unsigned char *raster; /* Decoded image data */
|
||||
unsigned long width, height;
|
||||
unsigned short red[COLSIZE];
|
||||
unsigned short green[COLSIZE];
|
||||
unsigned short blue[COLSIZE];
|
||||
char *filename, *imagename;
|
||||
|
||||
static uint16 compression = COMPRESSION_PACKBITS;
|
||||
static uint16 predictor = 0;
|
||||
static uint32 rowsperstrip = (uint32) -1;
|
||||
static int processCompressOptions(char*);
|
||||
|
||||
int convert(void);
|
||||
int checksignature(void);
|
||||
void readscreen(void);
|
||||
int readgifimage(char*);
|
||||
void readextension(void);
|
||||
int readraster(void);
|
||||
int process(int, unsigned char**);
|
||||
void initcolors(unsigned char [COLSIZE][3], int);
|
||||
void rasterize(int, char*);
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
int c, status;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:r:")) != -1)
|
||||
switch (c) {
|
||||
case 'c': /* compression scheme */
|
||||
if (!processCompressOptions(optarg))
|
||||
usage();
|
||||
break;
|
||||
case 'r': /* rows/strip */
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind != 2)
|
||||
usage();
|
||||
|
||||
makegamtab(GIFGAMMA);
|
||||
filename = argv[optind];
|
||||
imagename = argv[optind+1];
|
||||
if ((infile = fopen(imagename, "r" BINMODE)) != NULL) {
|
||||
int c;
|
||||
fclose(infile);
|
||||
printf("overwrite %s? ", imagename); fflush(stdout);
|
||||
c = getc(stdin);
|
||||
if (c != 'y' && c != 'Y')
|
||||
return (1);
|
||||
}
|
||||
if ((infile = fopen(filename, "r" BINMODE)) == NULL) {
|
||||
perror(filename);
|
||||
return (1);
|
||||
}
|
||||
status = convert();
|
||||
fclose(infile);
|
||||
return (status);
|
||||
}
|
||||
|
||||
static int
|
||||
processCompressOptions(char* opt)
|
||||
{
|
||||
if (streq(opt, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(opt, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (strneq(opt, "lzw", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_LZW;
|
||||
} else if (strneq(opt, "zip", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_DEFLATE;
|
||||
} else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
convert(void)
|
||||
{
|
||||
int ch;
|
||||
char* mode = "w";
|
||||
|
||||
if (!checksignature())
|
||||
return (-1);
|
||||
readscreen();
|
||||
while ((ch = getc(infile)) != ';' && ch != EOF) {
|
||||
switch (ch) {
|
||||
case '\0': break; /* this kludge for non-standard files */
|
||||
case ',': if (!readgifimage(mode))
|
||||
return (-1);
|
||||
mode = "a"; /* subsequent images append */
|
||||
break;
|
||||
case '!': readextension();
|
||||
break;
|
||||
default: fprintf(stderr, "illegal GIF block type\n");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
checksignature(void)
|
||||
{
|
||||
char buf[6];
|
||||
|
||||
fread(buf,1,6,infile);
|
||||
if (strncmp(buf,"GIF",3)) {
|
||||
fprintf(stderr, "file is not a GIF file\n");
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(&buf[3],"87a",3)) {
|
||||
fprintf(stderr, "unknown GIF version number\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* readscreen -
|
||||
* Get information which is global to all the images stored
|
||||
* in the file
|
||||
*/
|
||||
void
|
||||
readscreen(void)
|
||||
{
|
||||
unsigned char buf[7];
|
||||
|
||||
fread(buf,1,7,infile);
|
||||
global = buf[4] & 0x80;
|
||||
if (global) {
|
||||
globalbits = (buf[4] & 0x07) + 1;
|
||||
fread(globalmap,3,1<<globalbits,infile);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
readgifimage(char* mode)
|
||||
{
|
||||
unsigned char buf[9];
|
||||
int local, interleaved;
|
||||
unsigned char localmap[256][3];
|
||||
int localbits;
|
||||
int status;
|
||||
|
||||
if (fread(buf, 1, 9, infile) == 0) {
|
||||
perror(filename);
|
||||
return (0);
|
||||
}
|
||||
width = buf[4] + (buf[5] << 8);
|
||||
height = buf[6] + (buf[7] << 8);
|
||||
local = buf[8] & 0x80;
|
||||
interleaved = buf[8] & 0x40;
|
||||
|
||||
if (local == 0 && global == 0) {
|
||||
fprintf(stderr, "no colormap present for image\n");
|
||||
return (0);
|
||||
}
|
||||
if ((raster = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) {
|
||||
fprintf(stderr, "not enough memory for image\n");
|
||||
return (0);
|
||||
}
|
||||
if (local) {
|
||||
localbits = (buf[8] & 0x7) + 1;
|
||||
|
||||
fprintf(stderr, " local colors: %d\n", 1<<localbits);
|
||||
|
||||
fread(localmap, 3, 1<<localbits, infile);
|
||||
initcolors(localmap, 1<<localbits);
|
||||
} else if (global) {
|
||||
initcolors(globalmap, 1<<globalbits);
|
||||
}
|
||||
if (status = readraster())
|
||||
rasterize(interleaved, mode);
|
||||
_TIFFfree(raster);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* readextension -
|
||||
* Read a GIF extension block (and do nothing with it).
|
||||
*
|
||||
*/
|
||||
void
|
||||
readextension(void)
|
||||
{
|
||||
int count;
|
||||
char buf[255];
|
||||
|
||||
(void) getc(infile);
|
||||
while (count = getc(infile))
|
||||
fread(buf, 1, count, infile);
|
||||
}
|
||||
|
||||
/*
|
||||
* readraster -
|
||||
* Decode a raster image
|
||||
*
|
||||
*/
|
||||
int
|
||||
readraster(void)
|
||||
{
|
||||
unsigned char *fill = raster;
|
||||
unsigned char buf[255];
|
||||
register int bits=0;
|
||||
register unsigned long datum=0;
|
||||
register unsigned char *ch;
|
||||
register int count, code;
|
||||
int status = 1;
|
||||
|
||||
datasize = getc(infile);
|
||||
clear = 1 << datasize;
|
||||
eoi = clear + 1;
|
||||
avail = clear + 2;
|
||||
oldcode = -1;
|
||||
codesize = datasize + 1;
|
||||
codemask = (1 << codesize) - 1;
|
||||
for (code = 0; code < clear; code++) {
|
||||
prefix[code] = 0;
|
||||
suffix[code] = code;
|
||||
}
|
||||
stackp = stack;
|
||||
for (count = getc(infile); count > 0; count = getc(infile)) {
|
||||
fread(buf,1,count,infile);
|
||||
for (ch=buf; count-- > 0; ch++) {
|
||||
datum += (unsigned long) *ch << bits;
|
||||
bits += 8;
|
||||
while (bits >= codesize) {
|
||||
code = datum & codemask;
|
||||
datum >>= codesize;
|
||||
bits -= codesize;
|
||||
if (code == eoi) { /* This kludge put in */
|
||||
goto exitloop; /* because some GIF files*/
|
||||
} /* aren't standard */
|
||||
if (!process(code, &fill)) {
|
||||
status = 0;
|
||||
goto exitloop;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fill >= raster + width*height) {
|
||||
fprintf(stderr, "raster full before eoi code\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
exitloop:
|
||||
if (fill != raster + width*height) {
|
||||
fprintf(stderr, "warning: wrong rastersize: %ld bytes\n",
|
||||
(long) (fill-raster));
|
||||
fprintf(stderr, " instead of %ld bytes\n",
|
||||
(long) width*height);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* process -
|
||||
* Process a compression code. "clear" resets the code table.
|
||||
* Otherwise make a new code table entry, and output the bytes
|
||||
* associated with the code.
|
||||
*/
|
||||
int
|
||||
process(register int code, unsigned char** fill)
|
||||
{
|
||||
int incode;
|
||||
static unsigned char firstchar;
|
||||
|
||||
if (code == clear) {
|
||||
codesize = datasize + 1;
|
||||
codemask = (1 << codesize) - 1;
|
||||
avail = clear + 2;
|
||||
oldcode = -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (oldcode == -1) {
|
||||
*(*fill)++ = suffix[code];
|
||||
firstchar = oldcode = code;
|
||||
return 1;
|
||||
}
|
||||
if (code > avail) {
|
||||
fprintf(stderr, "code %d too large for %d\n", code, avail);
|
||||
return 0;
|
||||
}
|
||||
|
||||
incode = code;
|
||||
if (code == avail) { /* the first code is always < avail */
|
||||
*stackp++ = firstchar;
|
||||
code = oldcode;
|
||||
}
|
||||
while (code > clear) {
|
||||
*stackp++ = suffix[code];
|
||||
code = prefix[code];
|
||||
}
|
||||
|
||||
*stackp++ = firstchar = suffix[code];
|
||||
prefix[avail] = oldcode;
|
||||
suffix[avail] = firstchar;
|
||||
avail++;
|
||||
|
||||
if (((avail & codemask) == 0) && (avail < 4096)) {
|
||||
codesize++;
|
||||
codemask += avail;
|
||||
}
|
||||
oldcode = incode;
|
||||
do {
|
||||
*(*fill)++ = *--stackp;
|
||||
} while (stackp > stack);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* initcolors -
|
||||
* Convert a color map (local or global) to arrays with R, G and B
|
||||
* values.
|
||||
*
|
||||
*/
|
||||
void
|
||||
initcolors(unsigned char colormap[COLSIZE][3], int ncolors)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < ncolors; i++) {
|
||||
red[i] = gamtab[colormap[i][0]];
|
||||
green[i] = gamtab[colormap[i][1]];
|
||||
blue[i] = gamtab[colormap[i][2]];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rasterize(int interleaved, char* mode)
|
||||
{
|
||||
register long row;
|
||||
unsigned char *newras;
|
||||
unsigned char *ras;
|
||||
TIFF *tif;
|
||||
tstrip_t strip;
|
||||
tsize_t stripsize;
|
||||
|
||||
if ((newras = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) {
|
||||
fprintf(stderr, "not enough memory for image\n");
|
||||
return;
|
||||
}
|
||||
#define DRAWSEGMENT(offset, step) { \
|
||||
for (row = offset; row < height; row += step) { \
|
||||
_TIFFmemcpy(newras + row*width, ras, width);\
|
||||
ras += width; \
|
||||
} \
|
||||
}
|
||||
ras = raster;
|
||||
if (interleaved) {
|
||||
DRAWSEGMENT(0, 8);
|
||||
DRAWSEGMENT(4, 8);
|
||||
DRAWSEGMENT(2, 4);
|
||||
DRAWSEGMENT(1, 2);
|
||||
} else
|
||||
DRAWSEGMENT(0, 1);
|
||||
#undef DRAWSEGMENT
|
||||
|
||||
tif = TIFFOpen(imagename, mode);
|
||||
if (!tif) {
|
||||
TIFFError(imagename,"Can not open output image");
|
||||
exit(-1);
|
||||
}
|
||||
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32) width);
|
||||
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32) height);
|
||||
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
|
||||
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
|
||||
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
|
||||
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,
|
||||
rowsperstrip = TIFFDefaultStripSize(tif, rowsperstrip));
|
||||
TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
|
||||
switch (compression) {
|
||||
case COMPRESSION_LZW:
|
||||
case COMPRESSION_DEFLATE:
|
||||
if (predictor != 0)
|
||||
TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
|
||||
break;
|
||||
}
|
||||
TIFFSetField(tif, TIFFTAG_COLORMAP, red, green, blue);
|
||||
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
strip = 0;
|
||||
stripsize = TIFFStripSize(tif);
|
||||
for (row=0; row<height; row += rowsperstrip) {
|
||||
if (TIFFWriteEncodedStrip(tif, strip, newras+row*width, stripsize) < 0)
|
||||
break;
|
||||
strip++;
|
||||
}
|
||||
TIFFClose(tif);
|
||||
|
||||
_TIFFfree(newras);
|
||||
}
|
||||
Executable
+386
@@ -0,0 +1,386 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/pal2rgb.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define strneq(a,b,n) (strncmp(a,b,n) == 0)
|
||||
|
||||
static void usage(void);
|
||||
static void cpTags(TIFF* in, TIFF* out);
|
||||
|
||||
static int
|
||||
checkcmap(int n, uint16* r, uint16* g, uint16* b)
|
||||
{
|
||||
while (n-- > 0)
|
||||
if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
|
||||
return (16);
|
||||
fprintf(stderr, "Warning, assuming 8-bit colormap.\n");
|
||||
return (8);
|
||||
}
|
||||
|
||||
#define CopyField(tag, v) \
|
||||
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
|
||||
#define CopyField3(tag, v1, v2, v3) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
|
||||
|
||||
static uint16 compression = (uint16) -1;
|
||||
static uint16 predictor = 0;
|
||||
static int quality = 75; /* JPEG quality */
|
||||
static int jpegcolormode = JPEGCOLORMODE_RGB;
|
||||
static int processCompressOptions(char*);
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
uint16 bitspersample, shortv;
|
||||
uint32 imagewidth, imagelength;
|
||||
uint16 config = PLANARCONFIG_CONTIG;
|
||||
uint32 rowsperstrip = (uint32) -1;
|
||||
uint16 photometric = PHOTOMETRIC_RGB;
|
||||
uint16 *rmap, *gmap, *bmap;
|
||||
uint32 row;
|
||||
int cmap = -1;
|
||||
TIFF *in, *out;
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
|
||||
while ((c = getopt(argc, argv, "C:c:p:r:")) != -1)
|
||||
switch (c) {
|
||||
case 'C': /* force colormap interpretation */
|
||||
cmap = atoi(optarg);
|
||||
break;
|
||||
case 'c': /* compression scheme */
|
||||
if (!processCompressOptions(optarg))
|
||||
usage();
|
||||
break;
|
||||
case 'p': /* planar configuration */
|
||||
if (streq(optarg, "separate"))
|
||||
config = PLANARCONFIG_SEPARATE;
|
||||
else if (streq(optarg, "contig"))
|
||||
config = PLANARCONFIG_CONTIG;
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
case 'r': /* rows/strip */
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind != 2)
|
||||
usage();
|
||||
in = TIFFOpen(argv[optind], "r");
|
||||
if (in == NULL)
|
||||
return (-1);
|
||||
if (!TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &shortv) ||
|
||||
shortv != PHOTOMETRIC_PALETTE) {
|
||||
fprintf(stderr, "%s: Expecting a palette image.\n",
|
||||
argv[optind]);
|
||||
return (-1);
|
||||
}
|
||||
if (!TIFFGetField(in, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) {
|
||||
fprintf(stderr,
|
||||
"%s: No colormap (not a valid palette image).\n",
|
||||
argv[optind]);
|
||||
return (-1);
|
||||
}
|
||||
bitspersample = 0;
|
||||
TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample);
|
||||
if (bitspersample != 8) {
|
||||
fprintf(stderr, "%s: Sorry, can only handle 8-bit images.\n",
|
||||
argv[optind]);
|
||||
return (-1);
|
||||
}
|
||||
out = TIFFOpen(argv[optind+1], "w");
|
||||
if (out == NULL)
|
||||
return (-2);
|
||||
cpTags(in, out);
|
||||
TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &imagewidth);
|
||||
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength);
|
||||
if (compression != (uint16)-1)
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
else
|
||||
TIFFGetField(in, TIFFTAG_COMPRESSION, &compression);
|
||||
switch (compression) {
|
||||
case COMPRESSION_JPEG:
|
||||
if (jpegcolormode == JPEGCOLORMODE_RGB)
|
||||
photometric = PHOTOMETRIC_YCBCR;
|
||||
else
|
||||
photometric = PHOTOMETRIC_RGB;
|
||||
TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
|
||||
TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
|
||||
break;
|
||||
case COMPRESSION_LZW:
|
||||
case COMPRESSION_DEFLATE:
|
||||
if (predictor != 0)
|
||||
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
|
||||
break;
|
||||
}
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 3);
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
|
||||
rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip));
|
||||
(void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv);
|
||||
if (cmap == -1)
|
||||
cmap = checkcmap(1<<bitspersample, rmap, gmap, bmap);
|
||||
if (cmap == 16) {
|
||||
/*
|
||||
* Convert 16-bit colormap to 8-bit.
|
||||
*/
|
||||
int i;
|
||||
|
||||
for (i = (1<<bitspersample)-1; i >= 0; i--) {
|
||||
#define CVT(x) (((x) * 255) / ((1L<<16)-1))
|
||||
rmap[i] = CVT(rmap[i]);
|
||||
gmap[i] = CVT(gmap[i]);
|
||||
bmap[i] = CVT(bmap[i]);
|
||||
}
|
||||
}
|
||||
{ unsigned char *ibuf, *obuf;
|
||||
register unsigned char* pp;
|
||||
register uint32 x;
|
||||
ibuf = (unsigned char*)_TIFFmalloc(TIFFScanlineSize(in));
|
||||
obuf = (unsigned char*)_TIFFmalloc(TIFFScanlineSize(out));
|
||||
switch (config) {
|
||||
case PLANARCONFIG_CONTIG:
|
||||
for (row = 0; row < imagelength; row++) {
|
||||
if (!TIFFReadScanline(in, ibuf, row, 0))
|
||||
goto done;
|
||||
pp = obuf;
|
||||
for (x = 0; x < imagewidth; x++) {
|
||||
*pp++ = rmap[ibuf[x]];
|
||||
*pp++ = gmap[ibuf[x]];
|
||||
*pp++ = bmap[ibuf[x]];
|
||||
}
|
||||
if (!TIFFWriteScanline(out, obuf, row, 0))
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case PLANARCONFIG_SEPARATE:
|
||||
for (row = 0; row < imagelength; row++) {
|
||||
if (!TIFFReadScanline(in, ibuf, row, 0))
|
||||
goto done;
|
||||
for (pp = obuf, x = 0; x < imagewidth; x++)
|
||||
*pp++ = rmap[ibuf[x]];
|
||||
if (!TIFFWriteScanline(out, obuf, row, 0))
|
||||
goto done;
|
||||
for (pp = obuf, x = 0; x < imagewidth; x++)
|
||||
*pp++ = gmap[ibuf[x]];
|
||||
if (!TIFFWriteScanline(out, obuf, row, 0))
|
||||
goto done;
|
||||
for (pp = obuf, x = 0; x < imagewidth; x++)
|
||||
*pp++ = bmap[ibuf[x]];
|
||||
if (!TIFFWriteScanline(out, obuf, row, 0))
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
_TIFFfree(ibuf);
|
||||
_TIFFfree(obuf);
|
||||
}
|
||||
done:
|
||||
(void) TIFFClose(in);
|
||||
(void) TIFFClose(out);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
processCompressOptions(char* opt)
|
||||
{
|
||||
if (streq(opt, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(opt, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (strneq(opt, "jpeg", 4)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp && isdigit(cp[1]))
|
||||
quality = atoi(cp+1);
|
||||
if (cp && strchr(cp, 'r'))
|
||||
jpegcolormode = JPEGCOLORMODE_RAW;
|
||||
compression = COMPRESSION_JPEG;
|
||||
} else if (strneq(opt, "lzw", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_LZW;
|
||||
} else if (strneq(opt, "zip", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_DEFLATE;
|
||||
} else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
#define CopyField1(tag, v) \
|
||||
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
|
||||
#define CopyField2(tag, v1, v2) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
|
||||
#define CopyField3(tag, v1, v2, v3) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
|
||||
#define CopyField4(tag, v1, v2, v3, v4) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
|
||||
|
||||
static void
|
||||
cpTag(TIFF* in, TIFF* out, uint16 tag, uint16 count, TIFFDataType type)
|
||||
{
|
||||
uint16 shortv, shortv2, *shortav;
|
||||
float floatv, *floatav;
|
||||
char *stringv;
|
||||
uint32 longv;
|
||||
|
||||
switch (type) {
|
||||
case TIFF_SHORT:
|
||||
if (count == 1) {
|
||||
CopyField1(tag, shortv);
|
||||
} else if (count == 2) {
|
||||
CopyField2(tag, shortv, shortv2);
|
||||
} else if (count == (uint16) -1) {
|
||||
CopyField2(tag, shortv, shortav);
|
||||
}
|
||||
break;
|
||||
case TIFF_LONG:
|
||||
CopyField1(tag, longv);
|
||||
break;
|
||||
case TIFF_RATIONAL:
|
||||
if (count == 1) {
|
||||
CopyField1(tag, floatv);
|
||||
} else if (count == (uint16) -1) {
|
||||
CopyField1(tag, floatav);
|
||||
}
|
||||
break;
|
||||
case TIFF_ASCII:
|
||||
CopyField1(tag, stringv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#undef CopyField4
|
||||
#undef CopyField3
|
||||
#undef CopyField2
|
||||
#undef CopyField1
|
||||
|
||||
static struct cpTag {
|
||||
uint16 tag;
|
||||
uint16 count;
|
||||
TIFFDataType type;
|
||||
} tags[] = {
|
||||
{ TIFFTAG_IMAGEWIDTH, 1, TIFF_LONG },
|
||||
{ TIFFTAG_IMAGELENGTH, 1, TIFF_LONG },
|
||||
{ TIFFTAG_BITSPERSAMPLE, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_COMPRESSION, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_FILLORDER, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_ROWSPERSTRIP, 1, TIFF_LONG },
|
||||
{ TIFFTAG_GROUP3OPTIONS, 1, TIFF_LONG },
|
||||
{ TIFFTAG_SUBFILETYPE, 1, TIFF_LONG },
|
||||
{ TIFFTAG_THRESHHOLDING, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_DOCUMENTNAME, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_IMAGEDESCRIPTION, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_MAKE, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_MODEL, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_ORIENTATION, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_MINSAMPLEVALUE, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_MAXSAMPLEVALUE, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_XRESOLUTION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_YRESOLUTION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_PAGENAME, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_XPOSITION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_YPOSITION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG },
|
||||
{ TIFFTAG_RESOLUTIONUNIT, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_PAGENUMBER, 2, TIFF_SHORT },
|
||||
{ TIFFTAG_SOFTWARE, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_DATETIME, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_ARTIST, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_HOSTCOMPUTER, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_WHITEPOINT, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_PRIMARYCHROMATICITIES, (uint16) -1,TIFF_RATIONAL },
|
||||
{ TIFFTAG_HALFTONEHINTS, 2, TIFF_SHORT },
|
||||
{ TIFFTAG_BADFAXLINES, 1, TIFF_LONG },
|
||||
{ TIFFTAG_CLEANFAXDATA, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_CONSECUTIVEBADFAXLINES, 1, TIFF_LONG },
|
||||
{ TIFFTAG_INKSET, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_INKNAMES, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_DOTRANGE, 2, TIFF_SHORT },
|
||||
{ TIFFTAG_TARGETPRINTER, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_SAMPLEFORMAT, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_YCBCRCOEFFICIENTS, (uint16) -1,TIFF_RATIONAL },
|
||||
{ TIFFTAG_YCBCRSUBSAMPLING, 2, TIFF_SHORT },
|
||||
{ TIFFTAG_YCBCRPOSITIONING, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_REFERENCEBLACKWHITE, (uint16) -1,TIFF_RATIONAL },
|
||||
};
|
||||
#define NTAGS (sizeof (tags) / sizeof (tags[0]))
|
||||
|
||||
static void
|
||||
cpTags(TIFF* in, TIFF* out)
|
||||
{
|
||||
struct cpTag *p;
|
||||
for (p = tags; p < &tags[NTAGS]; p++)
|
||||
cpTag(in, out, p->tag, p->count, p->type);
|
||||
}
|
||||
#undef NTAGS
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: pal2rgb [options] input.tif output.tif",
|
||||
"where options are:",
|
||||
" -p contig pack samples contiguously (e.g. RGBRGB...)",
|
||||
" -p separate store samples separately (e.g. RRR...GGG...BBB...)",
|
||||
" -r # make each strip have no more than # rows",
|
||||
" -C 8 assume 8-bit colormap values (instead of 16-bit)",
|
||||
" -C 16 assume 16-bit colormap values",
|
||||
"",
|
||||
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
|
||||
" (no longer supported by default due to Unisys patent enforcement)",
|
||||
" -c zip[:opts] compress output with deflate encoding",
|
||||
" -c packbits compress output with packbits encoding",
|
||||
" -c none use no compression algorithm on output",
|
||||
"",
|
||||
"LZW and deflate options:",
|
||||
" # set predictor value",
|
||||
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
Executable
+242
@@ -0,0 +1,242 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/ppm2tiff.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#if defined(_WINDOWS) || defined(MSDOS)
|
||||
#define BINMODE "b"
|
||||
#else
|
||||
#define BINMODE
|
||||
#endif
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define strneq(a,b,n) (strncmp(a,b,n) == 0)
|
||||
|
||||
static uint16 compression = COMPRESSION_PACKBITS;
|
||||
static uint16 predictor = 0;
|
||||
static int quality = 75; /* JPEG quality */
|
||||
static int jpegcolormode = JPEGCOLORMODE_RGB;
|
||||
|
||||
static void usage(void);
|
||||
static int processCompressOptions(char*);
|
||||
|
||||
static void
|
||||
BadPPM(char* file)
|
||||
{
|
||||
fprintf(stderr, "%s: Not a PPM file.\n", file);
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
uint16 photometric;
|
||||
uint32 rowsperstrip = (uint32) -1;
|
||||
double resolution = -1;
|
||||
unsigned char *buf = NULL;
|
||||
uint32 row;
|
||||
tsize_t linebytes;
|
||||
uint16 spp;
|
||||
TIFF *out;
|
||||
FILE *in;
|
||||
uint32 w, h;
|
||||
int prec;
|
||||
char *infile;
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:r:R:")) != -1)
|
||||
switch (c) {
|
||||
case 'c': /* compression scheme */
|
||||
if (!processCompressOptions(optarg))
|
||||
usage();
|
||||
break;
|
||||
case 'r': /* rows/strip */
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
case 'R': /* resolution */
|
||||
resolution = atof(optarg);
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* If only one file is specified, read input from
|
||||
* stdin; otherwise usage is: ppm2tiff input output.
|
||||
*/
|
||||
if (argc - optind > 1) {
|
||||
infile = argv[optind++];
|
||||
in = fopen(infile, "r" BINMODE);
|
||||
if (in == NULL) {
|
||||
fprintf(stderr, "%s: Can not open.\n", infile);
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
infile = "<stdin>";
|
||||
in = stdin;
|
||||
}
|
||||
|
||||
if (getc(in) != 'P')
|
||||
BadPPM(infile);
|
||||
switch (getc(in)) {
|
||||
case '5': /* it's a PGM file */
|
||||
spp = 1;
|
||||
photometric = PHOTOMETRIC_MINISBLACK;
|
||||
break;
|
||||
case '6': /* it's a PPM file */
|
||||
spp = 3;
|
||||
photometric = PHOTOMETRIC_RGB;
|
||||
if (compression == COMPRESSION_JPEG &&
|
||||
jpegcolormode == JPEGCOLORMODE_RGB)
|
||||
photometric = PHOTOMETRIC_YCBCR;
|
||||
break;
|
||||
default:
|
||||
BadPPM(infile);
|
||||
}
|
||||
if (fscanf(in, " %ld %ld %d", &w, &h, &prec) != 3)
|
||||
BadPPM(infile);
|
||||
if (getc(in) != '\n' || w <= 0 || h <= 0 || prec != 255)
|
||||
BadPPM(infile);
|
||||
|
||||
out = TIFFOpen(argv[optind], "w");
|
||||
if (out == NULL)
|
||||
return (-4);
|
||||
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, w);
|
||||
TIFFSetField(out, TIFFTAG_IMAGELENGTH, h);
|
||||
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, spp);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
switch (compression) {
|
||||
case COMPRESSION_JPEG:
|
||||
TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
|
||||
TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
|
||||
break;
|
||||
case COMPRESSION_LZW:
|
||||
case COMPRESSION_DEFLATE:
|
||||
if (predictor != 0)
|
||||
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
|
||||
break;
|
||||
}
|
||||
linebytes = spp * w;
|
||||
if (TIFFScanlineSize(out) > linebytes)
|
||||
buf = (unsigned char *)_TIFFmalloc(linebytes);
|
||||
else
|
||||
buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(out));
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
|
||||
TIFFDefaultStripSize(out, rowsperstrip));
|
||||
if (resolution > 0) {
|
||||
TIFFSetField(out, TIFFTAG_XRESOLUTION, resolution);
|
||||
TIFFSetField(out, TIFFTAG_YRESOLUTION, resolution);
|
||||
TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
|
||||
}
|
||||
for (row = 0; row < h; row++) {
|
||||
if (fread(buf, linebytes, 1, in) != 1) {
|
||||
fprintf(stderr, "%s: scanline %lu: Read error.\n",
|
||||
infile, (unsigned long) row);
|
||||
break;
|
||||
}
|
||||
if (TIFFWriteScanline(out, buf, row, 0) < 0)
|
||||
break;
|
||||
}
|
||||
(void) TIFFClose(out);
|
||||
if (buf)
|
||||
_TIFFfree(buf);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
processCompressOptions(char* opt)
|
||||
{
|
||||
if (streq(opt, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(opt, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (strneq(opt, "jpeg", 4)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp && isdigit(cp[1]))
|
||||
quality = atoi(cp+1);
|
||||
if (cp && strchr(cp, 'r'))
|
||||
jpegcolormode = JPEGCOLORMODE_RAW;
|
||||
compression = COMPRESSION_JPEG;
|
||||
} else if (strneq(opt, "lzw", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_LZW;
|
||||
} else if (strneq(opt, "zip", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_DEFLATE;
|
||||
} else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: ppm2tiff [options] input.ppm output.tif",
|
||||
"where options are:",
|
||||
" -r # make each strip have no more than # rows",
|
||||
" -R # set x&y resolution (dpi)",
|
||||
"",
|
||||
" -c jpeg[:opts] compress output with JPEG encoding",
|
||||
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
|
||||
" (no longer supported by default due to Unisys patent enforcement)",
|
||||
" -c zip[:opts] compress output with deflate encoding",
|
||||
" -c packbits compress output with packbits encoding",
|
||||
" -c none use no compression algorithm on output",
|
||||
"",
|
||||
"JPEG options:",
|
||||
" # set compression quality level (0-100, default 75)",
|
||||
" r output color image as RGB rather than YCbCr",
|
||||
"LZW and deflate options:",
|
||||
" # set predictor value",
|
||||
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
Executable
+266
@@ -0,0 +1,266 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/ras2tiff.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "rasterfile.h"
|
||||
#include "tiffio.h"
|
||||
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x)+((y)-1))/(y))
|
||||
#endif
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define strneq(a,b,n) (strncmp(a,b,n) == 0)
|
||||
|
||||
#ifndef BINMODE
|
||||
#define BINMODE
|
||||
#endif
|
||||
|
||||
static uint16 compression = (uint16) -1;
|
||||
static int jpegcolormode = JPEGCOLORMODE_RGB;
|
||||
static int quality = 75; /* JPEG quality */
|
||||
static uint16 predictor = 0;
|
||||
|
||||
static void usage(void);
|
||||
static int processCompressOptions(char*);
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
unsigned char* buf;
|
||||
uint32 row;
|
||||
tsize_t linebytes, scanline;
|
||||
TIFF *out;
|
||||
FILE *in;
|
||||
struct rasterfile h;
|
||||
uint16 photometric;
|
||||
uint16 config = PLANARCONFIG_CONTIG;
|
||||
uint32 rowsperstrip = (uint32) -1;
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:r:")) != -1)
|
||||
switch (c) {
|
||||
case 'c': /* compression scheme */
|
||||
if (!processCompressOptions(optarg))
|
||||
usage();
|
||||
break;
|
||||
case 'r': /* rows/strip */
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind != 2)
|
||||
usage();
|
||||
in = fopen(argv[optind], "r" BINMODE);
|
||||
if (in == NULL) {
|
||||
fprintf(stderr, "%s: Can not open.\n", argv[optind]);
|
||||
return (-1);
|
||||
}
|
||||
if (fread(&h, sizeof (h), 1, in) != 1) {
|
||||
fprintf(stderr, "%s: Can not read header.\n", argv[optind]);
|
||||
return (-2);
|
||||
}
|
||||
if (h.ras_magic != RAS_MAGIC) {
|
||||
fprintf(stderr, "%s: Not a rasterfile.\n", argv[optind]);
|
||||
return (-3);
|
||||
}
|
||||
out = TIFFOpen(argv[optind+1], "w");
|
||||
if (out == NULL)
|
||||
return (-4);
|
||||
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) h.ras_width);
|
||||
TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) h.ras_height);
|
||||
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, h.ras_depth > 8 ? 3 : 1);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, h.ras_depth > 1 ? 8 : 1);
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
|
||||
if (h.ras_maptype != RMT_NONE) {
|
||||
uint16* red;
|
||||
register uint16* map;
|
||||
register int i, j;
|
||||
int mapsize;
|
||||
|
||||
buf = (unsigned char *)_TIFFmalloc(h.ras_maplength);
|
||||
if (buf == NULL) {
|
||||
fprintf(stderr, "No space to read in colormap.\n");
|
||||
return (-5);
|
||||
}
|
||||
if (fread(buf, h.ras_maplength, 1, in) != 1) {
|
||||
fprintf(stderr, "%s: Read error on colormap.\n",
|
||||
argv[optind]);
|
||||
return (-6);
|
||||
}
|
||||
mapsize = 1<<h.ras_depth;
|
||||
if (h.ras_maplength > mapsize*3) {
|
||||
fprintf(stderr,
|
||||
"%s: Huh, %d colormap entries, should be %d?\n",
|
||||
argv[optind], h.ras_maplength, mapsize*3);
|
||||
return (-7);
|
||||
}
|
||||
red = (uint16*)_TIFFmalloc(mapsize * 3 * sizeof (uint16));
|
||||
if (red == NULL) {
|
||||
fprintf(stderr, "No space for colormap.\n");
|
||||
return (-8);
|
||||
}
|
||||
map = red;
|
||||
for (j = 0; j < 3; j++) {
|
||||
#define SCALE(x) (((x)*((1L<<16)-1))/255)
|
||||
for (i = h.ras_maplength/3; i-- > 0;)
|
||||
*map++ = SCALE(*buf++);
|
||||
if ((i = h.ras_maplength/3) < mapsize) {
|
||||
i = mapsize - i;
|
||||
_TIFFmemset(map, 0, i*sizeof (uint16));
|
||||
map += i;
|
||||
}
|
||||
}
|
||||
TIFFSetField(out, TIFFTAG_COLORMAP,
|
||||
red, red + mapsize, red + 2*mapsize);
|
||||
photometric = PHOTOMETRIC_PALETTE;
|
||||
if (compression == (uint16) -1)
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
} else {
|
||||
/* XXX this is bogus... */
|
||||
photometric = h.ras_depth == 24 ?
|
||||
PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;
|
||||
if (compression == (uint16) -1)
|
||||
compression = COMPRESSION_LZW;
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
}
|
||||
switch (compression) {
|
||||
case COMPRESSION_JPEG:
|
||||
if (photometric == PHOTOMETRIC_RGB && jpegcolormode == JPEGCOLORMODE_RGB)
|
||||
photometric = PHOTOMETRIC_YCBCR;
|
||||
TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
|
||||
TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
|
||||
break;
|
||||
case COMPRESSION_LZW:
|
||||
case COMPRESSION_DEFLATE:
|
||||
if (predictor != 0)
|
||||
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
|
||||
break;
|
||||
}
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
linebytes = ((h.ras_depth*h.ras_width+15) >> 3) &~ 1;
|
||||
scanline = TIFFScanlineSize(out);
|
||||
if (scanline > linebytes) {
|
||||
buf = (unsigned char *)_TIFFmalloc(scanline);
|
||||
_TIFFmemset(buf+linebytes, 0, scanline-linebytes);
|
||||
} else
|
||||
buf = (unsigned char *)_TIFFmalloc(linebytes);
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
|
||||
TIFFDefaultStripSize(out, rowsperstrip));
|
||||
for (row = 0; row < h.ras_height; row++) {
|
||||
if (fread(buf, linebytes, 1, in) != 1) {
|
||||
fprintf(stderr, "%s: scanline %lu: Read error.\n",
|
||||
argv[optind], (unsigned long) row);
|
||||
break;
|
||||
}
|
||||
if (h.ras_type == RT_STANDARD && h.ras_depth == 24) {
|
||||
tsize_t cc = h.ras_width;
|
||||
unsigned char* cp = buf;
|
||||
#define SWAP(a,b) { unsigned char t = (a); (a) = (b); (b) = t; }
|
||||
do {
|
||||
SWAP(cp[0], cp[2]);
|
||||
cp += 3;
|
||||
} while (--cc);
|
||||
}
|
||||
if (TIFFWriteScanline(out, buf, row, 0) < 0)
|
||||
break;
|
||||
}
|
||||
(void) TIFFClose(out);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
processCompressOptions(char* opt)
|
||||
{
|
||||
if (streq(opt, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(opt, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (strneq(opt, "jpeg", 4)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp && isdigit(cp[1]))
|
||||
quality = atoi(cp+1);
|
||||
if (cp && strchr(cp, 'r'))
|
||||
jpegcolormode = JPEGCOLORMODE_RAW;
|
||||
compression = COMPRESSION_JPEG;
|
||||
} else if (strneq(opt, "lzw", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_LZW;
|
||||
} else if (strneq(opt, "zip", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_DEFLATE;
|
||||
} else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: ras2tiff [options] input.ras output.tif",
|
||||
"where options are:",
|
||||
" -r # make each strip have no more than # rows",
|
||||
"",
|
||||
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
|
||||
" (no longer supported by default due to Unisys patent enforcement)",
|
||||
" -c zip[:opts] compress output with deflate encoding",
|
||||
" -c jpeg[:opts]compress output with JPEG encoding",
|
||||
" -c packbits compress output with packbits encoding",
|
||||
" -c none use no compression algorithm on output",
|
||||
"",
|
||||
"JPEG options:",
|
||||
" # set compression quality level (0-100, default 75)",
|
||||
" r output color image as RGB rather than YCbCr",
|
||||
"For example, -c jpeg:r:50 to get JPEG-encoded RGB data with 50% comp. quality",
|
||||
"",
|
||||
"LZW and deflate options:",
|
||||
" # set predictor value",
|
||||
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/rasterfile.h,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Description of header for files containing raster images
|
||||
*/
|
||||
struct rasterfile {
|
||||
int ras_magic; /* magic number */
|
||||
int ras_width; /* width (pixels) of image */
|
||||
int ras_height; /* height (pixels) of image */
|
||||
int ras_depth; /* depth (1, 8, or 24 bits) of pixel */
|
||||
int ras_length; /* length (bytes) of image */
|
||||
int ras_type; /* type of file; see RT_* below */
|
||||
int ras_maptype; /* type of colormap; see RMT_* below */
|
||||
int ras_maplength; /* length (bytes) of following map */
|
||||
/* color map follows for ras_maplength bytes, followed by image */
|
||||
};
|
||||
#define RAS_MAGIC 0x59a66a95
|
||||
|
||||
/* Sun supported ras_type's */
|
||||
#define RT_OLD 0 /* Raw pixrect image in 68000 byte order */
|
||||
#define RT_STANDARD 1 /* Raw pixrect image in 68000 byte order */
|
||||
#define RT_BYTE_ENCODED 2 /* Run-length compression of bytes */
|
||||
#define RT_EXPERIMENTAL 0xffff /* Reserved for testing */
|
||||
|
||||
/* Sun registered ras_maptype's */
|
||||
#define RMT_RAW 2
|
||||
/* Sun supported ras_maptype's */
|
||||
#define RMT_NONE 0 /* ras_maplength is expected to be 0 */
|
||||
#define RMT_EQUAL_RGB 1 /* red[ras_maplength/3],green[],blue[] */
|
||||
|
||||
/*
|
||||
* NOTES:
|
||||
* Each line of the image is rounded out to a multiple of 16 bits.
|
||||
* This corresponds to the rounding convention used by the memory pixrect
|
||||
* package (/usr/include/pixrect/memvar.h) of the SunWindows system.
|
||||
* The ras_encoding field (always set to 0 by Sun's supported software)
|
||||
* was renamed to ras_length in release 2.0. As a result, rasterfiles
|
||||
* of type 0 generated by the old software claim to have 0 length; for
|
||||
* compatibility, code reading rasterfiles must be prepared to compute the
|
||||
* true length from the width, height, and depth fields.
|
||||
*/
|
||||
Executable
+341
@@ -0,0 +1,341 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/rgb2ycbcr.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define CopyField(tag, v) \
|
||||
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
|
||||
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x)+((y)-1))/(y))
|
||||
#endif
|
||||
#define roundup(x, y) (howmany(x,y)*((uint32)(y)))
|
||||
|
||||
#define LumaRed ycbcrCoeffs[0]
|
||||
#define LumaGreen ycbcrCoeffs[1]
|
||||
#define LumaBlue ycbcrCoeffs[2]
|
||||
|
||||
uint16 compression = COMPRESSION_PACKBITS;
|
||||
uint32 rowsperstrip = (uint32) -1;
|
||||
|
||||
uint16 horizSubSampling = 2; /* YCbCr horizontal subsampling */
|
||||
uint16 vertSubSampling = 2; /* YCbCr vertical subsampling */
|
||||
float ycbcrCoeffs[3] = { .299, .587, .114 };
|
||||
/* default coding range is CCIR Rec 601-1 with no headroom/footroom */
|
||||
float refBlackWhite[6] = { 0., 255., 128., 255., 128., 255. };
|
||||
|
||||
static int tiffcvt(TIFF* in, TIFF* out);
|
||||
static void usage(void);
|
||||
static void setupLumaTables(void);
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
TIFF *in, *out;
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:h:r:v:z")) != -1)
|
||||
switch (c) {
|
||||
case 'c':
|
||||
if (streq(optarg, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(optarg, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (streq(optarg, "lzw"))
|
||||
compression = COMPRESSION_LZW;
|
||||
else if (streq(optarg, "jpeg"))
|
||||
compression = COMPRESSION_JPEG;
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
case 'h':
|
||||
horizSubSampling = atoi(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
vertSubSampling = atoi(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
case 'z': /* CCIR Rec 601-1 w/ headroom/footroom */
|
||||
refBlackWhite[0] = 16.;
|
||||
refBlackWhite[1] = 235.;
|
||||
refBlackWhite[2] = 128.;
|
||||
refBlackWhite[3] = 240.;
|
||||
refBlackWhite[4] = 128.;
|
||||
refBlackWhite[5] = 240.;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind < 2)
|
||||
usage();
|
||||
out = TIFFOpen(argv[argc-1], "w");
|
||||
if (out == NULL)
|
||||
return (-2);
|
||||
setupLumaTables();
|
||||
for (; optind < argc-1; optind++) {
|
||||
in = TIFFOpen(argv[optind], "r");
|
||||
if (in != NULL) {
|
||||
do {
|
||||
if (!tiffcvt(in, out) ||
|
||||
!TIFFWriteDirectory(out)) {
|
||||
(void) TIFFClose(out);
|
||||
return (1);
|
||||
}
|
||||
} while (TIFFReadDirectory(in));
|
||||
(void) TIFFClose(in);
|
||||
}
|
||||
}
|
||||
(void) TIFFClose(out);
|
||||
return (0);
|
||||
}
|
||||
|
||||
float *lumaRed;
|
||||
float *lumaGreen;
|
||||
float *lumaBlue;
|
||||
float D1, D2;
|
||||
int Yzero;
|
||||
|
||||
static float*
|
||||
setupLuma(float c)
|
||||
{
|
||||
float *v = (float *)_TIFFmalloc(256 * sizeof (float));
|
||||
int i;
|
||||
for (i = 0; i < 256; i++)
|
||||
v[i] = c * i;
|
||||
return (v);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
V2Code(float f, float RB, float RW, int CR)
|
||||
{
|
||||
unsigned int c = (unsigned int)((((f)*(RW-RB)/CR)+RB)+.5);
|
||||
return (c > 255 ? 255 : c);
|
||||
}
|
||||
|
||||
static void
|
||||
setupLumaTables(void)
|
||||
{
|
||||
lumaRed = setupLuma(LumaRed);
|
||||
lumaGreen = setupLuma(LumaGreen);
|
||||
lumaBlue = setupLuma(LumaBlue);
|
||||
D1 = 1./(2 - 2*LumaBlue);
|
||||
D2 = 1./(2 - 2*LumaRed);
|
||||
Yzero = V2Code(0, refBlackWhite[0], refBlackWhite[1], 255);
|
||||
}
|
||||
|
||||
static void
|
||||
cvtClump(unsigned char* op, uint32* raster, uint32 ch, uint32 cw, uint32 w)
|
||||
{
|
||||
float Y, Cb = 0, Cr = 0;
|
||||
int j, k;
|
||||
/*
|
||||
* Convert ch-by-cw block of RGB
|
||||
* to YCbCr and sample accordingly.
|
||||
*/
|
||||
for (k = 0; k < ch; k++) {
|
||||
for (j = 0; j < cw; j++) {
|
||||
uint32 RGB = (raster - k*w)[j];
|
||||
Y = lumaRed[TIFFGetR(RGB)] +
|
||||
lumaGreen[TIFFGetG(RGB)] +
|
||||
lumaBlue[TIFFGetB(RGB)];
|
||||
/* accumulate chrominance */
|
||||
Cb += (TIFFGetB(RGB) - Y) * D1;
|
||||
Cr += (TIFFGetR(RGB) - Y) * D2;
|
||||
/* emit luminence */
|
||||
*op++ = V2Code(Y,
|
||||
refBlackWhite[0], refBlackWhite[1], 255);
|
||||
}
|
||||
for (; j < horizSubSampling; j++)
|
||||
*op++ = Yzero;
|
||||
}
|
||||
for (; k < vertSubSampling; k++) {
|
||||
for (j = 0; j < horizSubSampling; j++)
|
||||
*op++ = Yzero;
|
||||
}
|
||||
/* emit sampled chrominance values */
|
||||
*op++ = V2Code(Cb / (ch*cw), refBlackWhite[2], refBlackWhite[3], 127);
|
||||
*op++ = V2Code(Cr / (ch*cw), refBlackWhite[4], refBlackWhite[5], 127);
|
||||
}
|
||||
#undef LumaRed
|
||||
#undef LumaGreen
|
||||
#undef LumaBlue
|
||||
#undef V2Code
|
||||
|
||||
/*
|
||||
* Convert a strip of RGB data to YCbCr and
|
||||
* sample to generate the output data.
|
||||
*/
|
||||
static void
|
||||
cvtStrip(unsigned char* op, uint32* raster, uint32 nrows, uint32 width)
|
||||
{
|
||||
uint32 x;
|
||||
int clumpSize = vertSubSampling * horizSubSampling + 2;
|
||||
uint32 *tp;
|
||||
|
||||
for (; nrows >= vertSubSampling; nrows -= vertSubSampling) {
|
||||
tp = raster;
|
||||
for (x = width; x >= horizSubSampling; x -= horizSubSampling) {
|
||||
cvtClump(op, tp,
|
||||
vertSubSampling, horizSubSampling, width);
|
||||
op += clumpSize;
|
||||
tp += horizSubSampling;
|
||||
}
|
||||
if (x > 0) {
|
||||
cvtClump(op, tp, vertSubSampling, x, width);
|
||||
op += clumpSize;
|
||||
}
|
||||
raster -= vertSubSampling*width;
|
||||
}
|
||||
if (nrows > 0) {
|
||||
tp = raster;
|
||||
for (x = width; x >= horizSubSampling; x -= horizSubSampling) {
|
||||
cvtClump(op, tp, nrows, horizSubSampling, width);
|
||||
op += clumpSize;
|
||||
tp += horizSubSampling;
|
||||
}
|
||||
if (x > 0)
|
||||
cvtClump(op, tp, nrows, x, width);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
cvtRaster(TIFF* tif, uint32* raster, uint32 width, uint32 height)
|
||||
{
|
||||
uint32 y;
|
||||
tstrip_t strip = 0;
|
||||
tsize_t cc, acc;
|
||||
unsigned char* buf;
|
||||
uint32 rwidth = roundup(width, horizSubSampling);
|
||||
uint32 rheight = roundup(height, vertSubSampling);
|
||||
uint32 nrows = (rowsperstrip > rheight ? rheight : rowsperstrip);
|
||||
|
||||
cc = nrows*rwidth +
|
||||
2*((nrows*rwidth) / (horizSubSampling*vertSubSampling));
|
||||
buf = (unsigned char*)_TIFFmalloc(cc);
|
||||
for (y = height; (int32) y > 0; y -= nrows) {
|
||||
uint32 nr = (y > nrows ? nrows : y);
|
||||
cvtStrip(buf, raster + (y-1)*width, nr, width);
|
||||
nr = roundup(nr, vertSubSampling);
|
||||
acc = nr*rwidth +
|
||||
2*((nr*rwidth)/(horizSubSampling*vertSubSampling));
|
||||
if (!TIFFWriteEncodedStrip(tif, strip++, buf, acc)) {
|
||||
_TIFFfree(buf);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
tiffcvt(TIFF* in, TIFF* out)
|
||||
{
|
||||
uint32 width, height; /* image width & height */
|
||||
uint32* raster; /* retrieve RGBA image */
|
||||
uint16 shortv;
|
||||
float floatv;
|
||||
char *stringv;
|
||||
uint32 longv;
|
||||
|
||||
TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width);
|
||||
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height);
|
||||
raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32));
|
||||
if (raster == 0) {
|
||||
TIFFError(TIFFFileName(in), "No space for raster buffer");
|
||||
return (0);
|
||||
}
|
||||
if (!TIFFReadRGBAImage(in, width, height, raster, 0)) {
|
||||
_TIFFfree(raster);
|
||||
return (0);
|
||||
}
|
||||
|
||||
CopyField(TIFFTAG_SUBFILETYPE, longv);
|
||||
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
|
||||
TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
|
||||
if (compression == COMPRESSION_JPEG)
|
||||
TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW);
|
||||
CopyField(TIFFTAG_FILLORDER, shortv);
|
||||
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 3);
|
||||
CopyField(TIFFTAG_XRESOLUTION, floatv);
|
||||
CopyField(TIFFTAG_YRESOLUTION, floatv);
|
||||
CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
{ char buf[2048];
|
||||
char *cp = strrchr(TIFFFileName(in), '/');
|
||||
sprintf(buf, "YCbCr conversion of %s", cp ? cp+1 : TIFFFileName(in));
|
||||
TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, buf);
|
||||
}
|
||||
TIFFSetField(out, TIFFTAG_SOFTWARE, TIFFGetVersion());
|
||||
CopyField(TIFFTAG_DOCUMENTNAME, stringv);
|
||||
|
||||
TIFFSetField(out, TIFFTAG_REFERENCEBLACKWHITE, refBlackWhite);
|
||||
TIFFSetField(out, TIFFTAG_YCBCRSUBSAMPLING,
|
||||
horizSubSampling, vertSubSampling);
|
||||
TIFFSetField(out, TIFFTAG_YCBCRPOSITIONING, YCBCRPOSITION_CENTERED);
|
||||
TIFFSetField(out, TIFFTAG_YCBCRCOEFFICIENTS, ycbcrCoeffs);
|
||||
rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
|
||||
|
||||
return (cvtRaster(out, raster, width, height));
|
||||
}
|
||||
|
||||
static char* usageMsg[] = {
|
||||
"usage: rgb2ycbcr [-c comp] [-r rows] [-h N] [-v N] input... output\n",
|
||||
"where comp is one of the following compression algorithms:\n",
|
||||
" jpeg\t\tJPEG encoding\n",
|
||||
" lzw\t\tLempel-Ziv & Welch encoding\n",
|
||||
" (lzw no longer supported by default due to Unisys patent enforcement)",
|
||||
" packbits\tPackBits encoding\n",
|
||||
" none\t\tno compression\n",
|
||||
"and the other options are:\n",
|
||||
" -r\trows/strip\n",
|
||||
" -h\thorizontal sampling factor (1,2,4)\n",
|
||||
" -v\tvertical sampling factor (1,2,4)\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; usageMsg[i]; i++)
|
||||
fprintf(stderr, "%s", usageMsg[i]);
|
||||
exit(-1);
|
||||
}
|
||||
Executable
+321
@@ -0,0 +1,321 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/sgi2tiff.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <gl/image.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define strneq(a,b,n) (strncmp(a,b,n) == 0)
|
||||
|
||||
static short config = PLANARCONFIG_CONTIG;
|
||||
static uint16 compression = COMPRESSION_PACKBITS;
|
||||
static uint16 predictor = 0;
|
||||
static uint16 fillorder = 0;
|
||||
static uint32 rowsperstrip = (uint32) -1;
|
||||
static int jpegcolormode = JPEGCOLORMODE_RGB;
|
||||
static int quality = 75; /* JPEG quality */
|
||||
static uint16 photometric;
|
||||
|
||||
static void usage(void);
|
||||
static int cpContig(IMAGE*, TIFF*);
|
||||
static int cpSeparate(IMAGE*, TIFF*);
|
||||
static int processCompressOptions(char*);
|
||||
|
||||
/* XXX image library has no prototypes */
|
||||
extern IMAGE* iopen(const char*, const char*);
|
||||
extern void iclose(IMAGE*);
|
||||
extern void getrow(IMAGE*, short*, int, int);
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
IMAGE *in;
|
||||
TIFF *out;
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:p:r:")) != -1)
|
||||
switch (c) {
|
||||
case 'c': /* compression scheme */
|
||||
if (!processCompressOptions(optarg))
|
||||
usage();
|
||||
break;
|
||||
case 'f': /* fill order */
|
||||
if (streq(optarg, "lsb2msb"))
|
||||
fillorder = FILLORDER_LSB2MSB;
|
||||
else if (streq(optarg, "msb2lsb"))
|
||||
fillorder = FILLORDER_MSB2LSB;
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
case 'p': /* planar configuration */
|
||||
if (streq(optarg, "separate"))
|
||||
config = PLANARCONFIG_SEPARATE;
|
||||
else if (streq(optarg, "contig"))
|
||||
config = PLANARCONFIG_CONTIG;
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
case 'r': /* rows/strip */
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind != 2)
|
||||
usage();
|
||||
in = iopen(argv[optind], "r");
|
||||
if (in == NULL)
|
||||
return (-1);
|
||||
out = TIFFOpen(argv[optind+1], "w");
|
||||
if (out == NULL)
|
||||
return (-2);
|
||||
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) in->xsize);
|
||||
TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) in->ysize);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
if (in->zsize == 1)
|
||||
photometric = PHOTOMETRIC_MINISBLACK;
|
||||
else
|
||||
photometric = PHOTOMETRIC_RGB;
|
||||
switch (compression) {
|
||||
case COMPRESSION_JPEG:
|
||||
if (photometric == PHOTOMETRIC_RGB && jpegcolormode == JPEGCOLORMODE_RGB)
|
||||
photometric = PHOTOMETRIC_YCBCR;
|
||||
TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
|
||||
TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
|
||||
break;
|
||||
case COMPRESSION_LZW:
|
||||
case COMPRESSION_DEFLATE:
|
||||
if (predictor != 0)
|
||||
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
|
||||
break;
|
||||
}
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
if (fillorder != 0)
|
||||
TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
|
||||
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, in->zsize);
|
||||
if (in->zsize > 3) {
|
||||
uint16 v[1];
|
||||
v[0] = EXTRASAMPLE_UNASSALPHA;
|
||||
TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, v);
|
||||
}
|
||||
TIFFSetField(out, TIFFTAG_MINSAMPLEVALUE, (uint16) in->min);
|
||||
TIFFSetField(out, TIFFTAG_MAXSAMPLEVALUE, (uint16) in->max);
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
|
||||
if (config != PLANARCONFIG_SEPARATE)
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
|
||||
TIFFDefaultStripSize(out, rowsperstrip));
|
||||
else /* force 1 row/strip for library limitation */
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, 1L);
|
||||
if (in->name[0] != '\0')
|
||||
TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, in->name);
|
||||
if (config == PLANARCONFIG_CONTIG)
|
||||
cpContig(in, out);
|
||||
else
|
||||
cpSeparate(in, out);
|
||||
(void) iclose(in);
|
||||
(void) TIFFClose(out);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
processCompressOptions(char* opt)
|
||||
{
|
||||
if (streq(opt, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(opt, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (strneq(opt, "jpeg", 4)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp && isdigit(cp[1]))
|
||||
quality = atoi(cp+1);
|
||||
if (cp && strchr(cp, 'r'))
|
||||
jpegcolormode = JPEGCOLORMODE_RAW;
|
||||
compression = COMPRESSION_JPEG;
|
||||
} else if (strneq(opt, "lzw", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_LZW;
|
||||
} else if (strneq(opt, "zip", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_DEFLATE;
|
||||
} else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
cpContig(IMAGE* in, TIFF* out)
|
||||
{
|
||||
tdata_t buf = _TIFFmalloc(TIFFScanlineSize(out));
|
||||
short *r = NULL;
|
||||
int x, y;
|
||||
|
||||
if (in->zsize == 3) {
|
||||
short *g, *b;
|
||||
|
||||
r = (short *)_TIFFmalloc(3 * in->xsize * sizeof (short));
|
||||
g = r + in->xsize;
|
||||
b = g + in->xsize;
|
||||
for (y = in->ysize-1; y >= 0; y--) {
|
||||
uint8* pp = (uint8*) buf;
|
||||
|
||||
getrow(in, r, y, 0);
|
||||
getrow(in, g, y, 1);
|
||||
getrow(in, b, y, 2);
|
||||
for (x = 0; x < in->xsize; x++) {
|
||||
pp[0] = r[x];
|
||||
pp[1] = g[x];
|
||||
pp[2] = b[x];
|
||||
pp += 3;
|
||||
}
|
||||
if (TIFFWriteScanline(out, buf, in->ysize-y-1, 0) < 0)
|
||||
goto bad;
|
||||
}
|
||||
} else if (in->zsize == 4) {
|
||||
short *g, *b, *a;
|
||||
|
||||
r = (short *)_TIFFmalloc(4 * in->xsize * sizeof (short));
|
||||
g = r + in->xsize;
|
||||
b = g + in->xsize;
|
||||
a = b + in->xsize;
|
||||
for (y = in->ysize-1; y >= 0; y--) {
|
||||
uint8* pp = (uint8*) buf;
|
||||
|
||||
getrow(in, r, y, 0);
|
||||
getrow(in, g, y, 1);
|
||||
getrow(in, b, y, 2);
|
||||
getrow(in, a, y, 3);
|
||||
for (x = 0; x < in->xsize; x++) {
|
||||
pp[0] = r[x];
|
||||
pp[1] = g[x];
|
||||
pp[2] = b[x];
|
||||
pp[3] = a[x];
|
||||
pp += 4;
|
||||
}
|
||||
if (TIFFWriteScanline(out, buf, in->ysize-y-1, 0) < 0)
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
uint8* pp = (uint8*) buf;
|
||||
|
||||
r = (short *)_TIFFmalloc(in->xsize * sizeof (short));
|
||||
for (y = in->ysize-1; y >= 0; y--) {
|
||||
getrow(in, r, y, 0);
|
||||
for (x = in->xsize-1; x >= 0; x--)
|
||||
pp[x] = r[x];
|
||||
if (TIFFWriteScanline(out, buf, in->ysize-y-1, 0) < 0)
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
if (r)
|
||||
_TIFFfree(r);
|
||||
_TIFFfree(buf);
|
||||
return (1);
|
||||
bad:
|
||||
if (r)
|
||||
_TIFFfree(r);
|
||||
_TIFFfree(buf);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpSeparate(IMAGE* in, TIFF* out)
|
||||
{
|
||||
tdata_t buf = _TIFFmalloc(TIFFScanlineSize(out));
|
||||
short *r = (short *)_TIFFmalloc(in->xsize * sizeof (short));
|
||||
uint8* pp = (uint8*) buf;
|
||||
int x, y, z;
|
||||
|
||||
for (z = 0; z < in->zsize; z++) {
|
||||
for (y = in->ysize-1; y >= 0; y--) {
|
||||
getrow(in, r, y, z);
|
||||
for (x = 0; x < in->xsize; x++)
|
||||
pp[x] = r[x];
|
||||
if (TIFFWriteScanline(out, buf, in->ysize-y-1, z) < 0)
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
_TIFFfree(r);
|
||||
_TIFFfree(buf);
|
||||
return (1);
|
||||
bad:
|
||||
_TIFFfree(r);
|
||||
_TIFFfree(buf);
|
||||
return (0);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: sgi2tiff [options] input.rgb output.tif",
|
||||
"where options are:",
|
||||
" -r # make each strip have no more than # rows",
|
||||
"",
|
||||
" -p contig pack samples contiguously (e.g. RGBRGB...)",
|
||||
" -p separate store samples separately (e.g. RRR...GGG...BBB...)",
|
||||
"",
|
||||
" -f lsb2msb force lsb-to-msb FillOrder for output",
|
||||
" -f msb2lsb force msb-to-lsb FillOrder for output",
|
||||
"",
|
||||
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
|
||||
" (no longer supported by default due to Unisys patent enforcement)",
|
||||
" -c zip[:opts] compress output with deflate encoding",
|
||||
" -c jpeg[:opts]compress output with JPEG encoding",
|
||||
" -c packbits compress output with packbits encoding",
|
||||
" -c none use no compression algorithm on output",
|
||||
"",
|
||||
"JPEG options:",
|
||||
" # set compression quality level (0-100, default 75)",
|
||||
" r output color image as RGB rather than YCbCr",
|
||||
"",
|
||||
"LZW and deflate options:",
|
||||
" # set predictor value",
|
||||
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
Executable
+984
@@ -0,0 +1,984 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/sgigt.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gl.h>
|
||||
#include <device.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/* XXX fudge adjustment for window borders */
|
||||
#define YFUDGE 20
|
||||
#define XFUDGE 20
|
||||
|
||||
static tileContigRoutine putContig;
|
||||
static tileSeparateRoutine putSeparate;
|
||||
static uint32 width, height; /* window width & height */
|
||||
static uint32* raster = NULL; /* displayable image */
|
||||
|
||||
extern Colorindex greyi(int);
|
||||
static void setupColormapSupport(TIFFRGBAImage*);
|
||||
static void putContigAndDraw(TIFFRGBAImage*, uint32*,
|
||||
uint32, uint32, uint32, uint32, int32, int32, unsigned char*);
|
||||
static void putSeparateAndDraw(TIFFRGBAImage*, uint32*,
|
||||
uint32, uint32, uint32, uint32, int32, int32,
|
||||
unsigned char*, unsigned char*, unsigned char*, unsigned char*);
|
||||
|
||||
static int prevImage(char* argv[], int ix, int b, int e, int wrap);
|
||||
static int nextImage(char* argv[], int ix, int b, int e, int wrap);
|
||||
static void usage(void);
|
||||
static uint16 photoArg(const char*);
|
||||
static void beep(void);
|
||||
|
||||
extern char* optarg;
|
||||
extern int optind;
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
static Cursor hourglass = {
|
||||
0x1ff0, 0x1ff0, 0x0820, 0x0820,
|
||||
0x0820, 0x0c60, 0x06c0, 0x0100,
|
||||
0x0100, 0x06c0, 0x0c60, 0x0820,
|
||||
0x0820, 0x0820, 0x1ff0, 0x1ff0
|
||||
};
|
||||
int isRGB0 = -1, isRGB;
|
||||
int verbose = 0;
|
||||
int stoponerr = 0; /* stop on read error */
|
||||
char* filename;
|
||||
TIFF* tif = NULL;
|
||||
int fg = 0;
|
||||
int c;
|
||||
int dirnum = -1;
|
||||
int order0 = 0, order;
|
||||
uint32 diroff = 0;
|
||||
uint16 photo0 = (uint16) -1, photo;
|
||||
long x, y, xmax, ymax;
|
||||
int ix, nix;
|
||||
TIFFErrorHandler oerror = TIFFSetErrorHandler(NULL);
|
||||
TIFFErrorHandler owarning = TIFFSetWarningHandler(NULL);
|
||||
uint32 w, h;
|
||||
long wid = -1;
|
||||
|
||||
while ((c = getopt(argc, argv, "d:o:p:cerflmsvw")) != -1)
|
||||
switch (c) {
|
||||
case 'c':
|
||||
isRGB0 = 0;
|
||||
break;
|
||||
case 'd':
|
||||
dirnum = atoi(optarg);
|
||||
break;
|
||||
case 'e':
|
||||
oerror = TIFFSetErrorHandler(oerror);
|
||||
break;
|
||||
case 'f':
|
||||
fg = 1;
|
||||
break;
|
||||
case 'l':
|
||||
order0 = FILLORDER_LSB2MSB;
|
||||
break;
|
||||
case 'm':
|
||||
order0 = FILLORDER_MSB2LSB;
|
||||
break;
|
||||
case 'o':
|
||||
diroff = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'p':
|
||||
photo0 = photoArg(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
isRGB0 = 1;
|
||||
break;
|
||||
case 's':
|
||||
stoponerr = 1;
|
||||
break;
|
||||
case 'w':
|
||||
owarning = TIFFSetWarningHandler(owarning);
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind < 1)
|
||||
usage();
|
||||
xmax = getgdesc(GD_XPMAX) - XFUDGE;
|
||||
ymax = getgdesc(GD_YPMAX) - YFUDGE;
|
||||
ix = optind;
|
||||
do {
|
||||
tif = TIFFOpen(argv[ix], "r");
|
||||
} while (tif == NULL && (ix = nextImage(argv, ix, optind, argc, FALSE)));
|
||||
if (tif == NULL)
|
||||
exit(0);
|
||||
if (ix == optind) {
|
||||
/*
|
||||
* Set initial directory if user-specified
|
||||
* file was opened successfully.
|
||||
*/
|
||||
if (dirnum != -1 && !TIFFSetDirectory(tif, dirnum))
|
||||
TIFFError(argv[ix], "Error, seeking to directory %d", dirnum);
|
||||
if (diroff != 0 && !TIFFSetSubDirectory(tif, diroff))
|
||||
TIFFError(argv[ix], "Error, setting subdirectory at %#x", diroff);
|
||||
}
|
||||
isRGB = isRGB0;
|
||||
order = order0;
|
||||
photo = photo0;
|
||||
goto newfile0;
|
||||
for (;;) {
|
||||
TIFFRGBAImage img;
|
||||
char title[1024]; /* window title line */
|
||||
const char* cp;
|
||||
int isrgb;
|
||||
|
||||
if (order)
|
||||
TIFFSetField(tif, TIFFTAG_FILLORDER, order);
|
||||
if (photo != (uint16) -1)
|
||||
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photo);
|
||||
if (!TIFFRGBAImageBegin(&img, tif, stoponerr, title)) {
|
||||
TIFFError(filename, title);
|
||||
goto bad2;
|
||||
}
|
||||
/*
|
||||
* Use a full-color window if the image is
|
||||
* full color or a palette image and the
|
||||
* hardware support is present.
|
||||
*/
|
||||
isrgb = isRGB;
|
||||
if (isrgb == -1)
|
||||
isrgb = (img.bitspersample >= 8 &&
|
||||
(img.photometric == PHOTOMETRIC_RGB ||
|
||||
img.photometric == PHOTOMETRIC_YCBCR ||
|
||||
img.photometric == PHOTOMETRIC_SEPARATED ||
|
||||
img.photometric == PHOTOMETRIC_PALETTE ||
|
||||
img.photometric == PHOTOMETRIC_LOGLUV));
|
||||
/*
|
||||
* Check to see if the hardware can display 24-bit RGB.
|
||||
*/
|
||||
if (isrgb && getgdesc(GD_BITS_NORM_SNG_RED) < img.bitspersample &&
|
||||
!getgdesc(GD_DITHER)) {
|
||||
if (verbose)
|
||||
printf("Warning, display is incapable of full RGB,%s\n",
|
||||
" using dithered colormap");
|
||||
isrgb = 0;
|
||||
}
|
||||
/*
|
||||
* Colormap-based display is done by overriding the put
|
||||
* routine to install a private method that understands
|
||||
* how to convert RGBA values to suitable colormap indices.
|
||||
*/
|
||||
if (!isrgb)
|
||||
setupColormapSupport(&img);
|
||||
/*
|
||||
* Override default ``put routine'' with private
|
||||
* routine that also draws the raster on the display.
|
||||
*/
|
||||
if (img.put.any == 0) {
|
||||
TIFFError(filename,
|
||||
"No \"put\" routine; must not handle image format");
|
||||
goto bad3;
|
||||
}
|
||||
if (img.isContig) {
|
||||
putContig = img.put.contig;
|
||||
img.put.contig = putContigAndDraw;
|
||||
} else {
|
||||
putSeparate = img.put.separate;
|
||||
img.put.separate = putSeparateAndDraw;
|
||||
}
|
||||
/*
|
||||
* Setup the image raster as required.
|
||||
*/
|
||||
if ((w = img.width) > xmax)
|
||||
w = xmax;
|
||||
if ((h = img.height) > ymax)
|
||||
h = ymax;
|
||||
if (w != width || h != height) {
|
||||
if (raster != NULL)
|
||||
_TIFFfree(raster), raster = NULL;
|
||||
raster = (uint32*) _TIFFmalloc(w * h * sizeof (uint32));
|
||||
if (raster == NULL) {
|
||||
width = height = 0;
|
||||
TIFFError(filename, "No space for raster buffer");
|
||||
goto bad3;
|
||||
}
|
||||
width = w;
|
||||
height = h;
|
||||
}
|
||||
/*
|
||||
* Create a new window or reconfigure an existing
|
||||
* one to suit the image to be displayed.
|
||||
*/
|
||||
if (wid < 0) {
|
||||
x = (xmax+XFUDGE-width)/2;
|
||||
y = (ymax+YFUDGE-height)/2;
|
||||
prefposition(x, x+width-1, y, y+height-1);
|
||||
cp = strrchr(filename, '/');
|
||||
sprintf(title, "%s [%u] %s",
|
||||
cp == NULL ? filename : cp+1,
|
||||
(unsigned int) TIFFCurrentDirectory(tif),
|
||||
isrgb ? " rgb" : " cmap");
|
||||
if (fg)
|
||||
foreground();
|
||||
wid = winopen(title);
|
||||
if (wid < 0) {
|
||||
TIFFError(filename, "Can not create window");
|
||||
TIFFRGBAImageEnd(&img);
|
||||
break;
|
||||
}
|
||||
curstype(C16X1);
|
||||
defcursor(1, hourglass);
|
||||
qdevice(LEFTMOUSE);
|
||||
qdevice(MIDDLEMOUSE);
|
||||
qdevice(RIGHTMOUSE);
|
||||
qdevice(KEYBD);
|
||||
qdevice(PAGEUPKEY);
|
||||
qdevice(PAGEDOWNKEY);
|
||||
qdevice(HOMEKEY);
|
||||
qdevice(ENDKEY);
|
||||
} else {
|
||||
x = (xmax+XFUDGE-width)/2;
|
||||
y = (ymax+YFUDGE-height)/2;
|
||||
winposition(x, x+width-1, y, y+height-1);
|
||||
viewport(0, width-1, 0, height-1);
|
||||
cp = strrchr(filename, '/');
|
||||
sprintf(title, "%s [%u] %s",
|
||||
cp == NULL ? filename : cp+1,
|
||||
(unsigned int) TIFFCurrentDirectory(tif),
|
||||
isrgb ? " rgb" : " cmap");
|
||||
wintitle(title);
|
||||
}
|
||||
singlebuffer();
|
||||
if (isrgb) {
|
||||
RGBmode();
|
||||
gconfig();
|
||||
} else {
|
||||
cmode();
|
||||
gconfig();
|
||||
}
|
||||
/*
|
||||
* Fetch the image.
|
||||
*/
|
||||
setcursor(1, 0, 0);
|
||||
greyi(225);
|
||||
clear();
|
||||
(void) TIFFRGBAImageGet(&img, raster, width, height);
|
||||
setcursor(0, 0, 0);
|
||||
/*
|
||||
* Process input.
|
||||
*/
|
||||
for (;;) {
|
||||
short val;
|
||||
switch (qread(&val)) {
|
||||
case KEYBD:
|
||||
switch (val) {
|
||||
case 'b': /* photometric MinIsBlack */
|
||||
photo = PHOTOMETRIC_MINISBLACK;
|
||||
goto newpage;
|
||||
case 'l': /* lsb-to-msb FillOrder */
|
||||
order = FILLORDER_LSB2MSB;
|
||||
goto newpage;
|
||||
case 'm': /* msb-to-lsb FillOrder */
|
||||
order = FILLORDER_MSB2LSB;
|
||||
goto newpage;
|
||||
case 'c': /* colormap visual */
|
||||
isRGB = 0;
|
||||
goto newpage;
|
||||
case 'r': /* RGB visual */
|
||||
isRGB = 1;
|
||||
goto newpage;
|
||||
case 'w': /* photometric MinIsWhite */
|
||||
photo = PHOTOMETRIC_MINISWHITE;
|
||||
goto newpage;
|
||||
case 'W': /* toggle warnings */
|
||||
owarning = TIFFSetWarningHandler(owarning);
|
||||
goto newpage;
|
||||
case 'E': /* toggle errors */
|
||||
oerror = TIFFSetErrorHandler(oerror);
|
||||
goto newpage;
|
||||
case 'z': /* reset to defaults */
|
||||
case 'Z':
|
||||
order = order0;
|
||||
photo = photo0;
|
||||
isRGB = isRGB0;
|
||||
if (owarning == NULL)
|
||||
owarning = TIFFSetWarningHandler(NULL);
|
||||
if (oerror == NULL)
|
||||
oerror = TIFFSetErrorHandler(NULL);
|
||||
goto newpage;
|
||||
case 'q': /* exit */
|
||||
case '\033':
|
||||
TIFFRGBAImageEnd(&img);
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case PAGEUPKEY: /* previous logical image */
|
||||
if (val) {
|
||||
if (TIFFCurrentDirectory(tif) > 0) {
|
||||
if (TIFFSetDirectory(tif, TIFFCurrentDirectory(tif)-1))
|
||||
goto newpage;
|
||||
beep(); /* XXX */
|
||||
} else {
|
||||
ix = prevImage(argv, ix, optind, argc, TRUE);
|
||||
/* XXX set directory to last image in new file */
|
||||
goto newfile;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PAGEDOWNKEY: /* next logical image */
|
||||
if (val) {
|
||||
if (!TIFFLastDirectory(tif)) {
|
||||
if (TIFFReadDirectory(tif))
|
||||
goto newpage;
|
||||
beep(); /* XXX */
|
||||
} else {
|
||||
ix = nextImage(argv, ix, optind, argc, TRUE);
|
||||
goto newfile;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HOMEKEY: /* 1st image in current file */
|
||||
if (val) {
|
||||
if (TIFFSetDirectory(tif, 0))
|
||||
goto newpage;
|
||||
beep();
|
||||
}
|
||||
break;
|
||||
case ENDKEY: /* last image in current file */
|
||||
if (val) {
|
||||
/* XXX */
|
||||
beep();
|
||||
}
|
||||
break;
|
||||
case RIGHTMOUSE: /* previous file */
|
||||
if (val) {
|
||||
if (nix = prevImage(argv, ix, optind, argc, FALSE)) {
|
||||
ix = nix;
|
||||
goto newfile;
|
||||
}
|
||||
beep();
|
||||
}
|
||||
break;
|
||||
case LEFTMOUSE: /* next file */
|
||||
if (val) {
|
||||
if (nix = nextImage(argv, ix, optind, argc, FALSE)) {
|
||||
ix = nix;
|
||||
goto newfile;
|
||||
}
|
||||
beep();
|
||||
}
|
||||
break;
|
||||
case MIDDLEMOUSE: /* first file */
|
||||
if (val) {
|
||||
if (nix = nextImage(argv, optind-1, optind, argc, FALSE)) {
|
||||
ix = nix;
|
||||
goto newfile;
|
||||
}
|
||||
beep();
|
||||
}
|
||||
break;
|
||||
case REDRAW:
|
||||
lrectwrite(0, 0, width-1, height-1, raster);
|
||||
break;
|
||||
}
|
||||
}
|
||||
newfile:
|
||||
TIFFRGBAImageEnd(&img);
|
||||
if (tif != NULL && argv[ix] != filename)
|
||||
TIFFClose(tif), tif = NULL;
|
||||
/* fall thru... */
|
||||
newfile0:
|
||||
if (argv[ix] == NULL)
|
||||
break;
|
||||
filename = argv[ix];
|
||||
if (tif == NULL) {
|
||||
tif = TIFFOpen(filename, "r");
|
||||
if (tif == NULL)
|
||||
goto bad1;
|
||||
isRGB = isRGB0;
|
||||
order = order0;
|
||||
photo = photo0;
|
||||
}
|
||||
continue;
|
||||
newpage:
|
||||
TIFFRGBAImageEnd(&img);
|
||||
continue;
|
||||
bad3:
|
||||
TIFFRGBAImageEnd(&img);
|
||||
bad2:
|
||||
TIFFClose(tif), tif = NULL;
|
||||
bad1:
|
||||
argv[ix] = NULL; /* don't revisit file */
|
||||
ix = nextImage(argv, ix, optind, argc, TRUE);
|
||||
goto newfile0;
|
||||
}
|
||||
done:
|
||||
if (wid >= 0)
|
||||
winclose(wid);
|
||||
if (raster != NULL)
|
||||
_TIFFfree(raster);
|
||||
if (tif != NULL)
|
||||
TIFFClose(tif);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
prevImage(char* argv[], int ix, int b, int e, int wrap)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = ix-1; i >= b && argv[i] == NULL; i--)
|
||||
;
|
||||
if (i < b) {
|
||||
if (wrap) {
|
||||
for (i = e-1; i > ix && argv[i] == NULL; i--)
|
||||
;
|
||||
} else
|
||||
i = 0;
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
|
||||
static int
|
||||
nextImage(char* argv[], int ix, int b, int e, int wrap)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = ix+1; i < e && argv[i] == NULL; i++)
|
||||
;
|
||||
if (i >= e) {
|
||||
if (wrap) {
|
||||
for (i = b; i < ix && argv[i] == NULL; i++)
|
||||
;
|
||||
} else
|
||||
i = 0;
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
|
||||
static void
|
||||
beep(void)
|
||||
{
|
||||
greyi(0);
|
||||
clear();
|
||||
sginap(5);
|
||||
lrectwrite(0, 0, width-1, height-1, raster);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: tiffgt [options] file.tif",
|
||||
"where options are:",
|
||||
" -c use colormap visual",
|
||||
" -d dirnum set initial directory (default is 0)",
|
||||
" -e enable display of TIFF error messages",
|
||||
" -f run program in the foreground",
|
||||
" -l force lsb-to-msb FillOrder",
|
||||
" -m force msb-to-lsb FillOrder",
|
||||
" -o offset set initial directory offset",
|
||||
" -p photo override photometric interpretation",
|
||||
" -r use fullcolor visual",
|
||||
" -s stop decoding on first error (default is ignore errors)",
|
||||
" -v enable verbose mode",
|
||||
" -w enable display of TIFF warning messages",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static uint16
|
||||
photoArg(const char* arg)
|
||||
{
|
||||
if (strcmp(arg, "miniswhite") == 0)
|
||||
return (PHOTOMETRIC_MINISWHITE);
|
||||
else if (strcmp(arg, "minisblack") == 0)
|
||||
return (PHOTOMETRIC_MINISBLACK);
|
||||
else if (strcmp(arg, "rgb") == 0)
|
||||
return (PHOTOMETRIC_RGB);
|
||||
else if (strcmp(arg, "palette") == 0)
|
||||
return (PHOTOMETRIC_PALETTE);
|
||||
else if (strcmp(arg, "mask") == 0)
|
||||
return (PHOTOMETRIC_MASK);
|
||||
else if (strcmp(arg, "separated") == 0)
|
||||
return (PHOTOMETRIC_SEPARATED);
|
||||
else if (strcmp(arg, "ycbcr") == 0)
|
||||
return (PHOTOMETRIC_YCBCR);
|
||||
else if (strcmp(arg, "cielab") == 0)
|
||||
return (PHOTOMETRIC_CIELAB);
|
||||
else if (strcmp(arg, "logl") == 0)
|
||||
return (PHOTOMETRIC_LOGL);
|
||||
else if (strcmp(arg, "logluv") == 0)
|
||||
return (PHOTOMETRIC_LOGLUV);
|
||||
else
|
||||
return ((uint16) -1);
|
||||
}
|
||||
|
||||
static void
|
||||
putContigAndDraw(TIFFRGBAImage* img, uint32* raster,
|
||||
uint32 x, uint32 y, uint32 w, uint32 h,
|
||||
int32 fromskew, int32 toskew,
|
||||
unsigned char* cp)
|
||||
{
|
||||
(*putContig)(img, raster, x, y, w, h, fromskew, toskew, cp);
|
||||
if (x+w == width) {
|
||||
w = width;
|
||||
if (img->orientation == ORIENTATION_TOPLEFT)
|
||||
lrectwrite(0, y-(h-1), w-1, y, raster-x-(h-1)*w);
|
||||
else
|
||||
lrectwrite(0, y, w-1, y+h-1, raster);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
putSeparateAndDraw(TIFFRGBAImage* img, uint32* raster,
|
||||
uint32 x, uint32 y, uint32 w, uint32 h,
|
||||
int32 fromskew, int32 toskew,
|
||||
unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a)
|
||||
{
|
||||
(*putSeparate)(img, raster, x, y, w, h, fromskew, toskew, r, g, b, a);
|
||||
if (x+w == width) {
|
||||
w = width;
|
||||
if (img->orientation == ORIENTATION_TOPLEFT)
|
||||
lrectwrite(0, y-(h-1), w-1, y, raster-x-(h-1)*w);
|
||||
else
|
||||
lrectwrite(0, y, w-1, y+h-1, raster);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* {red,green,blue}_inverse are tables in libgutil.a that
|
||||
* do an inverse map from (r,g,b) to the closest colormap
|
||||
* index in the "standard" GL colormap. grey_inverse is
|
||||
* the equivalent map for mapping greyscale values to
|
||||
* colormap indices. We access these maps directly instead
|
||||
* of through the rgbi and greyi functions to avoid the
|
||||
* additional overhead of the color calls that they make.
|
||||
*/
|
||||
extern u_char red_inverse[256];
|
||||
extern u_char green_inverse[256];
|
||||
extern u_char blue_inverse[256];
|
||||
extern u_char grey_inverse[256];
|
||||
#define greyi(g) grey_inverse[g]
|
||||
|
||||
static u_char
|
||||
rgbi(u_char r, u_char g, u_char b)
|
||||
{
|
||||
return (r == g && g == b ? grey_inverse[r] :
|
||||
red_inverse[r] + green_inverse[g] + blue_inverse[b]);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following routines move decoded data returned
|
||||
* from the TIFF library into rasters that are suitable
|
||||
* for passing to lrecwrite. They do the necessary
|
||||
* conversions for when a colormap drawing mode is used.
|
||||
*/
|
||||
#define REPEAT8(op) REPEAT4(op); REPEAT4(op)
|
||||
#define REPEAT4(op) REPEAT2(op); REPEAT2(op)
|
||||
#define REPEAT2(op) op; op
|
||||
#define CASE8(x,op) \
|
||||
switch (x) { \
|
||||
case 7: op; case 6: op; case 5: op; \
|
||||
case 4: op; case 3: op; case 2: op; \
|
||||
case 1: op; \
|
||||
}
|
||||
#define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; }
|
||||
#define NOP
|
||||
|
||||
#define UNROLL8(w, op1, op2) { \
|
||||
uint32 _x; \
|
||||
for (_x = w; _x >= 8; _x -= 8) { \
|
||||
op1; \
|
||||
REPEAT8(op2); \
|
||||
} \
|
||||
if (_x > 0) { \
|
||||
op1; \
|
||||
CASE8(_x,op2); \
|
||||
} \
|
||||
}
|
||||
#define UNROLL4(w, op1, op2) { \
|
||||
uint32 _x; \
|
||||
for (_x = w; _x >= 4; _x -= 4) { \
|
||||
op1; \
|
||||
REPEAT4(op2); \
|
||||
} \
|
||||
if (_x > 0) { \
|
||||
op1; \
|
||||
CASE4(_x,op2); \
|
||||
} \
|
||||
}
|
||||
#define UNROLL2(w, op1, op2) { \
|
||||
uint32 _x; \
|
||||
for (_x = w; _x >= 2; _x -= 2) { \
|
||||
op1; \
|
||||
REPEAT2(op2); \
|
||||
} \
|
||||
if (_x) { \
|
||||
op1; \
|
||||
op2; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SKEW(r,g,b,skew) { r += skew; g += skew; b += skew; }
|
||||
|
||||
#define DECLAREContigPutFunc(name) \
|
||||
static void name(\
|
||||
TIFFRGBAImage* img, \
|
||||
uint32* cp, \
|
||||
uint32 x, uint32 y, \
|
||||
uint32 w, uint32 h, \
|
||||
int32 fromskew, int32 toskew, \
|
||||
u_char* pp \
|
||||
)
|
||||
|
||||
#define DECLARESepPutFunc(name) \
|
||||
static void name(\
|
||||
TIFFRGBAImage* img,\
|
||||
uint32* cp,\
|
||||
uint32 x, uint32 y, \
|
||||
uint32 w, uint32 h,\
|
||||
int32 fromskew, int32 toskew,\
|
||||
u_char* r, u_char* g, u_char* b, u_char* a\
|
||||
)
|
||||
|
||||
static tileContigRoutine libput;
|
||||
|
||||
/*
|
||||
* 8-bit packed samples => colormap
|
||||
*/
|
||||
DECLAREContigPutFunc(putcontig8bittile)
|
||||
{
|
||||
int samplesperpixel = img->samplesperpixel;
|
||||
TIFFRGBValue* Map = img->Map;
|
||||
|
||||
(void) y;
|
||||
fromskew *= samplesperpixel;
|
||||
if (Map) {
|
||||
while (h-- > 0) {
|
||||
for (x = w; x-- > 0;) {
|
||||
*cp++ = rgbi(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
|
||||
pp += samplesperpixel;
|
||||
}
|
||||
cp += toskew;
|
||||
pp += fromskew;
|
||||
}
|
||||
} else {
|
||||
while (h-- > 0) {
|
||||
for (x = w; x-- > 0;) {
|
||||
*cp++ = rgbi(pp[0], pp[1], pp[2]);
|
||||
pp += samplesperpixel;
|
||||
}
|
||||
cp += toskew;
|
||||
pp += fromskew;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert 8-bit packed samples => colormap
|
||||
*/
|
||||
DECLAREContigPutFunc(cvtcontig8bittile)
|
||||
{
|
||||
(*libput)(img, cp, x, y, w, h, fromskew, toskew, pp);
|
||||
while (h-- > 0) {
|
||||
UNROLL8(w, NOP,
|
||||
cp[0] = rgbi(TIFFGetR(cp[0]),TIFFGetG(cp[0]),TIFFGetB(cp[0])); cp++
|
||||
);
|
||||
cp += toskew;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 16-bit packed samples => colormap
|
||||
*/
|
||||
DECLAREContigPutFunc(putcontig16bittile)
|
||||
{
|
||||
int samplesperpixel = img->samplesperpixel;
|
||||
TIFFRGBValue* Map = img->Map;
|
||||
|
||||
(void) y;
|
||||
fromskew *= samplesperpixel;
|
||||
if (Map) {
|
||||
while (h-- > 0) {
|
||||
for (x = w; x-- > 0;) {
|
||||
*cp++ = rgbi(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
|
||||
pp += samplesperpixel;
|
||||
}
|
||||
cp += toskew;
|
||||
pp += fromskew;
|
||||
}
|
||||
} else {
|
||||
while (h-- > 0) {
|
||||
for (x = w; x-- > 0;) {
|
||||
*cp++ = rgbi(pp[0], pp[1], pp[2]);
|
||||
pp += samplesperpixel;
|
||||
}
|
||||
cp += toskew;
|
||||
pp += fromskew;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 8-bit unpacked samples => colormap
|
||||
*/
|
||||
DECLARESepPutFunc(putseparate8bittile)
|
||||
{
|
||||
TIFFRGBValue* Map = img->Map;
|
||||
|
||||
(void) y; (void) a;
|
||||
if (Map) {
|
||||
while (h-- > 0) {
|
||||
for (x = w; x-- > 0;)
|
||||
*cp++ = rgbi(Map[*r++], Map[*g++], Map[*b++]);
|
||||
SKEW(r, g, b, fromskew);
|
||||
cp += toskew;
|
||||
}
|
||||
} else {
|
||||
while (h-- > 0) {
|
||||
for (x = w; x-- > 0;)
|
||||
*cp++ = rgbi(*r++, *g++, *b++);
|
||||
SKEW(r, g, b, fromskew);
|
||||
cp += toskew;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 16-bit unpacked samples => colormap
|
||||
*/
|
||||
DECLARESepPutFunc(putseparate16bittile)
|
||||
{
|
||||
TIFFRGBValue* Map = img->Map;
|
||||
|
||||
(void) y; (void) a;
|
||||
if (Map) {
|
||||
while (h-- > 0) {
|
||||
for (x = 0; x < w; x++)
|
||||
*cp++ = rgbi(Map[*r++], Map[*g++], Map[*b++]);
|
||||
SKEW(r, g, b, fromskew);
|
||||
cp += toskew;
|
||||
}
|
||||
} else {
|
||||
while (h-- > 0) {
|
||||
for (x = 0; x < w; x++)
|
||||
*cp++ = rgbi(*r++, *g++, *b++);
|
||||
SKEW(r, g, b, fromskew);
|
||||
cp += toskew;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 8-bit packed CMYK samples => cmap
|
||||
*
|
||||
* NB: The conversion of CMYK->RGB is *very* crude.
|
||||
*/
|
||||
DECLAREContigPutFunc(putcontig8bitCMYKtile)
|
||||
{
|
||||
int samplesperpixel = img->samplesperpixel;
|
||||
TIFFRGBValue* Map = img->Map;
|
||||
uint16 r, g, b, k;
|
||||
|
||||
(void) y;
|
||||
fromskew *= samplesperpixel;
|
||||
if (Map) {
|
||||
while (h-- > 0) {
|
||||
for (x = w; x-- > 0;) {
|
||||
k = 255 - pp[3];
|
||||
r = (k*(255-pp[0]))/255;
|
||||
g = (k*(255-pp[1]))/255;
|
||||
b = (k*(255-pp[2]))/255;
|
||||
*cp++ = rgbi(Map[r], Map[g], Map[b]);
|
||||
pp += samplesperpixel;
|
||||
}
|
||||
pp += fromskew;
|
||||
cp += toskew;
|
||||
}
|
||||
} else {
|
||||
while (h-- > 0) {
|
||||
UNROLL8(w, NOP,
|
||||
k = 255 - pp[3];
|
||||
r = (k*(255-pp[0]))/255;
|
||||
g = (k*(255-pp[1]))/255;
|
||||
b = (k*(255-pp[2]))/255;
|
||||
*cp++ = rgbi(r, g, b);
|
||||
pp += samplesperpixel);
|
||||
cp += toskew;
|
||||
pp += fromskew;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define YCbCrtoRGB(dst, yc) { \
|
||||
int Y = (yc); \
|
||||
dst = rgbi( \
|
||||
clamptab[Y+Crrtab[Cr]], \
|
||||
clamptab[Y + (int)((Cbgtab[Cb]+Crgtab[Cr])>>16)], \
|
||||
clamptab[Y+Cbbtab[Cb]]); \
|
||||
}
|
||||
#define YCbCrSetup \
|
||||
TIFFYCbCrToRGB* ycbcr = img->ycbcr; \
|
||||
int* Crrtab = ycbcr->Cr_r_tab; \
|
||||
int* Cbbtab = ycbcr->Cb_b_tab; \
|
||||
int32* Crgtab = ycbcr->Cr_g_tab; \
|
||||
int32* Cbgtab = ycbcr->Cb_g_tab; \
|
||||
TIFFRGBValue* clamptab = ycbcr->clamptab
|
||||
|
||||
/*
|
||||
* 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
|
||||
*/
|
||||
DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
|
||||
{
|
||||
YCbCrSetup;
|
||||
uint32* cp1 = cp+w+toskew;
|
||||
int32 incr = 2*toskew+w;
|
||||
|
||||
(void) y;
|
||||
/* XXX adjust fromskew */
|
||||
for (; h >= 2; h -= 2) {
|
||||
x = w>>1;
|
||||
do {
|
||||
int Cb = pp[4];
|
||||
int Cr = pp[5];
|
||||
|
||||
YCbCrtoRGB(cp [0], pp[0]);
|
||||
YCbCrtoRGB(cp [1], pp[1]);
|
||||
YCbCrtoRGB(cp1[0], pp[2]);
|
||||
YCbCrtoRGB(cp1[1], pp[3]);
|
||||
|
||||
cp += 2, cp1 += 2;
|
||||
pp += 6;
|
||||
} while (--x);
|
||||
cp += incr, cp1 += incr;
|
||||
pp += fromskew;
|
||||
}
|
||||
}
|
||||
#undef YCbCrSetup
|
||||
#undef YCbCrtoRGB
|
||||
|
||||
/*
|
||||
* Setup to handle conversion for display in a colormap
|
||||
* window. Many cases are handled by massaging the mapping
|
||||
* tables used by the normal library code to convert 32-bit
|
||||
* packed RGBA samples into colormap indices. Other cases
|
||||
* are handled with special-case routines that replace the
|
||||
* normal ``put routine'' installed by the library.
|
||||
*/
|
||||
static void
|
||||
setupColormapSupport(TIFFRGBAImage* img)
|
||||
{
|
||||
int bitspersample = img->bitspersample;
|
||||
int i;
|
||||
|
||||
if (img->BWmap) {
|
||||
i = 255;
|
||||
do {
|
||||
uint32* p = img->BWmap[i];
|
||||
switch (bitspersample) {
|
||||
#define GREY(x) p[x] = greyi(TIFFGetR(p[x]))
|
||||
case 1: GREY(7); GREY(6); GREY(5); GREY(4);
|
||||
case 2: GREY(3); GREY(2);
|
||||
case 4: GREY(1);
|
||||
case 8: GREY(0);
|
||||
}
|
||||
#undef GREY
|
||||
} while (i--);
|
||||
} else if (img->PALmap) {
|
||||
i = 255;
|
||||
do {
|
||||
uint32 rgb;
|
||||
uint32* p = img->PALmap[i];
|
||||
#define CMAP(x) \
|
||||
(rgb = p[x], p[x] = rgbi(TIFFGetR(rgb),TIFFGetG(rgb),TIFFGetB(rgb)))
|
||||
switch (bitspersample) {
|
||||
case 1: CMAP(7); CMAP(6); CMAP(5); CMAP(4);
|
||||
case 2: CMAP(3); CMAP(2);
|
||||
case 4: CMAP(1);
|
||||
case 8: CMAP(0);
|
||||
}
|
||||
#undef CMAP
|
||||
} while (i--);
|
||||
} else if (img->isContig) {
|
||||
switch (img->photometric) {
|
||||
case PHOTOMETRIC_RGB:
|
||||
case PHOTOMETRIC_LOGLUV:
|
||||
switch (bitspersample) {
|
||||
case 8: img->put.contig = putcontig8bittile; break;
|
||||
case 16: img->put.contig = putcontig16bittile; break;
|
||||
}
|
||||
break;
|
||||
case PHOTOMETRIC_SEPARATED:
|
||||
switch (bitspersample) {
|
||||
case 8: img->put.contig = putcontig8bitCMYKtile; break;
|
||||
}
|
||||
break;
|
||||
case PHOTOMETRIC_YCBCR:
|
||||
if (img->bitspersample == 8) {
|
||||
uint16 hs, vs;
|
||||
TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
|
||||
&hs, &vs);
|
||||
switch ((hs<<4)|vs) {
|
||||
case 0x22: /* most common case */
|
||||
img->put.contig = putcontig8bitYCbCr22tile;
|
||||
break;
|
||||
default: /* all others cost more */
|
||||
libput = img->put.contig;
|
||||
img->put.contig = cvtcontig8bittile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (img->photometric) {
|
||||
case PHOTOMETRIC_RGB:
|
||||
switch (img->bitspersample) {
|
||||
case 8: img->put.separate = putseparate8bittile; break;
|
||||
case 16: img->put.separate = putseparate16bittile; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+310
@@ -0,0 +1,310 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/sgisv.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned long u_long;
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define strneq(a,b,n) (strncmp(a,b,n) == 0)
|
||||
|
||||
uint32 rowsperstrip = (uint32) -1;
|
||||
uint16 compression = COMPRESSION_PACKBITS;
|
||||
uint16 config = PLANARCONFIG_CONTIG;
|
||||
uint16 predictor = 0;
|
||||
int xmaxscreen;
|
||||
int ymaxscreen;
|
||||
uint16 photometric = PHOTOMETRIC_RGB;
|
||||
int jpegcolormode = JPEGCOLORMODE_RGB;
|
||||
int quality = 75; /* JPEG quality */
|
||||
|
||||
static void usage(void);
|
||||
static void tiffsv(char*, int, int, int, int);
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:p:r:")) != -1)
|
||||
switch (c) {
|
||||
case 'b': /* save as b&w */
|
||||
photometric = PHOTOMETRIC_MINISBLACK;
|
||||
break;
|
||||
case 'c': /* compression scheme */
|
||||
if (streq(optarg, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(optarg, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (strneq(optarg, "jpeg", 4)) {
|
||||
char* cp = strchr(optarg, ':');
|
||||
if (cp && isdigit(cp[1]))
|
||||
quality = atoi(cp+1);
|
||||
if (cp && strchr(cp, 'r'))
|
||||
jpegcolormode = JPEGCOLORMODE_RAW;
|
||||
compression = COMPRESSION_JPEG;
|
||||
} else if (strneq(optarg, "lzw", 3)) {
|
||||
char* cp = strchr(optarg, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_LZW;
|
||||
} else
|
||||
usage();
|
||||
break;
|
||||
case 'p': /* planar configuration */
|
||||
if (streq(optarg, "separate"))
|
||||
config = PLANARCONFIG_SEPARATE;
|
||||
else if (streq(optarg, "contig"))
|
||||
config = PLANARCONFIG_CONTIG;
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
case 'r': /* rows/strip */
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind != 1 && argc - optind != 5)
|
||||
usage();
|
||||
xmaxscreen = getgdesc(GD_XPMAX)-1;
|
||||
ymaxscreen = getgdesc(GD_YPMAX)-1;
|
||||
foreground();
|
||||
noport();
|
||||
winopen("tiffsv");
|
||||
if (argc - optind == 5)
|
||||
tiffsv(argv[optind],
|
||||
atoi(argv[optind+1]), atoi(argv[optind+2]),
|
||||
atoi(argv[optind+3]), atoi(argv[optind+4]));
|
||||
else
|
||||
tiffsv(argv[optind], 0, xmaxscreen, 0, ymaxscreen);
|
||||
return (0);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: tiffsv [options] outimage.tif [x1 x2 y1 y2] [-b]",
|
||||
"where options are:",
|
||||
" -p contig pack samples contiguously (e.g. RGBRGB...)",
|
||||
" -p separate store samples separately (e.g. RRR...GGG...BBB...)",
|
||||
"",
|
||||
" -r # make each strip have no more than # rows",
|
||||
"",
|
||||
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
|
||||
" (no longer supported by default due to Unisys patent enforcement)",
|
||||
" -c jpeg[:opts]compress output with JPEG encoding",
|
||||
" -c packbits compress output with packbits encoding",
|
||||
" -c none use no compression algorithm on output",
|
||||
"",
|
||||
"JPEG options:",
|
||||
" # set compression quality level (0-100, default 75)",
|
||||
" r output color image as RGB rather than YCbCr",
|
||||
"",
|
||||
"LZW options:",
|
||||
" # set predictor value for Lempel-Ziv & Welch encoding",
|
||||
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static void
|
||||
svRGBSeparate(TIFF* tif, u_long* ss, int xsize, int ysize)
|
||||
{
|
||||
tsize_t stripsize = TIFFStripSize(tif);
|
||||
u_char *rbuf = (u_char *)_TIFFmalloc(3*stripsize);
|
||||
u_char *gbuf = rbuf + stripsize;
|
||||
u_char *bbuf = gbuf + stripsize;
|
||||
register int y;
|
||||
|
||||
for (y = 0; y <= ysize; y += rowsperstrip) {
|
||||
u_char *rp, *gp, *bp;
|
||||
register int x;
|
||||
register uint32 n;
|
||||
|
||||
n = rowsperstrip;
|
||||
if (n > ysize-y+1)
|
||||
n = ysize-y+1;
|
||||
rp = rbuf; gp = gbuf; bp = bbuf;
|
||||
do {
|
||||
for (x = 0; x <= xsize; x++) {
|
||||
u_long v = ss[x];
|
||||
rp[x] = v;
|
||||
gp[x] = v >> 8;
|
||||
bp[x] = v >> 16;
|
||||
}
|
||||
rp += xsize+1, gp += xsize+1, bp += xsize+1;
|
||||
ss += xsize+1;
|
||||
} while (--n);
|
||||
if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,0),
|
||||
rbuf, stripsize) < 0)
|
||||
break;
|
||||
if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,1),
|
||||
gbuf, stripsize) < 0)
|
||||
break;
|
||||
if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,2),
|
||||
bbuf, stripsize) < 0)
|
||||
break;
|
||||
}
|
||||
_TIFFfree(rbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
svRGBContig(TIFF* tif, u_long* ss, int xsize, int ysize)
|
||||
{
|
||||
register int x, y;
|
||||
tsize_t stripsize = TIFFStripSize(tif);
|
||||
u_char *strip = (u_char *)_TIFFmalloc(stripsize);
|
||||
|
||||
for (y = 0; y <= ysize; y += rowsperstrip) {
|
||||
register u_char *pp = strip;
|
||||
register uint32 n;
|
||||
|
||||
n = rowsperstrip;
|
||||
if (n > ysize-y+1)
|
||||
n = ysize-y+1;
|
||||
do {
|
||||
for (x = 0; x <= xsize; x++) {
|
||||
u_long v = ss[x];
|
||||
pp[0] = v;
|
||||
pp[1] = v >> 8;
|
||||
pp[2] = v >> 16;
|
||||
pp += 3;
|
||||
}
|
||||
ss += xsize+1;
|
||||
} while (--n);
|
||||
if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,0),
|
||||
strip, stripsize) < 0)
|
||||
break;
|
||||
}
|
||||
_TIFFfree(strip);
|
||||
}
|
||||
|
||||
#undef RED
|
||||
#undef GREEN
|
||||
#undef BLUE
|
||||
#define CVT(x) (((x)*255)/100)
|
||||
#define RED CVT(28) /* 28% */
|
||||
#define GREEN CVT(59) /* 59% */
|
||||
#define BLUE CVT(11) /* 11% */
|
||||
|
||||
static void
|
||||
svGrey(TIFF* tif, u_long* ss, int xsize, int ysize)
|
||||
{
|
||||
register int x, y;
|
||||
u_char *buf = (u_char *)_TIFFmalloc(TIFFScanlineSize(tif));
|
||||
|
||||
for (y = 0; y <= ysize; y++) {
|
||||
for (x = 0; x <= xsize; x++) {
|
||||
u_char *cp = (u_char *)&ss[x];
|
||||
buf[x] = (RED*cp[3] + GREEN*cp[2] + BLUE*cp[1]) >> 8;
|
||||
}
|
||||
if (TIFFWriteScanline(tif, buf, (uint32) y, 0) < 0)
|
||||
break;
|
||||
ss += xsize+1;
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
}
|
||||
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#define ABS(x) ((x)<0?-(x):(x))
|
||||
|
||||
static void
|
||||
tiffsv(char* name, int x1, int x2, int y1, int y2)
|
||||
{
|
||||
TIFF *tif;
|
||||
int xsize, ysize;
|
||||
int xorg, yorg;
|
||||
u_long *scrbuf;
|
||||
|
||||
xorg = MIN(x1,x2);
|
||||
yorg = MIN(y1,y2);
|
||||
if (xorg<0)
|
||||
xorg = 0;
|
||||
if (yorg<0)
|
||||
yorg = 0;
|
||||
xsize = ABS(x2-x1);
|
||||
ysize = ABS(y2-y1);
|
||||
if (xorg+xsize > xmaxscreen)
|
||||
xsize = xmaxscreen-xorg;
|
||||
if (yorg+ysize > ymaxscreen)
|
||||
ysize = ymaxscreen-yorg;
|
||||
tif = TIFFOpen(name, "w");
|
||||
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32) (xsize+1));
|
||||
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32) (ysize+1));
|
||||
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
|
||||
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL,
|
||||
photometric == PHOTOMETRIC_RGB ? 3 : 1);
|
||||
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, config);
|
||||
TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
|
||||
switch (compression) {
|
||||
case COMPRESSION_JPEG:
|
||||
if (photometric == PHOTOMETRIC_RGB && jpegcolormode == JPEGCOLORMODE_RGB)
|
||||
photometric = PHOTOMETRIC_YCBCR;
|
||||
TIFFSetField(tif, TIFFTAG_JPEGQUALITY, quality);
|
||||
TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
|
||||
break;
|
||||
case COMPRESSION_LZW:
|
||||
if (predictor != 0)
|
||||
TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
|
||||
break;
|
||||
}
|
||||
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric);
|
||||
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT);
|
||||
rowsperstrip = TIFFDefaultStripSize(tif, rowsperstrip);
|
||||
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
|
||||
scrbuf = (u_long *)_TIFFmalloc((xsize+1)*(ysize+1)*sizeof (u_long));
|
||||
readdisplay(xorg, yorg, xorg+xsize, yorg+ysize, scrbuf, RD_FREEZE);
|
||||
if (photometric == PHOTOMETRIC_RGB) {
|
||||
if (config == PLANARCONFIG_SEPARATE)
|
||||
svRGBSeparate(tif, scrbuf, xsize, ysize);
|
||||
else
|
||||
svRGBContig(tif, scrbuf, xsize, ysize);
|
||||
} else
|
||||
svGrey(tif, scrbuf, xsize, ysize);
|
||||
(void) TIFFClose(tif);
|
||||
_TIFFfree((char *)scrbuf);
|
||||
}
|
||||
Executable
+572
@@ -0,0 +1,572 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/thumbnail.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994-1997 Sam Leffler
|
||||
* Copyright (c) 1994-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#define streq(a,b) (strcasecmp(a,b) == 0)
|
||||
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x)+((y)-1))/(y))
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
EXP50,
|
||||
EXP60,
|
||||
EXP70,
|
||||
EXP80,
|
||||
EXP90,
|
||||
EXP,
|
||||
LINEAR
|
||||
} Contrast;
|
||||
|
||||
static uint32 tnw = 216; /* thumbnail width */
|
||||
static uint32 tnh = 274; /* thumbnail height */
|
||||
static Contrast contrast = LINEAR; /* current contrast */
|
||||
static uint8* thumbnail;
|
||||
|
||||
static int cpIFD(TIFF*, TIFF*);
|
||||
static int generateThumbnail(TIFF*, TIFF*);
|
||||
static void initScale();
|
||||
static void usage(void);
|
||||
|
||||
extern char* optarg;
|
||||
extern int optind;
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
TIFF* in;
|
||||
TIFF* out;
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "w:h:c:")) != -1) {
|
||||
switch (c) {
|
||||
case 'w': tnw = strtoul(optarg, NULL, 0); break;
|
||||
case 'h': tnh = strtoul(optarg, NULL, 0); break;
|
||||
case 'c': contrast = streq(optarg, "exp50") ? EXP50 :
|
||||
streq(optarg, "exp60") ? EXP60 :
|
||||
streq(optarg, "exp70") ? EXP70 :
|
||||
streq(optarg, "exp80") ? EXP80 :
|
||||
streq(optarg, "exp90") ? EXP90 :
|
||||
streq(optarg, "exp") ? EXP :
|
||||
streq(optarg, "linear")? LINEAR :
|
||||
EXP;
|
||||
break;
|
||||
default: usage();
|
||||
}
|
||||
}
|
||||
if (argc-optind != 2)
|
||||
usage();
|
||||
thumbnail = (uint8*) _TIFFmalloc(tnw * tnh);
|
||||
out = TIFFOpen(argv[optind+1], "w");
|
||||
if (out == NULL)
|
||||
return (-2);
|
||||
in = TIFFOpen(argv[optind], "r");
|
||||
if (in != NULL) {
|
||||
initScale();
|
||||
do {
|
||||
if (!generateThumbnail(in, out))
|
||||
goto bad;
|
||||
if (!cpIFD(in, out) || !TIFFWriteDirectory(out))
|
||||
goto bad;
|
||||
} while (TIFFReadDirectory(in));
|
||||
(void) TIFFClose(in);
|
||||
}
|
||||
(void) TIFFClose(out);
|
||||
return (0);
|
||||
bad:
|
||||
(void) TIFFClose(out);
|
||||
return (1);
|
||||
}
|
||||
|
||||
#define CopyField1(tag, v) \
|
||||
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
|
||||
#define CopyField2(tag, v1, v2) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
|
||||
#define CopyField3(tag, v1, v2, v3) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
|
||||
#define CopyField4(tag, v1, v2, v3, v4) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
|
||||
|
||||
static void
|
||||
cpTag(TIFF* in, TIFF* out, uint16 tag, uint16 count, TIFFDataType type)
|
||||
{
|
||||
uint16 shortv, shortv2, *shortav;
|
||||
float floatv, *floatav;
|
||||
char *stringv;
|
||||
uint32 longv;
|
||||
|
||||
switch (type) {
|
||||
case TIFF_SHORT:
|
||||
if (count == 1) {
|
||||
CopyField1(tag, shortv);
|
||||
} else if (count == 2) {
|
||||
CopyField2(tag, shortv, shortv2);
|
||||
} else if (count == (uint16) -1) {
|
||||
CopyField2(tag, shortv, shortav);
|
||||
}
|
||||
break;
|
||||
case TIFF_LONG:
|
||||
CopyField1(tag, longv);
|
||||
break;
|
||||
case TIFF_RATIONAL:
|
||||
if (count == 1) {
|
||||
CopyField1(tag, floatv);
|
||||
} else if (count == (uint16) -1) {
|
||||
CopyField1(tag, floatav);
|
||||
}
|
||||
break;
|
||||
case TIFF_ASCII:
|
||||
CopyField1(tag, stringv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#undef CopyField4
|
||||
#undef CopyField3
|
||||
#undef CopyField2
|
||||
#undef CopyField1
|
||||
|
||||
static struct cpTag {
|
||||
uint16 tag;
|
||||
uint16 count;
|
||||
TIFFDataType type;
|
||||
} tags[] = {
|
||||
{ TIFFTAG_IMAGEWIDTH, 1, TIFF_LONG },
|
||||
{ TIFFTAG_IMAGELENGTH, 1, TIFF_LONG },
|
||||
{ TIFFTAG_BITSPERSAMPLE, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_COMPRESSION, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_FILLORDER, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_SAMPLESPERPIXEL, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_ROWSPERSTRIP, 1, TIFF_LONG },
|
||||
{ TIFFTAG_PLANARCONFIG, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_GROUP3OPTIONS, 1, TIFF_LONG },
|
||||
{ TIFFTAG_SUBFILETYPE, 1, TIFF_LONG },
|
||||
{ TIFFTAG_PHOTOMETRIC, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_THRESHHOLDING, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_DOCUMENTNAME, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_IMAGEDESCRIPTION, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_MAKE, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_MODEL, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_ORIENTATION, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_MINSAMPLEVALUE, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_MAXSAMPLEVALUE, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_XRESOLUTION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_YRESOLUTION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_PAGENAME, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_XPOSITION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_YPOSITION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG },
|
||||
{ TIFFTAG_RESOLUTIONUNIT, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_PAGENUMBER, 2, TIFF_SHORT },
|
||||
{ TIFFTAG_SOFTWARE, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_DATETIME, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_ARTIST, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_HOSTCOMPUTER, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_WHITEPOINT, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_PRIMARYCHROMATICITIES, (uint16) -1,TIFF_RATIONAL },
|
||||
{ TIFFTAG_HALFTONEHINTS, 2, TIFF_SHORT },
|
||||
{ TIFFTAG_BADFAXLINES, 1, TIFF_LONG },
|
||||
{ TIFFTAG_CLEANFAXDATA, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_CONSECUTIVEBADFAXLINES, 1, TIFF_LONG },
|
||||
{ TIFFTAG_INKSET, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_INKNAMES, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_DOTRANGE, 2, TIFF_SHORT },
|
||||
{ TIFFTAG_TARGETPRINTER, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_SAMPLEFORMAT, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_YCBCRCOEFFICIENTS, (uint16) -1,TIFF_RATIONAL },
|
||||
{ TIFFTAG_YCBCRSUBSAMPLING, 2, TIFF_SHORT },
|
||||
{ TIFFTAG_YCBCRPOSITIONING, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_REFERENCEBLACKWHITE, (uint16) -1,TIFF_RATIONAL },
|
||||
{ TIFFTAG_EXTRASAMPLES, (uint16) -1, TIFF_SHORT },
|
||||
};
|
||||
#define NTAGS (sizeof (tags) / sizeof (tags[0]))
|
||||
|
||||
static void
|
||||
cpTags(TIFF* in, TIFF* out)
|
||||
{
|
||||
struct cpTag *p;
|
||||
for (p = tags; p < &tags[NTAGS]; p++)
|
||||
cpTag(in, out, p->tag, p->count, p->type);
|
||||
}
|
||||
#undef NTAGS
|
||||
|
||||
static int
|
||||
cpStrips(TIFF* in, TIFF* out)
|
||||
{
|
||||
tsize_t bufsize = TIFFStripSize(in);
|
||||
unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize);
|
||||
|
||||
if (buf) {
|
||||
tstrip_t s, ns = TIFFNumberOfStrips(in);
|
||||
uint32 *bytecounts;
|
||||
|
||||
TIFFGetField(in, TIFFTAG_STRIPBYTECOUNTS, &bytecounts);
|
||||
for (s = 0; s < ns; s++) {
|
||||
if (bytecounts[s] > bufsize) {
|
||||
buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[s]);
|
||||
if (!buf)
|
||||
return (0);
|
||||
bufsize = bytecounts[s];
|
||||
}
|
||||
if (TIFFReadRawStrip(in, s, buf, bytecounts[s]) < 0 ||
|
||||
TIFFWriteRawStrip(out, s, buf, bytecounts[s]) < 0) {
|
||||
_TIFFfree(buf);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpTiles(TIFF* in, TIFF* out)
|
||||
{
|
||||
tsize_t bufsize = TIFFTileSize(in);
|
||||
unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize);
|
||||
|
||||
if (buf) {
|
||||
ttile_t t, nt = TIFFNumberOfTiles(in);
|
||||
uint32 *bytecounts;
|
||||
|
||||
TIFFGetField(in, TIFFTAG_TILEBYTECOUNTS, &bytecounts);
|
||||
for (t = 0; t < nt; t++) {
|
||||
if (bytecounts[t] > bufsize) {
|
||||
buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[t]);
|
||||
if (!buf)
|
||||
return (0);
|
||||
bufsize = bytecounts[t];
|
||||
}
|
||||
if (TIFFReadRawTile(in, t, buf, bytecounts[t]) < 0 ||
|
||||
TIFFWriteRawTile(out, t, buf, bytecounts[t]) < 0) {
|
||||
_TIFFfree(buf);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpIFD(TIFF* in, TIFF* out)
|
||||
{
|
||||
cpTags(in, out);
|
||||
if (TIFFIsTiled(in)) {
|
||||
if (!cpTiles(in, out))
|
||||
return (0);
|
||||
} else {
|
||||
if (!cpStrips(in, out))
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static uint16 photometric; /* current photometric of raster */
|
||||
static uint16 filterWidth; /* filter width in pixels */
|
||||
static uint16 stepSrcWidth; /* src image stepping width */
|
||||
static uint16 stepDstWidth; /* dest stepping width */
|
||||
static uint8* src0; /* horizontal bit stepping (start) */
|
||||
static uint8* src1; /* horizontal bit stepping (middle) */
|
||||
static uint8* src2; /* horizontal bit stepping (end) */
|
||||
static uint16* rowoff; /* row offset for stepping */
|
||||
static uint8 cmap[256]; /* colormap indexes */
|
||||
static uint8 bits[256]; /* count of bits set */
|
||||
|
||||
static void
|
||||
setupBitsTables()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 256; i++) {
|
||||
int n = 0;
|
||||
if (i&0x01) n++;
|
||||
if (i&0x02) n++;
|
||||
if (i&0x04) n++;
|
||||
if (i&0x08) n++;
|
||||
if (i&0x10) n++;
|
||||
if (i&0x20) n++;
|
||||
if (i&0x40) n++;
|
||||
if (i&0x80) n++;
|
||||
bits[i] = n;
|
||||
}
|
||||
}
|
||||
|
||||
static int clamp(float v, int low, int high)
|
||||
{ return (v < low ? low : v > high ? high : (int)v); }
|
||||
|
||||
#ifndef M_E
|
||||
#define M_E 2.7182818284590452354
|
||||
#endif
|
||||
|
||||
static void
|
||||
expFill(float pct[], uint32 p, uint32 n)
|
||||
{
|
||||
uint32 i;
|
||||
uint32 c = (p * n) / 100;
|
||||
for (i = 1; i < c; i++)
|
||||
pct[i] = 1-exp(i/((double)(n-1)))/ M_E;
|
||||
for (; i < n; i++)
|
||||
pct[i] = 0.;
|
||||
}
|
||||
|
||||
static void
|
||||
setupCmap()
|
||||
{
|
||||
float pct[256]; /* known to be large enough */
|
||||
uint32 i;
|
||||
pct[0] = 1; /* force white */
|
||||
switch (contrast) {
|
||||
case EXP50: expFill(pct, 50, 256); break;
|
||||
case EXP60: expFill(pct, 60, 256); break;
|
||||
case EXP70: expFill(pct, 70, 256); break;
|
||||
case EXP80: expFill(pct, 80, 256); break;
|
||||
case EXP90: expFill(pct, 90, 256); break;
|
||||
case EXP: expFill(pct, 100, 256); break;
|
||||
case LINEAR:
|
||||
for (i = 1; i < 256; i++)
|
||||
pct[i] = 1-((float)i)/(256-1);
|
||||
break;
|
||||
}
|
||||
switch (photometric) {
|
||||
case PHOTOMETRIC_MINISWHITE:
|
||||
for (i = 0; i < 256; i++)
|
||||
cmap[i] = clamp(255*pct[(256-1)-i], 0, 255);
|
||||
break;
|
||||
case PHOTOMETRIC_MINISBLACK:
|
||||
for (i = 0; i < 256; i++)
|
||||
cmap[i] = clamp(255*pct[i], 0, 255);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
initScale()
|
||||
{
|
||||
src0 = (uint8*) _TIFFmalloc(sizeof (uint8) * tnw);
|
||||
src1 = (uint8*) _TIFFmalloc(sizeof (uint8) * tnw);
|
||||
src2 = (uint8*) _TIFFmalloc(sizeof (uint8) * tnw);
|
||||
rowoff = (uint16*) _TIFFmalloc(sizeof (uint16) * tnw);
|
||||
filterWidth = 0;
|
||||
stepDstWidth = stepSrcWidth = 0;
|
||||
setupBitsTables();
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the horizontal accumulation parameteres
|
||||
* according to the widths of the src and dst images.
|
||||
*/
|
||||
static void
|
||||
setupStepTables(uint16 sw)
|
||||
{
|
||||
if (stepSrcWidth != sw || stepDstWidth != tnw) {
|
||||
int step = sw;
|
||||
int limit = tnw;
|
||||
int err = 0;
|
||||
uint32 sx = 0;
|
||||
uint32 x;
|
||||
int fw;
|
||||
uint8 b;
|
||||
for (x = 0; x < tnw; x++) {
|
||||
uint32 sx0 = sx;
|
||||
err += step;
|
||||
while (err >= limit) {
|
||||
err -= limit;
|
||||
sx++;
|
||||
}
|
||||
rowoff[x] = sx0 >> 3;
|
||||
fw = sx - sx0; /* width */
|
||||
b = (fw < 8) ? 0xff<<(8-fw) : 0xff;
|
||||
src0[x] = b >> (sx0&7);
|
||||
fw -= 8 - (sx0&7);
|
||||
if (fw < 0)
|
||||
fw = 0;
|
||||
src1[x] = fw >> 3;
|
||||
fw -= (fw>>3)<<3;
|
||||
src2[x] = 0xff << (8-fw);
|
||||
}
|
||||
stepSrcWidth = sw;
|
||||
stepDstWidth = tnw;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setrow(uint8* row, int nrows, const uint8* rows[])
|
||||
{
|
||||
uint32 x;
|
||||
uint32 area = nrows * filterWidth;
|
||||
for (x = 0; x < tnw; x++) {
|
||||
uint32 mask0 = src0[x];
|
||||
uint32 fw = src1[x];
|
||||
uint32 mask1 = src1[x];
|
||||
uint32 off = rowoff[x];
|
||||
uint32 acc = 0;
|
||||
uint32 y, i;
|
||||
for (y = 0; y < nrows; y++) {
|
||||
const uint8* src = rows[y] + off;
|
||||
acc += bits[*src++ & mask0];
|
||||
switch (fw) {
|
||||
default:
|
||||
for (i = fw; i > 8; i--)
|
||||
acc += bits[*src++];
|
||||
/* fall thru... */
|
||||
case 8: acc += bits[*src++];
|
||||
case 7: acc += bits[*src++];
|
||||
case 6: acc += bits[*src++];
|
||||
case 5: acc += bits[*src++];
|
||||
case 4: acc += bits[*src++];
|
||||
case 3: acc += bits[*src++];
|
||||
case 2: acc += bits[*src++];
|
||||
case 1: acc += bits[*src++];
|
||||
case 0: break;
|
||||
}
|
||||
acc += bits[*src & mask1];
|
||||
}
|
||||
*row++ = cmap[(255*acc)/area];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Install the specified image. The
|
||||
* image is resized to fit the display page using
|
||||
* a box filter. The resultant pixels are mapped
|
||||
* with a user-selectable contrast curve.
|
||||
*/
|
||||
static void
|
||||
setImage1(const uint8* br, uint32 rw, uint32 rh)
|
||||
{
|
||||
int step = rh;
|
||||
int limit = tnh;
|
||||
int err = 0;
|
||||
int bpr = howmany(rw,8);
|
||||
uint32 sy = 0;
|
||||
uint8* row = thumbnail;
|
||||
uint32 dy;
|
||||
for (dy = 0; dy < tnh; dy++) {
|
||||
const uint8* rows[256];
|
||||
int nrows = 1;
|
||||
rows[0] = br + bpr*sy;
|
||||
err += step;
|
||||
while (err >= limit) {
|
||||
err -= limit;
|
||||
sy++;
|
||||
if (err >= limit)
|
||||
rows[nrows++] = br + bpr*sy;
|
||||
}
|
||||
setrow(row, nrows, rows);
|
||||
row += tnw;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setImage(const uint8* br, uint32 rw, uint32 rh)
|
||||
{
|
||||
filterWidth = (uint16) ceil((double) rw / (double) tnw);
|
||||
setupStepTables(rw);
|
||||
setImage1(br, rw, rh);
|
||||
}
|
||||
|
||||
static int
|
||||
generateThumbnail(TIFF* in, TIFF* out)
|
||||
{
|
||||
unsigned char* raster;
|
||||
unsigned char* rp;
|
||||
uint32 sw, sh, rps;
|
||||
uint16 bps, spp;
|
||||
tsize_t rowsize, rastersize;
|
||||
tstrip_t s, ns = TIFFNumberOfStrips(in);
|
||||
uint32 diroff[1];
|
||||
|
||||
TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &sw);
|
||||
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &sh);
|
||||
TIFFGetFieldDefaulted(in, TIFFTAG_BITSPERSAMPLE, &bps);
|
||||
TIFFGetFieldDefaulted(in, TIFFTAG_SAMPLESPERPIXEL, &spp);
|
||||
TIFFGetFieldDefaulted(in, TIFFTAG_ROWSPERSTRIP, &rps);
|
||||
if (spp != 1 || bps != 1)
|
||||
return (0);
|
||||
rowsize = TIFFScanlineSize(in);
|
||||
rastersize = sh * rowsize;
|
||||
raster = (unsigned char*)_TIFFmalloc(rastersize);
|
||||
rp = raster;
|
||||
for (s = 0; s < ns; s++) {
|
||||
(void) TIFFReadEncodedStrip(in, s, rp, -1);
|
||||
rp += rps * rowsize;
|
||||
}
|
||||
TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric);
|
||||
setupCmap();
|
||||
setImage(raster, sw, sh);
|
||||
|
||||
TIFFSetField(out, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE);
|
||||
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (uint32) tnw);
|
||||
TIFFSetField(out, TIFFTAG_IMAGELENGTH, (uint32) tnh);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (uint16) 8);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, (uint16) 1);
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
cpTag(in, out, TIFFTAG_SOFTWARE, (uint16) -1, TIFF_ASCII);
|
||||
cpTag(in, out, TIFFTAG_IMAGEDESCRIPTION, (uint16) -1, TIFF_ASCII);
|
||||
cpTag(in, out, TIFFTAG_DATETIME, (uint16) -1, TIFF_ASCII);
|
||||
cpTag(in, out, TIFFTAG_HOSTCOMPUTER, (uint16) -1, TIFF_ASCII);
|
||||
diroff[0] = 0;
|
||||
TIFFSetField(out, TIFFTAG_SUBIFD, 1, diroff);
|
||||
return (TIFFWriteEncodedStrip(out, 0, thumbnail, tnw*tnh) != -1 &&
|
||||
TIFFWriteDirectory(out) != -1);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: thumbnail [options] input.tif output.tif",
|
||||
"where options are:",
|
||||
" -h # specify thumbnail image height (default is 274)",
|
||||
" -w # specify thumbnail image width (default is 216)",
|
||||
"",
|
||||
" -c linear use linear contrast curve",
|
||||
" -c exp50 use 50% exponential contrast curve",
|
||||
" -c exp60 use 60% exponential contrast curve",
|
||||
" -c exp70 use 70% exponential contrast curve",
|
||||
" -c exp80 use 80% exponential contrast curve",
|
||||
" -c exp90 use 90% exponential contrast curve",
|
||||
" -c exp use pure exponential contrast curve",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
Executable
+401
@@ -0,0 +1,401 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/tiff2bw.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "tiffio.h"
|
||||
|
||||
#define streq(a,b) (strcmp((a),(b)) == 0)
|
||||
#define strneq(a,b,n) (strncmp(a,b,n) == 0)
|
||||
|
||||
/* x% weighting -> fraction of full color */
|
||||
#define PCT(x) (((x)*255)/100)
|
||||
int RED = PCT(28); /* 28% */
|
||||
int GREEN = PCT(59); /* 59% */
|
||||
int BLUE = PCT(11); /* 11% */
|
||||
|
||||
static void usage(void);
|
||||
static int processCompressOptions(char*);
|
||||
|
||||
static void
|
||||
compresscontig(unsigned char* out, unsigned char* rgb, uint32 n)
|
||||
{
|
||||
register int v, red = RED, green = GREEN, blue = BLUE;
|
||||
|
||||
while (n-- > 0) {
|
||||
v = red*(*rgb++);
|
||||
v += green*(*rgb++);
|
||||
v += blue*(*rgb++);
|
||||
*out++ = v>>8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
compresssep(unsigned char* out,
|
||||
unsigned char* r, unsigned char* g, unsigned char* b, uint32 n)
|
||||
{
|
||||
register uint32 red = RED, green = GREEN, blue = BLUE;
|
||||
|
||||
while (n-- > 0)
|
||||
*out++ = (red*(*r++) + green*(*g++) + blue*(*b++)) >> 8;
|
||||
}
|
||||
|
||||
static int
|
||||
checkcmap(TIFF* tif, int n, uint16* r, uint16* g, uint16* b)
|
||||
{
|
||||
while (n-- > 0)
|
||||
if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
|
||||
return (16);
|
||||
TIFFWarning(TIFFFileName(tif), "Assuming 8-bit colormap");
|
||||
return (8);
|
||||
}
|
||||
|
||||
static void
|
||||
compresspalette(unsigned char* out, unsigned char* data, uint32 n, uint16* rmap, uint16* gmap, uint16* bmap)
|
||||
{
|
||||
register int v, red = RED, green = GREEN, blue = BLUE;
|
||||
|
||||
while (n-- > 0) {
|
||||
unsigned int ix = *data++;
|
||||
v = red*rmap[ix];
|
||||
v += green*gmap[ix];
|
||||
v += blue*bmap[ix];
|
||||
*out++ = v>>8;
|
||||
}
|
||||
}
|
||||
|
||||
static uint16 compression = (uint16) -1;
|
||||
static uint16 predictor = 0;
|
||||
static int jpegcolormode = JPEGCOLORMODE_RGB;
|
||||
static int quality = 75; /* JPEG quality */
|
||||
|
||||
static void cpTags(TIFF* in, TIFF* out);
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
uint32 rowsperstrip = (uint32) -1;
|
||||
TIFF *in, *out;
|
||||
uint32 w, h;
|
||||
uint16 samplesperpixel;
|
||||
uint16 bitspersample;
|
||||
uint16 config;
|
||||
uint16 photometric;
|
||||
uint16* red;
|
||||
uint16* green;
|
||||
uint16* blue;
|
||||
tsize_t rowsize;
|
||||
register uint32 row;
|
||||
register tsample_t s;
|
||||
unsigned char *inbuf, *outbuf;
|
||||
char thing[1024];
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:r:R:G:B:")) != -1)
|
||||
switch (c) {
|
||||
case 'c': /* compression scheme */
|
||||
if (!processCompressOptions(optarg))
|
||||
usage();
|
||||
break;
|
||||
case 'r': /* rows/strip */
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
case 'R':
|
||||
RED = PCT(atoi(optarg));
|
||||
break;
|
||||
case 'G':
|
||||
GREEN = PCT(atoi(optarg));
|
||||
break;
|
||||
case 'B':
|
||||
BLUE = PCT(atoi(optarg));
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind < 2)
|
||||
usage();
|
||||
in = TIFFOpen(argv[optind], "r");
|
||||
if (in == NULL)
|
||||
return (-1);
|
||||
photometric = 0;
|
||||
TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric);
|
||||
if (photometric != PHOTOMETRIC_RGB && photometric != PHOTOMETRIC_PALETTE ) {
|
||||
fprintf(stderr,
|
||||
"%s: Bad photometric; can only handle RGB and Palette images.\n",
|
||||
argv[optind]);
|
||||
return (-1);
|
||||
}
|
||||
TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
|
||||
if (samplesperpixel != 1 && samplesperpixel != 3) {
|
||||
fprintf(stderr, "%s: Bad samples/pixel %u.\n",
|
||||
argv[optind], samplesperpixel);
|
||||
return (-1);
|
||||
}
|
||||
TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample);
|
||||
if (bitspersample != 8) {
|
||||
fprintf(stderr,
|
||||
" %s: Sorry, only handle 8-bit samples.\n", argv[optind]);
|
||||
return (-1);
|
||||
}
|
||||
TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w);
|
||||
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &h);
|
||||
TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config);
|
||||
|
||||
out = TIFFOpen(argv[optind+1], "w");
|
||||
if (out == NULL)
|
||||
return (-1);
|
||||
cpTags(in, out);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
if (compression != (uint16) -1) {
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
switch (compression) {
|
||||
case COMPRESSION_JPEG:
|
||||
TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
|
||||
TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
|
||||
break;
|
||||
case COMPRESSION_LZW:
|
||||
case COMPRESSION_DEFLATE:
|
||||
if (predictor != 0)
|
||||
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
|
||||
sprintf(thing, "B&W version of %s", argv[optind]);
|
||||
TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, thing);
|
||||
TIFFSetField(out, TIFFTAG_SOFTWARE, "tiff2bw");
|
||||
outbuf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(out));
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
|
||||
TIFFDefaultStripSize(out, rowsperstrip));
|
||||
|
||||
#define pack(a,b) ((a)<<8 | (b))
|
||||
switch (pack(photometric, config)) {
|
||||
case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_CONTIG):
|
||||
case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_SEPARATE):
|
||||
TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue);
|
||||
/*
|
||||
* Convert 16-bit colormap to 8-bit (unless it looks
|
||||
* like an old-style 8-bit colormap).
|
||||
*/
|
||||
if (checkcmap(in, 1<<bitspersample, red, green, blue) == 16) {
|
||||
int i;
|
||||
#define CVT(x) (((x) * 255L) / ((1L<<16)-1))
|
||||
for (i = (1<<bitspersample)-1; i >= 0; i--) {
|
||||
red[i] = CVT(red[i]);
|
||||
green[i] = CVT(green[i]);
|
||||
blue[i] = CVT(blue[i]);
|
||||
}
|
||||
#undef CVT
|
||||
}
|
||||
inbuf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
|
||||
for (row = 0; row < h; row++) {
|
||||
if (TIFFReadScanline(in, inbuf, row, 0) < 0)
|
||||
break;
|
||||
compresspalette(outbuf, inbuf, w, red, green, blue);
|
||||
if (TIFFWriteScanline(out, outbuf, row, 0) < 0)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case pack(PHOTOMETRIC_RGB, PLANARCONFIG_CONTIG):
|
||||
inbuf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
|
||||
for (row = 0; row < h; row++) {
|
||||
if (TIFFReadScanline(in, inbuf, row, 0) < 0)
|
||||
break;
|
||||
compresscontig(outbuf, inbuf, w);
|
||||
if (TIFFWriteScanline(out, outbuf, row, 0) < 0)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case pack(PHOTOMETRIC_RGB, PLANARCONFIG_SEPARATE):
|
||||
rowsize = TIFFScanlineSize(in);
|
||||
inbuf = (unsigned char *)_TIFFmalloc(3*rowsize);
|
||||
for (row = 0; row < h; row++) {
|
||||
for (s = 0; s < 3; s++)
|
||||
if (TIFFReadScanline(in,
|
||||
inbuf+s*rowsize, row, s) < 0)
|
||||
return (-1);
|
||||
compresssep(outbuf,
|
||||
inbuf, inbuf+rowsize, inbuf+2*rowsize, w);
|
||||
if (TIFFWriteScanline(out, outbuf, row, 0) < 0)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#undef pack
|
||||
TIFFClose(out);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
processCompressOptions(char* opt)
|
||||
{
|
||||
if (streq(opt, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(opt, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (strneq(opt, "jpeg", 4)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp && isdigit(cp[1]))
|
||||
quality = atoi(cp+1);
|
||||
if (cp && strchr(cp, 'r'))
|
||||
jpegcolormode = JPEGCOLORMODE_RAW;
|
||||
compression = COMPRESSION_JPEG;
|
||||
} else if (strneq(opt, "lzw", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_LZW;
|
||||
} else if (strneq(opt, "zip", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_DEFLATE;
|
||||
} else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
#define CopyField1(tag, v) \
|
||||
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
|
||||
#define CopyField2(tag, v1, v2) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
|
||||
#define CopyField3(tag, v1, v2, v3) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
|
||||
#define CopyField4(tag, v1, v2, v3, v4) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
|
||||
|
||||
static void
|
||||
cpTag(TIFF* in, TIFF* out, uint16 tag, uint16 count, TIFFDataType type)
|
||||
{
|
||||
uint16 shortv, shortv2, *shortav;
|
||||
float floatv, *floatav;
|
||||
char *stringv;
|
||||
uint32 longv;
|
||||
|
||||
switch (type) {
|
||||
case TIFF_SHORT:
|
||||
if (count == 1) {
|
||||
CopyField1(tag, shortv);
|
||||
} else if (count == 2) {
|
||||
CopyField2(tag, shortv, shortv2);
|
||||
} else if (count == (uint16) -1) {
|
||||
CopyField2(tag, shortv, shortav);
|
||||
}
|
||||
break;
|
||||
case TIFF_LONG:
|
||||
CopyField1(tag, longv);
|
||||
break;
|
||||
case TIFF_RATIONAL:
|
||||
if (count == 1) {
|
||||
CopyField1(tag, floatv);
|
||||
} else if (count == (uint16) -1) {
|
||||
CopyField1(tag, floatav);
|
||||
}
|
||||
break;
|
||||
case TIFF_ASCII:
|
||||
CopyField1(tag, stringv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#undef CopyField4
|
||||
#undef CopyField3
|
||||
#undef CopyField2
|
||||
#undef CopyField1
|
||||
|
||||
static struct cpTag {
|
||||
uint16 tag;
|
||||
uint16 count;
|
||||
TIFFDataType type;
|
||||
} tags[] = {
|
||||
{ TIFFTAG_IMAGEWIDTH, 1, TIFF_LONG },
|
||||
{ TIFFTAG_IMAGELENGTH, 1, TIFF_LONG },
|
||||
{ TIFFTAG_FILLORDER, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_DOCUMENTNAME, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_MAKE, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_MODEL, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_ORIENTATION, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_XRESOLUTION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_YRESOLUTION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_PAGENAME, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_XPOSITION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_YPOSITION, 1, TIFF_RATIONAL },
|
||||
{ TIFFTAG_RESOLUTIONUNIT, 1, TIFF_SHORT },
|
||||
{ TIFFTAG_PAGENUMBER, 2, TIFF_SHORT },
|
||||
{ TIFFTAG_ARTIST, 1, TIFF_ASCII },
|
||||
{ TIFFTAG_HOSTCOMPUTER, 1, TIFF_ASCII },
|
||||
};
|
||||
#define NTAGS (sizeof (tags) / sizeof (tags[0]))
|
||||
|
||||
static void
|
||||
cpTags(TIFF* in, TIFF* out)
|
||||
{
|
||||
struct cpTag *p;
|
||||
for (p = tags; p < &tags[NTAGS]; p++)
|
||||
cpTag(in, out, p->tag, p->count, p->type);
|
||||
}
|
||||
#undef NTAGS
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: tiff2bw [options] input.tif output.tif",
|
||||
"where options are:",
|
||||
" -R % use #% from red channel",
|
||||
" -G % use #% from green channel",
|
||||
" -B % use #% from blue channel",
|
||||
"",
|
||||
" -r # make each strip have no more than # rows",
|
||||
"",
|
||||
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
|
||||
" (no longer supported by default due to Unisys patent enforcement)",
|
||||
" -c zip[:opts] compress output with deflate encoding",
|
||||
" -c packbits compress output with packbits encoding",
|
||||
" -c g3[:opts] compress output with CCITT Group 3 encoding",
|
||||
" -c g4 compress output with CCITT Group 4 encoding",
|
||||
" -c none use no compression algorithm on output",
|
||||
"",
|
||||
"LZW and deflate options:",
|
||||
" # set predictor value",
|
||||
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
Executable
+1408
File diff suppressed because it is too large
Load Diff
Executable
+453
@@ -0,0 +1,453 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/tiff2rgba.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define CopyField(tag, v) \
|
||||
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
|
||||
|
||||
#ifndef howmany
|
||||
#define howmany(x, y) (((x)+((y)-1))/(y))
|
||||
#endif
|
||||
#define roundup(x, y) (howmany(x,y)*((uint32)(y)))
|
||||
|
||||
uint16 compression = COMPRESSION_PACKBITS;
|
||||
uint32 rowsperstrip = (uint32) -1;
|
||||
int process_by_block = 0; /* default is whole image at once */
|
||||
|
||||
|
||||
static int tiffcvt(TIFF* in, TIFF* out);
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
TIFF *in, *out;
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:r:t:b")) != -1)
|
||||
switch (c) {
|
||||
case 'b':
|
||||
process_by_block = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (streq(optarg, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(optarg, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (streq(optarg, "lzw"))
|
||||
compression = COMPRESSION_LZW;
|
||||
else if (streq(optarg, "jpeg"))
|
||||
compression = COMPRESSION_JPEG;
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
if (argc - optind < 2)
|
||||
usage();
|
||||
|
||||
out = TIFFOpen(argv[argc-1], "w");
|
||||
if (out == NULL)
|
||||
return (-2);
|
||||
|
||||
for (; optind < argc-1; optind++) {
|
||||
in = TIFFOpen(argv[optind], "r");
|
||||
if (in != NULL) {
|
||||
do {
|
||||
if (!tiffcvt(in, out) ||
|
||||
!TIFFWriteDirectory(out)) {
|
||||
(void) TIFFClose(out);
|
||||
return (1);
|
||||
}
|
||||
} while (TIFFReadDirectory(in));
|
||||
(void) TIFFClose(in);
|
||||
}
|
||||
}
|
||||
(void) TIFFClose(out);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cvt_by_tile( TIFF *in, TIFF *out )
|
||||
|
||||
{
|
||||
uint32* raster; /* retrieve RGBA image */
|
||||
uint32 width, height; /* image width & height */
|
||||
uint32 tile_width, tile_height;
|
||||
uint32 row, col;
|
||||
uint32 *wrk_line;
|
||||
int ok = 1;
|
||||
|
||||
TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width);
|
||||
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height);
|
||||
|
||||
if( !TIFFGetField(in, TIFFTAG_TILEWIDTH, &tile_width)
|
||||
|| !TIFFGetField(in, TIFFTAG_TILELENGTH, &tile_height) ) {
|
||||
TIFFError(TIFFFileName(in), "Source image not tiled");
|
||||
return (0);
|
||||
}
|
||||
|
||||
TIFFSetField(out, TIFFTAG_TILEWIDTH, tile_width );
|
||||
TIFFSetField(out, TIFFTAG_TILELENGTH, tile_height );
|
||||
|
||||
/*
|
||||
* Allocate tile buffer
|
||||
*/
|
||||
raster = (uint32*)_TIFFmalloc(tile_width * tile_height * sizeof (uint32));
|
||||
if (raster == 0) {
|
||||
TIFFError(TIFFFileName(in), "No space for raster buffer");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a scanline buffer for swapping during the vertical
|
||||
* mirroring pass.
|
||||
*/
|
||||
wrk_line = (uint32*)_TIFFmalloc(tile_width * sizeof (uint32));
|
||||
if (wrk_line == 0) {
|
||||
TIFFError(TIFFFileName(in), "No space for raster scanline buffer");
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop over the tiles.
|
||||
*/
|
||||
for( row = 0; ok && row < height; row += tile_height )
|
||||
{
|
||||
for( col = 0; ok && col < width; col += tile_width )
|
||||
{
|
||||
int i_row;
|
||||
|
||||
/* Read the tile into an RGBA array */
|
||||
if (!TIFFReadRGBATile(in, col, row, raster)) {
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* For some reason the TIFFReadRGBATile() function chooses the
|
||||
* lower left corner as the origin. Vertically mirror scanlines.
|
||||
*/
|
||||
for( i_row = 0; i_row < tile_height / 2; i_row++ )
|
||||
{
|
||||
uint32 *top_line, *bottom_line;
|
||||
|
||||
top_line = raster + tile_width * i_row;
|
||||
bottom_line = raster + tile_width * (tile_height-i_row-1);
|
||||
|
||||
_TIFFmemcpy(wrk_line, top_line, 4*tile_width);
|
||||
_TIFFmemcpy(top_line, bottom_line, 4*tile_width);
|
||||
_TIFFmemcpy(bottom_line, wrk_line, 4*tile_width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out the result in a tile.
|
||||
*/
|
||||
|
||||
if( TIFFWriteEncodedTile( out,
|
||||
TIFFComputeTile( out, col, row, 0, 0),
|
||||
raster,
|
||||
4 * tile_width * tile_height ) == -1 )
|
||||
{
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_TIFFfree( raster );
|
||||
_TIFFfree( wrk_line );
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int
|
||||
cvt_by_strip( TIFF *in, TIFF *out )
|
||||
|
||||
{
|
||||
uint32* raster; /* retrieve RGBA image */
|
||||
uint32 width, height; /* image width & height */
|
||||
uint32 row;
|
||||
uint32 *wrk_line;
|
||||
int ok = 1;
|
||||
|
||||
TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width);
|
||||
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height);
|
||||
|
||||
if( !TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip) ) {
|
||||
TIFFError(TIFFFileName(in), "Source image not in strips");
|
||||
return (0);
|
||||
}
|
||||
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
|
||||
|
||||
/*
|
||||
* Allocate strip buffer
|
||||
*/
|
||||
raster = (uint32*)_TIFFmalloc(width * rowsperstrip * sizeof (uint32));
|
||||
if (raster == 0) {
|
||||
TIFFError(TIFFFileName(in), "No space for raster buffer");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a scanline buffer for swapping during the vertical
|
||||
* mirroring pass.
|
||||
*/
|
||||
wrk_line = (uint32*)_TIFFmalloc(width * sizeof (uint32));
|
||||
if (wrk_line == 0) {
|
||||
TIFFError(TIFFFileName(in), "No space for raster scanline buffer");
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop over the strips.
|
||||
*/
|
||||
for( row = 0; ok && row < height; row += rowsperstrip )
|
||||
{
|
||||
int rows_to_write, i_row;
|
||||
|
||||
/* Read the strip into an RGBA array */
|
||||
if (!TIFFReadRGBAStrip(in, row, raster)) {
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out the number of scanlines actually in this strip.
|
||||
*/
|
||||
if( row + rowsperstrip > height )
|
||||
rows_to_write = height - row;
|
||||
else
|
||||
rows_to_write = rowsperstrip;
|
||||
|
||||
/*
|
||||
* For some reason the TIFFReadRGBAStrip() function chooses the
|
||||
* lower left corner as the origin. Vertically mirror scanlines.
|
||||
*/
|
||||
|
||||
for( i_row = 0; i_row < rows_to_write / 2; i_row++ )
|
||||
{
|
||||
uint32 *top_line, *bottom_line;
|
||||
|
||||
top_line = raster + width * i_row;
|
||||
bottom_line = raster + width * (rows_to_write-i_row-1);
|
||||
|
||||
_TIFFmemcpy(wrk_line, top_line, 4*width);
|
||||
_TIFFmemcpy(top_line, bottom_line, 4*width);
|
||||
_TIFFmemcpy(bottom_line, wrk_line, 4*width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out the result in a strip
|
||||
*/
|
||||
|
||||
if( TIFFWriteEncodedStrip( out, row / rowsperstrip, raster,
|
||||
4 * rows_to_write * width ) == -1 )
|
||||
{
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_TIFFfree( raster );
|
||||
_TIFFfree( wrk_line );
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* cvt_whole_image()
|
||||
*
|
||||
* read the whole image into one big RGBA buffer and then write out
|
||||
* strips from that. This is using the traditional TIFFReadRGBAImage()
|
||||
* API that we trust.
|
||||
*/
|
||||
|
||||
static int
|
||||
cvt_whole_image( TIFF *in, TIFF *out )
|
||||
|
||||
{
|
||||
uint32* raster; /* retrieve RGBA image */
|
||||
uint32 width, height; /* image width & height */
|
||||
uint32 row;
|
||||
uint32 *wrk_line;
|
||||
|
||||
|
||||
TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width);
|
||||
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height);
|
||||
|
||||
rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
|
||||
|
||||
raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32));
|
||||
if (raster == 0) {
|
||||
TIFFError(TIFFFileName(in), "No space for raster buffer");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Read the image in one chunk into an RGBA array */
|
||||
if (!TIFFReadRGBAImage(in, width, height, raster, 0)) {
|
||||
_TIFFfree(raster);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* For some reason the TIFFReadRGBAImage() function chooses the
|
||||
lower left corner as the origin. Vertically mirror scanlines. */
|
||||
|
||||
wrk_line = (uint32*)_TIFFmalloc(width * sizeof (uint32));
|
||||
if (wrk_line == 0) {
|
||||
TIFFError(TIFFFileName(in), "No space for raster scanline buffer");
|
||||
return (0);
|
||||
}
|
||||
|
||||
for( row = 0; row < height / 2; row++ )
|
||||
{
|
||||
uint32 *top_line, *bottom_line;
|
||||
|
||||
top_line = raster + width * row;
|
||||
bottom_line = raster + width * (height-row-1);
|
||||
|
||||
_TIFFmemcpy(wrk_line, top_line, 4*width);
|
||||
_TIFFmemcpy(top_line, bottom_line, 4*width);
|
||||
_TIFFmemcpy(bottom_line, wrk_line, 4*width);
|
||||
}
|
||||
|
||||
_TIFFfree( wrk_line );
|
||||
|
||||
|
||||
/* Write out the result in strips */
|
||||
|
||||
for( row = 0; row < height; row += rowsperstrip )
|
||||
{
|
||||
uint32* raster_strip;
|
||||
int rows_to_write;
|
||||
|
||||
raster_strip = raster + row * width;
|
||||
|
||||
if( row + rowsperstrip > height )
|
||||
rows_to_write = height - row;
|
||||
else
|
||||
rows_to_write = rowsperstrip;
|
||||
|
||||
if( TIFFWriteEncodedStrip( out, row / rowsperstrip,
|
||||
raster_strip,
|
||||
4 * rows_to_write * width ) == -1 )
|
||||
{
|
||||
_TIFFfree( raster );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
_TIFFfree( raster );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
tiffcvt(TIFF* in, TIFF* out)
|
||||
{
|
||||
uint32 width, height; /* image width & height */
|
||||
uint16 shortv;
|
||||
float floatv;
|
||||
char *stringv;
|
||||
uint32 longv;
|
||||
uint16 v[1];
|
||||
|
||||
TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width);
|
||||
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height);
|
||||
|
||||
CopyField(TIFFTAG_SUBFILETYPE, longv);
|
||||
TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
|
||||
TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
|
||||
|
||||
CopyField(TIFFTAG_FILLORDER, shortv);
|
||||
TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 4);
|
||||
v[0] = EXTRASAMPLE_ASSOCALPHA;
|
||||
TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, v);
|
||||
CopyField(TIFFTAG_XRESOLUTION, floatv);
|
||||
CopyField(TIFFTAG_YRESOLUTION, floatv);
|
||||
CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(out, TIFFTAG_SOFTWARE, TIFFGetVersion());
|
||||
CopyField(TIFFTAG_DOCUMENTNAME, stringv);
|
||||
|
||||
if( process_by_block && TIFFIsTiled( in ) )
|
||||
return( cvt_by_tile( in, out ) );
|
||||
else if( process_by_block )
|
||||
return( cvt_by_strip( in, out ) );
|
||||
else
|
||||
return( cvt_whole_image( in, out ) );
|
||||
}
|
||||
|
||||
static char* usageMsg[] = {
|
||||
"usage: tiff2rgba [-c comp] [-r rows] [-b] input... output\n",
|
||||
"where comp is one of the following compression algorithms:\n",
|
||||
" jpeg\t\tJPEG encoding\n",
|
||||
" lzw\t\tLempel-Ziv & Welch encoding\n",
|
||||
" (lzw compression unsupported by default due to Unisys patent enforcement)\n",
|
||||
" packbits\tPackBits encoding\n",
|
||||
" none\t\tno compression\n",
|
||||
"and the other options are:\n",
|
||||
" -r\trows/strip\n",
|
||||
" -b (progress by block rather than as a whole image)\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; usageMsg[i]; i++)
|
||||
fprintf(stderr, "%s", usageMsg[i]);
|
||||
exit(-1);
|
||||
}
|
||||
Executable
+483
@@ -0,0 +1,483 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/tiffcmp.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
static int stopondiff = 1;
|
||||
static int stoponfirsttag = 1;
|
||||
static uint16 bitspersample = 1;
|
||||
static uint16 samplesperpixel = 1;
|
||||
static uint32 imagewidth;
|
||||
static uint32 imagelength;
|
||||
|
||||
static int tiffcmp(TIFF*, TIFF*);
|
||||
static int cmptags(TIFF*, TIFF*);
|
||||
static void ContigCompare(int, uint32, unsigned char*, unsigned char*, int);
|
||||
static void PrintDiff(uint32, int, uint32, int, int);
|
||||
static void SeparateCompare(int, int, uint32, unsigned char*, unsigned char*);
|
||||
static void eof(const char*, uint32, int);
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: tiffcmp [-l] [-t] [-z] file1 file2\n");
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
TIFF *tif1, *tif2;
|
||||
int c, dirnum;
|
||||
extern int optind;
|
||||
|
||||
while ((c = getopt(argc, argv, "ltz")) != -1)
|
||||
switch (c) {
|
||||
case 'l':
|
||||
stopondiff = 0;
|
||||
break;
|
||||
case 'z':
|
||||
stopondiff += 100;
|
||||
break;
|
||||
case 't':
|
||||
stoponfirsttag = 0;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind < 2)
|
||||
usage();
|
||||
tif1 = TIFFOpen(argv[optind], "r");
|
||||
if (tif1 == NULL)
|
||||
return (-1);
|
||||
tif2 = TIFFOpen(argv[optind+1], "r");
|
||||
if (tif2 == NULL)
|
||||
return (-2);
|
||||
dirnum = 0;
|
||||
while (tiffcmp(tif1, tif2)) {
|
||||
if (!TIFFReadDirectory(tif1)) {
|
||||
if (!TIFFReadDirectory(tif2))
|
||||
break;
|
||||
printf("No more directories for %s\n",
|
||||
TIFFFileName(tif1));
|
||||
return (1);
|
||||
} else if (!TIFFReadDirectory(tif2)) {
|
||||
printf("No more directories for %s\n",
|
||||
TIFFFileName(tif2));
|
||||
return (1);
|
||||
}
|
||||
printf("Directory %d:\n", ++dirnum);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define checkEOF(tif, row, sample) { \
|
||||
eof(TIFFFileName(tif), row, sample); \
|
||||
goto bad; \
|
||||
}
|
||||
|
||||
static int CheckShortTag(TIFF*, TIFF*, int, char*);
|
||||
static int CheckShort2Tag(TIFF*, TIFF*, int, char*);
|
||||
static int CheckShortArrayTag(TIFF*, TIFF*, int, char*);
|
||||
static int CheckLongTag(TIFF*, TIFF*, int, char*);
|
||||
static int CheckFloatTag(TIFF*, TIFF*, int, char*);
|
||||
static int CheckStringTag(TIFF*, TIFF*, int, char*);
|
||||
|
||||
static int
|
||||
tiffcmp(TIFF* tif1, TIFF* tif2)
|
||||
{
|
||||
uint16 config1, config2;
|
||||
tsize_t size1;
|
||||
uint32 s, row;
|
||||
unsigned char *buf1, *buf2;
|
||||
|
||||
if (!CheckShortTag(tif1, tif2, TIFFTAG_BITSPERSAMPLE, "BitsPerSample"))
|
||||
return (0);
|
||||
if (!CheckShortTag(tif1, tif2, TIFFTAG_SAMPLESPERPIXEL, "SamplesPerPixel"))
|
||||
return (0);
|
||||
if (!CheckLongTag(tif1, tif2, TIFFTAG_IMAGEWIDTH, "ImageWidth"))
|
||||
return (0);
|
||||
if (!cmptags(tif1, tif2))
|
||||
return (1);
|
||||
(void) TIFFGetField(tif1, TIFFTAG_BITSPERSAMPLE, &bitspersample);
|
||||
(void) TIFFGetField(tif1, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
|
||||
(void) TIFFGetField(tif1, TIFFTAG_IMAGEWIDTH, &imagewidth);
|
||||
(void) TIFFGetField(tif1, TIFFTAG_IMAGELENGTH, &imagelength);
|
||||
(void) TIFFGetField(tif1, TIFFTAG_PLANARCONFIG, &config1);
|
||||
(void) TIFFGetField(tif2, TIFFTAG_PLANARCONFIG, &config2);
|
||||
buf1 = (unsigned char *)_TIFFmalloc(size1 = TIFFScanlineSize(tif1));
|
||||
buf2 = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif2));
|
||||
if (buf1 == NULL || buf2 == NULL) {
|
||||
fprintf(stderr, "No space for scanline buffers\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (config1 != config2 && bitspersample != 8 && samplesperpixel > 1) {
|
||||
fprintf(stderr,
|
||||
"Can't handle different planar configuration w/ different bits/sample\n");
|
||||
goto bad;
|
||||
}
|
||||
#define pack(a,b) ((a)<<8)|(b)
|
||||
switch (pack(config1, config2)) {
|
||||
case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG):
|
||||
for (row = 0; row < imagelength; row++) {
|
||||
if (TIFFReadScanline(tif2, buf2, row, 0) < 0)
|
||||
checkEOF(tif2, row, -1)
|
||||
for (s = 0; s < samplesperpixel; s++) {
|
||||
if (TIFFReadScanline(tif1, buf1, row, s) < 0)
|
||||
checkEOF(tif1, row, s)
|
||||
SeparateCompare(1, s, row, buf2, buf1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE):
|
||||
for (row = 0; row < imagelength; row++) {
|
||||
if (TIFFReadScanline(tif1, buf1, row, 0) < 0)
|
||||
checkEOF(tif1, row, -1)
|
||||
for (s = 0; s < samplesperpixel; s++) {
|
||||
if (TIFFReadScanline(tif2, buf2, row, s) < 0)
|
||||
checkEOF(tif2, row, s)
|
||||
SeparateCompare(0, s, row, buf1, buf2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE):
|
||||
for (s = 0; s < samplesperpixel; s++)
|
||||
for (row = 0; row < imagelength; row++) {
|
||||
if (TIFFReadScanline(tif1, buf1, row, s) < 0)
|
||||
checkEOF(tif1, row, s)
|
||||
if (TIFFReadScanline(tif2, buf2, row, s) < 0)
|
||||
checkEOF(tif2, row, s)
|
||||
ContigCompare(s, row, buf1, buf2, size1);
|
||||
}
|
||||
break;
|
||||
case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_CONTIG):
|
||||
for (row = 0; row < imagelength; row++) {
|
||||
if (TIFFReadScanline(tif1, buf1, row, 0) < 0)
|
||||
checkEOF(tif1, row, -1)
|
||||
if (TIFFReadScanline(tif2, buf2, row, 0) < 0)
|
||||
checkEOF(tif2, row, -1)
|
||||
ContigCompare(-1, row, buf1, buf2, size1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (buf1) _TIFFfree(buf1);
|
||||
if (buf2) _TIFFfree(buf2);
|
||||
return (1);
|
||||
bad:
|
||||
if (stopondiff)
|
||||
exit(1);
|
||||
if (buf1) _TIFFfree(buf1);
|
||||
if (buf2) _TIFFfree(buf2);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define CmpShortField(tag, name) \
|
||||
if (!CheckShortTag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
|
||||
#define CmpShortField2(tag, name) \
|
||||
if (!CheckShort2Tag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
|
||||
#define CmpLongField(tag, name) \
|
||||
if (!CheckLongTag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
|
||||
#define CmpFloatField(tag, name) \
|
||||
if (!CheckFloatTag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
|
||||
#define CmpStringField(tag, name) \
|
||||
if (!CheckStringTag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
|
||||
#define CmpShortArrayField(tag, name) \
|
||||
if (!CheckShortArrayTag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
|
||||
|
||||
static int
|
||||
cmptags(TIFF* tif1, TIFF* tif2)
|
||||
{
|
||||
CmpLongField(TIFFTAG_SUBFILETYPE, "SubFileType");
|
||||
CmpLongField(TIFFTAG_IMAGEWIDTH, "ImageWidth");
|
||||
CmpLongField(TIFFTAG_IMAGELENGTH, "ImageLength");
|
||||
CmpShortField(TIFFTAG_BITSPERSAMPLE, "BitsPerSample");
|
||||
CmpShortField(TIFFTAG_COMPRESSION, "Compression");
|
||||
CmpShortField(TIFFTAG_PREDICTOR, "Predictor");
|
||||
CmpShortField(TIFFTAG_PHOTOMETRIC, "PhotometricInterpretation");
|
||||
CmpShortField(TIFFTAG_THRESHHOLDING, "Thresholding");
|
||||
CmpShortField(TIFFTAG_FILLORDER, "FillOrder");
|
||||
CmpShortField(TIFFTAG_ORIENTATION, "Orientation");
|
||||
CmpShortField(TIFFTAG_SAMPLESPERPIXEL, "SamplesPerPixel");
|
||||
CmpShortField(TIFFTAG_MINSAMPLEVALUE, "MinSampleValue");
|
||||
CmpShortField(TIFFTAG_MAXSAMPLEVALUE, "MaxSampleValue");
|
||||
CmpFloatField(TIFFTAG_XRESOLUTION, "XResolution");
|
||||
CmpFloatField(TIFFTAG_YRESOLUTION, "YResolution");
|
||||
CmpLongField(TIFFTAG_GROUP3OPTIONS, "Group3Options");
|
||||
CmpLongField(TIFFTAG_GROUP4OPTIONS, "Group4Options");
|
||||
CmpShortField(TIFFTAG_RESOLUTIONUNIT, "ResolutionUnit");
|
||||
CmpShortField(TIFFTAG_PLANARCONFIG, "PlanarConfiguration");
|
||||
CmpLongField(TIFFTAG_ROWSPERSTRIP, "RowsPerStrip");
|
||||
CmpFloatField(TIFFTAG_XPOSITION, "XPosition");
|
||||
CmpFloatField(TIFFTAG_YPOSITION, "YPosition");
|
||||
CmpShortField(TIFFTAG_GRAYRESPONSEUNIT, "GrayResponseUnit");
|
||||
CmpShortField(TIFFTAG_COLORRESPONSEUNIT, "ColorResponseUnit");
|
||||
#ifdef notdef
|
||||
{ uint16 *graycurve;
|
||||
CmpField(TIFFTAG_GRAYRESPONSECURVE, graycurve);
|
||||
}
|
||||
{ uint16 *red, *green, *blue;
|
||||
CmpField3(TIFFTAG_COLORRESPONSECURVE, red, green, blue);
|
||||
}
|
||||
{ uint16 *red, *green, *blue;
|
||||
CmpField3(TIFFTAG_COLORMAP, red, green, blue);
|
||||
}
|
||||
#endif
|
||||
CmpShortField2(TIFFTAG_PAGENUMBER, "PageNumber");
|
||||
CmpStringField(TIFFTAG_ARTIST, "Artist");
|
||||
CmpStringField(TIFFTAG_IMAGEDESCRIPTION,"ImageDescription");
|
||||
CmpStringField(TIFFTAG_MAKE, "Make");
|
||||
CmpStringField(TIFFTAG_MODEL, "Model");
|
||||
CmpStringField(TIFFTAG_SOFTWARE, "Software");
|
||||
CmpStringField(TIFFTAG_DATETIME, "DateTime");
|
||||
CmpStringField(TIFFTAG_HOSTCOMPUTER, "HostComputer");
|
||||
CmpStringField(TIFFTAG_PAGENAME, "PageName");
|
||||
CmpStringField(TIFFTAG_DOCUMENTNAME, "DocumentName");
|
||||
CmpShortField(TIFFTAG_MATTEING, "Matteing");
|
||||
CmpShortArrayField(TIFFTAG_EXTRASAMPLES,"ExtraSamples");
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
ContigCompare(int sample, uint32 row, unsigned char* p1, unsigned char* p2, int size)
|
||||
{
|
||||
register uint32 pix;
|
||||
register int ppb = 8/bitspersample;
|
||||
|
||||
if (memcmp(p1, p2, size) == 0)
|
||||
return;
|
||||
switch (bitspersample) {
|
||||
case 1: case 2: case 4: case 8: {
|
||||
register unsigned char *pix1 = p1, *pix2 = p2;
|
||||
|
||||
for (pix = 0; pix < imagewidth; pix1++, pix2++, pix += ppb)
|
||||
if (*pix1 != *pix2)
|
||||
PrintDiff(row, sample, pix,
|
||||
*pix1, *pix2);
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
register uint16 *pix1 = (uint16 *)p1, *pix2 = (uint16 *)p2;
|
||||
|
||||
for (pix = 0; pix < imagewidth; pix1++, pix2++, pix++)
|
||||
if (*pix1 != *pix2)
|
||||
PrintDiff(row, sample, pix,
|
||||
*pix1, *pix2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PrintDiff(uint32 row, int sample, uint32 pix, int w1, int w2)
|
||||
{
|
||||
register int mask1, mask2, s, bps;
|
||||
|
||||
if (sample < 0)
|
||||
sample = 0;
|
||||
bps = bitspersample;
|
||||
switch (bps) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
mask1 = ~((-1)<<bps);
|
||||
s = (8-bps);
|
||||
mask2 = mask1<<s;
|
||||
for (; mask2; mask2 >>= bps, s -= bps, pix++) {
|
||||
if ((w1 & mask2) ^ (w2 & mask2)) {
|
||||
printf(
|
||||
"Scanline %lu, pixel %lu, sample %d: %01x %01x\n",
|
||||
(long) row, (long) pix,
|
||||
sample, (w1 >> s) & mask1,
|
||||
(w2 >> s) & mask1 );
|
||||
if (--stopondiff == 0)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
printf("Scanline %lu, pixel %lu, sample %d: %02x %02x\n",
|
||||
(long) row, (long) pix, sample, w1, w2);
|
||||
if (--stopondiff == 0)
|
||||
exit(1);
|
||||
break;
|
||||
case 16:
|
||||
printf("Scanline %lu, pixel %lu, sample %d: %04x %04x\n",
|
||||
(long) row, (long) pix, sample, w1, w2);
|
||||
if (--stopondiff == 0)
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SeparateCompare(int reversed, int sample, uint32 row, unsigned char* cp1, unsigned char* p2)
|
||||
{
|
||||
uint32 npixels = imagewidth;
|
||||
register int pixel;
|
||||
|
||||
cp1 += sample;
|
||||
for (pixel = 0; npixels-- > 0; pixel++, cp1 += samplesperpixel, p2++)
|
||||
if (*cp1 != *p2) {
|
||||
printf("Scanline %lu, pixel %lu, sample %ld: ",
|
||||
(long) row, (long) pixel, (long) sample);
|
||||
if (reversed)
|
||||
printf("%02x %02x\n", *p2, *cp1);
|
||||
else
|
||||
printf("%02x %02x\n", *cp1, *p2);
|
||||
if (--stopondiff == 0)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
checkTag(TIFF* tif1, TIFF* tif2, int tag, char* name, void* p1, void* p2)
|
||||
{
|
||||
|
||||
if (TIFFGetField(tif1, tag, p1)) {
|
||||
if (!TIFFGetField(tif2, tag, p2)) {
|
||||
printf("%s tag appears only in %s\n",
|
||||
name, TIFFFileName(tif1));
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
} else if (TIFFGetField(tif2, tag, p2)) {
|
||||
printf("%s tag appears only in %s\n", name, TIFFFileName(tif2));
|
||||
return (0);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#define CHECK(cmp, fmt) { \
|
||||
switch (checkTag(tif1,tif2,tag,name,&v1,&v2)) { \
|
||||
case 1: if (cmp) \
|
||||
case -1: return (1); \
|
||||
printf(fmt, name, v1, v2); \
|
||||
} \
|
||||
return (0); \
|
||||
}
|
||||
|
||||
static int
|
||||
CheckShortTag(TIFF* tif1, TIFF* tif2, int tag, char* name)
|
||||
{
|
||||
uint16 v1, v2;
|
||||
CHECK(v1 == v2, "%s: %u %u\n");
|
||||
}
|
||||
|
||||
static int
|
||||
CheckShort2Tag(TIFF* tif1, TIFF* tif2, int tag, char* name)
|
||||
{
|
||||
uint16 v11, v12, v21, v22;
|
||||
|
||||
if (TIFFGetField(tif1, tag, &v11, &v12)) {
|
||||
if (!TIFFGetField(tif2, tag, &v21, &v22)) {
|
||||
printf("%s tag appears only in %s\n",
|
||||
name, TIFFFileName(tif1));
|
||||
return (0);
|
||||
}
|
||||
if (v11 == v21 && v12 == v22)
|
||||
return (1);
|
||||
printf("%s: <%u,%u> <%u,%u>\n", name, v11, v12, v21, v22);
|
||||
} else if (TIFFGetField(tif2, tag, &v21, &v22))
|
||||
printf("%s tag appears only in %s\n", name, TIFFFileName(tif2));
|
||||
else
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
CheckShortArrayTag(TIFF* tif1, TIFF* tif2, int tag, char* name)
|
||||
{
|
||||
uint16 n1, *a1;
|
||||
uint16 n2, *a2;
|
||||
|
||||
if (TIFFGetField(tif1, tag, &n1, &a1)) {
|
||||
if (!TIFFGetField(tif2, tag, &n2, &a2)) {
|
||||
printf("%s tag appears only in %s\n",
|
||||
name, TIFFFileName(tif1));
|
||||
return (0);
|
||||
}
|
||||
if (n1 == n2) {
|
||||
char* sep;
|
||||
uint16 i;
|
||||
|
||||
if (memcmp(a1, a2, n1) == 0)
|
||||
return (1);
|
||||
printf("%s: value mismatch, <%u:", name, n1);
|
||||
sep = "";
|
||||
for (i = 0; i < n1; i++)
|
||||
printf("%s%u", sep, a1[i]), sep = ",";
|
||||
printf("> and <%u: ", n2);
|
||||
sep = "";
|
||||
for (i = 0; i < n2; i++)
|
||||
printf("%s%u", sep, a2[i]), sep = ",";
|
||||
printf(">\n");
|
||||
} else
|
||||
printf("%s: %u items in %s, %u items in %s", name,
|
||||
n1, TIFFFileName(tif1),
|
||||
n2, TIFFFileName(tif2)
|
||||
);
|
||||
} else if (TIFFGetField(tif2, tag, &n2, &a2))
|
||||
printf("%s tag appears only in %s\n", name, TIFFFileName(tif2));
|
||||
else
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
CheckLongTag(TIFF* tif1, TIFF* tif2, int tag, char* name)
|
||||
{
|
||||
uint32 v1, v2;
|
||||
CHECK(v1 == v2, "%s: %lu %lu\n");
|
||||
}
|
||||
|
||||
static int
|
||||
CheckFloatTag(TIFF* tif1, TIFF* tif2, int tag, char* name)
|
||||
{
|
||||
float v1, v2;
|
||||
CHECK(v1 == v2, "%s: %g %g\n");
|
||||
}
|
||||
|
||||
static int
|
||||
CheckStringTag(TIFF* tif1, TIFF* tif2, int tag, char* name)
|
||||
{
|
||||
char *v1, *v2;
|
||||
CHECK(strcmp(v1, v2) == 0, "%s: \"%s\" \"%s\"\n");
|
||||
}
|
||||
|
||||
static void
|
||||
eof(const char* name, uint32 row, int s)
|
||||
{
|
||||
|
||||
printf("%s: EOF at scanline %lu", name, row);
|
||||
if (s >= 0)
|
||||
printf(", sample %d", s);
|
||||
printf("\n");
|
||||
}
|
||||
Executable
+1314
File diff suppressed because it is too large
Load Diff
Executable
+314
@@ -0,0 +1,314 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/tiffdither.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define strneq(a,b,n) (strncmp(a,b,n) == 0)
|
||||
|
||||
#define CopyField(tag, v) \
|
||||
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
|
||||
|
||||
uint32 imagewidth;
|
||||
uint32 imagelength;
|
||||
int threshold = 128;
|
||||
|
||||
static void usage(void);
|
||||
|
||||
/*
|
||||
* Floyd-Steinberg error propragation with threshold.
|
||||
* This code is stolen from tiffmedian.
|
||||
*/
|
||||
static void
|
||||
fsdither(TIFF* in, TIFF* out)
|
||||
{
|
||||
unsigned char *outline, *inputline, *inptr;
|
||||
short *thisline, *nextline, *tmpptr;
|
||||
register unsigned char *outptr;
|
||||
register short *thisptr, *nextptr;
|
||||
register uint32 i, j;
|
||||
uint32 imax, jmax;
|
||||
int lastline, lastpixel;
|
||||
int bit;
|
||||
tsize_t outlinesize;
|
||||
|
||||
imax = imagelength - 1;
|
||||
jmax = imagewidth - 1;
|
||||
inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
|
||||
thisline = (short *)_TIFFmalloc(imagewidth * sizeof (short));
|
||||
nextline = (short *)_TIFFmalloc(imagewidth * sizeof (short));
|
||||
outlinesize = TIFFScanlineSize(out);
|
||||
outline = (unsigned char *) _TIFFmalloc(outlinesize);
|
||||
|
||||
/*
|
||||
* Get first line
|
||||
*/
|
||||
if (TIFFReadScanline(in, inputline, 0, 0) <= 0)
|
||||
return;
|
||||
inptr = inputline;
|
||||
nextptr = nextline;
|
||||
for (j = 0; j < imagewidth; ++j)
|
||||
*nextptr++ = *inptr++;
|
||||
for (i = 1; i < imagelength; ++i) {
|
||||
tmpptr = thisline;
|
||||
thisline = nextline;
|
||||
nextline = tmpptr;
|
||||
lastline = (i == imax);
|
||||
if (TIFFReadScanline(in, inputline, i, 0) <= 0)
|
||||
break;
|
||||
inptr = inputline;
|
||||
nextptr = nextline;
|
||||
for (j = 0; j < imagewidth; ++j)
|
||||
*nextptr++ = *inptr++;
|
||||
thisptr = thisline;
|
||||
nextptr = nextline;
|
||||
_TIFFmemset(outptr = outline, 0, outlinesize);
|
||||
bit = 0x80;
|
||||
for (j = 0; j < imagewidth; ++j) {
|
||||
register int v;
|
||||
|
||||
lastpixel = (j == jmax);
|
||||
v = *thisptr++;
|
||||
if (v < 0)
|
||||
v = 0;
|
||||
else if (v > 255)
|
||||
v = 255;
|
||||
if (v > threshold) {
|
||||
*outptr |= bit;
|
||||
v -= 255;
|
||||
}
|
||||
bit >>= 1;
|
||||
if (bit == 0) {
|
||||
outptr++;
|
||||
bit = 0x80;
|
||||
}
|
||||
if (!lastpixel)
|
||||
thisptr[0] += v * 7 / 16;
|
||||
if (!lastline) {
|
||||
if (j != 0)
|
||||
nextptr[-1] += v * 3 / 16;
|
||||
*nextptr++ += v * 5 / 16;
|
||||
if (!lastpixel)
|
||||
nextptr[0] += v / 16;
|
||||
}
|
||||
}
|
||||
if (TIFFWriteScanline(out, outline, i-1, 0) < 0)
|
||||
break;
|
||||
}
|
||||
_TIFFfree(inputline);
|
||||
_TIFFfree(thisline);
|
||||
_TIFFfree(nextline);
|
||||
_TIFFfree(outline);
|
||||
}
|
||||
|
||||
static uint16 compression = COMPRESSION_PACKBITS;
|
||||
static uint16 predictor = 0;
|
||||
static uint32 group3options = 0;
|
||||
|
||||
static void
|
||||
processG3Options(char* cp)
|
||||
{
|
||||
if (cp = strchr(cp, ':')) {
|
||||
do {
|
||||
cp++;
|
||||
if (strneq(cp, "1d", 2))
|
||||
group3options &= ~GROUP3OPT_2DENCODING;
|
||||
else if (strneq(cp, "2d", 2))
|
||||
group3options |= GROUP3OPT_2DENCODING;
|
||||
else if (strneq(cp, "fill", 4))
|
||||
group3options |= GROUP3OPT_FILLBITS;
|
||||
else
|
||||
usage();
|
||||
} while (cp = strchr(cp, ':'));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
processCompressOptions(char* opt)
|
||||
{
|
||||
if (streq(opt, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(opt, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (strneq(opt, "g3", 2)) {
|
||||
processG3Options(opt);
|
||||
compression = COMPRESSION_CCITTFAX3;
|
||||
} else if (streq(opt, "g4"))
|
||||
compression = COMPRESSION_CCITTFAX4;
|
||||
else if (strneq(opt, "lzw", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_LZW;
|
||||
} else if (strneq(opt, "zip", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_DEFLATE;
|
||||
} else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
TIFF *in, *out;
|
||||
uint16 samplesperpixel, bitspersample = 1, shortv;
|
||||
float floatv;
|
||||
char thing[1024];
|
||||
uint32 rowsperstrip = (uint32) -1;
|
||||
int onestrip = 0;
|
||||
uint16 fillorder = 0;
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:f:r:t:")) != -1)
|
||||
switch (c) {
|
||||
case 'c': /* compression scheme */
|
||||
if (!processCompressOptions(optarg))
|
||||
usage();
|
||||
break;
|
||||
case 'f': /* fill order */
|
||||
if (streq(optarg, "lsb2msb"))
|
||||
fillorder = FILLORDER_LSB2MSB;
|
||||
else if (streq(optarg, "msb2lsb"))
|
||||
fillorder = FILLORDER_MSB2LSB;
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
case 'r': /* rows/strip */
|
||||
rowsperstrip = atoi(optarg);
|
||||
onestrip = 0;
|
||||
break;
|
||||
case 't':
|
||||
threshold = atoi(optarg);
|
||||
if (threshold < 0)
|
||||
threshold = 0;
|
||||
else if (threshold > 255)
|
||||
threshold = 255;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind < 2)
|
||||
usage();
|
||||
in = TIFFOpen(argv[optind], "r");
|
||||
if (in == NULL)
|
||||
return (-1);
|
||||
TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
|
||||
if (samplesperpixel != 1) {
|
||||
fprintf(stderr, "%s: Not a b&w image.\n", argv[0]);
|
||||
return (-1);
|
||||
}
|
||||
TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample);
|
||||
if (bitspersample != 8) {
|
||||
fprintf(stderr,
|
||||
" %s: Sorry, only handle 8-bit samples.\n", argv[0]);
|
||||
return (-1);
|
||||
}
|
||||
out = TIFFOpen(argv[optind+1], "w");
|
||||
if (out == NULL)
|
||||
return (-1);
|
||||
CopyField(TIFFTAG_IMAGEWIDTH, imagewidth);
|
||||
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength);
|
||||
TIFFSetField(out, TIFFTAG_IMAGELENGTH, imagelength-1);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
|
||||
TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
|
||||
TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
|
||||
sprintf(thing, "Dithered B&W version of %s", argv[optind]);
|
||||
TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, thing);
|
||||
CopyField(TIFFTAG_ORIENTATION, shortv);
|
||||
CopyField(TIFFTAG_XRESOLUTION, floatv);
|
||||
CopyField(TIFFTAG_YRESOLUTION, floatv);
|
||||
CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
|
||||
if (onestrip)
|
||||
rowsperstrip = imagelength-1;
|
||||
else
|
||||
rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
|
||||
switch (compression) {
|
||||
case COMPRESSION_CCITTFAX3:
|
||||
TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, group3options);
|
||||
break;
|
||||
case COMPRESSION_LZW:
|
||||
case COMPRESSION_DEFLATE:
|
||||
if (predictor)
|
||||
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
|
||||
break;
|
||||
}
|
||||
fsdither(in, out);
|
||||
TIFFClose(in);
|
||||
TIFFClose(out);
|
||||
return (0);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: tiffdither [options] input.tif output.tif",
|
||||
"where options are:",
|
||||
" -r # make each strip have no more than # rows",
|
||||
" -f lsb2msb force lsb-to-msb FillOrder for output",
|
||||
" -f msb2lsb force msb-to-lsb FillOrder for output",
|
||||
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
|
||||
" (no longer supported by default due to Unisys patent enforcement)",
|
||||
" -c zip[:opts] compress output with deflate encoding",
|
||||
" -c packbits compress output with packbits encoding",
|
||||
" -c g3[:opts] compress output with CCITT Group 3 encoding",
|
||||
" -c g4 compress output with CCITT Group 4 encoding",
|
||||
" -c none use no compression algorithm on output",
|
||||
"",
|
||||
"Group 3 options:",
|
||||
" 1d use default CCITT Group 3 1D-encoding",
|
||||
" 2d use optional CCITT Group 3 2D-encoding",
|
||||
" fill byte-align EOL codes",
|
||||
"For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
|
||||
"",
|
||||
"LZW and deflate options:",
|
||||
" # set predictor value",
|
||||
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
Executable
+755
@@ -0,0 +1,755 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/tiffdump.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(VMS)
|
||||
#include <unixio.h>
|
||||
#include <file.h>
|
||||
#elif defined(_WINDOWS)
|
||||
#include <io.h>
|
||||
#define off_t toff_t
|
||||
#include "tiffio.h"
|
||||
#include <fcntl.h>
|
||||
#elif defined(applec)
|
||||
#define open _open_ /* to avoid conflicts */
|
||||
#include <fcntl.h>
|
||||
#undef open
|
||||
int open(const char*, int, int);
|
||||
typedef unsigned int off_t;
|
||||
#else /* !VMS && !_WINDOWS && !applec */
|
||||
#ifdef unix
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#if defined(MSDOS)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
char* appname;
|
||||
char* curfile;
|
||||
int swabflag;
|
||||
int bigendian;
|
||||
int typeshift[13]; /* data type shift counts */
|
||||
long typemask[13]; /* data type masks */
|
||||
int maxitems = 24; /* maximum indirect data items to print */
|
||||
|
||||
char* bytefmt = "%s%#02x"; /* BYTE */
|
||||
char* sbytefmt = "%s%d"; /* SBYTE */
|
||||
char* shortfmt = "%s%u"; /* SHORT */
|
||||
char* sshortfmt = "%s%d"; /* SSHORT */
|
||||
char* longfmt = "%s%lu"; /* LONG */
|
||||
char* slongfmt = "%s%ld"; /* SLONG */
|
||||
char* rationalfmt = "%s%g"; /* RATIONAL */
|
||||
char* srationalfmt = "%s%g"; /* SRATIONAL */
|
||||
char* floatfmt = "%s%g"; /* FLOAT */
|
||||
char* doublefmt = "%s%g"; /* DOUBLE */
|
||||
|
||||
static void dump(int, uint32);
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-h] [-o offset] file.tif ...\n", appname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int one = 1, fd;
|
||||
int multiplefiles = (argc > 1);
|
||||
int c;
|
||||
uint32 diroff = (uint32) 0;
|
||||
bigendian = (*(char *)&one == 0);
|
||||
|
||||
appname = argv[0];
|
||||
while ((c = getopt(argc, argv, "m:o:h")) != -1) {
|
||||
switch (c) {
|
||||
case 'h': /* print values in hex */
|
||||
shortfmt = "%s%#x";
|
||||
sshortfmt = "%s%#x";
|
||||
longfmt = "%s%#lx";
|
||||
slongfmt = "%s%#lx";
|
||||
break;
|
||||
case 'o':
|
||||
diroff = (uint32) strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'm':
|
||||
maxitems = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if (optind >= argc)
|
||||
usage();
|
||||
for (; optind < argc; optind++) {
|
||||
fd = open(argv[optind], O_RDONLY|O_BINARY, 0);
|
||||
if (fd < 0) {
|
||||
perror(argv[0]);
|
||||
return (-1);
|
||||
}
|
||||
if (multiplefiles)
|
||||
printf("%s:\n", argv[optind]);
|
||||
curfile = argv[optind];
|
||||
swabflag = 0;
|
||||
dump(fd, diroff);
|
||||
close(fd);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static TIFFHeader hdr;
|
||||
|
||||
#define ord(e) ((int)e)
|
||||
|
||||
/*
|
||||
* Initialize shift & mask tables and byte
|
||||
* swapping state according to the file
|
||||
* byte order.
|
||||
*/
|
||||
static void
|
||||
InitByteOrder(int magic)
|
||||
{
|
||||
typemask[0] = 0;
|
||||
typemask[ord(TIFF_BYTE)] = 0xff;
|
||||
typemask[ord(TIFF_SBYTE)] = 0xff;
|
||||
typemask[ord(TIFF_UNDEFINED)] = 0xff;
|
||||
typemask[ord(TIFF_SHORT)] = 0xffff;
|
||||
typemask[ord(TIFF_SSHORT)] = 0xffff;
|
||||
typemask[ord(TIFF_LONG)] = 0xffffffff;
|
||||
typemask[ord(TIFF_SLONG)] = 0xffffffff;
|
||||
typemask[ord(TIFF_RATIONAL)] = 0xffffffff;
|
||||
typemask[ord(TIFF_SRATIONAL)] = 0xffffffff;
|
||||
typemask[ord(TIFF_FLOAT)] = 0xffffffff;
|
||||
typemask[ord(TIFF_DOUBLE)] = 0xffffffff;
|
||||
typeshift[0] = 0;
|
||||
typeshift[ord(TIFF_LONG)] = 0;
|
||||
typeshift[ord(TIFF_SLONG)] = 0;
|
||||
typeshift[ord(TIFF_RATIONAL)] = 0;
|
||||
typeshift[ord(TIFF_SRATIONAL)] = 0;
|
||||
typeshift[ord(TIFF_FLOAT)] = 0;
|
||||
typeshift[ord(TIFF_DOUBLE)] = 0;
|
||||
if (magic == TIFF_BIGENDIAN) {
|
||||
typeshift[ord(TIFF_BYTE)] = 24;
|
||||
typeshift[ord(TIFF_SBYTE)] = 24;
|
||||
typeshift[ord(TIFF_SHORT)] = 16;
|
||||
typeshift[ord(TIFF_SSHORT)] = 16;
|
||||
swabflag = !bigendian;
|
||||
} else {
|
||||
typeshift[ord(TIFF_BYTE)] = 0;
|
||||
typeshift[ord(TIFF_SBYTE)] = 0;
|
||||
typeshift[ord(TIFF_SHORT)] = 0;
|
||||
typeshift[ord(TIFF_SSHORT)] = 0;
|
||||
swabflag = bigendian;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 ReadDirectory(int, unsigned, uint32);
|
||||
static void ReadError(char*);
|
||||
static void Error(const char*, ...);
|
||||
static void Fatal(const char*, ...);
|
||||
|
||||
static void
|
||||
dump(int fd, uint32 diroff)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
lseek(fd, (off_t) 0, 0);
|
||||
if (read(fd, (char*) &hdr, sizeof (hdr)) != sizeof (hdr))
|
||||
ReadError("TIFF header");
|
||||
/*
|
||||
* Setup the byte order handling.
|
||||
*/
|
||||
if (hdr.tiff_magic != TIFF_BIGENDIAN && hdr.tiff_magic != TIFF_LITTLEENDIAN)
|
||||
Fatal("Not a TIFF file, bad magic number %u (%#x)",
|
||||
hdr.tiff_magic, hdr.tiff_magic);
|
||||
InitByteOrder(hdr.tiff_magic);
|
||||
/*
|
||||
* Swap header if required.
|
||||
*/
|
||||
if (swabflag) {
|
||||
TIFFSwabShort(&hdr.tiff_version);
|
||||
TIFFSwabLong(&hdr.tiff_diroff);
|
||||
}
|
||||
/*
|
||||
* Now check version (if needed, it's been byte-swapped).
|
||||
* Note that this isn't actually a version number, it's a
|
||||
* magic number that doesn't change (stupid).
|
||||
*/
|
||||
if (hdr.tiff_version != TIFF_VERSION)
|
||||
Fatal("Not a TIFF file, bad version number %u (%#x)",
|
||||
hdr.tiff_version, hdr.tiff_version);
|
||||
printf("Magic: %#x <%s-endian> Version: %#x\n",
|
||||
hdr.tiff_magic,
|
||||
hdr.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
|
||||
hdr.tiff_version);
|
||||
if (diroff == 0)
|
||||
diroff = hdr.tiff_diroff;
|
||||
for (i = 0; diroff != 0; i++) {
|
||||
if (i > 0)
|
||||
putchar('\n');
|
||||
diroff = ReadDirectory(fd, i, diroff);
|
||||
}
|
||||
}
|
||||
|
||||
static int datawidth[] = {
|
||||
0, /* nothing */
|
||||
1, /* TIFF_BYTE */
|
||||
1, /* TIFF_ASCII */
|
||||
2, /* TIFF_SHORT */
|
||||
4, /* TIFF_LONG */
|
||||
8, /* TIFF_RATIONAL */
|
||||
1, /* TIFF_SBYTE */
|
||||
1, /* TIFF_UNDEFINED */
|
||||
2, /* TIFF_SSHORT */
|
||||
4, /* TIFF_SLONG */
|
||||
8, /* TIFF_SRATIONAL */
|
||||
4, /* TIFF_FLOAT */
|
||||
8, /* TIFF_DOUBLE */
|
||||
};
|
||||
#define NWIDTHS (sizeof (datawidth) / sizeof (datawidth[0]))
|
||||
static int TIFFFetchData(int, TIFFDirEntry*, void*);
|
||||
static void PrintTag(FILE*, uint16);
|
||||
static void PrintType(FILE*, uint16);
|
||||
static void PrintData(FILE*, uint16, uint32, unsigned char*);
|
||||
static void PrintByte(FILE*, const char*, TIFFDirEntry*);
|
||||
static void PrintShort(FILE*, const char*, TIFFDirEntry*);
|
||||
static void PrintLong(FILE*, const char*, TIFFDirEntry*);
|
||||
|
||||
/*
|
||||
* Read the next TIFF directory from a file
|
||||
* and convert it to the internal format.
|
||||
* We read directories sequentially.
|
||||
*/
|
||||
static uint32
|
||||
ReadDirectory(int fd, unsigned ix, uint32 off)
|
||||
{
|
||||
register TIFFDirEntry *dp;
|
||||
register int n;
|
||||
TIFFDirEntry *dir = 0;
|
||||
uint16 dircount;
|
||||
int space;
|
||||
uint32 nextdiroff = 0;
|
||||
|
||||
if (off == 0) /* no more directories */
|
||||
goto done;
|
||||
if (lseek(fd, (off_t) off, 0) != off) {
|
||||
Fatal("Seek error accessing TIFF directory");
|
||||
goto done;
|
||||
}
|
||||
if (read(fd, (char*) &dircount, sizeof (uint16)) != sizeof (uint16)) {
|
||||
ReadError("directory count");
|
||||
goto done;
|
||||
}
|
||||
if (swabflag)
|
||||
TIFFSwabShort(&dircount);
|
||||
dir = (TIFFDirEntry *)_TIFFmalloc(dircount * sizeof (TIFFDirEntry));
|
||||
if (dir == NULL) {
|
||||
Fatal("No space for TIFF directory");
|
||||
goto done;
|
||||
}
|
||||
n = read(fd, (char*) dir, dircount*sizeof (*dp));
|
||||
if (n != dircount*sizeof (*dp)) {
|
||||
n /= sizeof (*dp);
|
||||
Error(
|
||||
"Could only read %u of %u entries in directory at offset %#lx",
|
||||
n, dircount, (unsigned long) off);
|
||||
dircount = n;
|
||||
}
|
||||
if (read(fd, (char*) &nextdiroff, sizeof (uint32)) != sizeof (uint32))
|
||||
nextdiroff = 0;
|
||||
if (swabflag)
|
||||
TIFFSwabLong(&nextdiroff);
|
||||
printf("Directory %u: offset %lu (%#lx) next %lu (%#lx)\n", ix,
|
||||
(unsigned long) off, (unsigned long) off,
|
||||
(unsigned long) nextdiroff, (unsigned long) nextdiroff);
|
||||
for (dp = dir, n = dircount; n > 0; n--, dp++) {
|
||||
if (swabflag) {
|
||||
TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
|
||||
TIFFSwabArrayOfLong(&dp->tdir_count, 2);
|
||||
}
|
||||
PrintTag(stdout, dp->tdir_tag);
|
||||
putchar(' ');
|
||||
PrintType(stdout, dp->tdir_type);
|
||||
putchar(' ');
|
||||
printf("%lu<", (unsigned long) dp->tdir_count);
|
||||
if (dp->tdir_type >= NWIDTHS) {
|
||||
printf(">\n");
|
||||
continue;
|
||||
}
|
||||
space = dp->tdir_count * datawidth[dp->tdir_type];
|
||||
if (space <= 4) {
|
||||
switch (dp->tdir_type) {
|
||||
case TIFF_FLOAT:
|
||||
case TIFF_UNDEFINED:
|
||||
case TIFF_ASCII: {
|
||||
unsigned char data[4];
|
||||
_TIFFmemcpy(data, &dp->tdir_offset, 4);
|
||||
if (swabflag)
|
||||
TIFFSwabLong((uint32*) data);
|
||||
PrintData(stdout,
|
||||
dp->tdir_type, dp->tdir_count, data);
|
||||
break;
|
||||
}
|
||||
case TIFF_BYTE:
|
||||
PrintByte(stdout, bytefmt, dp);
|
||||
break;
|
||||
case TIFF_SBYTE:
|
||||
PrintByte(stdout, sbytefmt, dp);
|
||||
break;
|
||||
case TIFF_SHORT:
|
||||
PrintShort(stdout, shortfmt, dp);
|
||||
break;
|
||||
case TIFF_SSHORT:
|
||||
PrintShort(stdout, sshortfmt, dp);
|
||||
break;
|
||||
case TIFF_LONG:
|
||||
PrintLong(stdout, longfmt, dp);
|
||||
break;
|
||||
case TIFF_SLONG:
|
||||
PrintLong(stdout, slongfmt, dp);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
unsigned char *data = (unsigned char *)_TIFFmalloc(space);
|
||||
if (data) {
|
||||
if (TIFFFetchData(fd, dp, data))
|
||||
if (dp->tdir_count > maxitems) {
|
||||
PrintData(stdout, dp->tdir_type,
|
||||
maxitems, data);
|
||||
printf(" ...");
|
||||
} else
|
||||
PrintData(stdout, dp->tdir_type,
|
||||
dp->tdir_count, data);
|
||||
_TIFFfree(data);
|
||||
} else
|
||||
Error("No space for data for tag %u",
|
||||
dp->tdir_tag);
|
||||
}
|
||||
printf(">\n");
|
||||
}
|
||||
done:
|
||||
if (dir)
|
||||
_TIFFfree((char *)dir);
|
||||
return (nextdiroff);
|
||||
}
|
||||
|
||||
static struct tagname {
|
||||
uint16 tag;
|
||||
char* name;
|
||||
} tagnames[] = {
|
||||
{ TIFFTAG_SUBFILETYPE, "SubFileType" },
|
||||
{ TIFFTAG_OSUBFILETYPE, "OldSubFileType" },
|
||||
{ TIFFTAG_IMAGEWIDTH, "ImageWidth" },
|
||||
{ TIFFTAG_IMAGELENGTH, "ImageLength" },
|
||||
{ TIFFTAG_BITSPERSAMPLE, "BitsPerSample" },
|
||||
{ TIFFTAG_COMPRESSION, "Compression" },
|
||||
{ TIFFTAG_PHOTOMETRIC, "Photometric" },
|
||||
{ TIFFTAG_THRESHHOLDING, "Threshholding" },
|
||||
{ TIFFTAG_CELLWIDTH, "CellWidth" },
|
||||
{ TIFFTAG_CELLLENGTH, "CellLength" },
|
||||
{ TIFFTAG_FILLORDER, "FillOrder" },
|
||||
{ TIFFTAG_DOCUMENTNAME, "DocumentName" },
|
||||
{ TIFFTAG_IMAGEDESCRIPTION, "ImageDescription" },
|
||||
{ TIFFTAG_MAKE, "Make" },
|
||||
{ TIFFTAG_MODEL, "Model" },
|
||||
{ TIFFTAG_STRIPOFFSETS, "StripOffsets" },
|
||||
{ TIFFTAG_ORIENTATION, "Orientation" },
|
||||
{ TIFFTAG_SAMPLESPERPIXEL, "SamplesPerPixel" },
|
||||
{ TIFFTAG_ROWSPERSTRIP, "RowsPerStrip" },
|
||||
{ TIFFTAG_STRIPBYTECOUNTS, "StripByteCounts" },
|
||||
{ TIFFTAG_MINSAMPLEVALUE, "MinSampleValue" },
|
||||
{ TIFFTAG_MAXSAMPLEVALUE, "MaxSampleValue" },
|
||||
{ TIFFTAG_XRESOLUTION, "XResolution" },
|
||||
{ TIFFTAG_YRESOLUTION, "YResolution" },
|
||||
{ TIFFTAG_PLANARCONFIG, "PlanarConfig" },
|
||||
{ TIFFTAG_PAGENAME, "PageName" },
|
||||
{ TIFFTAG_XPOSITION, "XPosition" },
|
||||
{ TIFFTAG_YPOSITION, "YPosition" },
|
||||
{ TIFFTAG_FREEOFFSETS, "FreeOffsets" },
|
||||
{ TIFFTAG_FREEBYTECOUNTS, "FreeByteCounts" },
|
||||
{ TIFFTAG_GRAYRESPONSEUNIT, "GrayResponseUnit" },
|
||||
{ TIFFTAG_GRAYRESPONSECURVE,"GrayResponseCurve" },
|
||||
{ TIFFTAG_GROUP3OPTIONS, "Group3Options" },
|
||||
{ TIFFTAG_GROUP4OPTIONS, "Group4Options" },
|
||||
{ TIFFTAG_RESOLUTIONUNIT, "ResolutionUnit" },
|
||||
{ TIFFTAG_PAGENUMBER, "PageNumber" },
|
||||
{ TIFFTAG_COLORRESPONSEUNIT,"ColorResponseUnit" },
|
||||
{ TIFFTAG_TRANSFERFUNCTION, "TransferFunction" },
|
||||
{ TIFFTAG_SOFTWARE, "Software" },
|
||||
{ TIFFTAG_DATETIME, "DateTime" },
|
||||
{ TIFFTAG_ARTIST, "Artist" },
|
||||
{ TIFFTAG_HOSTCOMPUTER, "HostComputer" },
|
||||
{ TIFFTAG_PREDICTOR, "Predictor" },
|
||||
{ TIFFTAG_WHITEPOINT, "Whitepoint" },
|
||||
{ TIFFTAG_PRIMARYCHROMATICITIES,"PrimaryChromaticities" },
|
||||
{ TIFFTAG_COLORMAP, "Colormap" },
|
||||
{ TIFFTAG_HALFTONEHINTS, "HalftoneHints" },
|
||||
{ TIFFTAG_TILEWIDTH, "TileWidth" },
|
||||
{ TIFFTAG_TILELENGTH, "TileLength" },
|
||||
{ TIFFTAG_TILEOFFSETS, "TileOffsets" },
|
||||
{ TIFFTAG_TILEBYTECOUNTS, "TileByteCounts" },
|
||||
{ TIFFTAG_BADFAXLINES, "BadFaxLines" },
|
||||
{ TIFFTAG_CLEANFAXDATA, "CleanFaxData" },
|
||||
{ TIFFTAG_CONSECUTIVEBADFAXLINES, "ConsecutiveBadFaxLines" },
|
||||
{ TIFFTAG_SUBIFD, "SubIFD" },
|
||||
{ TIFFTAG_INKSET, "InkSet" },
|
||||
{ TIFFTAG_INKNAMES, "InkNames" },
|
||||
{ TIFFTAG_NUMBEROFINKS, "NumberOfInks" },
|
||||
{ TIFFTAG_DOTRANGE, "DotRange" },
|
||||
{ TIFFTAG_TARGETPRINTER, "TargetPrinter" },
|
||||
{ TIFFTAG_EXTRASAMPLES, "ExtraSamples" },
|
||||
{ TIFFTAG_SAMPLEFORMAT, "SampleFormat" },
|
||||
{ TIFFTAG_SMINSAMPLEVALUE, "SMinSampleValue" },
|
||||
{ TIFFTAG_SMAXSAMPLEVALUE, "SMaxSampleValue" },
|
||||
{ TIFFTAG_JPEGPROC, "JPEGProcessingMode" },
|
||||
{ TIFFTAG_JPEGIFOFFSET, "JPEGInterchangeFormat" },
|
||||
{ TIFFTAG_JPEGIFBYTECOUNT, "JPEGInterchangeFormatLength" },
|
||||
{ TIFFTAG_JPEGRESTARTINTERVAL,"JPEGRestartInterval" },
|
||||
{ TIFFTAG_JPEGLOSSLESSPREDICTORS,"JPEGLosslessPredictors" },
|
||||
{ TIFFTAG_JPEGPOINTTRANSFORM,"JPEGPointTransform" },
|
||||
{ TIFFTAG_JPEGQTABLES, "JPEGQTables" },
|
||||
{ TIFFTAG_JPEGDCTABLES, "JPEGDCTables" },
|
||||
{ TIFFTAG_JPEGACTABLES, "JPEGACTables" },
|
||||
{ TIFFTAG_YCBCRCOEFFICIENTS,"YCbCrCoefficients" },
|
||||
{ TIFFTAG_YCBCRSUBSAMPLING, "YCbCrSubsampling" },
|
||||
{ TIFFTAG_YCBCRPOSITIONING, "YCbCrPositioning" },
|
||||
{ TIFFTAG_REFERENCEBLACKWHITE, "ReferenceBlackWhite" },
|
||||
{ TIFFTAG_REFPTS, "IgReferencePoints (Island Graphics)" },
|
||||
{ TIFFTAG_REGIONTACKPOINT, "IgRegionTackPoint (Island Graphics)" },
|
||||
{ TIFFTAG_REGIONWARPCORNERS,"IgRegionWarpCorners (Island Graphics)" },
|
||||
{ TIFFTAG_REGIONAFFINE, "IgRegionAffine (Island Graphics)" },
|
||||
{ TIFFTAG_MATTEING, "OBSOLETE Matteing (Silicon Graphics)" },
|
||||
{ TIFFTAG_DATATYPE, "OBSOLETE DataType (Silicon Graphics)" },
|
||||
{ TIFFTAG_IMAGEDEPTH, "ImageDepth (Silicon Graphics)" },
|
||||
{ TIFFTAG_TILEDEPTH, "TileDepth (Silicon Graphics)" },
|
||||
{ 32768, "OLD BOGUS Matteing tag" },
|
||||
{ TIFFTAG_COPYRIGHT, "Copyright" },
|
||||
{ TIFFTAG_ICCPROFILE, "ICC Profile" },
|
||||
{ TIFFTAG_JBIGOPTIONS, "JBIG Options" },
|
||||
{ TIFFTAG_STONITS, "StoNits" },
|
||||
};
|
||||
#define NTAGS (sizeof (tagnames) / sizeof (tagnames[0]))
|
||||
|
||||
static void
|
||||
PrintTag(FILE* fd, uint16 tag)
|
||||
{
|
||||
register struct tagname *tp;
|
||||
|
||||
for (tp = tagnames; tp < &tagnames[NTAGS]; tp++)
|
||||
if (tp->tag == tag) {
|
||||
fprintf(fd, "%s (%u)", tp->name, tag);
|
||||
return;
|
||||
}
|
||||
fprintf(fd, "%u (%#x)", tag, tag);
|
||||
}
|
||||
|
||||
static void
|
||||
PrintType(FILE* fd, uint16 type)
|
||||
{
|
||||
static char *typenames[] = {
|
||||
"0",
|
||||
"BYTE",
|
||||
"ASCII",
|
||||
"SHORT",
|
||||
"LONG",
|
||||
"RATIONAL",
|
||||
"SBYTE",
|
||||
"UNDEFINED",
|
||||
"SSHORT",
|
||||
"SLONG",
|
||||
"SRATIONAL",
|
||||
"FLOAT",
|
||||
"DOUBLE"
|
||||
};
|
||||
#define NTYPES (sizeof (typenames) / sizeof (typenames[0]))
|
||||
|
||||
if (type < NTYPES)
|
||||
fprintf(fd, "%s (%u)", typenames[type], type);
|
||||
else
|
||||
fprintf(fd, "%u (%#x)", type, type);
|
||||
}
|
||||
#undef NTYPES
|
||||
|
||||
static void
|
||||
PrintByte(FILE* fd, const char* fmt, TIFFDirEntry* dp)
|
||||
{
|
||||
char* sep = "";
|
||||
|
||||
if (hdr.tiff_magic != TIFF_LITTLEENDIAN) {
|
||||
switch ((int)dp->tdir_count) {
|
||||
case 4: fprintf(fd, fmt, sep, dp->tdir_offset&0xff);
|
||||
sep = " ";
|
||||
case 3: fprintf(fd, fmt, sep, (dp->tdir_offset>>8)&0xff);
|
||||
sep = " ";
|
||||
case 2: fprintf(fd, fmt, sep, (dp->tdir_offset>>16)&0xff);
|
||||
sep = " ";
|
||||
case 1: fprintf(fd, fmt, sep, dp->tdir_offset>>24);
|
||||
}
|
||||
} else {
|
||||
switch ((int)dp->tdir_count) {
|
||||
case 4: fprintf(fd, fmt, sep, dp->tdir_offset>>24);
|
||||
sep = " ";
|
||||
case 3: fprintf(fd, fmt, sep, (dp->tdir_offset>>16)&0xff);
|
||||
sep = " ";
|
||||
case 2: fprintf(fd, fmt, sep, (dp->tdir_offset>>8)&0xff);
|
||||
sep = " ";
|
||||
case 1: fprintf(fd, fmt, sep, dp->tdir_offset&0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PrintShort(FILE* fd, const char* fmt, TIFFDirEntry* dp)
|
||||
{
|
||||
char *sep = "";
|
||||
|
||||
if (hdr.tiff_magic != TIFF_LITTLEENDIAN) {
|
||||
switch (dp->tdir_count) {
|
||||
case 2: fprintf(fd, fmt, sep, dp->tdir_offset&0xffff);
|
||||
sep = " ";
|
||||
case 1: fprintf(fd, fmt, sep, dp->tdir_offset>>16);
|
||||
}
|
||||
} else {
|
||||
switch (dp->tdir_count) {
|
||||
case 2: fprintf(fd, fmt, sep, dp->tdir_offset>>16);
|
||||
sep = " ";
|
||||
case 1: fprintf(fd, fmt, sep, dp->tdir_offset&0xffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PrintLong(FILE* fd, const char* fmt, TIFFDirEntry* dp)
|
||||
{
|
||||
fprintf(fd, fmt, "", (long) dp->tdir_offset);
|
||||
}
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
static void
|
||||
PrintASCII(FILE* fd, uint32 cc, const unsigned char* cp)
|
||||
{
|
||||
for (; cc > 0; cc--, cp++) {
|
||||
const char* tp;
|
||||
|
||||
if (isprint(*cp)) {
|
||||
fputc(*cp, fd);
|
||||
continue;
|
||||
}
|
||||
for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++)
|
||||
if (*tp++ == *cp)
|
||||
break;
|
||||
if (*tp)
|
||||
fprintf(fd, "\\%c", *tp);
|
||||
else if (*cp)
|
||||
fprintf(fd, "\\%03o", *cp);
|
||||
else
|
||||
fprintf(fd, "\\0");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PrintData(FILE* fd, uint16 type, uint32 count, unsigned char* data)
|
||||
{
|
||||
char* sep = "";
|
||||
|
||||
switch (type) {
|
||||
case TIFF_BYTE:
|
||||
while (count-- > 0)
|
||||
fprintf(fd, bytefmt, sep, *data++), sep = " ";
|
||||
break;
|
||||
case TIFF_SBYTE:
|
||||
while (count-- > 0)
|
||||
fprintf(fd, sbytefmt, sep, *(char *)data++), sep = " ";
|
||||
break;
|
||||
case TIFF_UNDEFINED:
|
||||
while (count-- > 0)
|
||||
fprintf(fd, bytefmt, sep, *data++), sep = " ";
|
||||
break;
|
||||
case TIFF_ASCII:
|
||||
PrintASCII(fd, count, data);
|
||||
break;
|
||||
case TIFF_SHORT: {
|
||||
register uint16 *wp = (uint16*)data;
|
||||
while (count-- > 0)
|
||||
fprintf(fd, shortfmt, sep, *wp++), sep = " ";
|
||||
break;
|
||||
}
|
||||
case TIFF_SSHORT: {
|
||||
register int16 *wp = (int16*)data;
|
||||
while (count-- > 0)
|
||||
fprintf(fd, sshortfmt, sep, *wp++), sep = " ";
|
||||
break;
|
||||
}
|
||||
case TIFF_LONG: {
|
||||
register uint32 *lp = (uint32*)data;
|
||||
while (count-- > 0) {
|
||||
fprintf(fd, longfmt, sep, (unsigned long) *lp++);
|
||||
sep = " ";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TIFF_SLONG: {
|
||||
register int32 *lp = (int32*)data;
|
||||
while (count-- > 0)
|
||||
fprintf(fd, slongfmt, sep, (long) *lp++), sep = " ";
|
||||
break;
|
||||
}
|
||||
case TIFF_RATIONAL: {
|
||||
register uint32 *lp = (uint32*)data;
|
||||
while (count-- > 0) {
|
||||
if (lp[1] == 0)
|
||||
fprintf(fd, "%sNan (%lu/%lu)", sep,
|
||||
(unsigned long) lp[0],
|
||||
(unsigned long) lp[1]);
|
||||
else
|
||||
fprintf(fd, rationalfmt, sep,
|
||||
(double)lp[0] / (double)lp[1]);
|
||||
sep = " ";
|
||||
lp += 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TIFF_SRATIONAL: {
|
||||
register int32 *lp = (int32*)data;
|
||||
while (count-- > 0) {
|
||||
if (lp[1] == 0)
|
||||
fprintf(fd, "%sNan (%ld/%ld)", sep,
|
||||
(long) lp[0], (long) lp[1]);
|
||||
else
|
||||
fprintf(fd, srationalfmt, sep,
|
||||
(double)lp[0] / (double)lp[1]);
|
||||
sep = " ";
|
||||
lp += 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TIFF_FLOAT: {
|
||||
register float *fp = (float *)data;
|
||||
while (count-- > 0)
|
||||
fprintf(fd, floatfmt, sep, *fp++), sep = " ";
|
||||
break;
|
||||
}
|
||||
case TIFF_DOUBLE: {
|
||||
register double *dp = (double *)data;
|
||||
while (count-- > 0)
|
||||
fprintf(fd, doublefmt, sep, *dp++), sep = " ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch a contiguous directory item.
|
||||
*/
|
||||
static int
|
||||
TIFFFetchData(int fd, TIFFDirEntry* dir, void* cp)
|
||||
{
|
||||
int cc, w;
|
||||
|
||||
w = (dir->tdir_type < NWIDTHS ? datawidth[dir->tdir_type] : 0);
|
||||
cc = dir->tdir_count * w;
|
||||
if (lseek(fd, (off_t) dir->tdir_offset, 0) == dir->tdir_offset &&
|
||||
read(fd, cp, cc) == cc) {
|
||||
if (swabflag) {
|
||||
switch (dir->tdir_type) {
|
||||
case TIFF_SHORT:
|
||||
case TIFF_SSHORT:
|
||||
TIFFSwabArrayOfShort((uint16*) cp,
|
||||
dir->tdir_count);
|
||||
break;
|
||||
case TIFF_LONG:
|
||||
case TIFF_SLONG:
|
||||
case TIFF_FLOAT:
|
||||
TIFFSwabArrayOfLong((uint32*) cp,
|
||||
dir->tdir_count);
|
||||
break;
|
||||
case TIFF_RATIONAL:
|
||||
TIFFSwabArrayOfLong((uint32*) cp,
|
||||
2*dir->tdir_count);
|
||||
break;
|
||||
case TIFF_DOUBLE:
|
||||
TIFFSwabArrayOfDouble((double*) cp,
|
||||
dir->tdir_count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (cc);
|
||||
}
|
||||
Error("Error while reading data for tag %u", dir->tdir_tag);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ReadError(char* what)
|
||||
{
|
||||
Fatal("Error while reading %s", what);
|
||||
}
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static void
|
||||
vError(FILE* fd, const char* fmt, va_list ap)
|
||||
{
|
||||
fprintf(fd, "%s: ", curfile);
|
||||
vfprintf(fd, fmt, ap);
|
||||
fprintf(fd, ".\n");
|
||||
}
|
||||
|
||||
static void
|
||||
Error(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vError(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void
|
||||
Fatal(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vError(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(-1);
|
||||
}
|
||||
Executable
+429
@@ -0,0 +1,429 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/tiffinfo.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
|
||||
int showdata = 0; /* show data */
|
||||
int rawdata = 0; /* show raw/decoded data */
|
||||
int showwords = 0; /* show data as bytes/words */
|
||||
int readdata = 0; /* read data in file */
|
||||
int stoponerr = 1; /* stop on first read error */
|
||||
|
||||
static void usage(void);
|
||||
static void tiffinfo(TIFF*, uint16, long);
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int dirnum = -1, multiplefiles, c;
|
||||
uint16 order = 0;
|
||||
TIFF* tif;
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
long flags = 0;
|
||||
uint32 diroff = 0;
|
||||
int chopstrips = 0; /* disable strip chopping */
|
||||
|
||||
while ((c = getopt(argc, argv, "f:o:cdDSjlmrsvwz0123456789")) != -1)
|
||||
switch (c) {
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
case '8': case '9':
|
||||
dirnum = atoi(&argv[optind-1][1]);
|
||||
break;
|
||||
case 'd':
|
||||
showdata++;
|
||||
/* fall thru... */
|
||||
case 'D':
|
||||
readdata++;
|
||||
break;
|
||||
case 'c':
|
||||
flags |= TIFFPRINT_COLORMAP | TIFFPRINT_CURVES;
|
||||
break;
|
||||
case 'f': /* fill order */
|
||||
if (streq(optarg, "lsb2msb"))
|
||||
order = FILLORDER_LSB2MSB;
|
||||
else if (streq(optarg, "msb2lsb"))
|
||||
order = FILLORDER_MSB2LSB;
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
case 'i':
|
||||
stoponerr = 0;
|
||||
break;
|
||||
case 'o':
|
||||
diroff = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'j':
|
||||
flags |= TIFFPRINT_JPEGQTABLES |
|
||||
TIFFPRINT_JPEGACTABLES |
|
||||
TIFFPRINT_JPEGDCTABLES;
|
||||
break;
|
||||
case 'r':
|
||||
rawdata = 1;
|
||||
break;
|
||||
case 's':
|
||||
flags |= TIFFPRINT_STRIPS;
|
||||
break;
|
||||
case 'w':
|
||||
showwords = 1;
|
||||
break;
|
||||
case 'z':
|
||||
chopstrips = 1;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (optind >= argc)
|
||||
usage();
|
||||
multiplefiles = (argc - optind > 1);
|
||||
for (; optind < argc; optind++) {
|
||||
if (multiplefiles)
|
||||
printf("%s:\n", argv[optind]);
|
||||
tif = TIFFOpen(argv[optind], chopstrips ? "rC" : "rc");
|
||||
if (tif != NULL) {
|
||||
if (dirnum != -1) {
|
||||
if (TIFFSetDirectory(tif, dirnum))
|
||||
tiffinfo(tif, order, flags);
|
||||
} else if (diroff != 0) {
|
||||
if (TIFFSetSubDirectory(tif, diroff))
|
||||
tiffinfo(tif, order, flags);
|
||||
} else {
|
||||
do
|
||||
tiffinfo(tif, order, flags);
|
||||
while (TIFFReadDirectory(tif));
|
||||
}
|
||||
TIFFClose(tif);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: tiffinfo [options] input...",
|
||||
"where options are:",
|
||||
" -D read data",
|
||||
" -i ignore read errors",
|
||||
" -c display data for grey/color response curve or colormap",
|
||||
" -d display raw/decoded image data",
|
||||
" -f lsb2msb force lsb-to-msb FillOrder for input",
|
||||
" -f msb2lsb force msb-to-lsb FillOrder for input",
|
||||
" -j show JPEG tables",
|
||||
" -o offset set initial directory offset",
|
||||
" -r read/display raw image data instead of decoded data",
|
||||
" -s display strip offsets and byte counts",
|
||||
" -w display raw data in words rather than bytes",
|
||||
" -z enable strip chopping",
|
||||
" -# set initial directory (first directory is # 0)",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static void
|
||||
ShowStrip(tstrip_t strip, unsigned char* pp, uint32 nrow, tsize_t scanline)
|
||||
{
|
||||
register tsize_t cc;
|
||||
|
||||
printf("Strip %lu:\n", (unsigned long) strip);
|
||||
while (nrow-- > 0) {
|
||||
for (cc = 0; cc < scanline; cc++) {
|
||||
printf(" %02x", *pp++);
|
||||
if (((cc+1) % 24) == 0)
|
||||
putchar('\n');
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TIFFReadContigStripData(TIFF* tif)
|
||||
{
|
||||
unsigned char *buf;
|
||||
tsize_t scanline = TIFFScanlineSize(tif);
|
||||
|
||||
buf = (unsigned char *)_TIFFmalloc(TIFFStripSize(tif));
|
||||
if (buf) {
|
||||
uint32 row, h;
|
||||
uint32 rowsperstrip = (uint32)-1;
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
|
||||
TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
|
||||
for (row = 0; row < h; row += rowsperstrip) {
|
||||
uint32 nrow = (row+rowsperstrip > h ?
|
||||
h-row : rowsperstrip);
|
||||
tstrip_t strip = TIFFComputeStrip(tif, row, 0);
|
||||
if (TIFFReadEncodedStrip(tif, strip, buf, nrow*scanline) < 0) {
|
||||
if (stoponerr)
|
||||
break;
|
||||
} else if (showdata)
|
||||
ShowStrip(strip, buf, nrow, scanline);
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TIFFReadSeparateStripData(TIFF* tif)
|
||||
{
|
||||
unsigned char *buf;
|
||||
tsize_t scanline = TIFFScanlineSize(tif);
|
||||
|
||||
buf = (unsigned char *)_TIFFmalloc(TIFFStripSize(tif));
|
||||
if (buf) {
|
||||
uint32 row, h;
|
||||
uint32 rowsperstrip = (uint32)-1;
|
||||
tsample_t s, samplesperpixel;
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
|
||||
TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
|
||||
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
|
||||
for (row = 0; row < h; row += rowsperstrip) {
|
||||
for (s = 0; s < samplesperpixel; s++) {
|
||||
uint32 nrow = (row+rowsperstrip > h ?
|
||||
h-row : rowsperstrip);
|
||||
tstrip_t strip = TIFFComputeStrip(tif, row, s);
|
||||
if (TIFFReadEncodedStrip(tif, strip, buf, nrow*scanline) < 0) {
|
||||
if (stoponerr)
|
||||
break;
|
||||
} else if (showdata)
|
||||
ShowStrip(strip, buf, nrow, scanline);
|
||||
}
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ShowTile(uint32 row, uint32 col, tsample_t sample,
|
||||
unsigned char* pp, uint32 nrow, uint32 rowsize)
|
||||
{
|
||||
register tsize_t cc;
|
||||
|
||||
printf("Tile (%lu,%lu", (unsigned long) row, (unsigned long) col);
|
||||
if (sample != (tsample_t) -1)
|
||||
printf(",%u", sample);
|
||||
printf("):\n");
|
||||
while (nrow-- > 0) {
|
||||
for (cc = 0; cc < rowsize; cc++) {
|
||||
printf(" %02x", *pp++);
|
||||
if (((cc+1) % 24) == 0)
|
||||
putchar('\n');
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TIFFReadContigTileData(TIFF* tif)
|
||||
{
|
||||
unsigned char *buf;
|
||||
tsize_t rowsize = TIFFTileRowSize(tif);
|
||||
|
||||
buf = (unsigned char *)_TIFFmalloc(TIFFTileSize(tif));
|
||||
if (buf) {
|
||||
uint32 tw, th, w, h;
|
||||
uint32 row, col;
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
|
||||
TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
|
||||
TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
|
||||
for (row = 0; row < h; row += th) {
|
||||
for (col = 0; col < w; col += tw) {
|
||||
if (TIFFReadTile(tif, buf, col, row, 0, 0) < 0) {
|
||||
if (stoponerr)
|
||||
break;
|
||||
} else if (showdata)
|
||||
ShowTile(row, col, (tsample_t) -1, buf, th, rowsize);
|
||||
}
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TIFFReadSeparateTileData(TIFF* tif)
|
||||
{
|
||||
unsigned char *buf;
|
||||
tsize_t rowsize = TIFFTileRowSize(tif);
|
||||
|
||||
buf = (unsigned char *)_TIFFmalloc(TIFFTileSize(tif));
|
||||
if (buf) {
|
||||
uint32 tw, th, w, h;
|
||||
uint32 row, col;
|
||||
tsample_t s, samplesperpixel;
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
|
||||
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
|
||||
TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
|
||||
TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
|
||||
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
|
||||
for (row = 0; row < h; row += th) {
|
||||
for (col = 0; col < w; col += tw) {
|
||||
for (s = 0; s < samplesperpixel; s++) {
|
||||
if (TIFFReadTile(tif, buf, col, row, 0, s) < 0) {
|
||||
if (stoponerr)
|
||||
break;
|
||||
} else if (showdata)
|
||||
ShowTile(row, col, s, buf, th, rowsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TIFFReadData(TIFF* tif)
|
||||
{
|
||||
uint16 config;
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &config);
|
||||
if (TIFFIsTiled(tif)) {
|
||||
if (config == PLANARCONFIG_CONTIG)
|
||||
TIFFReadContigTileData(tif);
|
||||
else
|
||||
TIFFReadSeparateTileData(tif);
|
||||
} else {
|
||||
if (config == PLANARCONFIG_CONTIG)
|
||||
TIFFReadContigStripData(tif);
|
||||
else
|
||||
TIFFReadSeparateStripData(tif);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ShowRawBytes(unsigned char* pp, uint32 n)
|
||||
{
|
||||
tsize_t i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
printf(" %02x", *pp++);
|
||||
if (((i+1) % 24) == 0)
|
||||
printf("\n ");
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void
|
||||
ShowRawWords(uint16* pp, uint32 n)
|
||||
{
|
||||
tsize_t i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
printf(" %04x", *pp++);
|
||||
if (((i+1) % 15) == 0)
|
||||
printf("\n ");
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void
|
||||
TIFFReadRawData(TIFF* tif, int bitrev)
|
||||
{
|
||||
tstrip_t nstrips = TIFFNumberOfStrips(tif);
|
||||
const char* what = TIFFIsTiled(tif) ? "Tile" : "Strip";
|
||||
uint32* stripbc;
|
||||
|
||||
TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbc);
|
||||
if (nstrips > 0) {
|
||||
tsize_t bufsize = stripbc[0];
|
||||
tdata_t buf = _TIFFmalloc(bufsize);
|
||||
tstrip_t s;
|
||||
|
||||
for (s = 0; s < nstrips; s++) {
|
||||
if (stripbc[s] > bufsize) {
|
||||
buf = _TIFFrealloc(buf, stripbc[s]);
|
||||
bufsize = stripbc[s];
|
||||
}
|
||||
if (buf == NULL) {
|
||||
fprintf(stderr,
|
||||
"Cannot allocate buffer to read strip %lu\n",
|
||||
(unsigned long) s);
|
||||
break;
|
||||
}
|
||||
if (TIFFReadRawStrip(tif, s, buf, stripbc[s]) < 0) {
|
||||
fprintf(stderr, "Error reading strip %lu\n",
|
||||
(unsigned long) s);
|
||||
if (stoponerr)
|
||||
break;
|
||||
} else if (showdata) {
|
||||
if (bitrev) {
|
||||
TIFFReverseBits(buf, stripbc[s]);
|
||||
printf("%s %lu: (bit reversed)\n ",
|
||||
what, (unsigned long) s);
|
||||
} else
|
||||
printf("%s %lu:\n ", what,
|
||||
(unsigned long) s);
|
||||
if (showwords)
|
||||
ShowRawWords((uint16*) buf, stripbc[s]>>1);
|
||||
else
|
||||
ShowRawBytes((unsigned char*) buf, stripbc[s]);
|
||||
}
|
||||
}
|
||||
if (buf != NULL)
|
||||
_TIFFfree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tiffinfo(TIFF* tif, uint16 order, long flags)
|
||||
{
|
||||
TIFFPrintDirectory(tif, stdout, flags);
|
||||
if (!readdata)
|
||||
return;
|
||||
if (rawdata) {
|
||||
if (order) {
|
||||
uint16 o;
|
||||
TIFFGetFieldDefaulted(tif,
|
||||
TIFFTAG_FILLORDER, &o);
|
||||
TIFFReadRawData(tif, o != order);
|
||||
} else
|
||||
TIFFReadRawData(tif, 0);
|
||||
} else {
|
||||
if (order)
|
||||
TIFFSetField(tif, TIFFTAG_FILLORDER, order);
|
||||
TIFFReadData(tif);
|
||||
}
|
||||
}
|
||||
Executable
+890
@@ -0,0 +1,890 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/tiffmedian.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Apply median cut on an image.
|
||||
*
|
||||
* tiffmedian [-c n] [-f] input output
|
||||
* -C n - set colortable size. Default is 256.
|
||||
* -f - use Floyd-Steinberg dithering.
|
||||
* -c lzw - compress output with LZW
|
||||
* (no longer supported by default due to unisys patent enforcement)
|
||||
* -c none - use no compression on output
|
||||
* -c packbits - use packbits compression on output
|
||||
* -r n - create output with n rows/strip of data
|
||||
* (by default the compression scheme and rows/strip are taken
|
||||
* from the input file)
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* [1] Floyd-Steinberg dither:
|
||||
* I should point out that the actual fractions we used were, assuming
|
||||
* you are at X, moving left to right:
|
||||
*
|
||||
* X 7/16
|
||||
* 3/16 5/16 1/16
|
||||
*
|
||||
* Note that the error goes to four neighbors, not three. I think this
|
||||
* will probably do better (at least for black and white) than the
|
||||
* 3/8-3/8-1/4 distribution, at the cost of greater processing. I have
|
||||
* seen the 3/8-3/8-1/4 distribution described as "our" algorithm before,
|
||||
* but I have no idea who the credit really belongs to.
|
||||
|
||||
* Also, I should add that if you do zig-zag scanning (see my immediately
|
||||
* previous message), it is sufficient (but not quite as good) to send
|
||||
* half the error one pixel ahead (e.g. to the right on lines you scan
|
||||
* left to right), and half one pixel straight down. Again, this is for
|
||||
* black and white; I've not tried it with color.
|
||||
* --
|
||||
* Lou Steinberg
|
||||
*
|
||||
* [2] Color Image Quantization for Frame Buffer Display, Paul Heckbert,
|
||||
* Siggraph '82 proceedings, pp. 297-307
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#define MAX_CMAP_SIZE 256
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define strneq(a,b,n) (strncmp(a,b,n) == 0)
|
||||
|
||||
#define COLOR_DEPTH 8
|
||||
#define MAX_COLOR 256
|
||||
|
||||
#define B_DEPTH 5 /* # bits/pixel to use */
|
||||
#define B_LEN (1L<<B_DEPTH)
|
||||
|
||||
#define C_DEPTH 2
|
||||
#define C_LEN (1L<<C_DEPTH) /* # cells/color to use */
|
||||
|
||||
#define COLOR_SHIFT (COLOR_DEPTH-B_DEPTH)
|
||||
|
||||
typedef struct colorbox {
|
||||
struct colorbox *next, *prev;
|
||||
int rmin, rmax;
|
||||
int gmin, gmax;
|
||||
int bmin, bmax;
|
||||
int total;
|
||||
} Colorbox;
|
||||
|
||||
typedef struct {
|
||||
int num_ents;
|
||||
int entries[MAX_CMAP_SIZE][2];
|
||||
} C_cell;
|
||||
|
||||
uint16 rm[MAX_CMAP_SIZE], gm[MAX_CMAP_SIZE], bm[MAX_CMAP_SIZE];
|
||||
int bytes_per_pixel;
|
||||
int num_colors;
|
||||
int histogram[B_LEN][B_LEN][B_LEN];
|
||||
Colorbox *freeboxes;
|
||||
Colorbox *usedboxes;
|
||||
C_cell **ColorCells;
|
||||
TIFF *in, *out;
|
||||
uint32 rowsperstrip = (uint32) -1;
|
||||
uint16 compression = (uint16) -1;
|
||||
uint16 bitspersample = 1;
|
||||
uint16 samplesperpixel;
|
||||
uint32 imagewidth;
|
||||
uint32 imagelength;
|
||||
uint16 predictor = 0;
|
||||
|
||||
static void get_histogram(TIFF*, Colorbox*);
|
||||
static void splitbox(Colorbox*);
|
||||
static void shrinkbox(Colorbox*);
|
||||
static void map_colortable(void);
|
||||
static void quant(TIFF*, TIFF*);
|
||||
static void quant_fsdither(TIFF*, TIFF*);
|
||||
static Colorbox* largest_box(void);
|
||||
|
||||
static void usage(void);
|
||||
static int processCompressOptions(char*);
|
||||
|
||||
#define CopyField(tag, v) \
|
||||
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
int i, dither = 0;
|
||||
uint16 shortv, config, photometric;
|
||||
Colorbox *box_list, *ptr;
|
||||
float floatv;
|
||||
uint32 longv;
|
||||
int c;
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
|
||||
num_colors = MAX_CMAP_SIZE;
|
||||
while ((c = getopt(argc, argv, "c:C:r:f")) != -1)
|
||||
switch (c) {
|
||||
case 'c': /* compression scheme */
|
||||
if (!processCompressOptions(optarg))
|
||||
usage();
|
||||
break;
|
||||
case 'C': /* set colormap size */
|
||||
num_colors = atoi(optarg);
|
||||
if (num_colors > MAX_CMAP_SIZE) {
|
||||
fprintf(stderr,
|
||||
"-c: colormap too big, max %d\n",
|
||||
MAX_CMAP_SIZE);
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
case 'f': /* dither */
|
||||
dither = 1;
|
||||
break;
|
||||
case 'r': /* rows/strip */
|
||||
rowsperstrip = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if (argc - optind != 2)
|
||||
usage();
|
||||
in = TIFFOpen(argv[optind], "r");
|
||||
if (in == NULL)
|
||||
return (-1);
|
||||
TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &imagewidth);
|
||||
TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength);
|
||||
TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample);
|
||||
TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
|
||||
if (bitspersample != 8 && bitspersample != 16) {
|
||||
fprintf(stderr, "%s: Image must have at least 8-bits/sample\n",
|
||||
argv[optind]);
|
||||
return (-3);
|
||||
}
|
||||
if (!TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric) ||
|
||||
photometric != PHOTOMETRIC_RGB || samplesperpixel < 3) {
|
||||
fprintf(stderr, "%s: Image must have RGB data\n", argv[optind]);
|
||||
return (-4);
|
||||
}
|
||||
TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config);
|
||||
if (config != PLANARCONFIG_CONTIG) {
|
||||
fprintf(stderr, "%s: Can only handle contiguous data packing\n",
|
||||
argv[optind]);
|
||||
return (-5);
|
||||
}
|
||||
|
||||
/*
|
||||
* STEP 1: create empty boxes
|
||||
*/
|
||||
usedboxes = NULL;
|
||||
box_list = freeboxes = (Colorbox *)_TIFFmalloc(num_colors*sizeof (Colorbox));
|
||||
freeboxes[0].next = &freeboxes[1];
|
||||
freeboxes[0].prev = NULL;
|
||||
for (i = 1; i < num_colors-1; ++i) {
|
||||
freeboxes[i].next = &freeboxes[i+1];
|
||||
freeboxes[i].prev = &freeboxes[i-1];
|
||||
}
|
||||
freeboxes[num_colors-1].next = NULL;
|
||||
freeboxes[num_colors-1].prev = &freeboxes[num_colors-2];
|
||||
|
||||
/*
|
||||
* STEP 2: get histogram, initialize first box
|
||||
*/
|
||||
ptr = freeboxes;
|
||||
freeboxes = ptr->next;
|
||||
if (freeboxes)
|
||||
freeboxes->prev = NULL;
|
||||
ptr->next = usedboxes;
|
||||
usedboxes = ptr;
|
||||
if (ptr->next)
|
||||
ptr->next->prev = ptr;
|
||||
get_histogram(in, ptr);
|
||||
|
||||
/*
|
||||
* STEP 3: continually subdivide boxes until no more free
|
||||
* boxes remain or until all colors assigned.
|
||||
*/
|
||||
while (freeboxes != NULL) {
|
||||
ptr = largest_box();
|
||||
if (ptr != NULL)
|
||||
splitbox(ptr);
|
||||
else
|
||||
freeboxes = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* STEP 4: assign colors to all boxes
|
||||
*/
|
||||
for (i = 0, ptr = usedboxes; ptr != NULL; ++i, ptr = ptr->next) {
|
||||
rm[i] = ((ptr->rmin + ptr->rmax) << COLOR_SHIFT) / 2;
|
||||
gm[i] = ((ptr->gmin + ptr->gmax) << COLOR_SHIFT) / 2;
|
||||
bm[i] = ((ptr->bmin + ptr->bmax) << COLOR_SHIFT) / 2;
|
||||
}
|
||||
|
||||
/* We're done with the boxes now */
|
||||
_TIFFfree(box_list);
|
||||
freeboxes = usedboxes = NULL;
|
||||
|
||||
/*
|
||||
* STEP 5: scan histogram and map all values to closest color
|
||||
*/
|
||||
/* 5a: create cell list as described in Heckbert[2] */
|
||||
ColorCells = (C_cell **)_TIFFmalloc(C_LEN*C_LEN*C_LEN*sizeof (C_cell*));
|
||||
_TIFFmemset(ColorCells, 0, C_LEN*C_LEN*C_LEN*sizeof (C_cell*));
|
||||
/* 5b: create mapping from truncated pixel space to color
|
||||
table entries */
|
||||
map_colortable();
|
||||
|
||||
/*
|
||||
* STEP 6: scan image, match input values to table entries
|
||||
*/
|
||||
out = TIFFOpen(argv[optind+1], "w");
|
||||
if (out == NULL)
|
||||
return (-2);
|
||||
|
||||
CopyField(TIFFTAG_SUBFILETYPE, longv);
|
||||
CopyField(TIFFTAG_IMAGEWIDTH, longv);
|
||||
TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, (short)COLOR_DEPTH);
|
||||
if (compression != (uint16)-1) {
|
||||
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
|
||||
switch (compression) {
|
||||
case COMPRESSION_LZW:
|
||||
case COMPRESSION_DEFLATE:
|
||||
if (predictor != 0)
|
||||
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
CopyField(TIFFTAG_COMPRESSION, compression);
|
||||
TIFFSetField(out, TIFFTAG_PHOTOMETRIC, (short)PHOTOMETRIC_PALETTE);
|
||||
CopyField(TIFFTAG_ORIENTATION, shortv);
|
||||
TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, (short)1);
|
||||
CopyField(TIFFTAG_PLANARCONFIG, shortv);
|
||||
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
|
||||
TIFFDefaultStripSize(out, rowsperstrip));
|
||||
CopyField(TIFFTAG_MINSAMPLEVALUE, shortv);
|
||||
CopyField(TIFFTAG_MAXSAMPLEVALUE, shortv);
|
||||
CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
|
||||
CopyField(TIFFTAG_XRESOLUTION, floatv);
|
||||
CopyField(TIFFTAG_YRESOLUTION, floatv);
|
||||
CopyField(TIFFTAG_XPOSITION, floatv);
|
||||
CopyField(TIFFTAG_YPOSITION, floatv);
|
||||
|
||||
if (dither)
|
||||
quant_fsdither(in, out);
|
||||
else
|
||||
quant(in, out);
|
||||
/*
|
||||
* Scale colormap to TIFF-required 16-bit values.
|
||||
*/
|
||||
#define SCALE(x) (((x)*((1L<<16)-1))/255)
|
||||
for (i = 0; i < MAX_CMAP_SIZE; ++i) {
|
||||
rm[i] = SCALE(rm[i]);
|
||||
gm[i] = SCALE(gm[i]);
|
||||
bm[i] = SCALE(bm[i]);
|
||||
}
|
||||
TIFFSetField(out, TIFFTAG_COLORMAP, rm, gm, bm);
|
||||
(void) TIFFClose(out);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
processCompressOptions(char* opt)
|
||||
{
|
||||
if (streq(opt, "none"))
|
||||
compression = COMPRESSION_NONE;
|
||||
else if (streq(opt, "packbits"))
|
||||
compression = COMPRESSION_PACKBITS;
|
||||
else if (strneq(opt, "lzw", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_LZW;
|
||||
} else if (strneq(opt, "zip", 3)) {
|
||||
char* cp = strchr(opt, ':');
|
||||
if (cp)
|
||||
predictor = atoi(cp+1);
|
||||
compression = COMPRESSION_DEFLATE;
|
||||
} else
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
char* stuff[] = {
|
||||
"usage: tiffmedian [options] input.tif output.tif",
|
||||
"where options are:",
|
||||
" -r # make each strip have no more than # rows",
|
||||
" -C # create a colormap with # entries",
|
||||
" -f use Floyd-Steinberg dithering",
|
||||
" -c lzw[:opts] compress output with Lempel-Ziv & Welch encoding",
|
||||
" (no longer supported by default due to Unisys patent enforcement)",
|
||||
" -c zip[:opts] compress output with deflate encoding",
|
||||
" -c packbits compress output with packbits encoding",
|
||||
" -c none use no compression algorithm on output",
|
||||
"",
|
||||
"LZW and deflate options:",
|
||||
" # set predictor value",
|
||||
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
int i;
|
||||
|
||||
setbuf(stderr, buf);
|
||||
for (i = 0; stuff[i] != NULL; i++)
|
||||
fprintf(stderr, "%s\n", stuff[i]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static void
|
||||
get_histogram(TIFF* in, Colorbox* box)
|
||||
{
|
||||
register unsigned char *inptr;
|
||||
register int red, green, blue;
|
||||
register uint32 j, i;
|
||||
unsigned char *inputline;
|
||||
|
||||
inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
|
||||
if (inputline == NULL) {
|
||||
fprintf(stderr, "No space for scanline buffer\n");
|
||||
exit(-1);
|
||||
}
|
||||
box->rmin = box->gmin = box->bmin = 999;
|
||||
box->rmax = box->gmax = box->bmax = -1;
|
||||
box->total = imagewidth * imagelength;
|
||||
|
||||
{ register int *ptr = &histogram[0][0][0];
|
||||
for (i = B_LEN*B_LEN*B_LEN; i-- > 0;)
|
||||
*ptr++ = 0;
|
||||
}
|
||||
for (i = 0; i < imagelength; i++) {
|
||||
if (TIFFReadScanline(in, inputline, i, 0) <= 0)
|
||||
break;
|
||||
inptr = inputline;
|
||||
for (j = imagewidth; j-- > 0;) {
|
||||
red = *inptr++ >> COLOR_SHIFT;
|
||||
green = *inptr++ >> COLOR_SHIFT;
|
||||
blue = *inptr++ >> COLOR_SHIFT;
|
||||
if (red < box->rmin)
|
||||
box->rmin = red;
|
||||
if (red > box->rmax)
|
||||
box->rmax = red;
|
||||
if (green < box->gmin)
|
||||
box->gmin = green;
|
||||
if (green > box->gmax)
|
||||
box->gmax = green;
|
||||
if (blue < box->bmin)
|
||||
box->bmin = blue;
|
||||
if (blue > box->bmax)
|
||||
box->bmax = blue;
|
||||
histogram[red][green][blue]++;
|
||||
}
|
||||
}
|
||||
_TIFFfree(inputline);
|
||||
}
|
||||
|
||||
static Colorbox *
|
||||
largest_box(void)
|
||||
{
|
||||
register Colorbox *p, *b;
|
||||
register int size;
|
||||
|
||||
b = NULL;
|
||||
size = -1;
|
||||
for (p = usedboxes; p != NULL; p = p->next)
|
||||
if ((p->rmax > p->rmin || p->gmax > p->gmin ||
|
||||
p->bmax > p->bmin) && p->total > size)
|
||||
size = (b = p)->total;
|
||||
return (b);
|
||||
}
|
||||
|
||||
static void
|
||||
splitbox(Colorbox* ptr)
|
||||
{
|
||||
int hist2[B_LEN];
|
||||
int first, last;
|
||||
register Colorbox *new;
|
||||
register int *iptr, *histp;
|
||||
register int i, j;
|
||||
register int ir,ig,ib;
|
||||
register int sum, sum1, sum2;
|
||||
enum { RED, GREEN, BLUE } axis;
|
||||
|
||||
/*
|
||||
* See which axis is the largest, do a histogram along that
|
||||
* axis. Split at median point. Contract both new boxes to
|
||||
* fit points and return
|
||||
*/
|
||||
i = ptr->rmax - ptr->rmin;
|
||||
if (i >= ptr->gmax - ptr->gmin && i >= ptr->bmax - ptr->bmin)
|
||||
axis = RED;
|
||||
else if (ptr->gmax - ptr->gmin >= ptr->bmax - ptr->bmin)
|
||||
axis = GREEN;
|
||||
else
|
||||
axis = BLUE;
|
||||
/* get histogram along longest axis */
|
||||
switch (axis) {
|
||||
case RED:
|
||||
histp = &hist2[ptr->rmin];
|
||||
for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
|
||||
*histp = 0;
|
||||
for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
|
||||
iptr = &histogram[ir][ig][ptr->bmin];
|
||||
for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
|
||||
*histp += *iptr++;
|
||||
}
|
||||
histp++;
|
||||
}
|
||||
first = ptr->rmin;
|
||||
last = ptr->rmax;
|
||||
break;
|
||||
case GREEN:
|
||||
histp = &hist2[ptr->gmin];
|
||||
for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
|
||||
*histp = 0;
|
||||
for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
|
||||
iptr = &histogram[ir][ig][ptr->bmin];
|
||||
for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
|
||||
*histp += *iptr++;
|
||||
}
|
||||
histp++;
|
||||
}
|
||||
first = ptr->gmin;
|
||||
last = ptr->gmax;
|
||||
break;
|
||||
case BLUE:
|
||||
histp = &hist2[ptr->bmin];
|
||||
for (ib = ptr->bmin; ib <= ptr->bmax; ++ib) {
|
||||
*histp = 0;
|
||||
for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
|
||||
iptr = &histogram[ir][ptr->gmin][ib];
|
||||
for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
|
||||
*histp += *iptr;
|
||||
iptr += B_LEN;
|
||||
}
|
||||
}
|
||||
histp++;
|
||||
}
|
||||
first = ptr->bmin;
|
||||
last = ptr->bmax;
|
||||
break;
|
||||
}
|
||||
/* find median point */
|
||||
sum2 = ptr->total / 2;
|
||||
histp = &hist2[first];
|
||||
sum = 0;
|
||||
for (i = first; i <= last && (sum += *histp++) < sum2; ++i)
|
||||
;
|
||||
if (i == first)
|
||||
i++;
|
||||
|
||||
/* Create new box, re-allocate points */
|
||||
new = freeboxes;
|
||||
freeboxes = new->next;
|
||||
if (freeboxes)
|
||||
freeboxes->prev = NULL;
|
||||
if (usedboxes)
|
||||
usedboxes->prev = new;
|
||||
new->next = usedboxes;
|
||||
usedboxes = new;
|
||||
|
||||
histp = &hist2[first];
|
||||
for (sum1 = 0, j = first; j < i; j++)
|
||||
sum1 += *histp++;
|
||||
for (sum2 = 0, j = i; j <= last; j++)
|
||||
sum2 += *histp++;
|
||||
new->total = sum1;
|
||||
ptr->total = sum2;
|
||||
|
||||
new->rmin = ptr->rmin;
|
||||
new->rmax = ptr->rmax;
|
||||
new->gmin = ptr->gmin;
|
||||
new->gmax = ptr->gmax;
|
||||
new->bmin = ptr->bmin;
|
||||
new->bmax = ptr->bmax;
|
||||
switch (axis) {
|
||||
case RED:
|
||||
new->rmax = i-1;
|
||||
ptr->rmin = i;
|
||||
break;
|
||||
case GREEN:
|
||||
new->gmax = i-1;
|
||||
ptr->gmin = i;
|
||||
break;
|
||||
case BLUE:
|
||||
new->bmax = i-1;
|
||||
ptr->bmin = i;
|
||||
break;
|
||||
}
|
||||
shrinkbox(new);
|
||||
shrinkbox(ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
shrinkbox(Colorbox* box)
|
||||
{
|
||||
register int *histp, ir, ig, ib;
|
||||
|
||||
if (box->rmax > box->rmin) {
|
||||
for (ir = box->rmin; ir <= box->rmax; ++ir)
|
||||
for (ig = box->gmin; ig <= box->gmax; ++ig) {
|
||||
histp = &histogram[ir][ig][box->bmin];
|
||||
for (ib = box->bmin; ib <= box->bmax; ++ib)
|
||||
if (*histp++ != 0) {
|
||||
box->rmin = ir;
|
||||
goto have_rmin;
|
||||
}
|
||||
}
|
||||
have_rmin:
|
||||
if (box->rmax > box->rmin)
|
||||
for (ir = box->rmax; ir >= box->rmin; --ir)
|
||||
for (ig = box->gmin; ig <= box->gmax; ++ig) {
|
||||
histp = &histogram[ir][ig][box->bmin];
|
||||
ib = box->bmin;
|
||||
for (; ib <= box->bmax; ++ib)
|
||||
if (*histp++ != 0) {
|
||||
box->rmax = ir;
|
||||
goto have_rmax;
|
||||
}
|
||||
}
|
||||
}
|
||||
have_rmax:
|
||||
if (box->gmax > box->gmin) {
|
||||
for (ig = box->gmin; ig <= box->gmax; ++ig)
|
||||
for (ir = box->rmin; ir <= box->rmax; ++ir) {
|
||||
histp = &histogram[ir][ig][box->bmin];
|
||||
for (ib = box->bmin; ib <= box->bmax; ++ib)
|
||||
if (*histp++ != 0) {
|
||||
box->gmin = ig;
|
||||
goto have_gmin;
|
||||
}
|
||||
}
|
||||
have_gmin:
|
||||
if (box->gmax > box->gmin)
|
||||
for (ig = box->gmax; ig >= box->gmin; --ig)
|
||||
for (ir = box->rmin; ir <= box->rmax; ++ir) {
|
||||
histp = &histogram[ir][ig][box->bmin];
|
||||
ib = box->bmin;
|
||||
for (; ib <= box->bmax; ++ib)
|
||||
if (*histp++ != 0) {
|
||||
box->gmax = ig;
|
||||
goto have_gmax;
|
||||
}
|
||||
}
|
||||
}
|
||||
have_gmax:
|
||||
if (box->bmax > box->bmin) {
|
||||
for (ib = box->bmin; ib <= box->bmax; ++ib)
|
||||
for (ir = box->rmin; ir <= box->rmax; ++ir) {
|
||||
histp = &histogram[ir][box->gmin][ib];
|
||||
for (ig = box->gmin; ig <= box->gmax; ++ig) {
|
||||
if (*histp != 0) {
|
||||
box->bmin = ib;
|
||||
goto have_bmin;
|
||||
}
|
||||
histp += B_LEN;
|
||||
}
|
||||
}
|
||||
have_bmin:
|
||||
if (box->bmax > box->bmin)
|
||||
for (ib = box->bmax; ib >= box->bmin; --ib)
|
||||
for (ir = box->rmin; ir <= box->rmax; ++ir) {
|
||||
histp = &histogram[ir][box->gmin][ib];
|
||||
ig = box->gmin;
|
||||
for (; ig <= box->gmax; ++ig) {
|
||||
if (*histp != 0) {
|
||||
box->bmax = ib;
|
||||
goto have_bmax;
|
||||
}
|
||||
histp += B_LEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
have_bmax:
|
||||
;
|
||||
}
|
||||
|
||||
static C_cell *
|
||||
create_colorcell(int red, int green, int blue)
|
||||
{
|
||||
register int ir, ig, ib, i;
|
||||
register C_cell *ptr;
|
||||
int mindist, next_n;
|
||||
register int tmp, dist, n;
|
||||
|
||||
ir = red >> (COLOR_DEPTH-C_DEPTH);
|
||||
ig = green >> (COLOR_DEPTH-C_DEPTH);
|
||||
ib = blue >> (COLOR_DEPTH-C_DEPTH);
|
||||
ptr = (C_cell *)_TIFFmalloc(sizeof (C_cell));
|
||||
*(ColorCells + ir*C_LEN*C_LEN + ig*C_LEN + ib) = ptr;
|
||||
ptr->num_ents = 0;
|
||||
|
||||
/*
|
||||
* Step 1: find all colors inside this cell, while we're at
|
||||
* it, find distance of centermost point to furthest corner
|
||||
*/
|
||||
mindist = 99999999;
|
||||
for (i = 0; i < num_colors; ++i) {
|
||||
if (rm[i]>>(COLOR_DEPTH-C_DEPTH) != ir ||
|
||||
gm[i]>>(COLOR_DEPTH-C_DEPTH) != ig ||
|
||||
bm[i]>>(COLOR_DEPTH-C_DEPTH) != ib)
|
||||
continue;
|
||||
ptr->entries[ptr->num_ents][0] = i;
|
||||
ptr->entries[ptr->num_ents][1] = 0;
|
||||
++ptr->num_ents;
|
||||
tmp = rm[i] - red;
|
||||
if (tmp < (MAX_COLOR/C_LEN/2))
|
||||
tmp = MAX_COLOR/C_LEN-1 - tmp;
|
||||
dist = tmp*tmp;
|
||||
tmp = gm[i] - green;
|
||||
if (tmp < (MAX_COLOR/C_LEN/2))
|
||||
tmp = MAX_COLOR/C_LEN-1 - tmp;
|
||||
dist += tmp*tmp;
|
||||
tmp = bm[i] - blue;
|
||||
if (tmp < (MAX_COLOR/C_LEN/2))
|
||||
tmp = MAX_COLOR/C_LEN-1 - tmp;
|
||||
dist += tmp*tmp;
|
||||
if (dist < mindist)
|
||||
mindist = dist;
|
||||
}
|
||||
|
||||
/*
|
||||
* Step 3: find all points within that distance to cell.
|
||||
*/
|
||||
for (i = 0; i < num_colors; ++i) {
|
||||
if (rm[i] >> (COLOR_DEPTH-C_DEPTH) == ir &&
|
||||
gm[i] >> (COLOR_DEPTH-C_DEPTH) == ig &&
|
||||
bm[i] >> (COLOR_DEPTH-C_DEPTH) == ib)
|
||||
continue;
|
||||
dist = 0;
|
||||
if ((tmp = red - rm[i]) > 0 ||
|
||||
(tmp = rm[i] - (red + MAX_COLOR/C_LEN-1)) > 0 )
|
||||
dist += tmp*tmp;
|
||||
if ((tmp = green - gm[i]) > 0 ||
|
||||
(tmp = gm[i] - (green + MAX_COLOR/C_LEN-1)) > 0 )
|
||||
dist += tmp*tmp;
|
||||
if ((tmp = blue - bm[i]) > 0 ||
|
||||
(tmp = bm[i] - (blue + MAX_COLOR/C_LEN-1)) > 0 )
|
||||
dist += tmp*tmp;
|
||||
if (dist < mindist) {
|
||||
ptr->entries[ptr->num_ents][0] = i;
|
||||
ptr->entries[ptr->num_ents][1] = dist;
|
||||
++ptr->num_ents;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort color cells by distance, use cheap exchange sort
|
||||
*/
|
||||
for (n = ptr->num_ents - 1; n > 0; n = next_n) {
|
||||
next_n = 0;
|
||||
for (i = 0; i < n; ++i)
|
||||
if (ptr->entries[i][1] > ptr->entries[i+1][1]) {
|
||||
tmp = ptr->entries[i][0];
|
||||
ptr->entries[i][0] = ptr->entries[i+1][0];
|
||||
ptr->entries[i+1][0] = tmp;
|
||||
tmp = ptr->entries[i][1];
|
||||
ptr->entries[i][1] = ptr->entries[i+1][1];
|
||||
ptr->entries[i+1][1] = tmp;
|
||||
next_n = i;
|
||||
}
|
||||
}
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
map_colortable(void)
|
||||
{
|
||||
register int *histp = &histogram[0][0][0];
|
||||
register C_cell *cell;
|
||||
register int j, tmp, d2, dist;
|
||||
int ir, ig, ib, i;
|
||||
|
||||
for (ir = 0; ir < B_LEN; ++ir)
|
||||
for (ig = 0; ig < B_LEN; ++ig)
|
||||
for (ib = 0; ib < B_LEN; ++ib, histp++) {
|
||||
if (*histp == 0) {
|
||||
*histp = -1;
|
||||
continue;
|
||||
}
|
||||
cell = *(ColorCells +
|
||||
(((ir>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2) +
|
||||
((ig>>(B_DEPTH-C_DEPTH)) << C_DEPTH) +
|
||||
(ib>>(B_DEPTH-C_DEPTH))));
|
||||
if (cell == NULL )
|
||||
cell = create_colorcell(
|
||||
ir << COLOR_SHIFT,
|
||||
ig << COLOR_SHIFT,
|
||||
ib << COLOR_SHIFT);
|
||||
dist = 9999999;
|
||||
for (i = 0; i < cell->num_ents &&
|
||||
dist > cell->entries[i][1]; ++i) {
|
||||
j = cell->entries[i][0];
|
||||
d2 = rm[j] - (ir << COLOR_SHIFT);
|
||||
d2 *= d2;
|
||||
tmp = gm[j] - (ig << COLOR_SHIFT);
|
||||
d2 += tmp*tmp;
|
||||
tmp = bm[j] - (ib << COLOR_SHIFT);
|
||||
d2 += tmp*tmp;
|
||||
if (d2 < dist) {
|
||||
dist = d2;
|
||||
*histp = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* straight quantization. Each pixel is mapped to the colors
|
||||
* closest to it. Color values are rounded to the nearest color
|
||||
* table entry.
|
||||
*/
|
||||
static void
|
||||
quant(TIFF* in, TIFF* out)
|
||||
{
|
||||
unsigned char *outline, *inputline;
|
||||
register unsigned char *outptr, *inptr;
|
||||
register uint32 i, j;
|
||||
register int red, green, blue;
|
||||
|
||||
inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
|
||||
outline = (unsigned char *)_TIFFmalloc(imagewidth);
|
||||
for (i = 0; i < imagelength; i++) {
|
||||
if (TIFFReadScanline(in, inputline, i, 0) <= 0)
|
||||
break;
|
||||
inptr = inputline;
|
||||
outptr = outline;
|
||||
for (j = 0; j < imagewidth; j++) {
|
||||
red = *inptr++ >> COLOR_SHIFT;
|
||||
green = *inptr++ >> COLOR_SHIFT;
|
||||
blue = *inptr++ >> COLOR_SHIFT;
|
||||
*outptr++ = histogram[red][green][blue];
|
||||
}
|
||||
if (TIFFWriteScanline(out, outline, i, 0) < 0)
|
||||
break;
|
||||
}
|
||||
_TIFFfree(inputline);
|
||||
_TIFFfree(outline);
|
||||
}
|
||||
|
||||
#define SWAP(type,a,b) { type p; p = a; a = b; b = p; }
|
||||
|
||||
#define GetInputLine(tif, row, bad) \
|
||||
if (TIFFReadScanline(tif, inputline, row, 0) <= 0) \
|
||||
bad; \
|
||||
inptr = inputline; \
|
||||
nextptr = nextline; \
|
||||
for (j = 0; j < imagewidth; ++j) { \
|
||||
*nextptr++ = *inptr++; \
|
||||
*nextptr++ = *inptr++; \
|
||||
*nextptr++ = *inptr++; \
|
||||
}
|
||||
#define GetComponent(raw, cshift, c) \
|
||||
cshift = raw; \
|
||||
if (cshift < 0) \
|
||||
cshift = 0; \
|
||||
else if (cshift >= MAX_COLOR) \
|
||||
cshift = MAX_COLOR-1; \
|
||||
c = cshift; \
|
||||
cshift >>= COLOR_SHIFT;
|
||||
|
||||
static void
|
||||
quant_fsdither(TIFF* in, TIFF* out)
|
||||
{
|
||||
unsigned char *outline, *inputline, *inptr;
|
||||
short *thisline, *nextline;
|
||||
register unsigned char *outptr;
|
||||
register short *thisptr, *nextptr;
|
||||
register uint32 i, j;
|
||||
uint32 imax, jmax;
|
||||
int lastline, lastpixel;
|
||||
|
||||
imax = imagelength - 1;
|
||||
jmax = imagewidth - 1;
|
||||
inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in));
|
||||
thisline = (short *)_TIFFmalloc(imagewidth * 3 * sizeof (short));
|
||||
nextline = (short *)_TIFFmalloc(imagewidth * 3 * sizeof (short));
|
||||
outline = (unsigned char *) _TIFFmalloc(TIFFScanlineSize(out));
|
||||
|
||||
GetInputLine(in, 0, goto bad); /* get first line */
|
||||
for (i = 1; i <= imagelength; ++i) {
|
||||
SWAP(short *, thisline, nextline);
|
||||
lastline = (i >= imax);
|
||||
if (i <= imax)
|
||||
GetInputLine(in, i, break);
|
||||
thisptr = thisline;
|
||||
nextptr = nextline;
|
||||
outptr = outline;
|
||||
for (j = 0; j < imagewidth; ++j) {
|
||||
int red, green, blue;
|
||||
register int oval, r2, g2, b2;
|
||||
|
||||
lastpixel = (j == jmax);
|
||||
GetComponent(*thisptr++, r2, red);
|
||||
GetComponent(*thisptr++, g2, green);
|
||||
GetComponent(*thisptr++, b2, blue);
|
||||
oval = histogram[r2][g2][b2];
|
||||
if (oval == -1) {
|
||||
int ci;
|
||||
register int cj, tmp, d2, dist;
|
||||
register C_cell *cell;
|
||||
|
||||
cell = *(ColorCells +
|
||||
(((r2>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2) +
|
||||
((g2>>(B_DEPTH-C_DEPTH)) << C_DEPTH ) +
|
||||
(b2>>(B_DEPTH-C_DEPTH))));
|
||||
if (cell == NULL)
|
||||
cell = create_colorcell(red,
|
||||
green, blue);
|
||||
dist = 9999999;
|
||||
for (ci = 0; ci < cell->num_ents && dist > cell->entries[ci][1]; ++ci) {
|
||||
cj = cell->entries[ci][0];
|
||||
d2 = (rm[cj] >> COLOR_SHIFT) - r2;
|
||||
d2 *= d2;
|
||||
tmp = (gm[cj] >> COLOR_SHIFT) - g2;
|
||||
d2 += tmp*tmp;
|
||||
tmp = (bm[cj] >> COLOR_SHIFT) - b2;
|
||||
d2 += tmp*tmp;
|
||||
if (d2 < dist) {
|
||||
dist = d2;
|
||||
oval = cj;
|
||||
}
|
||||
}
|
||||
histogram[r2][g2][b2] = oval;
|
||||
}
|
||||
*outptr++ = oval;
|
||||
red -= rm[oval];
|
||||
green -= gm[oval];
|
||||
blue -= bm[oval];
|
||||
if (!lastpixel) {
|
||||
thisptr[0] += blue * 7 / 16;
|
||||
thisptr[1] += green * 7 / 16;
|
||||
thisptr[2] += red * 7 / 16;
|
||||
}
|
||||
if (!lastline) {
|
||||
if (j != 0) {
|
||||
nextptr[-3] += blue * 3 / 16;
|
||||
nextptr[-2] += green * 3 / 16;
|
||||
nextptr[-1] += red * 3 / 16;
|
||||
}
|
||||
nextptr[0] += blue * 5 / 16;
|
||||
nextptr[1] += green * 5 / 16;
|
||||
nextptr[2] += red * 5 / 16;
|
||||
if (!lastpixel) {
|
||||
nextptr[3] += blue / 16;
|
||||
nextptr[4] += green / 16;
|
||||
nextptr[5] += red / 16;
|
||||
}
|
||||
nextptr += 3;
|
||||
}
|
||||
}
|
||||
if (TIFFWriteScanline(out, outline, i-1, 0) < 0)
|
||||
break;
|
||||
}
|
||||
bad:
|
||||
_TIFFfree(inputline);
|
||||
_TIFFfree(thisline);
|
||||
_TIFFfree(nextline);
|
||||
_TIFFfree(outline);
|
||||
}
|
||||
Executable
+226
@@ -0,0 +1,226 @@
|
||||
/* $Header: /home/cvsroot/libtiff/tools/tiffsplit.c,v 1.1.1.1 2000/06/24 19:10:16 tshead Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992-1997 Sam Leffler
|
||||
* Copyright (c) 1992-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tiffio.h"
|
||||
|
||||
#define streq(a,b) (strcmp(a,b) == 0)
|
||||
#define CopyField(tag, v) \
|
||||
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
|
||||
#define CopyField2(tag, v1, v2) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
|
||||
#define CopyField3(tag, v1, v2, v3) \
|
||||
if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
|
||||
|
||||
static char fname[1024+1];
|
||||
|
||||
static int tiffcp(TIFF*, TIFF*);
|
||||
static void newfilename(void);
|
||||
static int cpStrips(TIFF*, TIFF*);
|
||||
static int cpTiles(TIFF*, TIFF*);
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
TIFF *in, *out;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: tiffsplit input.tif [prefix]\n");
|
||||
return (-3);
|
||||
}
|
||||
if (argc > 2)
|
||||
strcpy(fname, argv[2]);
|
||||
in = TIFFOpen(argv[1], "r");
|
||||
if (in != NULL) {
|
||||
do {
|
||||
char path[1024+1];
|
||||
newfilename();
|
||||
strcpy(path, fname);
|
||||
strcat(path, ".tif");
|
||||
out = TIFFOpen(path, "w");
|
||||
if (out == NULL)
|
||||
return (-2);
|
||||
if (!tiffcp(in, out))
|
||||
return (-1);
|
||||
TIFFClose(out);
|
||||
} while (TIFFReadDirectory(in));
|
||||
(void) TIFFClose(in);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
newfilename(void)
|
||||
{
|
||||
static int first = 1;
|
||||
static long fnum;
|
||||
static short defname;
|
||||
static char *fpnt;
|
||||
|
||||
if (first) {
|
||||
if (fname[0]) {
|
||||
fpnt = fname + strlen(fname);
|
||||
defname = 0;
|
||||
} else {
|
||||
fname[0] = 'x';
|
||||
fpnt = fname + 1;
|
||||
defname = 1;
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
#define MAXFILES 676
|
||||
if (fnum == MAXFILES) {
|
||||
if (!defname || fname[0] == 'z') {
|
||||
fprintf(stderr, "tiffsplit: too many files.\n");
|
||||
exit(1);
|
||||
}
|
||||
fname[0]++;
|
||||
fnum = 0;
|
||||
}
|
||||
fpnt[0] = fnum / 26 + 'a';
|
||||
fpnt[1] = fnum % 26 + 'a';
|
||||
fnum++;
|
||||
}
|
||||
|
||||
static int
|
||||
tiffcp(TIFF* in, TIFF* out)
|
||||
{
|
||||
short bitspersample, samplesperpixel, shortv, *shortav;
|
||||
uint32 w, l;
|
||||
float floatv;
|
||||
char *stringv;
|
||||
uint32 longv;
|
||||
|
||||
CopyField(TIFFTAG_SUBFILETYPE, longv);
|
||||
CopyField(TIFFTAG_TILEWIDTH, w);
|
||||
CopyField(TIFFTAG_TILELENGTH, l);
|
||||
CopyField(TIFFTAG_IMAGEWIDTH, w);
|
||||
CopyField(TIFFTAG_IMAGELENGTH, l);
|
||||
CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample);
|
||||
CopyField(TIFFTAG_COMPRESSION, shortv);
|
||||
CopyField(TIFFTAG_PREDICTOR, shortv);
|
||||
CopyField(TIFFTAG_PHOTOMETRIC, shortv);
|
||||
CopyField(TIFFTAG_THRESHHOLDING, shortv);
|
||||
CopyField(TIFFTAG_FILLORDER, shortv);
|
||||
CopyField(TIFFTAG_ORIENTATION, shortv);
|
||||
CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
|
||||
CopyField(TIFFTAG_MINSAMPLEVALUE, shortv);
|
||||
CopyField(TIFFTAG_MAXSAMPLEVALUE, shortv);
|
||||
CopyField(TIFFTAG_XRESOLUTION, floatv);
|
||||
CopyField(TIFFTAG_YRESOLUTION, floatv);
|
||||
CopyField(TIFFTAG_GROUP3OPTIONS, longv);
|
||||
CopyField(TIFFTAG_GROUP4OPTIONS, longv);
|
||||
CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
|
||||
CopyField(TIFFTAG_PLANARCONFIG, shortv);
|
||||
CopyField(TIFFTAG_ROWSPERSTRIP, longv);
|
||||
CopyField(TIFFTAG_XPOSITION, floatv);
|
||||
CopyField(TIFFTAG_YPOSITION, floatv);
|
||||
CopyField(TIFFTAG_IMAGEDEPTH, longv);
|
||||
CopyField(TIFFTAG_TILEDEPTH, longv);
|
||||
CopyField2(TIFFTAG_EXTRASAMPLES, shortv, shortav);
|
||||
{ uint16 *red, *green, *blue;
|
||||
CopyField3(TIFFTAG_COLORMAP, red, green, blue);
|
||||
}
|
||||
{ uint16 shortv2;
|
||||
CopyField2(TIFFTAG_PAGENUMBER, shortv, shortv2);
|
||||
}
|
||||
CopyField(TIFFTAG_ARTIST, stringv);
|
||||
CopyField(TIFFTAG_IMAGEDESCRIPTION, stringv);
|
||||
CopyField(TIFFTAG_MAKE, stringv);
|
||||
CopyField(TIFFTAG_MODEL, stringv);
|
||||
CopyField(TIFFTAG_SOFTWARE, stringv);
|
||||
CopyField(TIFFTAG_DATETIME, stringv);
|
||||
CopyField(TIFFTAG_HOSTCOMPUTER, stringv);
|
||||
CopyField(TIFFTAG_PAGENAME, stringv);
|
||||
CopyField(TIFFTAG_DOCUMENTNAME, stringv);
|
||||
if (TIFFIsTiled(in))
|
||||
return (cpTiles(in, out));
|
||||
else
|
||||
return (cpStrips(in, out));
|
||||
}
|
||||
|
||||
static int
|
||||
cpStrips(TIFF* in, TIFF* out)
|
||||
{
|
||||
tsize_t bufsize = TIFFStripSize(in);
|
||||
unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize);
|
||||
|
||||
if (buf) {
|
||||
tstrip_t s, ns = TIFFNumberOfStrips(in);
|
||||
uint32 *bytecounts;
|
||||
|
||||
TIFFGetField(in, TIFFTAG_STRIPBYTECOUNTS, &bytecounts);
|
||||
for (s = 0; s < ns; s++) {
|
||||
if (bytecounts[s] > bufsize) {
|
||||
buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[s]);
|
||||
if (!buf)
|
||||
return (0);
|
||||
bufsize = bytecounts[s];
|
||||
}
|
||||
if (TIFFReadRawStrip(in, s, buf, bytecounts[s]) < 0 ||
|
||||
TIFFWriteRawStrip(out, s, buf, bytecounts[s]) < 0) {
|
||||
_TIFFfree(buf);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpTiles(TIFF* in, TIFF* out)
|
||||
{
|
||||
tsize_t bufsize = TIFFTileSize(in);
|
||||
unsigned char *buf = (unsigned char *)_TIFFmalloc(bufsize);
|
||||
|
||||
if (buf) {
|
||||
ttile_t t, nt = TIFFNumberOfTiles(in);
|
||||
uint32 *bytecounts;
|
||||
|
||||
TIFFGetField(in, TIFFTAG_TILEBYTECOUNTS, &bytecounts);
|
||||
for (t = 0; t < nt; t++) {
|
||||
if (bytecounts[t] > bufsize) {
|
||||
buf = (unsigned char *)_TIFFrealloc(buf, bytecounts[t]);
|
||||
if (!buf)
|
||||
return (0);
|
||||
bufsize = bytecounts[t];
|
||||
}
|
||||
if (TIFFReadRawTile(in, t, buf, bytecounts[t]) < 0 ||
|
||||
TIFFWriteRawTile(out, t, buf, bytecounts[t]) < 0) {
|
||||
_TIFFfree(buf);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
_TIFFfree(buf);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
Executable
+161
@@ -0,0 +1,161 @@
|
||||
float ycbcrCoeffs[3] = { .299, .587, .114 };
|
||||
/* default coding range is CCIR Rec 601-1 with no headroom/footroom */
|
||||
unsigned long refBlackWhite[6] = { 0, 255, 128, 255, 128, 255 };
|
||||
|
||||
#define LumaRed ycbcrCoeffs[0]
|
||||
#define LumaGreen ycbcrCoeffs[1]
|
||||
#define LumaBlue ycbcrCoeffs[2]
|
||||
|
||||
long eRtotal = 0;
|
||||
long eGtotal = 0;
|
||||
long eBtotal = 0;
|
||||
long preveRtotal = 0;
|
||||
long preveGtotal = 0;
|
||||
long preveBtotal = 0;
|
||||
unsigned long AbseRtotal = 0;
|
||||
unsigned long AbseGtotal = 0;
|
||||
unsigned long AbseBtotal = 0;
|
||||
unsigned long eCodes = 0;
|
||||
unsigned long preveCodes = 0;
|
||||
unsigned long eBits = 0;
|
||||
unsigned long preveBits = 0;
|
||||
|
||||
static void setupLumaTables();
|
||||
static int abs(int v) { return (v < 0 ? -v : v); }
|
||||
static double pct(int v,double range) { return (v*100. / range); }
|
||||
static void check(int R, int G, int B);
|
||||
|
||||
float D1, D2;
|
||||
float D3, D4;
|
||||
float D5, D6;
|
||||
|
||||
int
|
||||
main(int argc, char* argv)
|
||||
{
|
||||
int R, G, B;
|
||||
|
||||
if (argc > 1) {
|
||||
refBlackWhite[0] = 16;
|
||||
refBlackWhite[1] = 235;
|
||||
refBlackWhite[2] = 128;
|
||||
refBlackWhite[3] = 240;
|
||||
refBlackWhite[4] = 128;
|
||||
refBlackWhite[5] = 240;
|
||||
}
|
||||
D3 = 2 - 2*LumaRed;
|
||||
D4 = 2 - 2*LumaBlue;
|
||||
D1 = 1. / D3;
|
||||
D2 = 1. / D4;
|
||||
D5 = D3*LumaRed / LumaGreen;
|
||||
D6 = D4*LumaBlue / LumaGreen;
|
||||
setupLumaTables();
|
||||
for (R = 0; R < 256; R++) {
|
||||
for (G = 0; G < 256; G++)
|
||||
for (B = 0; B < 256; B++)
|
||||
check(R, G, B);
|
||||
printf("[%3u] c %u/%u b %u/%u (R %u/%d/%u G %u/%d/%u B %u/%d/%u)\n"
|
||||
, R
|
||||
, eCodes - preveCodes, eCodes
|
||||
, eBits - preveBits, eBits
|
||||
, abs(AbseRtotal - preveRtotal), eRtotal , AbseRtotal
|
||||
, abs(AbseGtotal - preveGtotal), eGtotal , AbseGtotal
|
||||
, abs(AbseBtotal - preveBtotal), eBtotal , AbseBtotal
|
||||
);
|
||||
preveRtotal = AbseRtotal;
|
||||
preveGtotal = AbseGtotal;
|
||||
preveBtotal = AbseBtotal;
|
||||
preveCodes = eCodes;
|
||||
preveBits = eBits;
|
||||
}
|
||||
printf("%u total codes\n", 256*256*256);
|
||||
printf("total error: %u codes %u bits (R %d/%u G %d/%u B %d/%u)\n"
|
||||
, eCodes
|
||||
, eBits
|
||||
, eRtotal , AbseRtotal
|
||||
, eGtotal , AbseGtotal
|
||||
, eBtotal , AbseBtotal
|
||||
);
|
||||
return (0);
|
||||
}
|
||||
|
||||
float *lumaRed;
|
||||
float *lumaGreen;
|
||||
float *lumaBlue;
|
||||
|
||||
static float*
|
||||
setupLuma(float c)
|
||||
{
|
||||
float *v = (float *)_TIFFmalloc(256 * sizeof (float));
|
||||
int i;
|
||||
for (i = 0; i < 256; i++)
|
||||
v[i] = c * i;
|
||||
return (v);
|
||||
}
|
||||
|
||||
static void
|
||||
setupLumaTables(void)
|
||||
{
|
||||
lumaRed = setupLuma(LumaRed);
|
||||
lumaGreen = setupLuma(LumaGreen);
|
||||
lumaBlue = setupLuma(LumaBlue);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
V2Code(float f, unsigned long RB, unsigned long RW, int CR)
|
||||
{
|
||||
unsigned int c = (unsigned int)((((f)*(RW-RB)/CR)+RB)+.5);
|
||||
return (c > 255 ? 255 : c);
|
||||
}
|
||||
|
||||
#define Code2V(c, RB, RW, CR) ((((c)-(int)RB)*(float)CR)/(float)(RW-RB))
|
||||
|
||||
#define CLAMP(f,min,max) \
|
||||
(int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5)
|
||||
|
||||
static
|
||||
void
|
||||
check(int R, int G, int B)
|
||||
{
|
||||
float Y, Cb, Cr;
|
||||
int iY, iCb, iCr;
|
||||
float rY, rCb, rCr;
|
||||
float rR, rG, rB;
|
||||
int eR, eG, eB;
|
||||
|
||||
Y = lumaRed[R] + lumaGreen[G] + lumaBlue[B];
|
||||
Cb = (B - Y)*D2;
|
||||
Cr = (R - Y)*D1;
|
||||
iY = V2Code(Y, refBlackWhite[0], refBlackWhite[1], 255);
|
||||
iCb = V2Code(Cb, refBlackWhite[2], refBlackWhite[3], 127);
|
||||
iCr = V2Code(Cr, refBlackWhite[4], refBlackWhite[5], 127);
|
||||
rCb = Code2V(iCb, refBlackWhite[2], refBlackWhite[3], 127);
|
||||
rCr = Code2V(iCr, refBlackWhite[4], refBlackWhite[5], 127);
|
||||
rY = Code2V(iY, refBlackWhite[0], refBlackWhite[1], 255);
|
||||
rR = rY + rCr*D3;
|
||||
rB = rY + rCb*D4;
|
||||
rG = rY - rCb*D6 - rCr*D5;
|
||||
eR = R - CLAMP(rR,0,255);
|
||||
eG = G - CLAMP(rG,0,255);
|
||||
eB = B - CLAMP(rB,0,255);
|
||||
if (abs(eR) > 1 || abs(eG) > 1 || abs(eB) > 1) {
|
||||
printf("R %u G %u B %u", R, G, B);
|
||||
printf(" Y %g Cb %g Cr %g", Y, Cb, Cr);
|
||||
printf(" iY %u iCb %u iCr %u", iY, iCb, iCr);
|
||||
printf("\n -> Y %g Cb %g Cr %g", rY, rCb, rCr);
|
||||
printf(" R %g (%u) G %g (%u) B %g (%u) E=[%d %d %d])\n"
|
||||
, rR, CLAMP(rR,0,255)
|
||||
, rG, CLAMP(rG,0,255)
|
||||
, rB, CLAMP(rB,0,255)
|
||||
, eR, eG, eB
|
||||
);
|
||||
}
|
||||
eRtotal += eR;
|
||||
eGtotal += eG;
|
||||
eBtotal += eB;
|
||||
AbseRtotal += abs(eR);
|
||||
AbseGtotal += abs(eG);
|
||||
AbseBtotal += abs(eB);
|
||||
if (eR | eG | eB)
|
||||
eCodes++;
|
||||
eBits += abs(eR) + abs(eG) + abs(eB);
|
||||
}
|
||||
Reference in New Issue
Block a user