/****************************************************************************** * SAGE - Scalable Adaptive Graphics Environment * * Copyright (C) 2004 Electronic Visualization Laboratory, * University of Illinois at Chicago * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the distribution. * * Neither the name of the University of Illinois at Chicago nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Direct questions, comments etc about SAGE to http://www.evl.uic.edu/cavern/forum/ * *****************************************************************************/ #ifndef lint static char sccsid[] = "@(#)sgigt.c 1.8 4/25/89"; #endif #include #include #include #include "tiffio.h" #include "imginfo.h" static u_long *raster; /* displayable image */ static u_short bitspersample; static u_short samplesperpixel; static u_short photometric; static u_short orientation; static u_short *redcmap, *greencmap, *bluecmap;/* colormap for palette images */ #define rgba(r, g, b, a) ((a)<<24 | (b)<<16 | (g)<<8 | (r)) #define rgbi(r, g, b) (0xFF000000 | (b)<<16 | (g)<<8 | (r)) IMG * TIFFmakedisp(fname) char *fname; { TIFF *tif; short width, height; register IMG *im; tif = TIFFOpen(fname, "r"); if(tif == NULL) return NULL; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); im = (IMG *)malloc(sizeof(IMG)); im->type = IT_LONG; im->rowbytes = sizeof(long) * width; im->xsize = width; im->ysize = height; im->data = (unsigned char *)malloc(im->rowbytes * height); if(im->data == NULL) { fprintf(stderr, "Can't malloc %d bytes of memory for image\n", im->rowbytes * height); exit(2); } if(tiffgt(tif, width, height, (u_long *)im->data) == 0) { free(im->data); free(im); im = NULL; } TIFFClose(tif); return im; } RGBvalue **BWmap; static tiffgt(tif, w, h, raster) TIFF *tif; int w, h; u_long *raster; { u_short minsamplevalue, maxsamplevalue, planarconfig; RGBvalue *Map; int e; if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) { switch (samplesperpixel) { case 1: photometric = PHOTOMETRIC_MINISBLACK; break; case 3: case 4: photometric = PHOTOMETRIC_RGB; break; default: fprintf(stderr, "Missing needed \"%s\" tag.\n", "PhotometricInterpretation"); return (0); } printf("No \"PhotometricInterpretation\" tag, assuming %s.\n", photometric == PHOTOMETRIC_RGB ? "RGB" : "min-is-black"); } if (!TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel)) samplesperpixel = 1; if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample)) bitspersample = 8; if (!TIFFGetField(tif, TIFFTAG_MINSAMPLEVALUE, &minsamplevalue)) minsamplevalue = 0; if (!TIFFGetField(tif, TIFFTAG_MAXSAMPLEVALUE, &maxsamplevalue)) maxsamplevalue = (1< 0;) { pp[0] = Map[pp[0]]; pp[1] = Map[pp[1]]; pp[2] = Map[pp[2]]; pp += samplesperpixel; } pp = buf; } if(samplesperpixel == 4) { for(x = w; --x >= 0; pp += 4) *cp++ = rgba(pp[0], pp[1], pp[2],pp[3]); } else { for (x = w; x-- > 0; pp += samplesperpixel) *cp++ = rgbi(pp[0], pp[1], pp[2]); } break; case 16: { register u_short *wp; if (Map) { wp = (u_short *)pp; for (x = w; x-- > 0;) { wp[0] = Map[wp[0]]; wp[1] = Map[wp[1]]; wp[2] = Map[wp[2]]; wp += samplesperpixel; } } wp = (u_short *)pp; for (x = w; x-- > 0;) { *cp++ = rgbi(wp[0], wp[1], wp[2]); wp += samplesperpixel; } break; } } break; case PHOTOMETRIC_PALETTE: for (x = w; x-- > 0;) { RGBvalue c = *pp++; *cp++ = rgbi(redcmap[c], greencmap[c], bluecmap[c]); } break; case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISBLACK: if(samplesperpixel > 1) goto rgb; if (bitspersample == 8) { register RGBvalue c; for (x = w; x-- > 0;) { c = Map[*pp++]; *cp++ = rgbi(c, c, c); } } else gtbw(bitspersample, w, cp, pp); break; } y += (orientation == ORIENTATION_TOPLEFT ? -1 : 1); } return (1); } gtseparate(tif, raster, Map, h, w) TIFF *tif; u_long *raster; register RGBvalue *Map; int h, w; { register u_long *cp; register int x; u_char *red; int scanline, row, y; scanline = TIFFScanlineSize(tif); switch (samplesperpixel) { case 1: red = (u_char *)malloc(scanline); break; case 3: case 4: red = (u_char *)malloc(4*scanline); break; } y = setorientation(tif, h); for (row = 0; row < h; row++) { cp = raster + y*w; if (TIFFReadScanline(tif, red, row, 0) < 0) break; switch (photometric) { case PHOTOMETRIC_RGB: { register u_char *r, *g, *b, *a; r = red; if (TIFFReadScanline(tif, g = r + scanline, row, 1) < 0) break; if (TIFFReadScanline(tif, b = g + scanline, row, 2) < 0) break; if(samplesperpixel == 4) { a = b + scanline; if(TIFFReadScanline(tif, a, row, 3) < 0) break; } switch (bitspersample) { case 8: if(samplesperpixel == 4) { for(x = w; --x >= 0; ) *cp++ = rgba(*r++, *g++, *b++, *a++); } else { for (x = w; x-- > 0;) *cp++ = rgbi(*r++, *g++, *b++); } break; case 16: #define wp(x) ((u_short *)(x)) for (x = 0; x < w; x++) *cp++ = rgbi( Map[wp(r)[x]], Map[wp(g)[x]], Map[wp(b)[x]]); break; #undef wp } break; } case PHOTOMETRIC_PALETTE: { register u_char *pp = red; for (x = w; x-- > 0;) { RGBvalue c = *pp++; *cp++ = rgbi(redcmap[c], greencmap[c], bluecmap[c]); } break; } case PHOTOMETRIC_MINISWHITE: case PHOTOMETRIC_MINISBLACK: if (bitspersample == 8) { register u_short *pp = (u_short *)red; register RGBvalue c; for (x = w; x-- > 0;) { c = Map[*pp++]; *cp++ = rgbi(c, c, c); } } else gtbw(bitspersample, w, Map, cp, red); break; } y += (orientation == ORIENTATION_TOPLEFT ? -1 : 1); } if (red) free(red); return (1); } /* * Greyscale images with less than 8 bits/sample are handled * with a table to avoid lots of shits and masks. The table * is setup so that gtbw (below) can retrieve 8/bitspersample * pixel values simply by indexing into the table with one * number. */ makebwmap(Map) RGBvalue *Map; { register int i; int nsamples = 8 / bitspersample; register RGBvalue *p; BWmap = (RGBvalue **)malloc( 256*sizeof (RGBvalue *)+(256*nsamples*sizeof(RGBvalue))); if (BWmap == NULL) { fprintf(stderr, "No space for B&W mapping table.\n"); return (0); } p = (RGBvalue *)(BWmap + 256); for (i = 0; i < 256; i++) { BWmap[i] = p; switch (bitspersample) { case 1: *p++ = Map[i>>7]; *p++ = Map[(i>>6)&1]; *p++ = Map[(i>>5)&1]; *p++ = Map[(i>>4)&1]; *p++ = Map[(i>>3)&1]; *p++ = Map[(i>>2)&1]; *p++ = Map[(i>>1)&1]; *p++ = Map[i&1]; break; case 2: *p++ = Map[i>>6]; *p++ = Map[(i>>4)&3]; *p++ = Map[(i>>2)&3]; *p++ = Map[i&3]; break; case 4: *p++ = Map[i>>4]; *p++ = Map[i&0xf]; break; } } return (1); } #define REPEAT8(op) REPEAT4(op); REPEAT4(op) #define REPEAT4(op) REPEAT2(op); REPEAT2(op) #define REPEAT2(op) op; op gtbw(bitspersample, w, cp, pp) int bitspersample, w; register u_long *cp; register u_char *pp; { register RGBvalue c, *bw; register int x; switch (bitspersample) { case 1: for (x = w; x > 0; x -= 8) { bw = BWmap[*pp++]; REPEAT8(c = *bw++; *cp++ = rgbi(c, c, c)); } break; case 2: for (x = w; x > 0; x -= 4) { bw = BWmap[*pp++]; REPEAT4(c = *bw++; *cp++ = rgbi(c, c, c)); } break; case 4: for (x = w; x > 0; x -= 2) { bw = BWmap[*pp++]; REPEAT2(c = *bw++; *cp++ = rgbi(c, c, c)); } break; } }