|
kusano |
7d535a |
#ifndef lint
|
|
kusano |
7d535a |
static char id[] = "$Id: tif2ras.c,v 1.3 2010-06-08 18:55:15 bfriesen Exp $";
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
/*-
|
|
kusano |
7d535a |
* tif2ras.c - Converts from a Tagged Image File Format image to a Sun Raster.
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* Copyright (c) 1990 by Sun Microsystems, Inc.
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* Author: Patrick J. Naughton
|
|
kusano |
7d535a |
* naughton@wind.sun.com
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* Permission to use, copy, modify, and distribute this software and its
|
|
kusano |
7d535a |
* documentation for any purpose and without fee is hereby granted,
|
|
kusano |
7d535a |
* provided that the above copyright notice appear in all copies and that
|
|
kusano |
7d535a |
* both that copyright notice and this permission notice appear in
|
|
kusano |
7d535a |
* supporting documentation.
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* This file is provided AS IS with no warranties of any kind. The author
|
|
kusano |
7d535a |
* shall have no liability with respect to the infringement of copyrights,
|
|
kusano |
7d535a |
* trade secrets or any patents by this file or any part thereof. In no
|
|
kusano |
7d535a |
* event will the author be liable for any lost revenue or profits or
|
|
kusano |
7d535a |
* other special, indirect and consequential damages.
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* Comments and additions should be sent to the author:
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* Patrick J. Naughton
|
|
kusano |
7d535a |
* Sun Microsystems
|
|
kusano |
7d535a |
* 2550 Garcia Ave, MS 14-40
|
|
kusano |
7d535a |
* Mountain View, CA 94043
|
|
kusano |
7d535a |
* (415) 336-1080
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* Revision History:
|
|
kusano |
7d535a |
* 10-Jan-89: Created.
|
|
kusano |
7d535a |
* 06-Mar-90: Change to byte encoded rasterfiles.
|
|
kusano |
7d535a |
* fix bug in call to ReadScanline().
|
|
kusano |
7d535a |
* fix bug in CVT() macro.
|
|
kusano |
7d535a |
* fix assignment of td, (missing &).
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* Description:
|
|
kusano |
7d535a |
* This program takes a MicroSoft/Aldus "Tagged Image File Format" image or
|
|
kusano |
7d535a |
* "TIFF" file as input and writes a Sun Rasterfile [see rasterfile(5)]. The
|
|
kusano |
7d535a |
* output file may be standard output, but the input TIFF file must be a real
|
|
kusano |
7d535a |
* file since seek(2) is used.
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
#include <stdio.h></stdio.h>
|
|
kusano |
7d535a |
#include <pixrect pixrect_hs.h=""></pixrect>
|
|
kusano |
7d535a |
#include "tiffio.h"
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
typedef int boolean;
|
|
kusano |
7d535a |
#define True (1)
|
|
kusano |
7d535a |
#define False (0)
|
|
kusano |
7d535a |
#define CVT(x) (((x) * 255) / ((1L<<16)-1))
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
boolean Verbose = False;
|
|
kusano |
7d535a |
char *pname; /* program name (used for error messages) */
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
void
|
|
kusano |
7d535a |
error(s1, s2)
|
|
kusano |
7d535a |
char *s1,
|
|
kusano |
7d535a |
*s2;
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
fprintf(stderr, s1, pname, s2);
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
void
|
|
kusano |
7d535a |
usage()
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
error("usage: %s -[vq] TIFFfile [rasterfile]\n", NULL);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
main(argc, argv)
|
|
kusano |
7d535a |
int argc;
|
|
kusano |
7d535a |
char *argv[];
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
char *inf = NULL;
|
|
kusano |
7d535a |
char *outf = NULL;
|
|
kusano |
7d535a |
FILE *fp;
|
|
kusano |
7d535a |
long width,
|
|
kusano |
7d535a |
height;
|
|
kusano |
7d535a |
int depth,
|
|
kusano |
7d535a |
numcolors;
|
|
kusano |
7d535a |
register TIFF *tif;
|
|
kusano |
7d535a |
TIFFDirectory *td;
|
|
kusano |
7d535a |
register u_char *inp,
|
|
kusano |
7d535a |
*outp;
|
|
kusano |
7d535a |
register int col,
|
|
kusano |
7d535a |
i;
|
|
kusano |
7d535a |
register long row;
|
|
kusano |
7d535a |
u_char *Map = NULL;
|
|
kusano |
7d535a |
u_char *buf;
|
|
kusano |
7d535a |
short bitspersample;
|
|
kusano |
7d535a |
short samplesperpixel;
|
|
kusano |
7d535a |
short photometric;
|
|
kusano |
7d535a |
u_short *redcolormap,
|
|
kusano |
7d535a |
*bluecolormap,
|
|
kusano |
7d535a |
*greencolormap;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
Pixrect *pix; /* The Sun Pixrect */
|
|
kusano |
7d535a |
colormap_t Colormap; /* The Pixrect Colormap */
|
|
kusano |
7d535a |
u_char red[256],
|
|
kusano |
7d535a |
green[256],
|
|
kusano |
7d535a |
blue[256];
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
setbuf(stderr, NULL);
|
|
kusano |
7d535a |
pname = argv[0];
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
while (--argc) {
|
|
kusano |
7d535a |
if ((++argv)[0][0] == '-')
|
|
kusano |
7d535a |
switch (argv[0][1]) {
|
|
kusano |
7d535a |
case 'v':
|
|
kusano |
7d535a |
Verbose = True;
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case 'q':
|
|
kusano |
7d535a |
usage();
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
default:
|
|
kusano |
7d535a |
fprintf(stderr, "%s: illegal option -%c.\n", pname,
|
|
kusano |
7d535a |
argv[0][1]);
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
else if (inf == NULL)
|
|
kusano |
7d535a |
inf = argv[0];
|
|
kusano |
7d535a |
else if (outf == NULL)
|
|
kusano |
7d535a |
outf = argv[0];
|
|
kusano |
7d535a |
else
|
|
kusano |
7d535a |
usage();
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (inf == NULL)
|
|
kusano |
7d535a |
error("%s: can't read input file from a stream.\n", NULL);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "Reading %s...", inf);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
tif = TIFFOpen(inf, "r");
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (tif == NULL)
|
|
kusano |
7d535a |
error("%s: error opening TIFF file %s", inf);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
TIFFPrintDirectory(tif, stderr, True, False, False);
|
|
kusano |
7d535a |
TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
|
|
kusano |
7d535a |
if (bitspersample > 8)
|
|
kusano |
7d535a |
error("%s: can't handle more than 8-bits per sample\n", NULL);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
|
|
kusano |
7d535a |
switch (samplesperpixel) {
|
|
kusano |
7d535a |
case 1:
|
|
kusano |
7d535a |
if (bitspersample == 1)
|
|
kusano |
7d535a |
depth = 1;
|
|
kusano |
7d535a |
else
|
|
kusano |
7d535a |
depth = 8;
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case 3:
|
|
kusano |
7d535a |
case 4:
|
|
kusano |
7d535a |
depth = 24;
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
default:
|
|
kusano |
7d535a |
error("%s: only handle 1-channel gray scale or 3-channel color\n");
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
|
|
kusano |
7d535a |
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "%dx%dx%d image, ", width, height, depth);
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "%d bits/sample, %d samples/pixel, ",
|
|
kusano |
7d535a |
bitspersample, samplesperpixel);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
pix = mem_create(width, height, depth);
|
|
kusano |
7d535a |
if (pix == (Pixrect *) NULL)
|
|
kusano |
7d535a |
error("%s: can't allocate memory for output pixrect...\n", NULL);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
numcolors = (1 << bitspersample);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
|
|
kusano |
7d535a |
if (numcolors == 2) {
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "monochrome ");
|
|
kusano |
7d535a |
Colormap.type = RMT_NONE;
|
|
kusano |
7d535a |
Colormap.length = 0;
|
|
kusano |
7d535a |
Colormap.map[0] = Colormap.map[1] = Colormap.map[2] = NULL;
|
|
kusano |
7d535a |
} else {
|
|
kusano |
7d535a |
switch (photometric) {
|
|
kusano |
7d535a |
case PHOTOMETRIC_MINISBLACK:
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "%d graylevels (min=black), ", numcolors);
|
|
kusano |
7d535a |
Map = (u_char *) malloc(numcolors * sizeof(u_char));
|
|
kusano |
7d535a |
for (i = 0; i < numcolors; i++)
|
|
kusano |
7d535a |
Map[i] = (255 * i) / numcolors;
|
|
kusano |
7d535a |
Colormap.type = RMT_EQUAL_RGB;
|
|
kusano |
7d535a |
Colormap.length = numcolors;
|
|
kusano |
7d535a |
Colormap.map[0] = Colormap.map[1] = Colormap.map[2] = Map;
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case PHOTOMETRIC_MINISWHITE:
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "%d graylevels (min=white), ", numcolors);
|
|
kusano |
7d535a |
Map = (u_char *) malloc(numcolors * sizeof(u_char));
|
|
kusano |
7d535a |
for (i = 0; i < numcolors; i++)
|
|
kusano |
7d535a |
Map[i] = 255 - ((255 * i) / numcolors);
|
|
kusano |
7d535a |
Colormap.type = RMT_EQUAL_RGB;
|
|
kusano |
7d535a |
Colormap.length = numcolors;
|
|
kusano |
7d535a |
Colormap.map[0] = Colormap.map[1] = Colormap.map[2] = Map;
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case PHOTOMETRIC_RGB:
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "truecolor ");
|
|
kusano |
7d535a |
Colormap.type = RMT_NONE;
|
|
kusano |
7d535a |
Colormap.length = 0;
|
|
kusano |
7d535a |
Colormap.map[0] = Colormap.map[1] = Colormap.map[2] = NULL;
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case PHOTOMETRIC_PALETTE:
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "colormapped ");
|
|
kusano |
7d535a |
Colormap.type = RMT_EQUAL_RGB;
|
|
kusano |
7d535a |
Colormap.length = numcolors;
|
|
kusano |
7d535a |
memset(red, 0, sizeof(red));
|
|
kusano |
7d535a |
memset(green, 0, sizeof(green));
|
|
kusano |
7d535a |
memset(blue, 0, sizeof(blue));
|
|
kusano |
7d535a |
TIFFGetField(tif, TIFFTAG_COLORMAP,
|
|
kusano |
7d535a |
&redcolormap, &greencolormap, &bluecolormap);
|
|
kusano |
7d535a |
for (i = 0; i < numcolors; i++) {
|
|
kusano |
7d535a |
red[i] = (u_char) CVT(redcolormap[i]);
|
|
kusano |
7d535a |
green[i] = (u_char) CVT(greencolormap[i]);
|
|
kusano |
7d535a |
blue[i] = (u_char) CVT(bluecolormap[i]);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
Colormap.map[0] = red;
|
|
kusano |
7d535a |
Colormap.map[1] = green;
|
|
kusano |
7d535a |
Colormap.map[2] = blue;
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case PHOTOMETRIC_MASK:
|
|
kusano |
7d535a |
error("%s: Don't know how to handle PHOTOMETRIC_MASK\n");
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case PHOTOMETRIC_DEPTH:
|
|
kusano |
7d535a |
error("%s: Don't know how to handle PHOTOMETRIC_DEPTH\n");
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
default:
|
|
kusano |
7d535a |
error("%s: unknown photometric (cmap): %d\n", photometric);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
buf = (u_char *) malloc(TIFFScanlineSize(tif));
|
|
kusano |
7d535a |
if (buf == NULL)
|
|
kusano |
7d535a |
error("%s: can't allocate memory for scanline buffer...\n", NULL);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
for (row = 0; row < height; row++) {
|
|
kusano |
7d535a |
if (TIFFReadScanline(tif, buf, row, 0) < 0)
|
|
kusano |
7d535a |
error("%s: bad data read on line: %d\n", row);
|
|
kusano |
7d535a |
inp = buf;
|
|
kusano |
7d535a |
outp = (u_char *) mprd_addr(mpr_d(pix), 0, row);
|
|
kusano |
7d535a |
switch (photometric) {
|
|
kusano |
7d535a |
case PHOTOMETRIC_RGB:
|
|
kusano |
7d535a |
if (samplesperpixel == 4)
|
|
kusano |
7d535a |
for (col = 0; col < width; col++) {
|
|
kusano |
7d535a |
*outp++ = *inp++; /* Blue */
|
|
kusano |
7d535a |
*outp++ = *inp++; /* Green */
|
|
kusano |
7d535a |
*outp++ = *inp++; /* Red */
|
|
kusano |
7d535a |
inp++; /* skip alpha channel */
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
else
|
|
kusano |
7d535a |
for (col = 0; col < width; col++) {
|
|
kusano |
7d535a |
*outp++ = *inp++; /* Blue */
|
|
kusano |
7d535a |
*outp++ = *inp++; /* Green */
|
|
kusano |
7d535a |
*outp++ = *inp++; /* Red */
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case PHOTOMETRIC_MINISWHITE:
|
|
kusano |
7d535a |
case PHOTOMETRIC_MINISBLACK:
|
|
kusano |
7d535a |
switch (bitspersample) {
|
|
kusano |
7d535a |
case 1:
|
|
kusano |
7d535a |
for (col = 0; col < ((width + 7) / 8); col++)
|
|
kusano |
7d535a |
*outp++ = *inp++;
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case 2:
|
|
kusano |
7d535a |
for (col = 0; col < ((width + 3) / 4); col++) {
|
|
kusano |
7d535a |
*outp++ = (*inp >> 6) & 3;
|
|
kusano |
7d535a |
*outp++ = (*inp >> 4) & 3;
|
|
kusano |
7d535a |
*outp++ = (*inp >> 2) & 3;
|
|
kusano |
7d535a |
*outp++ = *inp++ & 3;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case 4:
|
|
kusano |
7d535a |
for (col = 0; col < width / 2; col++) {
|
|
kusano |
7d535a |
*outp++ = *inp >> 4;
|
|
kusano |
7d535a |
*outp++ = *inp++ & 0xf;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case 8:
|
|
kusano |
7d535a |
for (col = 0; col < width; col++)
|
|
kusano |
7d535a |
*outp++ = *inp++;
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
default:
|
|
kusano |
7d535a |
error("%s: bad bits/sample: %d\n", bitspersample);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
case PHOTOMETRIC_PALETTE:
|
|
kusano |
7d535a |
memcpy(outp, inp, width);
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
default:
|
|
kusano |
7d535a |
error("%s: unknown photometric (write): %d\n", photometric);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
free((char *) buf);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "done.\n");
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (outf == NULL || strcmp(outf, "Standard Output") == 0) {
|
|
kusano |
7d535a |
outf = "Standard Output";
|
|
kusano |
7d535a |
fp = stdout;
|
|
kusano |
7d535a |
} else {
|
|
kusano |
7d535a |
if (!(fp = fopen(outf, "w")))
|
|
kusano |
7d535a |
error("%s: %s couldn't be opened for writing.\n", outf);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "Writing rasterfile in %s...", outf);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (pr_dump(pix, fp, &Colormap, RT_BYTE_ENCODED, 0) == PIX_ERR)
|
|
kusano |
7d535a |
error("%s: error writing Sun Rasterfile: %s\n", outf);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (Verbose)
|
|
kusano |
7d535a |
fprintf(stderr, "done.\n");
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
pr_destroy(pix);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (fp != stdout)
|
|
kusano |
7d535a |
fclose(fp);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
exit(0);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Local Variables:
|
|
kusano |
7d535a |
* mode: c
|
|
kusano |
7d535a |
* c-basic-offset: 8
|
|
kusano |
7d535a |
* fill-column: 78
|
|
kusano |
7d535a |
* End:
|
|
kusano |
7d535a |
*/
|