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:
2014-07-19 07:44:42 +00:00
commit f81ae811ca
429 changed files with 82326 additions and 0 deletions
+259
View File
@@ -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
+137
View File
@@ -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
+31
View File
@@ -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
View File
@@ -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);
}
+359
View File
@@ -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);
}
+513
View File
@@ -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);
}
+386
View File
@@ -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);
}
+242
View File
@@ -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);
}
+266
View File
@@ -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);
}
+41
View File
@@ -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.
*/
+341
View File
@@ -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);
}
+321
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+572
View File
@@ -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);
}
+401
View File
@@ -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);
}
+1408
View File
File diff suppressed because it is too large Load Diff
+453
View File
@@ -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);
}
+483
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+314
View File
@@ -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);
}
+755
View File
@@ -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);
}
+429
View File
@@ -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);
}
}
+890
View File
@@ -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);
}
+226
View File
@@ -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
View File
@@ -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);
}