예제 #1
1
파일: tiffdither.c 프로젝트: aosm/tcl
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);
	if (fillorder)
		TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
	else
		CopyField(TIFFTAG_FILLORDER, shortv);
	sprintf(thing, "Dithered B&W version of %s", argv[optind]);
	TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, thing);
	CopyField(TIFFTAG_PHOTOMETRIC, shortv);
	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);
}
예제 #2
0
파일: raw_decode.c 프로젝트: blowekamp/vxl
int
main(int argc, char **argv)
{
	TIFF		*tif;
	static const char *srcfilerel = "images/quad-tile.jpg.tiff";
	char *srcdir = NULL;
	char srcfile[1024];
	unsigned short h, v;
	int status;
	unsigned char *buffer;
	uint32 *rgba_buffer;
	tsize_t sz, szout;
	unsigned int pixel_status = 0;

        (void) argc;
        (void) argv;

	if ((srcdir = getenv("srcdir")) == NULL) {
		srcdir = ".";
	}
        printf("XXXXXXXX %s",srcdir);
	if ((strlen(srcdir) + 1 + strlen(srcfilerel)) >= sizeof(srcfile)) {
		fprintf( stderr, "srcdir too long %s\n", srcdir);
		exit( 1 );
	}
	strcpy(srcfile,srcdir);
	strcat(srcfile,"/");
	strcat(srcfile,srcfilerel);

	tif = TIFFOpen(srcfile,"r");
	if ( tif == NULL ) {
		fprintf( stderr, "Could not open %s\n", srcfile);
		exit( 1 );
	}

	status = TIFFGetField(tif,TIFFTAG_YCBCRSUBSAMPLING, &h, &v);
	if ( status == 0 || h != 2 || v != 2) {
		fprintf( stderr, "Could not retrieve subsampling tag.\n" );
		exit(1);
	}

	/*
	 * What is the appropriate size of a YCbCr encoded tile?
	 */
	sz = TIFFTileSize(tif);
	if( sz != 24576) {
		fprintf(stderr, "tiles are %d bytes\n", (int)sz);
		exit(1);
	}

	buffer = (unsigned char *) malloc(sz);

	/*
	 * Read a tile in decompressed form, but still YCbCr subsampled.
	 */
	szout = TIFFReadEncodedTile(tif,9,buffer,sz);
	if (szout != sz) {
		fprintf( stderr, 
			 "Did not get expected result code from TIFFReadEncodedTile()(%d instead of %d)\n", 
			 (int) szout, (int) sz );
		return 1;
	}

	if( check_cluster( 0, buffer, cluster_0 )
	    || check_cluster( 64, buffer, cluster_64 )
	    || check_cluster( 128, buffer, cluster_128 ) ) {
		exit(1);
	}
	free(buffer);

	/*
	 * Read a tile using the built-in conversion to RGB format provided by the JPEG library.
	 */
	TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);

	sz = TIFFTileSize(tif);
	if( sz != 128*128*3) {
		fprintf(stderr, "tiles are %d bytes\n", (int)sz);
		exit(1);
	}

	buffer = (unsigned char *) malloc(sz);

	szout = TIFFReadEncodedTile(tif,9,buffer,sz);
	if (szout != sz) {
		fprintf( stderr, 
			 "Did not get expected result code from TIFFReadEncodedTile()(%d instead of %d)\n", 
			 (int) szout, (int) sz );
		return 1;
	}

	/*
	 * JPEG decoding is inherently inexact, so we can't test for exact
	 * pixel values.  (Well, if we knew exactly which libjpeg version
	 * we were using, and with what settings, we could expect specific
	 * values ... but it's not worth the trouble to keep track of.)
	 * Hence, use ranges of expected values.  The ranges may need to be
	 * widened over time as more versions of libjpeg appear.
	 */
	pixel_status |= check_rgb_pixel( 0, 15, 18, 0, 0, 18, 41, buffer );
	pixel_status |= check_rgb_pixel( 64, 0, 0, 0, 0, 0, 2, buffer );
	pixel_status |= check_rgb_pixel( 512, 5, 6, 34, 36, 182, 196, buffer );

	free( buffer );

	TIFFClose(tif);

	/*
	 * Reopen and test reading using the RGBA interface.
	 */
	tif = TIFFOpen(srcfile,"r");
	
	sz = 128 * 128 * sizeof(uint32);
	rgba_buffer = (uint32 *) malloc(sz);
	
	if (!TIFFReadRGBATile( tif, 1*128, 2*128, rgba_buffer )) {
		fprintf( stderr, "TIFFReadRGBATile() returned failure code.\n" );
		return 1;
	}

	/*
	 * Currently TIFFReadRGBATile() just uses JPEGCOLORMODE_RGB so this
	 * trivally matches the last results.  Eventually we should actually
	 * accomplish it from the YCbCr subsampled buffer ourselves in which
	 * case the results may be subtly different but similar.
	 */
	pixel_status |= check_rgba_pixel( 0, 15, 18, 0, 0, 18, 41, 255, 255,
					  rgba_buffer );
	pixel_status |= check_rgba_pixel( 64, 0, 0, 0, 0, 0, 2, 255, 255,
					  rgba_buffer );
	pixel_status |= check_rgba_pixel( 512, 5, 6, 34, 36, 182, 196, 255, 255,
					  rgba_buffer );

	free( rgba_buffer );
	TIFFClose(tif);

	if (pixel_status) {
		exit(1);
	}
	
	exit( 0 );
}
예제 #3
0
int tiff_write(char *file, Pic *pic)
{
    TIFF *tif;

    uint32 samples_per_pixel = pic->bpp;
    uint32 w = pic->nx;
    uint32 h = pic->ny;
    uint32 scanline_size = samples_per_pixel * w;
    uint32 y;
    char *scanline, *scanline_buf;

    tif = TIFFOpen(file, "w");
    if( !tif )
	return FALSE;

    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w);
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h);

    /* These are the charateristics of our Pic data */
    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel);
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    if (samples_per_pixel<3)
	TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
    else
	TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);

    /*
     * Turn on LZW compression.
     * Shhhhh!  Don't tell Unisys!
     */
    TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
    /*
     * Predictors:
     *     1 (default) -- No predictor
     *     2           -- Horizontal differencing
     */
    TIFFSetField(tif, TIFFTAG_PREDICTOR, 2);
    
    if( TIFFScanlineSize(tif) != scanline_size )
    {
	fprintf(stderr,
		"TIFF: Mismatch with library's expected scanline size!\n");
	return FALSE;
    }
    
    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, -1));

    scanline_buf = (char *)malloc(scanline_size);
    if (!scanline_buf) {
	fprintf(stderr, "TIFF: Can't allocate scanline buffer!\n");
	return FALSE;
    }
    scanline = pic->pix;
    for(y=0; y<h; y++)
    {
	memcpy(scanline_buf, scanline, scanline_size);
	TIFFWriteScanline(tif, scanline_buf, y, 0);
	    /* note that TIFFWriteScanline modifies the buffer you pass it */
	scanline += scanline_size;
    }
    free(scanline_buf);

    TIFFClose(tif);

    return TRUE;
}
예제 #4
0
bool
TIFFOutput::put_parameter (const std::string &name, TypeDesc type,
                           const void *data)
{
    if (Strutil::iequals(name, "Artist") && type == TypeDesc::STRING) {
        TIFFSetField (m_tif, TIFFTAG_ARTIST, *(char**)data);
        return true;
    }
    if (Strutil::iequals(name, "Compression") && type == TypeDesc::STRING) {
        int compress = COMPRESSION_LZW;  // default
        const char *str = *(char **)data;
        if (str) {
            if (Strutil::iequals (str, "none"))
                compress = COMPRESSION_NONE;
            else if (Strutil::iequals (str, "lzw"))
                compress = COMPRESSION_LZW;
            else if (Strutil::iequals (str, "zip") || Strutil::iequals (str, "deflate"))
                compress = COMPRESSION_ADOBE_DEFLATE;
            else if (Strutil::iequals (str, "packbits"))
                compress = COMPRESSION_PACKBITS;
            else if (Strutil::iequals (str, "ccittrle"))
                compress = COMPRESSION_CCITTRLE;
        }
        TIFFSetField (m_tif, TIFFTAG_COMPRESSION, compress);
        // Use predictor when using compression
        if (compress == COMPRESSION_LZW || compress == COMPRESSION_ADOBE_DEFLATE) {
            if (m_spec.format == TypeDesc::FLOAT || m_spec.format == TypeDesc::DOUBLE || m_spec.format == TypeDesc::HALF) {
                // TIFFSetField (m_tif, TIFFTAG_PREDICTOR, PREDICTOR_FLOATINGPOINT);

                // Older versions of libtiff did not support this
                // predictor.  So to prevent us from writing TIFF files
                // that certain apps can't read, don't use it. Ugh.
                // FIXME -- lift this restriction when we think the newer
                // libtiff is widespread enough to no longer worry about this.
            }
            else
                TIFFSetField (m_tif, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL);
        }
    }
    if (Strutil::iequals(name, "Copyright") && type == TypeDesc::STRING) {
        TIFFSetField (m_tif, TIFFTAG_COPYRIGHT, *(char**)data);
        return true;
    }
    if (Strutil::iequals(name, "DateTime") && type == TypeDesc::STRING) {
        TIFFSetField (m_tif, TIFFTAG_DATETIME, *(char**)data);
        return true;
    }
    if ((Strutil::iequals(name, "name") || Strutil::iequals(name, "DocumentName")) && type == TypeDesc::STRING) {
        TIFFSetField (m_tif, TIFFTAG_DOCUMENTNAME, *(char**)data);
        return true;
    }
    if (Strutil::iequals(name,"fovcot") && type == TypeDesc::FLOAT) {
        double d = *(float *)data;
        TIFFSetField (m_tif, TIFFTAG_PIXAR_FOVCOT, d);
        return true;
    }
    if ((Strutil::iequals(name, "host") || Strutil::iequals(name, "HostComputer")) && type == TypeDesc::STRING) {
        TIFFSetField (m_tif, TIFFTAG_HOSTCOMPUTER, *(char**)data);
        return true;
    }
    if ((Strutil::iequals(name, "description") || Strutil::iequals(name, "ImageDescription")) &&
          type == TypeDesc::STRING) {
        TIFFSetField (m_tif, TIFFTAG_IMAGEDESCRIPTION, *(char**)data);
        return true;
    }
    if (Strutil::iequals(name, "tiff:Predictor") && type == TypeDesc::INT) {
        TIFFSetField (m_tif, TIFFTAG_PREDICTOR, *(int *)data);
        return true;
    }
    if (Strutil::iequals(name, "ResolutionUnit") && type == TypeDesc::STRING) {
        const char *s = *(char**)data;
        bool ok = true;
        if (Strutil::iequals (s, "none"))
            TIFFSetField (m_tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE);
        else if (Strutil::iequals (s, "in") || Strutil::iequals (s, "inch"))
            TIFFSetField (m_tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
        else if (Strutil::iequals (s, "cm"))
            TIFFSetField (m_tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER);
        else ok = false;
        return ok;
    }
    if (Strutil::iequals(name, "ResolutionUnit") && type == TypeDesc::UINT) {
        TIFFSetField (m_tif, TIFFTAG_RESOLUTIONUNIT, *(unsigned int *)data);
        return true;
    }
    if (Strutil::iequals(name, "tiff:RowsPerStrip")
          && ! m_spec.tile_width /* don't set rps for tiled files */
          && m_planarconfig == PLANARCONFIG_CONTIG /* only for contig */) {
        if (type == TypeDesc::INT) {
            TIFFSetField (m_tif, TIFFTAG_ROWSPERSTRIP,
                          std::min (*(int*)data, m_spec.height));
            return true;
        } else if (type == TypeDesc::STRING) {
            // Back-compatibility with Entropy and PRMan
            TIFFSetField (m_tif, TIFFTAG_ROWSPERSTRIP,
                          std::min (atoi(*(char **)data), m_spec.height));
            return true;
        }
    }
    if (Strutil::iequals(name, "Software") && type == TypeDesc::STRING) {
        TIFFSetField (m_tif, TIFFTAG_SOFTWARE, *(char**)data);
        return true;
    }
    if (Strutil::iequals(name, "tiff:SubFileType") && type == TypeDesc::INT) {
        TIFFSetField (m_tif, TIFFTAG_SUBFILETYPE, *(int*)data);
        return true;
    }
    if (Strutil::iequals(name, "textureformat") && type == TypeDesc::STRING) {
        TIFFSetField (m_tif, TIFFTAG_PIXAR_TEXTUREFORMAT, *(char**)data);
        return true;
    }
    if (Strutil::iequals(name, "wrapmodes") && type == TypeDesc::STRING) {
        TIFFSetField (m_tif, TIFFTAG_PIXAR_WRAPMODES, *(char**)data);
        return true;
    }
    if (Strutil::iequals(name, "worldtocamera") && type == TypeDesc::TypeMatrix) {
        TIFFSetField (m_tif, TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA, data);
        return true;
    }
    if (Strutil::iequals(name, "worldtoscreen") && type == TypeDesc::TypeMatrix) {
        TIFFSetField (m_tif, TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN, data);
        return true;
    }
    if (Strutil::iequals(name, "XResolution") && type == TypeDesc::FLOAT) {
        TIFFSetField (m_tif, TIFFTAG_XRESOLUTION, *(float *)data);
        return true;
    }
    if (Strutil::iequals(name, "YResolution") && type == TypeDesc::FLOAT) {
        TIFFSetField (m_tif, TIFFTAG_YRESOLUTION, *(float *)data);
        return true;
    }

    // FIXME -- we don't currently support writing of EXIF fields.  TIFF
    // in theory allows it, using a custom IFD directory, but at
    // present, it appears that libtiff only supports reading custom
    // IFD's, not writing them.

    return false;
}
예제 #5
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
    TIFF *faxTIFF = NULL;
    FIBITMAP *dib = NULL;
    FIMEMORY *memory = NULL;

    //int verbose = 0;
    int stretch = 0;
    int rows;
    float resX = 204.0;
    float resY = 196.0;

    uint32 xsize = G3_DEFAULT_WIDTH;
    int compression_in = COMPRESSION_CCITTFAX3;
    int fillorder_in = FILLORDER_LSB2MSB;
    uint32 group3options_in = 0;    // 1d-encoded
    uint32 group4options_in = 0;    // compressed
    int photometric_in = PHOTOMETRIC_MINISWHITE;

    if(handle==NULL) return NULL;

    try {
        // set default load options

        compression_in = COMPRESSION_CCITTFAX3;         // input is g3-encoded
        group3options_in &= ~GROUP3OPT_2DENCODING;      // input is 1d-encoded (g3 only)
        fillorder_in = FILLORDER_MSB2LSB;               // input has msb-to-lsb fillorder

        /*
          Original input-related fax2tiff options

          while ((c = getopt(argc, argv, "R:X:o:1234ABLMPUW5678abcflmprsuvwz?")) != -1) {
          switch (c) {
          // input-related options
          case '3':       // input is g3-encoded
          compression_in = COMPRESSION_CCITTFAX3;
          break;
          case '4':       // input is g4-encoded
          compression_in = COMPRESSION_CCITTFAX4;
          break;
          case 'U':       // input is uncompressed (g3 and g4)
          group3options_in |= GROUP3OPT_UNCOMPRESSED;
          group4options_in |= GROUP4OPT_UNCOMPRESSED;
          break;
          case '1':       // input is 1d-encoded (g3 only)
          group3options_in &= ~GROUP3OPT_2DENCODING;
          break;
          case '2':       // input is 2d-encoded (g3 only)
          group3options_in |= GROUP3OPT_2DENCODING;
          break;
          case 'P':   // input has not-aligned EOL (g3 only)
          group3options_in &= ~GROUP3OPT_FILLBITS;
          break;
          case 'A':       // input has aligned EOL (g3 only)
          group3options_in |= GROUP3OPT_FILLBITS;
          break;
          case 'W':       // input has 0 mean white
          photometric_in = PHOTOMETRIC_MINISWHITE;
          break;
          case 'B':       // input has 0 mean black
          photometric_in = PHOTOMETRIC_MINISBLACK;
          break;
          case 'L':       // input has lsb-to-msb fillorder
          fillorder_in = FILLORDER_LSB2MSB;
          break;
          case 'M':       // input has msb-to-lsb fillorder
          fillorder_in = FILLORDER_MSB2LSB;
          break;
          case 'R':       // input resolution
          resY = (float) atof(optarg);
          break;
          case 'X':       // input width
          xsize = (uint32) atoi(optarg);
          break;

          // output-related options
          case 's':       // stretch image by dup'ng scanlines
          stretch = 1;
          break;
          case 'v':       // -v for info
          verbose++;
          break;
          }
          }

        */

        // open a temporary memory buffer to save decoded scanlines
        memory = FreeImage_OpenMemory();
        if(!memory) throw FI_MSG_ERROR_MEMORY;

        // wrap the raw fax file
        faxTIFF = TIFFClientOpen("(FakeInput)", "w",
                                 // TIFFClientOpen() fails if we don't set existing value here
                                 NULL,
                                 _g3ReadProc, _g3WriteProc,
                                 _g3SeekProc, _g3CloseProc,
                                 _g3SizeProc, _g3MapProc,
                                 _g3UnmapProc);

        if (faxTIFF == NULL) {
            throw "Can not create fake input file";
        }
        TIFFSetMode(faxTIFF, O_RDONLY);
        TIFFSetField(faxTIFF, TIFFTAG_IMAGEWIDTH, xsize);
        TIFFSetField(faxTIFF, TIFFTAG_SAMPLESPERPIXEL, 1);
        TIFFSetField(faxTIFF, TIFFTAG_BITSPERSAMPLE, 1);
        TIFFSetField(faxTIFF, TIFFTAG_FILLORDER, fillorder_in);
        TIFFSetField(faxTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
        TIFFSetField(faxTIFF, TIFFTAG_PHOTOMETRIC, photometric_in);
        TIFFSetField(faxTIFF, TIFFTAG_YRESOLUTION, resY);
        TIFFSetField(faxTIFF, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);

        // NB: this must be done after directory info is setup
        TIFFSetField(faxTIFF, TIFFTAG_COMPRESSION, compression_in);
        if (compression_in == COMPRESSION_CCITTFAX3)
            TIFFSetField(faxTIFF, TIFFTAG_GROUP3OPTIONS, group3options_in);
        else if (compression_in == COMPRESSION_CCITTFAX4)
            TIFFSetField(faxTIFF, TIFFTAG_GROUP4OPTIONS, group4options_in);

        resX = 204;
        if (!stretch) {
            TIFFGetField(faxTIFF, TIFFTAG_YRESOLUTION, &resY);
        } else {
            resY = 196;
        }

        // decode the raw fax data
        rows = copyFaxFile(io, handle, faxTIFF, xsize, stretch, memory);
        if(rows <= 0) throw "Error when decoding raw fax file : check the decoder options";


        // allocate the output dib
        dib = FreeImage_Allocate(xsize, rows, 1);
        unsigned pitch = FreeImage_GetPitch(dib);
        uint32 linesize = TIFFhowmany8(xsize);

        // fill the bitmap structure ...
        // ... palette
        RGBQUAD *pal = FreeImage_GetPalette(dib);
        if(photometric_in == PHOTOMETRIC_MINISWHITE) {
            pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
            pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 0;
        } else {
            pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
            pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
        }
        // ... resolution
        FreeImage_SetDotsPerMeterX(dib, (unsigned)(resX/0.0254000 + 0.5));
        FreeImage_SetDotsPerMeterY(dib, (unsigned)(resY/0.0254000 + 0.5));

        // read the decoded scanline and fill the bitmap data
        FreeImage_SeekMemory(memory, 0, SEEK_SET);
        BYTE *bits = FreeImage_GetScanLine(dib, rows - 1);
        for(int k = 0; k < rows; k++) {
            FreeImage_ReadMemory(bits, linesize, 1, memory);
            bits -= pitch;
        }

        // free the TIFF wrapper
        TIFFClose(faxTIFF);

        // free the memory buffer
        FreeImage_CloseMemory(memory);

    } catch(const char *message) {
        if(memory) FreeImage_CloseMemory(memory);
        if(faxTIFF) TIFFClose(faxTIFF);
        if(dib) FreeImage_Unload(dib);
        FreeImage_OutputMessageProc(s_format_id, message);
        return NULL;
    }

    return dib;

}
예제 #6
0
파일: main.c 프로젝트: 3660628/hunter
int
main()
{
  TIFF    *tif;
  size_t    i;
  unsigned char  buf[] = { 0, 127, 255 };
  char    *value;

  /* Test whether we can write tags. */
  tif = TIFFOpen(filename, "w");
  if (!tif) {
    fprintf (stderr, "Can't create test TIFF file %s.\n", filename);
    return 1;
  }

  if (!TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, 1)) {
    fprintf (stderr, "Can't set ImageWidth tag.\n");
    goto failure;
  }
  if (!TIFFSetField(tif, TIFFTAG_IMAGELENGTH, 1)) {
    fprintf (stderr, "Can't set ImageLength tag.\n");
    goto failure;
  }
  if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8)) {
    fprintf (stderr, "Can't set BitsPerSample tag.\n");
    goto failure;
  }
  if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, sizeof(buf))) {
    fprintf (stderr, "Can't set SamplesPerPixel tag.\n");
    goto failure;
  }
  if (!TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) {
    fprintf (stderr, "Can't set PlanarConfiguration tag.\n");
    goto failure;
  }
  if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)) {
    fprintf (stderr, "Can't set PhotometricInterpretation tag.\n");
    goto failure;
  }

  for (i = 0; i < NTAGS; i++) {
    if (!TIFFSetField(tif, ascii_tags[i].tag,
          ascii_tags[i].value)) {
      fprintf(stderr, "Can't set tag %lu.\n",
        (unsigned long)ascii_tags[i].tag);
      goto failure;
    }
  }

  /* InkNames tag has special form, so we handle it separately. */
  if (!TIFFSetField(tif, TIFFTAG_NUMBEROFINKS, 3)) {
    fprintf (stderr, "Can't set tag %d (NUMBEROFINKS).\n",
                         TIFFTAG_NUMBEROFINKS);
    goto failure;
  }
  if (!TIFFSetField(tif, TIFFTAG_INKNAMES, ink_names_size, ink_names)) {
    fprintf (stderr, "Can't set tag %d (INKNAMES).\n",
       TIFFTAG_INKNAMES);
    goto failure;
  }

  /* Write dummy pixel data. */
  if (!TIFFWriteScanline(tif, buf, 0, 0) < 0) {
    fprintf (stderr, "Can't write image data.\n");
    goto failure;
  }

  TIFFClose(tif);

  /* Ok, now test whether we can read written values. */
  tif = TIFFOpen(filename, "r");
  if (!tif) {
    fprintf (stderr, "Can't open test TIFF file %s.\n", filename);
    return 1;
  }

  for (i = 0; i < NTAGS; i++) {
    if (!TIFFGetField(tif, ascii_tags[i].tag, &value)
        || strcmp(value, ascii_tags[i].value)) {
      fprintf(stderr, "Can't get tag %lu.\n",
        (unsigned long)ascii_tags[i].tag);
      goto failure;
    }
  }

  if (!TIFFGetField(tif, TIFFTAG_INKNAMES, &value)
      || memcmp(value, ink_names, ink_names_size)) {
    fprintf (stderr, "Can't get tag %d (INKNAMES).\n",
       TIFFTAG_INKNAMES);
    goto failure;
  }

  TIFFClose(tif);

  /* All tests passed; delete file and exit with success status. */
  unlink(filename);
  return 0;

failure:
  /*
   * Something goes wrong; close file and return unsuccessful status.
   * Do not remove the file for further manual investigation.
   */
  TIFFClose(tif);
  return 1;
}
예제 #7
0
/** Opens a TIFF file.
  * \param[in] fileName The name of the file to open.
  * \param[in] openMode Mask defining how the file should be opened; bits are 
  *            NDFileModeRead, NDFileModeWrite, NDFileModeAppend, NDFileModeMultiple
  * \param[in] pArray A pointer to an NDArray; this is used to determine the array and attribute properties.
  */
asynStatus NDFileTIFF::openFile(const char *fileName, NDFileOpenMode_t openMode, NDArray *pArray)
{
    /* When we create TIFF variables and dimensions, we get back an
     * ID for each one. */
    static const char *functionName = "openFile";
    size_t sizeX, sizeY, rowsPerStrip;
    int bitsPerSample=8, sampleFormat=SAMPLEFORMAT_INT, samplesPerPixel, photoMetric, planarConfig;
    int colorMode=NDColorModeMono;
    NDAttribute *pAttribute = NULL;
    char tagString[MAX_ATTRIBUTE_STRING_SIZE] = {0};
    char attrString[MAX_ATTRIBUTE_STRING_SIZE] = {0};

    /* We don't support reading yet */
    if (openMode & NDFileModeRead) return(asynError);

    /* We don't support opening an existing file for appending yet */
    if (openMode & NDFileModeAppend) return(asynError);

   /* Create the file. */
    if ((this->output = TIFFOpen(fileName, "w")) == NULL ) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
        "%s:%s error opening file %s\n",
        driverName, functionName, fileName);
        return(asynError);
    }
    /* We do some special treatment based on colorMode */
    pAttribute = pArray->pAttributeList->find("ColorMode");
    if (pAttribute) pAttribute->getValue(NDAttrInt32, &colorMode);

    switch (pArray->dataType) {
        case NDInt8:
            sampleFormat = SAMPLEFORMAT_INT;
            bitsPerSample = 8;
            break;
        case NDUInt8:
            sampleFormat = SAMPLEFORMAT_UINT;
            bitsPerSample = 8;
            break;
        case NDInt16:
            sampleFormat = SAMPLEFORMAT_INT;
            bitsPerSample = 16;
            break;
        case NDUInt16:
            sampleFormat = SAMPLEFORMAT_UINT;
            bitsPerSample = 16;
            break;
        case NDInt32:
            sampleFormat = SAMPLEFORMAT_INT;
            bitsPerSample = 32;
            break;
        case NDUInt32:
            sampleFormat = SAMPLEFORMAT_UINT;
            bitsPerSample = 32;
            break;
        case NDFloat32:
            sampleFormat = SAMPLEFORMAT_IEEEFP;
            bitsPerSample = 32;
            break;
        case NDFloat64:
            sampleFormat = SAMPLEFORMAT_IEEEFP;
            bitsPerSample = 64;
            break;
    }
    if (pArray->ndims == 2) {
        sizeX = pArray->dims[0].size;
        sizeY = pArray->dims[1].size;
        rowsPerStrip = sizeY;
        samplesPerPixel = 1;
        photoMetric = PHOTOMETRIC_MINISBLACK;
        planarConfig = PLANARCONFIG_CONTIG;
        this->colorMode = NDColorModeMono;
    } else if ((pArray->ndims == 3) && (pArray->dims[0].size == 3) && (colorMode == NDColorModeRGB1)) {
        sizeX = pArray->dims[1].size;
        sizeY = pArray->dims[2].size;
        rowsPerStrip = sizeY;
        samplesPerPixel = 3;
        photoMetric = PHOTOMETRIC_RGB;
        planarConfig = PLANARCONFIG_CONTIG;
        this->colorMode = NDColorModeRGB1;
    } else if ((pArray->ndims == 3) && (pArray->dims[1].size == 3) && (colorMode == NDColorModeRGB2)) {
        sizeX = pArray->dims[0].size;
        sizeY = pArray->dims[2].size;
        rowsPerStrip = 1;
        samplesPerPixel = 3;
        photoMetric = PHOTOMETRIC_RGB;
        planarConfig = PLANARCONFIG_SEPARATE;
        this->colorMode = NDColorModeRGB2;
    } else if ((pArray->ndims == 3) && (pArray->dims[2].size == 3) && (colorMode == NDColorModeRGB3)) {
        sizeX = pArray->dims[0].size;
        sizeY = pArray->dims[1].size;
        rowsPerStrip = sizeY;
        samplesPerPixel = 3;
        photoMetric = PHOTOMETRIC_RGB;
        planarConfig = PLANARCONFIG_SEPARATE;
        this->colorMode = NDColorModeRGB3;
    } else {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, 
            "%s:%s: unsupported array structure\n",
            driverName, functionName);
        return(asynError);
    }

    /* this is in the unallocated 'reusable' range */
    static const int TIFFTAG_NDTIMESTAMP    = 65000;
    static const int TIFFTAG_UNIQUEID       = 65001;
    static const int TIFFTAG_EPICSTSSEC     = 65002;
    static const int TIFFTAG_EPICSTSNSEC    = 65003;
    static const TIFFFieldInfo NDTimeStampFI = {
        TIFFTAG_NDTIMESTAMP,1,1,TIFF_DOUBLE,FIELD_CUSTOM,1,0,(char *)"NDTimeStamp"
    };
    static const TIFFFieldInfo NDUniqueIdFI = {
        TIFFTAG_UNIQUEID,1,1,TIFF_LONG,FIELD_CUSTOM,1,0,(char *)"NDUniqueId"
    };
    static const TIFFFieldInfo EPICSTSSecFI = {
        TIFFTAG_EPICSTSSEC,1,1,TIFF_LONG,FIELD_CUSTOM,1,0,(char *)"EPICSTSSec"
    };
    static const TIFFFieldInfo EPICSTSNsecFI = {
        TIFFTAG_EPICSTSNSEC,1,1,TIFF_LONG,FIELD_CUSTOM,1,0,(char *)"EPICSTSNsec"
    };
    TIFFMergeFieldInfo(output, &NDTimeStampFI, 1);
    TIFFMergeFieldInfo(output, &NDUniqueIdFI, 1);
    TIFFMergeFieldInfo(output, &EPICSTSSecFI, 1);
    TIFFMergeFieldInfo(output, &EPICSTSNsecFI, 1);
    TIFFSetField(this->output, TIFFTAG_NDTIMESTAMP, pArray->timeStamp);
    TIFFSetField(this->output, TIFFTAG_UNIQUEID, pArray->uniqueId);
    TIFFSetField(this->output, TIFFTAG_EPICSTSSEC, pArray->epicsTS.secPastEpoch);
    TIFFSetField(this->output, TIFFTAG_EPICSTSNSEC, pArray->epicsTS.nsec);
    TIFFSetField(this->output, TIFFTAG_BITSPERSAMPLE, bitsPerSample);
    TIFFSetField(this->output, TIFFTAG_SAMPLEFORMAT, sampleFormat);
    TIFFSetField(this->output, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel);
    TIFFSetField(this->output, TIFFTAG_PHOTOMETRIC, photoMetric);
    TIFFSetField(this->output, TIFFTAG_PLANARCONFIG, planarConfig);
    TIFFSetField(this->output, TIFFTAG_IMAGEWIDTH, (epicsUInt32)sizeX);
    TIFFSetField(this->output, TIFFTAG_IMAGELENGTH, (epicsUInt32)sizeY);
    TIFFSetField(this->output, TIFFTAG_ROWSPERSTRIP, (epicsUInt32)rowsPerStrip);
    
    this->pFileAttributes->clear();
    this->getAttributes(this->pFileAttributes);
    pArray->pAttributeList->copy(this->pFileAttributes);
 
    pAttribute = this->pFileAttributes->find("Model");
    if (pAttribute) {
        pAttribute->getValue(NDAttrString, tagString);
        TIFFSetField(this->output, TIFFTAG_MODEL, tagString);
    } else {
        TIFFSetField(this->output, TIFFTAG_MODEL, "Unknown");
    }
    
    pAttribute = this->pFileAttributes->find("Manufacturer");
    if (pAttribute) {
        pAttribute->getValue(NDAttrString, tagString);
        TIFFSetField(this->output, TIFFTAG_MAKE, tagString);
    } else {
        TIFFSetField(this->output, TIFFTAG_MAKE, "Unknown");
    }

    TIFFSetField(this->output, TIFFTAG_SOFTWARE, "EPICS areaDetector");

    int count = 0;
    int tagId = TIFFTAG_START_;
   
    numAttributes_ = this->pFileAttributes->count();
    asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
        "%s:%s this->pFileAttributes->count(): %d\n",
        driverName, functionName, numAttributes_);

    fieldInfo_ = (TIFFFieldInfo**) malloc(numAttributes_ * sizeof(TIFFFieldInfo *));
    if (fieldInfo_ == NULL) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
            "%s:%s error, fieldInfo_ malloc failed. file: %s\n",
            driverName, functionName, fileName);
        return asynError;
    }
    for (int i=0; i<numAttributes_; ++i) {
        asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
            "%s:%s Initializing %d fieldInfo_ entry.\n",
            driverName, functionName, i);
        fieldInfo_[i] = NULL;
    }
    
    asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
        "%s:%s Looping over attributes...\n",
        driverName, functionName);

    pAttribute = this->pFileAttributes->next(NULL);
    while (pAttribute) {
        const char *attributeName = pAttribute->getName();
        //const char *attributeDescription = pAttribute->getDescription();
        const char *attributeSource = pAttribute->getSource();

        asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
          "%s:%s : attribute: %s, source: %s\n",
          driverName, functionName, attributeName, attributeSource);

        NDAttrDataType_t attrDataType;
        size_t attrSize;
        NDAttrValue value;
        pAttribute->getValueInfo(&attrDataType, &attrSize);
        memset(tagString, 0, MAX_ATTRIBUTE_STRING_SIZE);

        switch (attrDataType) {
            case NDAttrInt8:
            case NDAttrUInt8:
            case NDAttrInt16:
            case NDAttrUInt16:
            case NDAttrInt32:
            case NDAttrUInt32: {
                pAttribute->getValue(attrDataType, &value.i32);
                epicsSnprintf(tagString, MAX_ATTRIBUTE_STRING_SIZE, "%s:%d", attributeName, value.i32);
                break;
            }
            case NDAttrFloat32: {
                pAttribute->getValue(attrDataType, &value.f32);
                epicsSnprintf(tagString, MAX_ATTRIBUTE_STRING_SIZE, "%s:%f", attributeName, value.f32);
                break;
            }
            case NDAttrFloat64: {
                pAttribute->getValue(attrDataType, &value.f64);
                epicsSnprintf(tagString, MAX_ATTRIBUTE_STRING_SIZE, "%s:%f", attributeName, value.f64);
                break;
            }
            case NDAttrString: {
                memset(attrString, 0, MAX_ATTRIBUTE_STRING_SIZE);
                pAttribute->getValue(attrDataType, attrString, MAX_ATTRIBUTE_STRING_SIZE);
                epicsSnprintf(tagString, MAX_ATTRIBUTE_STRING_SIZE, "%s:%s", attributeName, attrString);
                break;
            }
            case NDAttrUndefined:
                break;
            default:
                asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                          "%s:%s error, unknown attrDataType=%d\n",
                          driverName, functionName, attrDataType);
                return asynError;
                break;
        }

        if (attrDataType != NDAttrUndefined) {
            asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW,
                "%s:%s : tagId: %d, tagString: %s\n",
                  driverName, functionName, tagId, tagString);
            fieldInfo_[count] = (TIFFFieldInfo*) malloc(sizeof(TIFFFieldInfo));
            populateAsciiFieldInfo(fieldInfo_[count], tagId, attributeName);
            TIFFMergeFieldInfo(output, fieldInfo_[count], 1);
            TIFFSetField(this->output, tagId, tagString);
            ++count;
            ++tagId;
            if ((tagId == TIFFTAG_END_) || (count > numAttributes_)) {
                asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
                    "%s:%s error, Too many tags/attributes for file. tagId: %d, count: %d\n",
                    driverName, functionName, tagId, count);
                break;
            }
        }
        pAttribute = this->pFileAttributes->next(pAttribute);
    }
    
    return(asynSuccess);
}
예제 #8
0
void
rasterize(int interleaved, char* mode)
{
    register unsigned 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);
}
예제 #9
0
int
TIFFImageIterBegin(TIFFImageIter* img, TIFF* tif, int stop, char emsg[1024])
{
    uint16* sampleinfo;
    uint16 extrasamples;
    uint16 planarconfig;
    int colorchannels;

    img->tif = tif;
    img->stoponerr = stop;
    TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
    img->alpha = 0;
    TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
    TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
	&extrasamples, &sampleinfo);
    if (extrasamples == 1)
	switch (sampleinfo[0]) {
	case EXTRASAMPLE_ASSOCALPHA:	/* data is pre-multiplied */
	case EXTRASAMPLE_UNASSALPHA:	/* data is not pre-multiplied */
	    img->alpha = sampleinfo[0];
	    break;
	}
    colorchannels = img->samplesperpixel - extrasamples;
    TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
    if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) {
	switch (colorchannels) {
	case 1:
	    if (isCCITTCompression(tif))
		img->photometric = PHOTOMETRIC_MINISWHITE;
	    else
		img->photometric = PHOTOMETRIC_MINISBLACK;
	    break;
	case 3:
	    img->photometric = PHOTOMETRIC_RGB;
	    break;
	default:
	    sprintf(emsg, "Missing needed %s tag", photoTag);
	    return (0);
	}
    }
    switch (img->photometric) {
    case PHOTOMETRIC_PALETTE:
	if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
	    &img->redcmap, &img->greencmap, &img->bluecmap)) {
		TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Missing required \"Colormap\" tag");
	    return (0);
	}
	/* fall thru... */
    case PHOTOMETRIC_MINISWHITE:
    case PHOTOMETRIC_MINISBLACK:
/* This should work now so skip the check - BSR
	if (planarconfig == PLANARCONFIG_CONTIG && img->samplesperpixel != 1) {
	    sprintf(emsg,
		"Sorry, can not handle contiguous data with %s=%d, and %s=%d",
		photoTag, img->photometric,
		"Samples/pixel", img->samplesperpixel);
	    return (0);
	}
 */
	break;
    case PHOTOMETRIC_YCBCR:
	if (planarconfig != PLANARCONFIG_CONTIG) {
	    sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d",
		"Planarconfiguration", planarconfig);
	    return (0);
	}
	/* It would probably be nice to have a reality check here. */
	{ uint16 compress;
	  TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
	  if (compress == COMPRESSION_JPEG && planarconfig == PLANARCONFIG_CONTIG) {
	    /* can rely on libjpeg to convert to RGB */
	    /* XXX should restore current state on exit */
	    TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
	    img->photometric = PHOTOMETRIC_RGB;
	  }
	}
	break;
    case PHOTOMETRIC_RGB: 
	if (colorchannels < 3) {
	    sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
		"Color channels", colorchannels);
	    return (0);
	}
	break;
    case PHOTOMETRIC_SEPARATED: {
	uint16 inkset;
	TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
	if (inkset != INKSET_CMYK) {
	    sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
		"InkSet", inkset);
	    return (0);
	}
	if (img->samplesperpixel != 4) {
	    sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
		"Samples/pixel", img->samplesperpixel);
	    return (0);
	}
	break;
    }
    default:
	sprintf(emsg, "Sorry, can not handle image with %s=%d",
	    photoTag, img->photometric);
	return (0);
    }
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);

    TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
    switch (img->orientation) {
    case ORIENTATION_BOTRIGHT:
    case ORIENTATION_RIGHTBOT:	/* XXX */
    case ORIENTATION_LEFTBOT:	/* XXX */
	TIFFWarning(TIFFFileName(tif), "using bottom-left orientation");
	img->orientation = ORIENTATION_BOTLEFT;
	/* fall thru... */
    case ORIENTATION_BOTLEFT:
	break;
    case ORIENTATION_TOPRIGHT:
    case ORIENTATION_RIGHTTOP:	/* XXX */
    case ORIENTATION_LEFTTOP:	/* XXX */
    default:
	TIFFWarning(TIFFFileName(tif), "using top-left orientation");
	img->orientation = ORIENTATION_TOPLEFT;
	/* fall thru... */
    case ORIENTATION_TOPLEFT:
	break;
    }

    img->isContig =
	!(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1);
    if (img->isContig) {
	img->get = TIFFIsTiled(tif) ? gtTileContig : gtStripContig;
    } else {
	img->get = TIFFIsTiled(tif) ? gtTileSeparate : gtStripSeparate;
    }
    return (1);
}
예제 #10
0
파일: tiff-rgb.c 프로젝트: 3v1n0/wxWidgets
int main(int argc, char **argv)
{
    char *          input_file = NULL;
    double          image_gamma = TIFF_GAMMA;
    int             i, j;
    TIFF *          tif;
    unsigned char * scan_line;
    uint16          red[CMSIZE], green[CMSIZE], blue[CMSIZE];
    float	    refblackwhite[2*3];

    programName = argv[0];

    switch (argc) {
    case 2:
        image_gamma = TIFF_GAMMA;
        input_file = argv[1];
        break;
    case 4:
        if (!strcmp(argv[1], "-gamma")) {
            image_gamma = atof(argv[2]);
            input_file = argv[3];
        } else
            Usage();
        break;
    default:
        Usage();
    }

    for (i = 0; i < CMSIZE; i++) {
        if (i == 0)
            red[i] = green[i] = blue[i] = 0;
        else {
            red[i] = ROUND((pow(i / 255.0, 1.0 / image_gamma) * 65535.0));
            green[i] = ROUND((pow(i / 255.0, 1.0 / image_gamma) * 65535.0));
            blue[i] = ROUND((pow(i / 255.0, 1.0 / image_gamma) * 65535.0));
        }
    }
    refblackwhite[0] = 0.0; refblackwhite[1] = 255.0;
    refblackwhite[2] = 0.0; refblackwhite[3] = 255.0;
    refblackwhite[4] = 0.0; refblackwhite[5] = 255.0;

    if ((tif = TIFFOpen(input_file, "w")) == NULL) {
        fprintf(stderr, "can't open %s as a TIFF file\n", input_file);
        exit(0);
    }

    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, WIDTH);
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, HEIGHT);
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1);
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE);
#ifdef notdef
    TIFFSetField(tif, TIFFTAG_WHITEPOINT, whitex, whitey);
    TIFFSetField(tif, TIFFTAG_PRIMARYCHROMATICITIES, primaries);
#endif
    TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, refblackwhite);
    TIFFSetField(tif, TIFFTAG_TRANSFERFUNCTION, red, green, blue);

    scan_line = (unsigned char *) malloc(WIDTH * 3);

    for (i = 0; i < 255; i++) {
        for (j = 0; j < 75; j++) {
             scan_line[j * 3] = 255;
             scan_line[(j * 3) + 1] = 255 - i;
             scan_line[(j * 3) + 2] = 255 - i;
        }
        for (j = 75; j < 150; j++) {
             scan_line[j * 3] = 255 - i;
             scan_line[(j * 3) + 1] = 255;
             scan_line[(j * 3) + 2] = 255 - i;
        }
        for (j = 150; j < 225; j++) {
             scan_line[j * 3] = 255 - i;
             scan_line[(j * 3) + 1] = 255 - i;
             scan_line[(j * 3) + 2] = 255;
        }
        for (j = 225; j < 300; j++) {
             scan_line[j * 3] = (i - 1) / 2;
             scan_line[(j * 3) + 1] = (i - 1) / 2;
             scan_line[(j * 3) + 2] = (i - 1) / 2;
        }
        for (j = 300; j < 375; j++) {
             scan_line[j * 3] = 255 - i;
             scan_line[(j * 3) + 1] = 255;
             scan_line[(j * 3) + 2] = 255;
        }
        for (j = 375; j < 450; j++) {
             scan_line[j * 3] = 255;
             scan_line[(j * 3) + 1] = 255 - i;
             scan_line[(j * 3) + 2] = 255;
        }
        for (j = 450; j < 525; j++) {
             scan_line[j * 3] = 255;
             scan_line[(j * 3) + 1] = 255;
             scan_line[(j * 3) + 2] = 255 - i;
        }
        TIFFWriteScanline(tif, scan_line, i, 0);
    }
    for (i = 255; i < 512; i++) {
        for (j = 0; j < 75; j++) {
             scan_line[j * 3] = i;
             scan_line[(j * 3) + 1] = 0;
             scan_line[(j * 3) + 2] = 0;
        }
        for (j = 75; j < 150; j++) {
             scan_line[j * 3] = 0;
             scan_line[(j * 3) + 1] = i;
             scan_line[(j * 3) + 2] = 0;
        }
        for (j = 150; j < 225; j++) {
             scan_line[j * 3] = 0;
             scan_line[(j * 3) + 1] = 0;
             scan_line[(j * 3) + 2] = i;
        }
        for (j = 225; j < 300; j++) {
             scan_line[j * 3] = (i - 1) / 2;
             scan_line[(j * 3) + 1] = (i - 1) / 2;
             scan_line[(j * 3) + 2] = (i - 1) / 2;
        }
        for (j = 300; j < 375; j++) {
             scan_line[j * 3] = 0;
             scan_line[(j * 3) + 1] = i;
             scan_line[(j * 3) + 2] = i;
        }
        for (j = 375; j < 450; j++) {
             scan_line[j * 3] = i;
             scan_line[(j * 3) + 1] = 0;
             scan_line[(j * 3) + 2] = i;
        }
        for (j = 450; j < 525; j++) {
             scan_line[j * 3] = i;
             scan_line[(j * 3) + 1] = i;
             scan_line[(j * 3) + 2] = 0;
        }
        TIFFWriteScanline(tif, scan_line, i, 0);
    }

    free(scan_line);
    TIFFClose(tif);
    exit(0);
}
예제 #11
0
void writeIfd0(FILE *fptr, DngWriter *writer)
{
    /* Write the header */
    WriteHexString(fptr,"4d4d002a");    /* Big endian & TIFF identifier */
    offset = writer->rawwidht * writer->rawheight * 3 + 8;
    putc((offset & 0xff000000) / 16777216,fptr);
    putc((offset & 0x00ff0000) / 65536,fptr);
    putc((offset & 0x0000ff00) / 256,fptr);
    putc((offset & 0x000000ff),fptr);

    //raw file ?
    /* Write the binary data */
    for (j=0;j<ny;j++) {
        for (i=0;i<nx;i++) {
            //... calculate the RGB value between 0 and 255 ...
            fputc(red,fptr);
            fputc(green,fptr);
            fputc(blue,fptr);
        }
    }

    /* Write the footer */
    WriteHexString(fptr,"000e");  /* The number of directory entries (14) */

    //Use Tiff Tags for ints added To DngWriter Header file

    WriteHexString(fptr,TagGen(TIFFTAG_SUBFILETYPE,Sshort));  /* The number of directory entries (14) */

    //TIFFSetField (tif, TIFFTAG_SUBFILETYPE, 0);

    /* Width tag, short int */
    WriteHexString(fptr,"0100000300000001");
    fputc((writer->rawwidht & 0xff00) / 256,fptr);    /* Image width */
    fputc((writer->rawwidht & 0x00ff),fptr);
    WriteHexString(fptr,"0000");

    /* Height tag, short int */
    WriteHexString(fptr,"0101000300000001");
    fputc((writer->rawheight & 0xff00) / 256,fptr);    /* Image height */
    fputc((writer->rawheight & 0x00ff),fptr);
    WriteHexString(fptr,"0000");

    LOGD("subfiletype");

    assert(TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, writer->rawwidht) != 0);
    LOGD("width");


    assert(TIFFSetField(tif, TIFFTAG_IMAGELENGTH, writer->rawheight) != 0);
    LOGD("height");


    if(writer->rawType > 0)
        assert(TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16) != 0);
    else
        assert(TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 10) != 0);
    LOGD("bitspersample");
    assert(TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA) != 0);
    LOGD("PhotometricCFA");
    //assert(TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 480/2) != 0);
    assert(TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE) != 0);
    LOGD("Compression");
    TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, 1);
    LOGD("sampelsperpixel");
    TIFFSetField(tif, TIFFTAG_MAKE, writer->_make);
    LOGD("make");
    TIFFSetField(tif, TIFFTAG_MODEL, writer->_model);
    LOGD("model");
    try
    {
        if(0 == strcmp(writer->_orientation,"0") )
            TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
        if(0 == strcmp(writer->_orientation,"90") )
            TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_RIGHTTOP);
        if(0 == strcmp(writer->_orientation,"180") )
            TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_BOTRIGHT);
        if(0 == strcmp(writer->_orientation,"270") )
            TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_LEFTBOT);
        LOGD("orientation");
    }
    catch(...)
    {
        LOGD("Caught NULL NOT SET Orientation");
    }
    assert(TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) != 0);
    LOGD("planarconfig");
    //assert(TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3) != 0);
    TIFFSetField(tif, TIFFTAG_SOFTWARE, "FreedCam by Troop");
    LOGD("software");
    TIFFSetField(tif, TIFFTAG_DNGVERSION, "\001\003\0\0");
    TIFFSetField(tif, TIFFTAG_DNGBACKWARDVERSION, "\001\001\0\0");
    LOGD("dngversion");
    TIFFSetField(tif, TIFFTAG_UNIQUECAMERAMODEL, "SonyIMX");
    LOGD("CameraModel");
    TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, writer->_imagedescription);
    LOGD("imagedescription");
    TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, writer->colorMatrix2);
    LOGD("colormatrix1");
    TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, writer->neutralColorMatrix);
    LOGD("neutralMatrix");
    TIFFSetField(tif, TIFFTAG_CALIBRATIONILLUMINANT1, 21);

    TIFFSetField(tif, TIFFTAG_CALIBRATIONILLUMINANT2, 17);

    TIFFSetField(tif, TIFFTAG_COLORMATRIX2, 9, writer->colorMatrix1);

    static const float cam_foward1[] = {
            // R 	G     	B
            0.6648, 0.2566, 0.0429, 0.197, 0.9994, -0.1964, -0.0894, -0.2304, 1.145
    };

    static const float cam_foward2[] = {
            0.6617, 0.3849, -0.0823, 0.24, 1.1138, -0.3538, -0.0062, -0.1147, 0.946
    };

    static const float cam_nex_foward1[] = {
            // R 	G     	B
            0.6328, 0.0469, 0.2813, 0.1641, 0.7578, 0.0781, -0.0469, -0.6406, 1.5078
    };

    static const float cam_nex_foward2[] = {
            0.7578, 0.0859, 0.1172, 0.2734, 0.8281, -0.1016, 0.0156, -0.2813, 1.0859
    };
    TIFFSetField(tif, TIFFTAG_FOWARDMATRIX1, 9,  writer->fowardMatrix2);
    TIFFSetField(tif, TIFFTAG_FOWARDMATRIX2, 9,  writer->fowardMatrix1);
    static const float testNR[] = {
            0.00051471, 0, 0.00051471,0, 0.00051471, 0};
    TIFFSetField(tif, TIFFTAG_NOISEPROFILE, 6,  writer->noiseMatrix);



    LOGD("colormatrix2");
    //////////////////////////////IFD POINTERS///////////////////////////////////////
    ///GPS//////////
    // TIFFSetField (tif, TIFFTAG_GPSIFD, gpsIFD_offset);
    ///EXIF////////

}
예제 #12
0
int render_tiff_int16(struct image *image, const char *filename, double boost)
{
#ifdef HAVE_TIFF
	TIFF *th;
	int16_t *line;
	int x, y;
	double max;

	th = TIFFOpen(filename, "w");
	if ( th == NULL ) return 1;

	TIFFSetField(th, TIFFTAG_IMAGEWIDTH, image->width);
	TIFFSetField(th, TIFFTAG_IMAGELENGTH, image->height);
	TIFFSetField(th, TIFFTAG_SAMPLESPERPIXEL, 1);
	TIFFSetField(th, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); /* (signed) */
	TIFFSetField(th, TIFFTAG_BITSPERSAMPLE, 16);
	TIFFSetField(th, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
	TIFFSetField(th, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
	TIFFSetField(th, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
	TIFFSetField(th, TIFFTAG_ROWSPERSTRIP,
	             TIFFDefaultStripSize(th, image->width*4));

	line = _TIFFmalloc(TIFFScanlineSize(th));
	max = 0.0;
	for ( y=0; y<image->height; y++ ) {
	for ( x=0;x<image->width; x++ ) {
		double val;
		val = image->data[x+image->height*y];
		if ( val > max ) max = val;
	}
	}
	max /= 32767.0;

	for ( y=0; y<image->height; y++ ) {
		for ( x=0;x<image->width; x++ ) {

			double val;

			val = image->data[x+(image->height-1-y)*image->width];
			val *= ((double)boost/max);

			/* Clamp to 16-bit range,
			 * and work round inability of most readers to deal
			 * with signed integers. */
			val += 1000.0;
			if ( val > 32767.0 ) val = 32767.0;
			if ( val < 0.0 ) val = 0.0;

			line[x] = val;
		}

		TIFFWriteScanline(th, line, y, 0);
	}
	_TIFFfree(line);

	TIFFClose(th);
#else
	STATUS("No TIFF support.\n");
#endif
	return 0;
}
예제 #13
0
int writeColorTiff(const std::string filename, DataArray<uint8_t>::Pointer image, int width, int height,
                   const std::string imageDescription, int orientation)
{

  int err;
   TIFF *out;
   std::string dateTime;
   char software[1024];
   tsize_t area;

   if (NULL == image)
   {
     return -1;
   }
   out = TIFFOpen(filename.c_str(), "w");
   if (out == NULL)
   {
     printf("Could not open output file '%s' for writing.\n", filename.c_str());
     return -1;
   }

   err = 0;
   // set the basic values
   err = TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
   err = TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
   err = TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8);
   err = TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 3);
   err = TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, height); // 1 strip
   err = TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // single image plane

   dateTime = tifDateTime();
   err = TIFFSetField(out, TIFFTAG_DATETIME, dateTime.c_str());
   // String based tags
   if (filename.empty() == false)
   {
     err = TIFFSetField(out, TIFFTAG_DOCUMENTNAME, filename.c_str());
   }
   if (imageDescription.empty() == false)
   {
     err = TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, imageDescription.c_str());
   }

   err = TIFFSetField(out, TIFFTAG_ORIENTATION, orientation);
   err = TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);


 #if USE_LZW_COMPRESSION
   err = TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
   err = TIFFSetField(image, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL);
 #else
   err = TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
 #endif

   // Insert Resolution Units here if possible


   memset(software, 0, 1024);
   snprintf(software, 1024, "%s using libTif", EbsdLib::Version::Complete().c_str());

   err = TIFFSetField(out, TIFFTAG_SOFTWARE, software);

   err = TIFFSetField(out, TIFFTAG_HOSTCOMPUTER, MXADATAMODEL_SYSTEM);

   // Write the information to the file
   area = (tsize_t)( width *  height * 3);
   err = TIFFWriteEncodedStrip(out, 0, image->GetVoidPointer(0), area);
   if (err != area)
   {
     err = -1;
   }
   else
   {
     err = 1;
   }

   (void)TIFFClose(out);
   return err;
}
예제 #14
0
int
main(int argc, char **argv)
{
	TIFF		*tif;
	int		i;
	unsigned char	buf[3] = { 0, 127, 255 };

	/* Test whether we can write tags. */
	tif = TIFFOpen(filename, "w");
	if (!tif) {
		fprintf (stderr, "Can't create test TIFF file %s.\n", filename);
		return 1;
	}

	if (!TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width)) {
		fprintf (stderr, "Can't set ImageWidth tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_IMAGELENGTH, length)) {
		fprintf (stderr, "Can't set ImageLength tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8)) {
		fprintf (stderr, "Can't set BitsPerSample tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3)) {
		fprintf (stderr, "Can't set SamplesPerPixel tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rows_per_strip)) {
		fprintf (stderr, "Can't set SamplesPerPixel tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) {
		fprintf (stderr, "Can't set PlanarConfiguration tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)) {
		fprintf (stderr, "Can't set PhotometricInterpretation tag.\n");
		goto failure;
	}

	for (i = 0; i < NTAGS; i++) {
		if (!TIFFSetField(tif, long_tags[i].tag,
				  long_tags[i].value)) {
			fprintf(stderr, "Can't set tag %d.\n",
				(int)long_tags[i].tag);
			goto failure;
		}
	}

	/* Write dummy pixel data. */
	if (!TIFFWriteScanline(tif, buf, 0, 0) < 0) {
		fprintf (stderr, "Can't write image data.\n");
		goto failure;
	}

	TIFFClose(tif);
	
	/* Ok, now test whether we can read written values. */
	tif = TIFFOpen(filename, "r");
	if (!tif) {
		fprintf (stderr, "Can't open test TIFF file %s.\n", filename);
		return 1;
	}

	if (CheckLongField(tif, TIFFTAG_IMAGEWIDTH, width) < 0)
		goto failure;

	if (CheckLongField(tif, TIFFTAG_IMAGELENGTH, length) < 0)
		goto failure;

	if (CheckLongField(tif, TIFFTAG_ROWSPERSTRIP, rows_per_strip) < 0)
		goto failure;

	for (i = 0; i < NTAGS; i++) {
		if (CheckLongField(tif, long_tags[i].tag,
				   long_tags[i].value) < 0)
			goto failure;
	}

	TIFFClose(tif);
	
	/* All tests passed; delete file and exit with success status. */
	unlink(filename);
	return 0;

failure:
	/* Something goes wrong; close file and return unsuccessful status. */
	TIFFClose(tif);
	unlink(filename);
	return 1;
}
예제 #15
0
bool CoImageTIF::Decode (FILE* pFile)
{
	Release();
	XFileDisk hFile(pFile);

	TIFF* m_tif = _TIFFOpenEx(&hFile, "rb");

	uint32 height=0;
	uint32 width=0;
	uint16 bitspersample=1;
	uint16 samplesperpixel=1;
	uint32 rowsperstrip=(DWORD)-1;
	uint16 photometric=0;
	uint16 compression=1;
	uint16 orientation = ORIENTATION_TOPLEFT; //<vho>
	uint16 res_unit; //<Trifon>
	uint32 x, y;
	float resolution, offset;
	BOOL isRGB;
	BYTE *bits;		//pointer to source data
	BYTE *bits2;	//pointer to destination data

  try
  {
	//check if it's a tiff file
	if (!m_tif)
		throw "Error encountered while opening TIFF file";

	// <Robert Abram> - 12/2002 : get NumFrames directly, instead of looping
	// m_Info.nNumFrames=0;
	// while(TIFFSetDirectory(m_tif,(uint16)m_Info.nNumFrames)) m_Info.nNumFrames++;
	m_Info.nNumFrames = TIFFNumberOfDirectories(m_tif);

	if (!TIFFSetDirectory(m_tif, (uint16)m_Info.nFrame))
		throw "Error: page not present in TIFF file";			

	//get image info
	TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width);
	TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height);
	TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
	TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
	TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);   
	TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &photometric);
	TIFFGetField(m_tif, TIFFTAG_ORIENTATION, &orientation);

	if (m_Info.nEscape == -1) 
	{
		// Return output dimensions only
		m_Head.biWidth = width;
		m_Head.biHeight = height;
		throw "output dimensions returned";
	}

	TIFFGetFieldDefaulted(m_tif, TIFFTAG_RESOLUTIONUNIT, &res_unit);
	if (TIFFGetField(m_tif, TIFFTAG_XRESOLUTION, &resolution))
	{
		if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);
		SetXDPI((long)resolution);
	}
	if (TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &resolution))
	{
		if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);
		SetYDPI((long)resolution);
	}

	if (TIFFGetField(m_tif, TIFFTAG_XPOSITION, &offset))	m_Info.xOffset = (long)offset;
	if (TIFFGetField(m_tif, TIFFTAG_YPOSITION, &offset))	m_Info.yOffset = (long)offset;

	m_Head.biClrUsed=0;
	m_Info.nBkgndIndex =-1;

	if (rowsperstrip>height)
	{
		rowsperstrip=height;
		TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
	}

	isRGB = (bitspersample >= 8) &&
		(photometric == PHOTOMETRIC_RGB) ||
		(photometric == PHOTOMETRIC_YCBCR) ||
		(photometric == PHOTOMETRIC_SEPARATED) ||
		(photometric == PHOTOMETRIC_LOGL) ||
		(photometric == PHOTOMETRIC_LOGLUV);

	if (isRGB)
	{
		m_Head.biBitCount=24;
	}
	else
	{
		if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE))
		{
			if	(bitspersample == 1){
				m_Head.biBitCount=1;		//B&W image
				m_Head.biClrUsed =2;
			} 
			else if (bitspersample == 4)
			{
				m_Head.biBitCount=4;		//16 colors gray scale
				m_Head.biClrUsed =16;
			} 
			else
			{
				m_Head.biBitCount=8;		//gray scale
				m_Head.biClrUsed =256;
			}
		} 
		else if (bitspersample == 4) 
		{
			m_Head.biBitCount=4;			// 16 colors
			m_Head.biClrUsed=16;
		} 
		else 
		{
			m_Head.biBitCount=8;			//256 colors
			m_Head.biClrUsed=256;
		}
	}

	if (m_Info.nEscape)  throw "Cancelled"; // <vho> - cancel decoding

	CreateInfo(height, width, m_Head.biBitCount, CVLIB_IMG_FORMAT_TIF);
	if (m_Info.pImage == NULL)
		m_Info.pImage = (BYTE*)malloc (m_Head.biSizeImage);

	if (!GetPalette())
		throw "CoImageTIF can't create image";

#if CVLIB_IMG_SUPPORT_ALPHA
	if (samplesperpixel==4)
		AlphaCreate();
	if (samplesperpixel==2 && bitspersample==8)
		AlphaCreate();
#endif //CVLIB_IMG_SUPPORT_ALPHA

	TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression);
	SetCodecOption(compression); // <DPR> save original compression type

	if (isRGB) 
	{
		// FromFile the whole image into one big RGBA buffer using
		// the traditional TIFFReadRGBAImage() API that we trust.
		uint32* raster;		// retrieve RGBA image
		uint32 *row;

		raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32));
		if (raster == NULL) throw "No space for raster buffer";
			
		// FromFile the image in one chunk into an RGBA array
		if(!TIFFReadRGBAImage(m_tif, width, height, raster, 1)) 
		{
				_TIFFfree(raster);
				throw "Corrupted TIFF file!";
		}

		// read the raster lines and save them in the DIB
		// with RGB mode, we have to change the order of the 3 samples RGB
		row = &raster[0];
		bits2 = m_Info.pImage;
		for (y = 0; y < height; y++) 
		{

			if (m_Info.nEscape)
			{ // <vho> - cancel decoding
				_TIFFfree(raster);
				throw "Cancelled";
			}

			bits = bits2;
			for (x = 0; x < width; x++) 
			{
				*bits++ = (BYTE)TIFFGetB(row[x]);
				*bits++ = (BYTE)TIFFGetG(row[x]);
				*bits++ = (BYTE)TIFFGetR(row[x]);
#if CVLIB_IMG_SUPPORT_ALPHA
				if (samplesperpixel==4) 
					m_matA.data.ptr[y][x] = (BYTE)TIFFGetA(row[x]);
#endif //CVLIB_IMG_SUPPORT_ALPHA
			}
			row += width;
			bits2 += m_Info.dwEffWidth;
		}
		_TIFFfree(raster);
	} 
	else
	{
		RGBQUAD1 *pal;
		pal=(RGBQUAD1*)calloc(256,sizeof(RGBQUAD1));
		if (pal==NULL) throw "Unable to allocate TIFF palette";

		// set up the colormap based on photometric	
		switch(photometric) 
		{
			case PHOTOMETRIC_MINISBLACK:	// bitmap and greyscale image types
			case PHOTOMETRIC_MINISWHITE:
				if (bitspersample == 1)
				{	// Monochrome image
					if (photometric == PHOTOMETRIC_MINISBLACK) 
						pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
					else
						pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
				}
				else 
				{		// need to build the scale for greyscale images
					if (photometric == PHOTOMETRIC_MINISBLACK) 
					{
						for (DWORD i=0; i<m_Head.biClrUsed; i++)
							pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(i*(255/(m_Head.biClrUsed-1)));
					}
					else
					{
						for (DWORD i=0; i<m_Head.biClrUsed; i++)
							pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(255-i*(255/(m_Head.biClrUsed-1)));
					}
				}
				break;
			case PHOTOMETRIC_PALETTE:	// color map indexed
				uint16 *red;
				uint16 *green;
				uint16 *blue;
				TIFFGetField(m_tif, TIFFTAG_COLORMAP, &red, &green, &blue); 

				// Is the palette 16 or 8 bits ?
				BOOL Palette16Bits = FALSE;
				int n=1<<bitspersample;
				while (n-- > 0) {
					if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256) 
					{
						Palette16Bits=TRUE;
						break;
					}
				}

				// load the palette in the DIB
				for (int i = (1 << bitspersample) - 1; i >= 0; i--) 
				{
					if (Palette16Bits) 
					{
						pal[i].rgbRed =(BYTE) CVT(red[i]);
						pal[i].rgbGreen = (BYTE) CVT(green[i]);
						pal[i].rgbBlue = (BYTE) CVT(blue[i]);           
					} 
					else
					{
						pal[i].rgbRed = (BYTE) red[i];
						pal[i].rgbGreen = (BYTE) green[i];
						pal[i].rgbBlue = (BYTE) blue[i];        
					}
				}
				break;
		}
		SetPalette(pal,m_Head.biClrUsed);	//palette assign
		free(pal);

		// read the tiff lines and save them in the DIB
		uint32 nrow;
		uint32 ys;
		int line = CalculateLine(width, bitspersample * samplesperpixel);
		long bitsize= TIFFStripSize(m_tif);
		//verify bitsize: could be wrong if StripByteCounts is missing.
		if (bitsize>(long)(m_Head.biSizeImage*samplesperpixel))
			bitsize=m_Head.biSizeImage*samplesperpixel;

		int tiled_image = TIFFIsTiled(m_tif);
		uint32 tw, tl;
		BYTE* tilebuf;
		if (tiled_image)
		{
			TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &tw);
			TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &tl);
			rowsperstrip = tl;
			bitsize = TIFFTileSize(m_tif) * (int)(1+width/tw);
			tilebuf = (BYTE*)malloc(TIFFTileSize(m_tif));
		}
		
		bits = (BYTE*)malloc(bitsize);
		if (bits==NULL)
		{
			throw "CoImageTIF can't allocate memory";
		}

		for (ys = 0; ys < height; ys += rowsperstrip) 
		{
			if (m_Info.nEscape)
			{ // <vho> - cancel decoding
				free(bits);
				throw "Cancelled";
			}

			nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip);

			if (tiled_image)
			{
				uint32 imagew = TIFFScanlineSize(m_tif);
				uint32 tilew  = TIFFTileRowSize(m_tif);
				int iskew = imagew - tilew;
				uint8* bufp = (uint8*) bits;

				uint32 colb = 0;
				for (uint32 col = 0; col < width; col += tw) 
				{
					if (TIFFReadTile(m_tif, tilebuf, col, ys, 0, 0) < 0)
					{
						free(tilebuf);
						free(bits);
						throw "Corrupted tiled TIFF file!";
					}

					if (colb + tw > imagew) 
					{
						uint32 owidth = imagew - colb;
						uint32 oskew = tilew - owidth;
						TileToStrip(bufp + colb, tilebuf, nrow, owidth, oskew + iskew, oskew );
					} 
					else
					{
						TileToStrip(bufp + colb, tilebuf, nrow, tilew, iskew, 0);
					}
					colb += tilew;
				}

			} 
			else 
			{
				if (TIFFReadEncodedStrip(m_tif, TIFFComputeStrip(m_tif, ys, 0), bits, nrow * line) == -1) 
				{
					free(bits);
					throw "Corrupted TIFF file!";
				}
			}

			for (y = 0; y < nrow; y++) 
			{
				long offset=(nrow-y-1)*line;
				if (bitspersample==16) 
					for (DWORD xi=0;xi<width;xi++) 
						bits[xi+offset]=bits[xi*2+offset+1];
				if (samplesperpixel==1) 
				{ //simple 8bpp image
					memcpy(
						m_Info.pImage+m_Info.dwEffWidth*(height-ys-nrow+y),
						bits+offset,
						m_Info.dwEffWidth);
				}
				else if (samplesperpixel==2)  //8bpp image with alpha layer
				{ 
					int xi=0;
					int ii=0;
					int yi=height-ys-nrow+y;
					while (ii<line)
					{
						SetPixelIndex(xi,yi,bits[ii+offset]);
#if CVLIB_IMG_SUPPORT_ALPHA
						m_matA.data.ptr[yi][xi] = bits[ii+offset+1];
#endif //CVLIB_IMG_SUPPORT_ALPHA
						ii+=2;
						xi++;
						if (xi>=(int)width)
						{
							yi--;
							xi=0;
						}
					}
				} 
				else
				{ //photometric==PHOTOMETRIC_CIELAB
					if (m_Head.biBitCount!=24)
					{ //fix image
						CreateInfo(height,width,24,CVLIB_IMG_FORMAT_BMP);
#if CVLIB_IMG_SUPPORT_ALPHA
 						if (samplesperpixel==4)
							AlphaCreate();
#endif //CVLIB_IMG_SUPPORT_ALPHA
					}

					int xi=0;
					int ii=0;
					int yi=height-ys-nrow+y;
					RGBQUAD1 c;
					int l,a,b,bitsoffset;
					double p,cx,cy,cz,cr,cg,cb;
					while (ii<line){
						bitsoffset = ii*samplesperpixel+offset;
						l=bits[bitsoffset];
						a=bits[bitsoffset+1];
						b=bits[bitsoffset+2];
						if (a>127) a-=256;
						if (b>127) b-=256;
						// lab to xyz
						p = (l/2.55 + 16) / 116.0;
						cx = pow( p + a * 0.002, 3);
						cy = pow( p, 3);
						cz = pow( p - b * 0.005, 3);
						// white point
						cx*=0.95047;
						//cy*=1.000;
						cz*=1.0883;
						// xyz to rgb
						cr =  3.240479 * cx - 1.537150 * cy - 0.498535 * cz;
						cg = -0.969256 * cx + 1.875992 * cy + 0.041556 * cz;
						cb =  0.055648 * cx - 0.204043 * cy + 1.057311 * cz;

						if ( cr > 0.00304 ) cr = 1.055 * pow(cr,0.41667) - 0.055;
							else            cr = 12.92 * cr;
						if ( cg > 0.00304 ) cg = 1.055 * pow(cg,0.41667) - 0.055;
							else            cg = 12.92 * cg;
						if ( cb > 0.00304 ) cb = 1.055 * pow(cb,0.41667) - 0.055;
							else            cb = 12.92 * cb;

						c.rgbRed  =(BYTE)max(0,min(255,(int)(cr*255)));
						c.rgbGreen=(BYTE)max(0,min(255,(int)(cg*255)));
						c.rgbBlue =(BYTE)max(0,min(255,(int)(cb*255)));

						SetPixelColor(xi,yi,c);
#if CVLIB_IMG_SUPPORT_ALPHA
 						if (samplesperpixel==4)
							m_matA.data.ptr[yi][xi] = bits[bitsoffset+3];
#endif //CVLIB_IMG_SUPPORT_ALPHA
						ii++;
						xi++;
						if (xi>=(int)width)
						{
							yi--;
							xi=0;
						}
					}
				}
			}
		}
		free(bits);
		if (tiled_image) free(tilebuf);

// 		switch(orientation)
// 		{
// 		case ORIENTATION_TOPRIGHT: /* row 0 top, col 0 rhs */
// 			Mirror();
// 			break;
// 		case ORIENTATION_BOTRIGHT: /* row 0 bottom, col 0 rhs */
// 			Flip();
// 			Mirror();
// 			break;
// 		case ORIENTATION_BOTLEFT: /* row 0 bottom, col 0 lhs */
// 			Flip();
// 			break;
// 		case ORIENTATION_LEFTTOP: /* row 0 lhs, col 0 top */
// 			RotateRight();
// 			Mirror();
// 			break;
// 		case ORIENTATION_RIGHTTOP: /* row 0 rhs, col 0 top */
// 			RotateLeft();
// 			break;
// 		case ORIENTATION_RIGHTBOT: /* row 0 rhs, col 0 bottom */
// 			RotateLeft();
// 			Mirror();
// 			break;
// 		case ORIENTATION_LEFTBOT: /* row 0 lhs, col 0 bottom */
// 			RotateRight();
// 			break;
// 		}

	}
  } 
  catch (char *message) 
  {
	  strncpy(m_Info.szLastError,message,255);
	  if (m_tif) TIFFClose(m_tif);
	  if (m_Info.nEscape==-1) return true;
	  return false;
  }
	TIFFClose(m_tif);

	ImageIterator iter(this);
	iter.BMP2XYZ(m_Info.pImage);

	if (m_Info.pImage)
		free (m_Info.pImage);
	m_Info.pImage = NULL;
	return true;
}
예제 #16
0
	    int WriteBuffers( int frame_from = 0, int frame_to = -1, int offset = 0 )
	    {
	        int frames_written(0);
	        if ( !m_VideoAsset) {
	            return frames_written;
	        }


	        int frame = frame_from;
	        if ( frame_to == -1 || frame_to >= m_VideoAsset->GetNumberOfFrames() ) {
	            frame_to = m_VideoAsset->GetNumberOfFrames() - 1;
	        }
	        double frame_time = m_VideoAsset->GetFormat().GetFrameTime();
	        while ( frame <= frame_to )
	        {
                pei::Format tFmt;
                pei::SurfacePtr surface = m_VideoAsset->Decode( tFmt, (double)frame*frame_time );
                if ( !surface )
                {
                    break;
                }
                char file[ 256 ];
                std::string fms = m_directory + "/" + m_format_string + "." + GetFileExtension();
                sprintf( file, fms.c_str(), offset + frame++ );
                TIFF *image = TIFFOpen( file, "w");
                if (image == NULL){
                    std::cerr << "Could not '" << file << "' for writing\n";
                    break;
                }
                surface->Lock();
                int spp = surface->GetBytesPerPixel();
                int bps = surface->GetDepth() / spp;
                 // We need to set some values for basic tags before we can add any data
                TIFFSetField(image, TIFFTAG_IMAGEWIDTH, surface->GetWidth());
                TIFFSetField(image, TIFFTAG_IMAGELENGTH, surface->GetHeight());
                TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, spp);
                TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bps);

                TIFFSetField(image, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT );
                TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
                TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);

                // TODO: Give encoder options to set compression ratio, etc.
                TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
                TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);

                TIFFSetField(image, TIFFTAG_XRESOLUTION, 150.0);
                TIFFSetField(image, TIFFTAG_YRESOLUTION, 150.0);
                TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);

                //TIFFScanlineSize( image, surface->GetPitch( ) );
                TIFFSetField( image, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(image, surface->GetPitch()));
                for ( int y = 0; y < (int)surface->GetHeight(); y++ ) {
                    void *buf = (void*)((char*)surface->GetPixels() + surface->GetPitch()*y);
                    if ( TIFFWriteScanline( image, buf, y, 0 ) < 0) break;
                }

                // Close the file
                TIFFClose(image);
                surface->Unlock();
                frames_written++;
	        };
	        return frames_written;
	    }
예제 #17
0
bool CoImageTIF::EncodeBody(void* m_tif, bool multipage, int page, int pagecount)
{
	TIFF* pTIF = (TIFF*)m_tif;

	SetBpp24();

	uint32 height=m_Head.biHeight;
	uint32 width=m_Head.biWidth;
	uint16 bitcount=m_Head.biBitCount;
	uint16 bitspersample;
	uint16 samplesperpixel;
	uint16 photometric=0;
	uint16 compression;
//	uint16 pitch;
//	int line;
	uint32 x, y;

	samplesperpixel = ((bitcount == 24) || (bitcount == 32)) ? (BYTE)3 : (BYTE)1;
#if CVLIB_IMG_SUPPORT_ALPHA
	if (bitcount==24 && m_matA.IsValid()) { bitcount=32; samplesperpixel=4; }
#endif //CVLIB_IMG_SUPPORT_ALPHA

	bitspersample = bitcount / samplesperpixel;

// 	if (m_Info.pImage == NULL)
// 		m_Info.pImage = (BYTE*)malloc (m_Head.biSizeImage);
	ImageIterator iter(this);
	iter.XYZ2BMP();

	//set the PHOTOMETRIC tag
	RGBQUAD1 *rgb = GetPalette();
	switch (bitcount) 
	{
// 		case 1:
// 			if (CompareColors(&rgb[0],&rgb[1])<0) 
// 			{
// 				/* <abe> some viewers do not handle PHOTOMETRIC_MINISBLACK:
// 				 * let's transform the image in PHOTOMETRIC_MINISWHITE
// 				 */
// 				//invert the colors
// 				RGBQUAD1 tempRGB=GetPaletteColor(0);
// 				SetPaletteColor(0,GetPaletteColor(1));
// 				SetPaletteColor(1,tempRGB);
// 				//invert the pixels
// 				BYTE *iSrc=iter.m_pbTemp;/*m_Info.pImage*/;
// 				for (unsigned long i=0;i<m_Head.biSizeImage;i++)
// 				{
// 					*iSrc=(BYTE)~(*(iSrc));
// 					iSrc++;
// 				}
// 				photometric = PHOTOMETRIC_MINISWHITE;
// 				//photometric = PHOTOMETRIC_MINISBLACK;
// 			} 
// 			else
// 			{
// 				photometric = PHOTOMETRIC_MINISWHITE;
// 			}
// 			break;
// 		case 4:	// Check if the DIB has a color or a greyscale palette
// 		case 8:
// 			photometric = PHOTOMETRIC_MINISBLACK; //default to gray scale
// 			for (x = 0; x < m_Head.biClrUsed; x++) 
// 			{
// 				if ((rgb->rgbRed != x)||(rgb->rgbRed != rgb->rgbGreen)||(rgb->rgbRed != rgb->rgbBlue))
// 				{
// 					photometric = PHOTOMETRIC_PALETTE;
// 					break;
// 				}
// 				rgb++;
// 			}
// 			break;
		case 24:
		case 32:
			photometric = PHOTOMETRIC_RGB;			
			break;
	}

#if CVLIB_IMG_SUPPORT_ALPHA
 	if (m_matA.IsValid() && bitcount==8) samplesperpixel=2; //8bpp + alpha layer
#endif //CVLIB_IMG_SUPPORT_ALPHA

//	line = CalculateLine(width, bitspersample * samplesperpixel);
//	pitch = (uint16)CalculatePitch(line);

	//prepare the palette struct
// 	RGBQUAD1 pal[256];
// 	if (GetPalette())
// 	{
// 		BYTE b;
// 		memcpy(pal,GetPalette(),GetPaletteSize());
// 		for(WORD a=0;a<m_Head.biClrUsed;a++){	//swap blue and red components
// 			b=pal[a].rgbBlue; pal[a].rgbBlue=pal[a].rgbRed; pal[a].rgbRed=b;
// 		}
// 	}

	// handle standard width/height/bpp stuff
	TIFFSetField(pTIF, TIFFTAG_IMAGEWIDTH, width);
	TIFFSetField(pTIF, TIFFTAG_IMAGELENGTH, height);
	TIFFSetField(pTIF, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
	TIFFSetField(pTIF, TIFFTAG_BITSPERSAMPLE, bitspersample);
	TIFFSetField(pTIF, TIFFTAG_PHOTOMETRIC, photometric);
	TIFFSetField(pTIF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);	// single image plane 
	TIFFSetField(pTIF, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);

	uint32 rowsperstrip = TIFFDefaultStripSize(pTIF, (uint32) -1);  //<REC> gives better compression
	TIFFSetField(pTIF, TIFFTAG_ROWSPERSTRIP, rowsperstrip);

	// handle metrics
	TIFFSetField(pTIF, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
	TIFFSetField(pTIF, TIFFTAG_XRESOLUTION, (float)m_Info.xDPI);
	TIFFSetField(pTIF, TIFFTAG_YRESOLUTION, (float)m_Info.yDPI);
//	TIFFSetField(pTIF, TIFFTAG_XPOSITION, (float)m_Info.xOffset);
//	TIFFSetField(pTIF, TIFFTAG_YPOSITION, (float)m_Info.yOffset);

	// multi-paging - Thanks to Abe <God(dot)bless(at)marihuana(dot)com>
	if (multipage)
	{
		char page_number[20];
		sprintf(page_number, "Page %d", page);

		TIFFSetField(pTIF, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
		TIFFSetField(pTIF, TIFFTAG_PAGENUMBER, page,pagecount);
		TIFFSetField(pTIF, TIFFTAG_PAGENAME, page_number);
	}
	else 
	{
		TIFFSetField(pTIF, TIFFTAG_SUBFILETYPE, 0);
	}

	// palettes (image colormaps are automatically scaled to 16-bits)
// 	if (photometric == PHOTOMETRIC_PALETTE) 
// 	{
// 		uint16 *r, *g, *b;
// 		r = (uint16 *) _TIFFmalloc(sizeof(uint16) * 3 * 256);
// 		g = r + 256;
// 		b = g + 256;
// 
// 		for (int i = 255; i >= 0; i--) 
// 		{
// 			b[i] = (uint16)SCALE((uint16)pal[i].rgbRed);
// 			g[i] = (uint16)SCALE((uint16)pal[i].rgbGreen);
// 			r[i] = (uint16)SCALE((uint16)pal[i].rgbBlue);
// 		}
// 
// 		TIFFSetField(pTIF, TIFFTAG_COLORMAP, r, g, b);
// 		_TIFFfree(r);
// 	}

	// compression
	if (GetCodecOption(CVLIB_IMG_FORMAT_TIF)) 
	{
		compression = (WORD)GetCodecOption(CVLIB_IMG_FORMAT_TIF);
	}
	else 
	{
		switch (bitcount) 
		{
			case 1 :
				compression = COMPRESSION_CCITTFAX4;
				break;
			case 4 :
			case 8 :
				compression = COMPRESSION_LZW;
				break;
			case 24 :
			case 32 :
				compression = COMPRESSION_JPEG;
				break;
			default :
				compression = COMPRESSION_NONE;
				break;
		}
	}
	TIFFSetField(pTIF, TIFFTAG_COMPRESSION, compression);

	switch (compression) 
	{
	case COMPRESSION_JPEG:
		TIFFSetField(pTIF, TIFFTAG_JPEGQUALITY, m_Info.nQuality);
		TIFFSetField(pTIF, TIFFTAG_ROWSPERSTRIP, ((7+rowsperstrip)>>3)<<3);
   		break;
	case COMPRESSION_LZW:
		if (bitcount>=8) TIFFSetField(pTIF, TIFFTAG_PREDICTOR, 2);
		break;
	}

	// read the DIB lines from bottom to top and save them in the TIF

	BYTE *bits;
	switch(bitcount) 
	{				
		case 1 :
		case 4 :
		case 8 :
		{
			if (samplesperpixel==1)
			{
				for (y = 0; y < height; y++) 
				{
					bits= iter.m_pbTemp + (height - y - 1)*m_Info.dwEffWidth;
					if (TIFFWriteScanline(pTIF,bits, y, 0)==-1) return false;
				}
			}
#if CVLIB_IMG_SUPPORT_ALPHA
			else 
			{ //8bpp + alpha layer
				bits = (BYTE*)malloc(2*width);
				if (!bits) return false;
				for (y = 0; y < height; y++) 
				{
					for (x=0;x<width;x++)
					{
						bits[2*x]=GetPixelIndex(x,height - y - 1);
						bits[2*x+1]=m_matA.data.ptr[height - y - 1][x];
					}
					if (TIFFWriteScanline(pTIF,bits, y, 0)==-1) 
					{
						free(bits);
						return false;
					}
				}
				free(bits);
			}
#endif //CVLIB_IMG_SUPPORT_ALPHA
			break;
		}				
		case 24:
		{
			BYTE *buffer = (BYTE *)malloc(m_Info.dwEffWidth);
			if (!buffer) return false;
			for (y = 0; y < height; y++) 
			{
				// get a pointer to the scanline
				memcpy(buffer, iter.m_pbTemp + (height - y - 1)*m_Info.dwEffWidth, m_Info.dwEffWidth);
				// TIFFs store color data RGB instead of BGR
				BYTE *pBuf = buffer;
				for (x = 0; x < width; x++) 
				{
					BYTE tmp = pBuf[0];
					pBuf[0] = pBuf[2];
					pBuf[2] = tmp;
					pBuf += 3;
				}
				// write the scanline to disc
				if (TIFFWriteScanline(pTIF, buffer, y, 0)==-1)
				{
					free(buffer);
					return false;
				}
			}
			free(buffer);
			break;
		}				
		case 32 :
		{
#if CVLIB_IMG_SUPPORT_ALPHA
			BYTE *buffer = (BYTE *)malloc((m_Info.dwEffWidth*4)/3);
			if (!buffer) return false;
			for (y = 0; y < height; y++) 
			{
				// get a pointer to the scanline
				memcpy(buffer, iter.m_pbTemp + (height - y - 1)*m_Info.dwEffWidth, m_Info.dwEffWidth);
				// TIFFs store color data RGB instead of BGR
				BYTE *pSrc = buffer + 3 * width;
				BYTE *pDst = buffer + 4 * width;
				for (x = 0; x < width; x++) 
				{
					pDst-=4;
					pSrc-=3;
					pDst[3] = m_matA.data.ptr[height-y-1][width-x-1];
					pDst[2] = pSrc[0];
					pDst[1] = pSrc[1];
					pDst[0] = pSrc[2];
				}
				// write the scanline to disc
				if (TIFFWriteScanline(pTIF, buffer, y, 0)==-1)
				{
					free(buffer);
					return false;
				}
			}
			free(buffer);
#endif //CVLIB_IMG_SUPPORT_ALPHA
			break;
		}				
	}
	return true;
}
예제 #18
0
void writeTIFF(const char *pszFile, HDC hdc)
{
	precondition_throw(pszFile != NULL, "Path to TIFF file cannot be null.");
	precondition_throw(hdc != NULL, "Source device context cannot be null.");

	HBITMAP hbm = (HBITMAP) ::GetCurrentObject(hdc, OBJ_BITMAP);
	DIBSECTION ds = {255};
	memset(&ds,255,sizeof(ds));
	::GetObject(hbm, sizeof(DIBSECTION), &ds);

	LONG buffWidth    = ds.dsBmih.biWidth;
	LONG buffHeight   = (ds.dsBmih.biHeight < 0) ? ds.dsBmih.biHeight * -1 : ds.dsBmih.biHeight;
	WORD planes       = ds.dsBmih.biPlanes;
	WORD bitsPerPixel = ds.dsBmih.biBitCount;

	if (planes != 1)
		throw std::runtime_error("Unsupported image format.");

	long padding = 0;
	while ((buffWidth * 3 + padding) % sizeof(DWORD) != 0)
		++padding;

	long pitchBytes  = buffWidth * 3 + padding;
	long neededBytes = pitchBytes * buffHeight;

	ScopedArray<BYTE> spBuffer(new BYTE[neededBytes]);
	memset(spBuffer.get(), 0, neededBytes);

	BITMAPINFO bmi = {0};
	bmi.bmiHeader.biSize        = sizeof(bmi.bmiHeader);
	bmi.bmiHeader.biPlanes      = 1;
	bmi.bmiHeader.biBitCount    = 24;
	bmi.bmiHeader.biCompression = BI_RGB;		
	bmi.bmiHeader.biWidth       = buffWidth;
	bmi.bmiHeader.biHeight      = buffHeight * -1;

	::GetDIBits(hdc, hbm, 0, buffHeight, spBuffer.get(), &bmi, DIB_RGB_COLORS);

	TIFF *pTIFF = TIFFOpen(pszFile, "w");
	if (!pTIFF)
		throw std::runtime_error("Couldn't create specified TIFF file.");

	ScopeGuard guardTIFF = MakeGuard(TIFFClose, pTIFF);

	TIFFSetField(pTIFF, TIFFTAG_IMAGEWIDTH, buffWidth);
	TIFFSetField(pTIFF, TIFFTAG_IMAGELENGTH, buffHeight);
	TIFFSetField(pTIFF, TIFFTAG_SAMPLESPERPIXEL, 3);
	TIFFSetField(pTIFF, TIFFTAG_BITSPERSAMPLE, 8);
	TIFFSetField(pTIFF, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
	TIFFSetField(pTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
	TIFFSetField(pTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);

	long packedSize = buffWidth * buffHeight * 3;
	ScopedArray<BYTE> spPackedBuffer(new BYTE[packedSize]);

	BYTE *pDest = spPackedBuffer.get();
	BYTE *pSrc = spBuffer.get();
	for (long y = 0; y < buffHeight; ++y)
	{
		for (long x = 0; x < buffWidth; ++x)
		{
			// Swapping bytes so the byte order is as we expect
			pDest[0] = pSrc[2];
			pDest[1] = pSrc[1];
			pDest[2] = pSrc[0];
			pDest += 3;
			pSrc  += 3;
		}
		pSrc += padding;
	}

	if (TIFFWriteEncodedStrip(pTIFF, 0, spPackedBuffer.get(), buffWidth * buffHeight * 3) == 0)
		throw std::runtime_error("Couldn't write image.");
}
예제 #19
0
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);
}
예제 #20
0
bool wxTIFFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
{
    TIFF *tif = TIFFwxOpen( stream, "image", "w" );

    if (!tif)
    {
        if (verbose)
            wxLogError( _("TIFF: Error saving image.") );

        return false;
    }

    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH,  (uint32)image->GetWidth());
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32)image->GetHeight());
    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);

    if ( image->HasOption(wxIMAGE_OPTION_RESOLUTIONX) &&
            image->HasOption(wxIMAGE_OPTION_RESOLUTIONY) )
    {
        TIFFSetField(tif, TIFFTAG_XRESOLUTION,
                        image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX));
        TIFFSetField(tif, TIFFTAG_YRESOLUTION,
                        image->GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY));
    }

    int spp = image->GetOptionInt(wxIMAGE_OPTION_SAMPLESPERPIXEL);
    if ( !spp )
        spp = 3;

    int bpp = image->GetOptionInt(wxIMAGE_OPTION_BITSPERSAMPLE);
    if ( !bpp )
        bpp=8;

    int compression = image->GetOptionInt(wxIMAGE_OPTION_COMPRESSION);
    if ( !compression )
        compression=COMPRESSION_LZW;

    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, spp);
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bpp);
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, spp*bpp == 1 ? PHOTOMETRIC_MINISBLACK
                                                        : PHOTOMETRIC_RGB);
    TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);

    // scanlinesize if determined by spp and bpp
    tsize_t linebytes = (tsize_t)image->GetWidth() * spp * bpp / 8;

    if ( (image->GetWidth() % 8 > 0) && (spp * bpp < 8) )
        linebytes+=1;

    unsigned char *buf;

    if (TIFFScanlineSize(tif) > linebytes || (spp * bpp < 24))
    {
        buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif));
        if (!buf)
        {
            if (verbose)
                wxLogError( _("TIFF: Couldn't allocate memory.") );

            TIFFClose( tif );

            return false;
        }
    }
    else
    {
        buf = NULL;
    }

    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,TIFFDefaultStripSize(tif, (uint32) -1));

    uint8 bitmask;

    unsigned char *ptr = image->GetData();
    for ( int row = 0; row < image->GetHeight(); row++ )
    {
        if ( buf )
        {
            if ( spp * bpp > 1 )
            {
                // color image
                memcpy(buf, ptr, image->GetWidth());
            }
            else // black and white image
            {
                for ( int column = 0; column < linebytes; column++ )
                {
                    uint8 reverse = 0;
                    bitmask = 1;
                    for ( int bp = 0; bp < 8; bp++ )
                    {
                        if ( ptr[column*24 + bp*3] > 0 )
                        {
                            // check only red as this is sufficient
                            reverse = reverse | 128 >> bp;
                        }

                        bitmask <<= 1;
                    }

                    buf[column] = reverse;
                }
            }
        }

        if ( TIFFWriteScanline(tif, buf ? buf : ptr, (uint32)row, 0) < 0 )
        {
            if (verbose)
                wxLogError( _("TIFF: Error writing image.") );

            TIFFClose( tif );
            if (buf)
                _TIFFfree(buf);

            return false;
        }

        ptr += image->GetWidth()*3;
    }
예제 #21
0
파일: tiff.c 프로젝트: AlicVB/darktable
int write_image(dt_imageio_module_data_t *d_tmp, const char *filename, const void *in_void,
                dt_colorspaces_color_profile_type_t over_type, const char *over_filename,
                void *exif, int exif_len, int imgid, int num, int total, dt_dev_pixelpipe_t *pipe)
{
  const dt_imageio_tiff_t *d = (dt_imageio_tiff_t *)d_tmp;

  uint8_t *profile = NULL;
  uint32_t profile_len = 0;

  TIFF *tif = NULL;

  void *rowdata = NULL;

  int rc = 1; // default to error

  if(imgid > 0)
  {
    cmsHPROFILE out_profile = dt_colorspaces_get_output_profile(imgid, over_type, over_filename)->profile;
    cmsSaveProfileToMem(out_profile, 0, &profile_len);
    if(profile_len > 0)
    {
      profile = malloc(profile_len);
      if(!profile)
      {
        rc = 1;
        goto exit;
      }
      cmsSaveProfileToMem(out_profile, profile, &profile_len);
    }
  }

  // Create little endian tiff image
#ifdef _WIN32
  wchar_t *wfilename = g_utf8_to_utf16(filename, -1, NULL, NULL, NULL);
  tif = TIFFOpenW(wfilename, "wl");
  g_free(wfilename);
#else
  tif = TIFFOpen(filename, "wl");
#endif
  if(!tif)
  {
    rc = 1;
    goto exit;
  }

  // http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf (dated 2002)
  // "A proprietary ZIP/Flate compression code (0x80b2) has been used by some"
  // "software vendors. This code should be considered obsolete. We recommend"
  // "that TIFF implementations recognize and read the obsolete code but only"
  // "write the official compression code (0x0008)."
  // http://www.awaresystems.be/imaging/tiff/tifftags/compression.html
  // http://www.awaresystems.be/imaging/tiff/tifftags/predictor.html
  if(d->compress == 1)
  {
    TIFFSetField(tif, TIFFTAG_COMPRESSION, (uint16_t)COMPRESSION_ADOBE_DEFLATE);
    TIFFSetField(tif, TIFFTAG_PREDICTOR, (uint16_t)PREDICTOR_NONE);
    TIFFSetField(tif, TIFFTAG_ZIPQUALITY, (uint16_t)d->compresslevel);
  }
  else if(d->compress == 2)
  {
    TIFFSetField(tif, TIFFTAG_COMPRESSION, (uint16_t)COMPRESSION_ADOBE_DEFLATE);
    TIFFSetField(tif, TIFFTAG_PREDICTOR, (uint16_t)PREDICTOR_HORIZONTAL);
    TIFFSetField(tif, TIFFTAG_ZIPQUALITY, (uint16_t)d->compresslevel);
  }
  else if(d->compress == 3)
  {
    TIFFSetField(tif, TIFFTAG_COMPRESSION, (uint16_t)COMPRESSION_ADOBE_DEFLATE);
    if(d->bpp == 32)
      TIFFSetField(tif, TIFFTAG_PREDICTOR, (uint16_t)PREDICTOR_FLOATINGPOINT);
    else
      TIFFSetField(tif, TIFFTAG_PREDICTOR, (uint16_t)PREDICTOR_HORIZONTAL);
    TIFFSetField(tif, TIFFTAG_ZIPQUALITY, (uint16_t)d->compresslevel);
  }
  else // (d->compress == 0)
  {
    TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
  }

  TIFFSetField(tif, TIFFTAG_FILLORDER, (uint16_t)FILLORDER_MSB2LSB);
  if(profile != NULL)
  {
    TIFFSetField(tif, TIFFTAG_ICCPROFILE, (uint32_t)profile_len, profile);
  }
  TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (uint16_t)3);
  TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, (uint16_t)d->bpp);
  TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, (uint16_t)(d->bpp == 32 ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT));
  TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32_t)d->global.width);
  TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32_t)d->global.height);
  TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, (uint16_t)PHOTOMETRIC_RGB);
  TIFFSetField(tif, TIFFTAG_PLANARCONFIG, (uint16_t)PLANARCONFIG_CONTIG);
  TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, (uint32_t)1);
  TIFFSetField(tif, TIFFTAG_ORIENTATION, (uint16_t)ORIENTATION_TOPLEFT);

  int resolution = dt_conf_get_int("metadata/resolution");
  if(resolution > 0)
  {
    TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)resolution);
    TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float)resolution);
    TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, (uint16_t)RESUNIT_INCH);
  }

  const size_t rowsize = (d->global.width * 3) * d->bpp / 8;
  if((rowdata = malloc(rowsize)) == NULL)
  {
    rc = 1;
    goto exit;
  }

  if(d->bpp == 32)
  {
    for(int y = 0; y < d->global.height; y++)
    {
      float *in = (float *)in_void + (size_t)4 * y * d->global.width;
      float *out = (float *)rowdata;

      for(int x = 0; x < d->global.width; x++, in += 4, out += 3)
      {
        memcpy(out, in, 3 * sizeof(float));
      }

      if(TIFFWriteScanline(tif, rowdata, y, 0) == -1)
      {
        rc = 1;
        goto exit;
      }
    }
  }
  else if(d->bpp == 16)
  {
    for(int y = 0; y < d->global.height; y++)
    {
      uint16_t *in = (uint16_t *)in_void + (size_t)4 * y * d->global.width;
      uint16_t *out = (uint16_t *)rowdata;

      for(int x = 0; x < d->global.width; x++, in += 4, out += 3)
      {
        memcpy(out, in, 3 * sizeof(uint16_t));
      }

      if(TIFFWriteScanline(tif, rowdata, y, 0) == -1)
      {
        rc = 1;
        goto exit;
      }
    }
  }
  else
  {
    for(int y = 0; y < d->global.height; y++)
    {
      uint8_t *in = (uint8_t *)in_void + (size_t)4 * y * d->global.width;
      uint8_t *out = (uint8_t *)rowdata;

      for(int x = 0; x < d->global.width; x++, in += 4, out += 3)
      {
        memcpy(out, in, 3 * sizeof(uint8_t));
      }

      if(TIFFWriteScanline(tif, rowdata, y, 0) == -1)
      {
        rc = 1;
        goto exit;
      }
    }
  }

  // success
  rc = 0;

exit:
  // close the file before adding exif data
  if(tif)
  {
    TIFFClose(tif);
    tif = NULL;
  }
  if(!rc && exif)
  {
    rc = dt_exif_write_blob(exif, exif_len, filename, d->compress > 0);
    // Until we get symbolic error status codes, if rc is 1, return 0
    rc = (rc == 1) ? 0 : 1;
  }
  free(profile);
  profile = NULL;
  free(rowdata);
  rowdata = NULL;

  return rc;
}
예제 #22
0
파일: custom_dir.c 프로젝트: hjmjohnson/vxl
int
main()
{
	TIFF		*tif;
	unsigned char	buf[SPP] = { 0, 127, 255 };
	uint64          dir_offset = 0, dir_offset2 = 0;
	uint64          read_dir_offset = 0, read_dir_offset2 = 0;
	uint64          *dir_offset2_ptr = NULL;
	char           *ascii_value;
	uint16          count16 = 0;


	/* We write the main directory as a simple image. */
	tif = TIFFOpen(filename, "w+");
	if (!tif) {
		fprintf (stderr, "Can't create test TIFF file %s.\n", filename);
		return 1;
	}

	if (!TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width)) {
		fprintf (stderr, "Can't set ImageWidth tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_IMAGELENGTH, length)) {
		fprintf (stderr, "Can't set ImageLength tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps)) {
		fprintf (stderr, "Can't set BitsPerSample tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, SPP)) {
		fprintf (stderr, "Can't set SamplesPerPixel tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rows_per_strip)) {
		fprintf (stderr, "Can't set SamplesPerPixel tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_PLANARCONFIG, planarconfig)) {
		fprintf (stderr, "Can't set PlanarConfiguration tag.\n");
		goto failure;
	}
	if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric)) {
		fprintf (stderr, "Can't set PhotometricInterpretation tag.\n");
		goto failure;
	}

	/* Write dummy pixel data. */
	if (TIFFWriteScanline(tif, buf, 0, 0) == -1) {
		fprintf (stderr, "Can't write image data.\n");
		goto failure;
	}

        if (!TIFFWriteDirectory( tif )) {
		fprintf (stderr, "TIFFWriteDirectory() failed.\n");
		goto failure;
	}

	/*
	 * Now create an EXIF directory.
	 */
	if (TIFFCreateEXIFDirectory(tif) != 0) {
		fprintf (stderr, "TIFFCreateEXIFDirectory() failed.\n" );
		goto failure;
	}

	if (!TIFFSetField( tif, EXIFTAG_SPECTRALSENSITIVITY, "EXIF Spectral Sensitivity")) {
		fprintf (stderr, "Can't write SPECTRALSENSITIVITY\n" );
		goto failure;
	}

        if (!TIFFWriteCustomDirectory( tif, &dir_offset )) {
		fprintf (stderr, "TIFFWriteCustomDirectory() with EXIF failed.\n");
		goto failure;
	}

	/*
	 * Now create a custom directory with tags that conflict with mainline
	 * TIFF tags.
	 */

	TIFFFreeDirectory( tif );
	if (TIFFCreateCustomDirectory(tif, &customFieldArray) != 0) {
		fprintf (stderr, "TIFFCreateEXIFDirectory() failed.\n" );
		goto failure;
	}

	if (!TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, "*Custom1")) { /* not really IMAGEWIDTH */
		fprintf (stderr, "Can't write pseudo-IMAGEWIDTH.\n" );
		goto failure;
	}

	if (!TIFFSetField( tif, TIFFTAG_DOTRANGE, "*Custom2")) { /* not really DOTWIDTH */
		fprintf (stderr, "Can't write pseudo-DOTWIDTH.\n" );
		goto failure;
	}

        if (!TIFFWriteCustomDirectory( tif, &dir_offset2 )) {
		fprintf (stderr, "TIFFWriteCustomDirectory() with EXIF failed.\n");
		goto failure;
	}

	/*
	 * Go back to the first directory, and add the EXIFIFD pointer.
	 */
	TIFFSetDirectory(tif, 0);
	TIFFSetField(tif, TIFFTAG_EXIFIFD, dir_offset );
	TIFFSetField(tif, TIFFTAG_SUBIFD, 1, &dir_offset2 );

	TIFFClose(tif);

	/* Ok, now test whether we can read written values in the EXIF directory. */
	tif = TIFFOpen(filename, "r");

	TIFFGetField(tif, TIFFTAG_EXIFIFD, &read_dir_offset );
	if( read_dir_offset != dir_offset ) {
		fprintf (stderr, "Did not get expected EXIFIFD.\n" );
		goto failure;
	}

	TIFFGetField(tif, TIFFTAG_SUBIFD, &count16, &dir_offset2_ptr );
	read_dir_offset2 = dir_offset2_ptr[0];
	if( read_dir_offset2 != dir_offset2 || count16 != 1) {
		fprintf (stderr, "Did not get expected SUBIFD.\n" );
		goto failure;
	}

	if( !TIFFReadEXIFDirectory(tif, read_dir_offset) ) {
		fprintf (stderr, "TIFFReadEXIFDirectory() failed.\n" );
		goto failure;
	}

	if (!TIFFGetField( tif, EXIFTAG_SPECTRALSENSITIVITY, &ascii_value) ) {
		fprintf (stderr, "reading SPECTRALSENSITIVITY failed.\n" );
		goto failure;
	}

	if( strcmp(ascii_value,"EXIF Spectral Sensitivity") != 0) {
		fprintf (stderr, "got wrong SPECTRALSENSITIVITY value.\n" );
		goto failure;
	}

	/* Try reading the Custom directory */

	if( !TIFFReadCustomDirectory(tif, read_dir_offset2, &customFieldArray) ) {
		fprintf (stderr, "TIFFReadCustomDirectory() failed.\n" );
		goto failure;
	}

	if (!TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &ascii_value) ) {
		fprintf (stderr, "reading pseudo-IMAGEWIDTH failed.\n" );
		goto failure;
	}

	if( strcmp(ascii_value,"*Custom1") != 0) {
		fprintf (stderr, "got wrong pseudo-IMAGEWIDTH value.\n" );
		goto failure;
	}

	if (!TIFFGetField( tif, TIFFTAG_DOTRANGE, &ascii_value) ) {
		fprintf (stderr, "reading pseudo-DOTRANGE failed.\n" );
		goto failure;
	}

	if( strcmp(ascii_value,"*Custom2") != 0) {
		fprintf (stderr, "got wrong pseudo-DOTRANGE value.\n" );
		goto failure;
	}

	TIFFClose(tif);

	/* All tests passed; delete file and exit with success status. */
	unlink(filename);
	return 0;

failure:
	/*
	 * Something goes wrong; close file and return unsuccessful status.
	 * Do not remove the file for further manual investigation.
	 */
	TIFFClose(tif);
	return 1;
}
예제 #23
0
int
main(int argc, char* argv[])
{
	uint32	width, length;
	uint16	nbands = 1;		/* number of bands in input image */
        uint16	depth = 8;		/* bits per pixel in input image */
	uint32	rowsperstrip = (uint32) -1;
        uint16	photometric = PHOTOMETRIC_MINISBLACK;
	int	fd = 0;
	struct stat instat;
	char	*outfilename = NULL, *infilename = NULL;
	TIFF	*out = NULL;

	BMPFileHeader file_hdr;
        BMPInfoHeader info_hdr;
        int     bmp_type;
        uint32  clr_tbl_size, n_clr_elems = 3;
        unsigned char *clr_tbl;
	unsigned short *red_tbl = NULL, *green_tbl = NULL, *blue_tbl = NULL;
	uint32	row, clr;

	int	c;
	extern int optind;
	extern char* optarg;

	while ((c = getopt(argc, argv, "c:r:o:h")) != -1) {
		switch (c) {
		case 'c':		/* compression scheme */
			if (!processCompressOptions(optarg))
				usage();
			break;
		case 'r':		/* rows/strip */
			rowsperstrip = atoi(optarg);
			break;
		case 'o':
			outfilename = optarg;
			break;
		case 'h':
			usage();
		default:
			break;
		}
	}

	if (argc - optind < 2)
		usage();

	if (outfilename == NULL)
		outfilename = argv[argc-1];
	out = TIFFOpen(outfilename, "w");
	if (out == NULL) {
		TIFFError(infilename, "Cannot open file %s for output",
			  outfilename);
		goto bad3;
	}
	

	while (optind < argc-1) {
		infilename = argv[optind];
		optind++;
	    
		fd = open(infilename, O_RDONLY|O_BINARY, 0);
		if (fd < 0) {
			TIFFError(infilename, "Cannot open input file");
			return -1;
		}

		read(fd, file_hdr.bType, 2);
		if(file_hdr.bType[0] != 'B' || file_hdr.bType[1] != 'M') {
			TIFFError(infilename, "File is not BMP");
			goto bad;
		}

/* -------------------------------------------------------------------- */
/*      Read the BMPFileHeader. We need iOffBits value only             */
/* -------------------------------------------------------------------- */
		lseek(fd, 10, SEEK_SET);
		read(fd, &file_hdr.iOffBits, 4);
#ifdef WORDS_BIGENDIAN
		TIFFSwabLong(&file_hdr.iOffBits);
#endif
		fstat(fd, &instat);
		file_hdr.iSize = instat.st_size;

/* -------------------------------------------------------------------- */
/*      Read the BMPInfoHeader.                                         */
/* -------------------------------------------------------------------- */

		lseek(fd, BFH_SIZE, SEEK_SET);
		read(fd, &info_hdr.iSize, 4);
#ifdef WORDS_BIGENDIAN
		TIFFSwabLong(&info_hdr.iSize);
#endif

		if (info_hdr.iSize == BIH_WIN4SIZE)
			bmp_type = BMPT_WIN4;
		else if (info_hdr.iSize == BIH_OS21SIZE)
			bmp_type = BMPT_OS21;
		else if (info_hdr.iSize == BIH_OS22SIZE
			 || info_hdr.iSize == 16)
			bmp_type = BMPT_OS22;
		else
			bmp_type = BMPT_WIN5;

		if (bmp_type == BMPT_WIN4
		    || bmp_type == BMPT_WIN5
		    || bmp_type == BMPT_OS22) {
			read(fd, &info_hdr.iWidth, 4);
			read(fd, &info_hdr.iHeight, 4);
			read(fd, &info_hdr.iPlanes, 2);
			read(fd, &info_hdr.iBitCount, 2);
			read(fd, &info_hdr.iCompression, 4);
			read(fd, &info_hdr.iSizeImage, 4);
			read(fd, &info_hdr.iXPelsPerMeter, 4);
			read(fd, &info_hdr.iYPelsPerMeter, 4);
			read(fd, &info_hdr.iClrUsed, 4);
			read(fd, &info_hdr.iClrImportant, 4);
#ifdef WORDS_BIGENDIAN
			TIFFSwabLong((uint32*) &info_hdr.iWidth);
			TIFFSwabLong((uint32*) &info_hdr.iHeight);
			TIFFSwabShort((uint16*) &info_hdr.iPlanes);
			TIFFSwabShort((uint16*) &info_hdr.iBitCount);
			TIFFSwabLong((uint32*) &info_hdr.iCompression);
			TIFFSwabLong((uint32*) &info_hdr.iSizeImage);
			TIFFSwabLong((uint32*) &info_hdr.iXPelsPerMeter);
			TIFFSwabLong((uint32*) &info_hdr.iYPelsPerMeter);
			TIFFSwabLong((uint32*) &info_hdr.iClrUsed);
			TIFFSwabLong((uint32*) &info_hdr.iClrImportant);
#endif
			n_clr_elems = 4;
		}

		if (bmp_type == BMPT_OS22) {
			/* 
			 * FIXME: different info in different documents
			 * regarding this!
			 */
			 n_clr_elems = 3;
		}

		if (bmp_type == BMPT_OS21) {
			int16  iShort;

			read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
			TIFFSwabShort((uint16*) &iShort);
#endif
			info_hdr.iWidth = iShort;
			read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
			TIFFSwabShort((uint16*) &iShort);
#endif
			info_hdr.iHeight = iShort;
			read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
			TIFFSwabShort((uint16*) &iShort);
#endif
			info_hdr.iPlanes = iShort;
			read(fd, &iShort, 2);
#ifdef WORDS_BIGENDIAN
			TIFFSwabShort((uint16*) &iShort);
#endif
			info_hdr.iBitCount = iShort;
			info_hdr.iCompression = BMPC_RGB;
			n_clr_elems = 3;
		}

		if (info_hdr.iBitCount != 1  && info_hdr.iBitCount != 4  &&
		    info_hdr.iBitCount != 8  && info_hdr.iBitCount != 16 &&
		    info_hdr.iBitCount != 24 && info_hdr.iBitCount != 32) {
		    TIFFError(infilename,
			      "Cannot process BMP file with bit count %d",
			      info_hdr.iBitCount);
		    close(fd);
		    return 0;
		}

		width = info_hdr.iWidth;
		length = (info_hdr.iHeight > 0) ? info_hdr.iHeight : -info_hdr.iHeight;

		switch (info_hdr.iBitCount)
		{
			case 1:
			case 4:
			case 8:
				nbands = 1;
				depth = info_hdr.iBitCount;
				photometric = PHOTOMETRIC_PALETTE;
				/* Allocate memory for colour table and read it. */
				if (info_hdr.iClrUsed)
				    clr_tbl_size =
					    ((uint32)(1<<depth)<info_hdr.iClrUsed)
					    ? (uint32) (1 << depth)
					    : info_hdr.iClrUsed;
				else
				    clr_tbl_size = 1 << depth;
				clr_tbl = (unsigned char *)
					_TIFFmalloc(n_clr_elems * clr_tbl_size);
				if (!clr_tbl) {
					TIFFError(infilename,
					"Can't allocate space for color table");
					goto bad;
				}

				lseek(fd, BFH_SIZE + info_hdr.iSize, SEEK_SET);
				read(fd, clr_tbl, n_clr_elems * clr_tbl_size);

				red_tbl = (unsigned short*)
					_TIFFmalloc(1<<depth * sizeof(unsigned short));
				if (!red_tbl) {
					TIFFError(infilename,
				"Can't allocate space for red component table");
					_TIFFfree(clr_tbl);
					goto bad1;
				}
				green_tbl = (unsigned short*)
					_TIFFmalloc(1<<depth * sizeof(unsigned short));
				if (!green_tbl) {
					TIFFError(infilename,
				"Can't allocate space for green component table");
					_TIFFfree(clr_tbl);
					goto bad2;
				}
				blue_tbl = (unsigned short*)
					_TIFFmalloc(1<<depth * sizeof(unsigned short));
				if (!blue_tbl) {
					TIFFError(infilename,
				"Can't allocate space for blue component table");
					_TIFFfree(clr_tbl);
					goto bad3;
				}

				for(clr = 0; clr < clr_tbl_size; clr++) {
				    red_tbl[clr] = 257*clr_tbl[clr*n_clr_elems+2];
				    green_tbl[clr] = 257*clr_tbl[clr*n_clr_elems+1];
				    blue_tbl[clr] = 257*clr_tbl[clr*n_clr_elems];
				}

				_TIFFfree(clr_tbl);
				break;
			case 16:
			case 24:
				nbands = 3;
				depth = info_hdr.iBitCount / nbands;
				photometric = PHOTOMETRIC_RGB;
				break;
			case 32:
				nbands = 3;
				depth = 8;
				photometric = PHOTOMETRIC_RGB;
				break;
			default:
				break;
		}

/* -------------------------------------------------------------------- */
/*  Create output file.                                                 */
/* -------------------------------------------------------------------- */

		TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
		TIFFSetField(out, TIFFTAG_IMAGELENGTH, length);
		TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
		TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, nbands);
		TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, depth);
		TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
		TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
		TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
			     TIFFDefaultStripSize(out, rowsperstrip));
		
		if (red_tbl && green_tbl && blue_tbl) {
			TIFFSetField(out, TIFFTAG_COLORMAP,
				     red_tbl, green_tbl, blue_tbl);
		}
		
		if (compression == (uint16) -1)
			compression = COMPRESSION_PACKBITS;
		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;
		}

/* -------------------------------------------------------------------- */
/*  Read uncompressed image data.                                       */
/* -------------------------------------------------------------------- */

		if (info_hdr.iCompression == BMPC_RGB) {
			uint32 offset, size;
			char *scanbuf;

			/* XXX: Avoid integer overflow. We can calculate size
			 * in one step using
			 *
			 *  size = ((width * info_hdr.iBitCount + 31) & ~31) / 8
			 *
			 * formulae, but we should check for overflow
			 * conditions during calculation.
			 */
			size = width * info_hdr.iBitCount + 31;
			if (!width || !info_hdr.iBitCount
			    || (size - 31) / info_hdr.iBitCount != width ) {
				TIFFError(infilename,
					  "Wrong image parameters; can't "
					  "allocate space for scanline buffer");
				goto bad3;
			}
			size = (size & ~31) / 8;

			scanbuf = (char *) _TIFFmalloc(size);
			if (!scanbuf) {
				TIFFError(infilename,
				"Can't allocate space for scanline buffer");
				goto bad3;
			}

			for (row = 0; row < length; row++) {
				if (info_hdr.iHeight > 0)
					offset = file_hdr.iOffBits+(length-row-1)*size;
				else
					offset = file_hdr.iOffBits + row * size;
				if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
					TIFFError(infilename,
						  "scanline %lu: Seek error",
						  (unsigned long) row);
					break;
				}

				if (read(fd, scanbuf, size) < 0) {
					TIFFError(infilename,
						  "scanline %lu: Read error",
						  (unsigned long) row);
					break;
				}

				rearrangePixels(scanbuf, width, info_hdr.iBitCount);

				if (TIFFWriteScanline(out, scanbuf, row, 0)<0) {
					TIFFError(infilename,
						  "scanline %lu: Write error",
						  (unsigned long) row);
					break;
				}
			}

			_TIFFfree(scanbuf);

/* -------------------------------------------------------------------- */
/*  Read compressed image data.                                         */
/* -------------------------------------------------------------------- */

		} else if ( info_hdr.iCompression == BMPC_RLE8
			    || info_hdr.iCompression == BMPC_RLE4 ) {
			uint32		i, j, k, runlength;
			uint32		compr_size, uncompr_size;
			unsigned char   *comprbuf;
			unsigned char   *uncomprbuf;

			compr_size = file_hdr.iSize - file_hdr.iOffBits;
			uncompr_size = width * length;
			comprbuf = (unsigned char *) _TIFFmalloc( compr_size );
			if (!comprbuf) {
				TIFFError(infilename,
			"Can't allocate space for compressed scanline buffer");
				goto bad3;
			}
			uncomprbuf = (unsigned char *)_TIFFmalloc(uncompr_size);
			if (!uncomprbuf) {
				TIFFError(infilename,
			"Can't allocate space for uncompressed scanline buffer");
				goto bad3;
			}

			lseek(fd, file_hdr.iOffBits, SEEK_SET);
			read(fd, comprbuf, compr_size);
			i = 0;
			j = 0;
			if (info_hdr.iBitCount == 8) {		/* RLE8 */
			    while(j < uncompr_size && i < compr_size) {
				if ( comprbuf[i] ) {
				    runlength = comprbuf[i++];
				    while( runlength > 0
					   && j < uncompr_size
					   && i < compr_size ) {
					uncomprbuf[j++] = comprbuf[i];
					runlength--;
				    }
				    i++;
				} else {
				    i++;
				    if (comprbuf[i] == 0) /* Next scanline */
					i++;
				    else if (comprbuf[i] == 1) /* End of image */
					break;
				    else if (comprbuf[i] == 2) { /* Move to... */
					i++;
					if (i < compr_size - 1) {
					    j+=comprbuf[i]+comprbuf[i+1]*width;
					    i += 2;
					}
					else
					    break;
				    } else {            /* Absolute mode */
					runlength = comprbuf[i++];
					for (k = 0; k < runlength && j < uncompr_size && i < compr_size; k++)
					    uncomprbuf[j++] = comprbuf[i++];
					if ( k & 0x01 )
					    i++;
				    }
				}
			    }
			}
			else {				    /* RLE4 */
			    while( j < uncompr_size && i < compr_size ) {
				if ( comprbuf[i] ) {
				    runlength = comprbuf[i++];
				    while( runlength > 0 && j < uncompr_size && i < compr_size ) {
					if ( runlength & 0x01 )
					    uncomprbuf[j++] = (comprbuf[i] & 0xF0) >> 4;
					else
					    uncomprbuf[j++] = comprbuf[i] & 0x0F;
					runlength--;
				    }
				    i++;
				} else {
				    i++;
				    if (comprbuf[i] == 0) /* Next scanline */
					i++;
				    else if (comprbuf[i] == 1) /* End of image */
					break;
				    else if (comprbuf[i] == 2) { /* Move to... */
					i++;
					if (i < compr_size - 1) {
					    j+=comprbuf[i]+comprbuf[i+1]*width;
					    i += 2;
					}
					else
					    break;
				    } else {            /* Absolute mode */
					runlength = comprbuf[i++];
					for (k = 0; k < runlength && j < uncompr_size && i < compr_size; k++) {
					    if (k & 0x01)
						uncomprbuf[j++] = comprbuf[i++] & 0x0F;
					    else
						uncomprbuf[j++] = (comprbuf[i] & 0xF0) >> 4;
					}
					if (k & 0x01)
					    i++;
				    }
				}
			    }
			}
예제 #24
0
int main(int argc, char **argv)
{
    int             bits_per_pixel = 8, cmsize, i, j, k,
                    gray_index, chunk_size = 32, nchunks = 16;
    unsigned char * scan_line;
    uint16 *        gray;
    float           refblackwhite[2*1];
    TIFF *          tif;

    programName = argv[0];

    if (argc != 4)
        Usage();

    if (!strcmp(argv[1], "-depth"))
         bits_per_pixel = atoi(argv[2]);
    else
         Usage();

    switch (bits_per_pixel) {
        case 8:
            nchunks = 16;
            chunk_size = 32;
            break;
        case 4:
            nchunks = 4;
            chunk_size = 128;
            break;
        case 2:
            nchunks = 2;
            chunk_size = 256;
            break;
        default:
            Usage();
    }

    cmsize = nchunks * nchunks;
    gray = (uint16 *) malloc(cmsize * sizeof(uint16));

    gray[0] = 3000;
    for (i = 1; i < cmsize; i++)
        gray[i] = (uint16) (-log10((double) i / (cmsize - 1)) * 1000);

    refblackwhite[0] = 0.0;
    refblackwhite[1] = (float)((1L<<bits_per_pixel) - 1);

    if ((tif = TIFFOpen(argv[3], "w")) == NULL) {
        fprintf(stderr, "can't open %s as a TIFF file\n", argv[3]);
		free(gray);
        return 0;
    }

    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, WIDTH);
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, HEIGHT);
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bits_per_pixel);
    TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1);
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, refblackwhite);
    TIFFSetField(tif, TIFFTAG_TRANSFERFUNCTION, gray);
    TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE);

    scan_line = (unsigned char *) malloc(WIDTH / (8 / bits_per_pixel));

    for (i = 0; i < HEIGHT; i++) {
        for (j = 0, k = 0; j < WIDTH;) {
            gray_index = (j / chunk_size) + ((i / chunk_size) * nchunks);

            switch (bits_per_pixel) {
            case 8:
                scan_line[k++] = gray_index;
                j++;
                break;
            case 4:
                scan_line[k++] = (gray_index << 4) + gray_index;
                j += 2;
                break;
            case 2:
                scan_line[k++] = (gray_index << 6) + (gray_index << 4)
                    + (gray_index << 2) + gray_index;
                j += 4;
                break;
            }
        }
        TIFFWriteScanline(tif, scan_line, i, 0);
    }

    free(scan_line);
    TIFFClose(tif);
    return 0;
}
예제 #25
0
bool
TIFFOutput::open (const std::string &name, const ImageSpec &userspec,
                  OpenMode mode)
{
    if (mode == AppendMIPLevel) {
        error ("%s does not support MIP levels", format_name());
        return false;
    }

    close ();  // Close any already-opened file
    m_spec = userspec;  // Stash the spec

    // Check for things this format doesn't support
    if (m_spec.width < 1 || m_spec.height < 1) {
        error ("Image resolution must be at least 1x1, you asked for %d x %d",
               m_spec.width, m_spec.height);
        return false;
    }
    if (m_spec.depth < 1)
        m_spec.depth = 1;

    // Open the file
#ifdef _WIN32
    std::wstring wname = Strutil::utf8_to_utf16 (name);
    m_tif = TIFFOpenW (wname.c_str(), mode == AppendSubimage ? "a" : "w");
#else
    m_tif = TIFFOpen (name.c_str(), mode == AppendSubimage ? "a" : "w");
#endif
    if (! m_tif) {
        error ("Can't open \"%s\" for output.", name.c_str());
        return false;
    }

    TIFFSetField (m_tif, TIFFTAG_XPOSITION, (float)m_spec.x);
    TIFFSetField (m_tif, TIFFTAG_YPOSITION, (float)m_spec.y);
    TIFFSetField (m_tif, TIFFTAG_IMAGEWIDTH, m_spec.width);
    TIFFSetField (m_tif, TIFFTAG_IMAGELENGTH, m_spec.height);
    if ((m_spec.full_width != 0 || m_spec.full_height != 0) &&
        (m_spec.full_width != m_spec.width || m_spec.full_height != m_spec.height)) {
        TIFFSetField (m_tif, TIFFTAG_PIXAR_IMAGEFULLWIDTH, m_spec.full_width);
        TIFFSetField (m_tif, TIFFTAG_PIXAR_IMAGEFULLLENGTH, m_spec.full_height);
    }
    if (m_spec.tile_width) {
        TIFFSetField (m_tif, TIFFTAG_TILEWIDTH, m_spec.tile_width);
        TIFFSetField (m_tif, TIFFTAG_TILELENGTH, m_spec.tile_height);
    } else {
        // Scanline images must set rowsperstrip
        TIFFSetField (m_tif, TIFFTAG_ROWSPERSTRIP, 32);
    }
    TIFFSetField (m_tif, TIFFTAG_SAMPLESPERPIXEL, m_spec.nchannels);
    TIFFSetField (m_tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); // always
    
    int bps, sampformat;
    switch (m_spec.format.basetype) {
    case TypeDesc::INT8:
        bps = 8;
        sampformat = SAMPLEFORMAT_INT;
        break;
    case TypeDesc::UINT8:
        bps = 8;
        sampformat = SAMPLEFORMAT_UINT;
        break;
    case TypeDesc::INT16:
        bps = 16;
        sampformat = SAMPLEFORMAT_INT;
        break;
    case TypeDesc::UINT16:
        bps = 16;
        sampformat = SAMPLEFORMAT_UINT;
        break;
    case TypeDesc::HALF:
        // Silently change requests for unsupported 'half' to 'float'
        m_spec.set_format (TypeDesc::FLOAT);
    case TypeDesc::FLOAT:
        bps = 32;
        sampformat = SAMPLEFORMAT_IEEEFP;
        break;
    case TypeDesc::DOUBLE:
        bps = 64;
        sampformat = SAMPLEFORMAT_IEEEFP;
        break;
    default:
        error ("TIFF doesn't support %s images (\"%s\")",
               m_spec.format.c_str(), name.c_str());
        close();
        return false;
    }
    TIFFSetField (m_tif, TIFFTAG_BITSPERSAMPLE, bps);
    TIFFSetField (m_tif, TIFFTAG_SAMPLEFORMAT, sampformat);

    int photo = (m_spec.nchannels > 1 ? PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK);
    TIFFSetField (m_tif, TIFFTAG_PHOTOMETRIC, photo);

    // ExtraSamples tag
    if (m_spec.nchannels > 3) {
        bool unass = m_spec.get_int_attribute("oiio:UnassociatedAlpha", 0);
        short e = m_spec.nchannels-3;
        std::vector<unsigned short> extra (e);
        for (int c = 0;  c < e;  ++c) {
            if (m_spec.alpha_channel == (c+3))
                extra[c] = unass ? EXTRASAMPLE_UNASSALPHA : EXTRASAMPLE_ASSOCALPHA;
            else
                extra[c] = EXTRASAMPLE_UNSPECIFIED;
        }
        TIFFSetField (m_tif, TIFFTAG_EXTRASAMPLES, e, &extra[0]);
    }

    // Default to LZW compression if no request came with the user spec
    if (! m_spec.find_attribute("compression"))
        m_spec.attribute ("compression", "lzw");

    ImageIOParameter *param;
    const char *str = NULL;

    // Did the user request separate planar configuration?
    m_planarconfig = PLANARCONFIG_CONTIG;
    if ((param = m_spec.find_attribute("planarconfig", TypeDesc::STRING)) ||
        (param = m_spec.find_attribute("tiff:planarconfig", TypeDesc::STRING))) {
        str = *(char **)param->data();
        if (str && Strutil::iequals (str, "separate")) {
            m_planarconfig = PLANARCONFIG_SEPARATE;
            if (! m_spec.tile_width) {
                // I can only seem to make separate planarconfig work when
                // rowsperstrip is 1.
                TIFFSetField (m_tif, TIFFTAG_ROWSPERSTRIP, 1);
            }
        }
    }
    TIFFSetField (m_tif, TIFFTAG_PLANARCONFIG, m_planarconfig);

    // Automatically set date field if the client didn't supply it.
    if (! m_spec.find_attribute("DateTime")) {
        time_t now;
        time (&now);
        struct tm mytm;
        Sysutil::get_local_time (&now, &mytm);
        std::string date = Strutil::format ("%4d:%02d:%02d %2d:%02d:%02d",
                               mytm.tm_year+1900, mytm.tm_mon+1, mytm.tm_mday,
                               mytm.tm_hour, mytm.tm_min, mytm.tm_sec);
        m_spec.attribute ("DateTime", date);
    }

    if (Strutil::iequals (m_spec.get_string_attribute ("oiio:ColorSpace"), "sRGB"))
        m_spec.attribute ("Exif:ColorSpace", 1);

    // Deal with all other params
    for (size_t p = 0;  p < m_spec.extra_attribs.size();  ++p)
        put_parameter (m_spec.extra_attribs[p].name().string(),
                       m_spec.extra_attribs[p].type(),
                       m_spec.extra_attribs[p].data());

    std::vector<char> iptc;
    encode_iptc_iim (m_spec, iptc);
    if (iptc.size()) {
        iptc.resize ((iptc.size()+3) & (0xffff-3));  // round up
        TIFFSetField (m_tif, TIFFTAG_RICHTIFFIPTC, iptc.size()/4, &iptc[0]);
    }

    std::string xmp = encode_xmp (m_spec, true);
    if (! xmp.empty())
        TIFFSetField (m_tif, TIFFTAG_XMLPACKET, xmp.size(), xmp.c_str());
    
    TIFFCheckpointDirectory (m_tif);  // Ensure the header is written early
    m_checkpointTimer.start(); // Initialize the to the fileopen time
    m_checkpointItems = 0; // Number of tiles or scanlines we've written
    
    return true;
}
예제 #26
0
/// Write TIFF header
static void writeHeader(TIFF* tif, const V2i& imageSize,
                        int nchans, bool useFloat,
                        bool tiled, const V2i& tileSize)
{
    uint16 bitsPerSample = 8;
    uint16 photometric = PHOTOMETRIC_RGB;
    uint16 sampleFormat = SAMPLEFORMAT_UINT;
    if(useFloat)
    {
        bitsPerSample = 8*sizeof(float);
        sampleFormat = SAMPLEFORMAT_IEEEFP;
    }
    if(nchans == 1)
        photometric = PHOTOMETRIC_MINISBLACK;
    // Write TIFF header
    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, uint32(imageSize.x));
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, uint32(imageSize.y));
    TIFFSetField(tif, TIFFTAG_ORIENTATION, uint16(ORIENTATION_TOPLEFT));
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, uint16(PLANARCONFIG_CONTIG));
    TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, uint16(RESUNIT_NONE));
    TIFFSetField(tif, TIFFTAG_XRESOLUTION, 1.0f);
    TIFFSetField(tif, TIFFTAG_YRESOLUTION, 1.0f);
    TIFFSetField(tif, TIFFTAG_COMPRESSION, uint16(COMPRESSION_LZW));
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, uint16(nchans));
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitsPerSample);
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric);
    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, sampleFormat);
    TIFFSetField(tif, TIFFTAG_SOFTWARE, "Aqsis-2.0 (aka newcore)");
    if(tiled)
    {
        TIFFSetField(tif, TIFFTAG_TILEWIDTH, tileSize.x);
        TIFFSetField(tif, TIFFTAG_TILELENGTH, tileSize.y);
    }
    else
        TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, 0));
}
예제 #27
0
static void
write_surface_to_tiff (cairo_surface_t *surface, TIFF *tif)
{
	int cairo_width = cairo_image_surface_get_width (surface);
	int cairo_height = cairo_image_surface_get_height (surface);
	int cairo_stride = cairo_image_surface_get_stride (surface);
	guchar *cairo_data = cairo_image_surface_get_data (surface);

	TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, cairo_width);
	TIFFSetField (tif, TIFFTAG_IMAGELENGTH, cairo_height);
	TIFFSetField (tif, TIFFTAG_ROWSPERSTRIP, 64);
	TIFFSetField (tif, TIFFTAG_COMPRESSION, compression);
	TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
	TIFFSetField (tif, TIFFTAG_XRESOLUTION, (float) dpi);
	TIFFSetField (tif, TIFFTAG_YRESOLUTION, (float) dpi);
	TIFFSetField (tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);

	int ri;
	if (compression == COMPRESSION_CCITTFAX3 || compression == COMPRESSION_CCITTFAX4) {
		TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, 1);
		TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, 1);
		TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);

		guchar *cd0 = cairo_data;
		guchar *cd1 = cairo_data + cairo_stride;
		for (ri = 0; ri < cairo_height; ri++) {
			if (ri == cairo_height - 1) cd1 = NULL;
			guchar scanline[cairo_width / 8 + 1];
			memset (scanline, 0, sizeof (scanline));
			get_bw_scanline (scanline, cd0, cd1, cairo_width);
			cd0 = cd1;
			cd1 += cairo_stride;
			TIFFWriteScanline (tif, scanline, ri, 0);
		}
	} else {
		if (compression == COMPRESSION_JPEG)
			TIFFSetField (tif, TIFFTAG_JPEGQUALITY, jpeg_quality);
		TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, 8);
		TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, 3);
		TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);

		guchar *cd = cairo_data;
		for (ri = 0; ri < cairo_height; ri++) {
			guchar scanline[cairo_width * 3];
			get_rgb_scanline (scanline, cd, cairo_width);
			cd += cairo_stride;
			TIFFWriteScanline (tif, scanline, ri, 0);
		}
	}
	TIFFWriteDirectory (tif);
}
예제 #28
0
파일: io-tiff.c 프로젝트: ayamda/gdk-pixbuf
static gboolean
gdk_pixbuf__tiff_image_save_to_callback (GdkPixbufSaveFunc   save_func,
                                         gpointer            user_data,
                                         GdkPixbuf          *pixbuf, 
                                         gchar             **keys,
                                         gchar             **values,
                                         GError            **error)
{
        TIFF *tiff;
        gint width, height, rowstride;
        guchar *pixels;
        gboolean has_alpha;
        gushort alpha_samples[1] = { EXTRASAMPLE_UNASSALPHA };
        int y;
        TiffSaveContext *context;
        gboolean retval;
        guchar *icc_profile = NULL;
        gsize icc_profile_size = 0;

        tiff_push_handlers ();

        context = create_save_context ();
        tiff = TIFFClientOpen ("libtiff-pixbuf", "w", context,  
                               tiff_save_read, tiff_save_write, 
                               tiff_save_seek, tiff_save_close, 
                               tiff_save_size, 
                               NULL, NULL);

        if (!tiff || global_error) {
                tiff_set_error (error,
                                GDK_PIXBUF_ERROR_FAILED,
                                _("Failed to save TIFF image"));

                tiff_pop_handlers ();

                free_save_context (context);
                return FALSE;
        }

        rowstride = gdk_pixbuf_get_rowstride (pixbuf);
        pixels = gdk_pixbuf_get_pixels (pixbuf);

        has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);

        height = gdk_pixbuf_get_height (pixbuf);
        width = gdk_pixbuf_get_width (pixbuf);

        TIFFSetField (tiff, TIFFTAG_IMAGEWIDTH, width);
        TIFFSetField (tiff, TIFFTAG_IMAGELENGTH, height);
        TIFFSetField (tiff, TIFFTAG_BITSPERSAMPLE, 8);
        TIFFSetField (tiff, TIFFTAG_SAMPLESPERPIXEL, has_alpha ? 4 : 3);
        TIFFSetField (tiff, TIFFTAG_ROWSPERSTRIP, height);

        /* libtiff supports a number of 'codecs' such as:
           1 None, 2 Huffman, 5 LZW, 7 JPEG, 8 Deflate, see tiff.h */
        if (keys && *keys && values && *values) {
            guint i = 0;

            while (keys[i]) {
                if (g_str_equal (keys[i], "compression")) {
                    guint16 codec = strtol (values[i], NULL, 0);
                    if (TIFFIsCODECConfigured (codec))
                        TIFFSetField (tiff, TIFFTAG_COMPRESSION, codec);
                    else {
                        tiff_set_error (error,
                                        GDK_PIXBUF_ERROR_FAILED,
                                        _("TIFF compression doesn't refer to a valid codec."));
                        retval = FALSE;
                        goto cleanup;
                    }
                } else if (g_str_equal (keys[i], "icc-profile")) {
                        /* decode from base64 */
                        icc_profile = g_base64_decode (values[i], &icc_profile_size);
                        if (icc_profile_size < 127) {
                            g_set_error (error,
                                         GDK_PIXBUF_ERROR,
                                         GDK_PIXBUF_ERROR_BAD_OPTION,
                                         _("Color profile has invalid length %d."),
                                         (gint)icc_profile_size);
                            retval = FALSE;
                            goto cleanup;
                        }
                }
                i++;
            }
        }

        if (has_alpha)
                TIFFSetField (tiff, TIFFTAG_EXTRASAMPLES, 1, alpha_samples);

        TIFFSetField (tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
        TIFFSetField (tiff, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);        
        TIFFSetField (tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);

        if (icc_profile != NULL)
                TIFFSetField (tiff, TIFFTAG_ICCPROFILE, icc_profile_size, icc_profile);

        for (y = 0; y < height; y++) {
                if (TIFFWriteScanline (tiff, pixels + y * rowstride, y, 0) == -1 ||
                    global_error)
                        break;
        }

        if (global_error) {
                tiff_set_error (error,
                                GDK_PIXBUF_ERROR_FAILED,
                                _("Failed to write TIFF data"));

                TIFFClose (tiff);
                retval = FALSE;
                goto cleanup;
        }

        TIFFClose (tiff);
        if (global_error) {
                tiff_set_error (error,
                                GDK_PIXBUF_ERROR_FAILED,
                                _("TIFFClose operation failed"));
                retval = FALSE;
                goto cleanup;
        }


        /* Now call the callback */
        retval = save_func (context->buffer, context->used, error, user_data);

cleanup:
        g_free (icc_profile);
        tiff_pop_handlers ();
        free_save_context (context);
        return retval;
}
예제 #29
0
int
main(int argc, char *argv[]) {
	int fa,nfa;				/* argument we're looking at */
	char in_name[100];		/* Raster file name */
	char out_name[100];		/* Raster file name */
	int slow = 0;
	int check = 0;
	int i, rv = 0;

	TIFF *rh = NULL, *wh = NULL;
	int x, y, width, height;					/* Size of image */
	uint16 samplesperpixel, bitspersample;
	int no_pmtc;								/* Number of input photometrics */
	uint16 photometric, pmtc[10];				/* Photometrics of input file, and input profile */
	uint16 pconfig;								/* Planar configuration */
	uint16 resunits;
	float resx, resy;
	tdata_t *inbuf, *outbuf, *checkbuf = NULL;

	/* IMDI */
	imdi *s = NULL;
	sucntx su;		/* Setup context */
	unsigned char *inp[MAX_CHAN];
	unsigned char *outp[MAX_CHAN];
	int clutres = 33;

	/* Error check */
	int mxerr = 0;
	double avgerr = 0.0;
	double avgcount = 0.0;

	if (argc < 2)
		usage();

	su.verb = 0;
	su.icombine = 0;
	su.ocombine = 0;
	su.dolink = 0;
	su.in.intent = icmDefaultIntent;
	su.out.intent = icmDefaultIntent;

	/* Process the arguments */
	for(fa = 1;fa < argc;fa++) {
		nfa = fa;					/* skip to nfa if next argument is used */
		if (argv[fa][0] == '-')	{	/* Look for any flags */
			char *na = NULL;		/* next argument after flag, null if none */

			if (argv[fa][2] != '\000')
				na = &argv[fa][2];		/* next is directly after flag */
			else {
				if ((fa+1) < argc) {
					if (argv[fa+1][0] != '-') {
						nfa = fa + 1;
						na = argv[nfa];		/* next is seperate non-flag argument */
					}
				}
			}

			if (argv[fa][1] == '?')
				usage();

			/* Slow, Precise */
			else if (argv[fa][1] == 'p' || argv[fa][1] == 'P') {
				slow = 1;
			}

			/* Combine per channel curves */
			else if (argv[fa][1] == 'c' || argv[fa][1] == 'C') {
				su.icombine = 1;
				su.ocombine = 1;
			}

			/* Check curves */
			else if (argv[fa][1] == 'k' || argv[fa][1] == 'K') {
				check = 1;
			}

			/* Link profiles */
			else if (argv[fa][1] == 'l' || argv[fa][1] == 'L') {
				su.dolink = 1;
			}

			/* Input profile Intent */
			else if (argv[fa][1] == 'i' || argv[fa][1] == 'I') {
				fa = nfa;
				if (na == NULL) usage();
    			switch (na[0]) {
					case 'p':
					case 'P':
						su.in.intent = icPerceptual;
						break;
					case 'r':
					case 'R':
						su.in.intent = icRelativeColorimetric;
						break;
					case 's':
					case 'S':
						su.in.intent = icSaturation;
						break;
					case 'a':
					case 'A':
						su.in.intent = icAbsoluteColorimetric;
						break;
					default:
						usage();
				}
			}

			/* Output profile Intent */
			else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') {
				fa = nfa;
				if (na == NULL) usage();
    			switch (na[0]) {
					case 'p':
					case 'P':
						su.out.intent = icPerceptual;
						break;
					case 'r':
					case 'R':
						su.out.intent = icRelativeColorimetric;
						break;
					case 's':
					case 'S':
						su.out.intent = icSaturation;
						break;
					case 'a':
					case 'A':
						su.out.intent = icAbsoluteColorimetric;
						break;
					default:
						usage();
				}
			}

			/* Verbosity */
			else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
				su.verb = 1;
			}

			else 
				usage();
		} else
			break;
	}

	if (su.dolink) {
		if (fa >= argc || argv[fa][0] == '-') usage();
		strcpy(su.in.name,argv[fa++]);

		if (fa >= argc || argv[fa][0] == '-') usage();
		strcpy(su.out.name,argv[fa++]);
	} else {
		if (fa >= argc || argv[fa][0] == '-') usage();
		strcpy(su.dev.name,argv[fa++]);
	}

	if (fa >= argc || argv[fa][0] == '-') usage();
	strcpy(in_name,argv[fa++]);

	if (fa >= argc || argv[fa][0] == '-') usage();
	strcpy(out_name,argv[fa++]);

	/* - - - - - - - - - - - - - - - - */

	if (su.dolink) {
		icColorSpaceSignature natpcs;

		/* Open up the input device profile for reading */
		if ((su.in.fp = new_icmFileStd_name(su.in.name,"r")) == NULL)
			error ("Can't open file '%s'",su.in.name);
		
		if ((su.in.c = new_icc()) == NULL)
			error ("Creation of Input profile ICC object failed");
	
		/* Read header etc. */
		if ((rv = su.in.c->read(su.in.c,su.in.fp,0)) != 0)
			error ("%d, %s on file '%s'",rv,su.in.c->err,su.in.name);
		su.in.h = su.in.c->header;
	
		/* Check that it is a suitable device input icc */
		if (su.in.h->deviceClass != icSigInputClass
		 && su.in.h->deviceClass != icSigDisplayClass
		 && su.in.h->deviceClass != icSigOutputClass
		 && su.in.h->deviceClass != icSigColorSpaceClass)	/* For sRGB etc. */
			error("Input profile isn't a device profile");
	
		/* Get a conversion object */
		if ((su.in.luo = su.in.c->get_luobj(su.in.c, icmFwd, su.in.intent,
		                                             icSigLabData, icmLuOrdNorm)) == NULL)
			error ("%d, %s for profile '%s'",su.in.c->errc, su.in.c->err, su.in.name);
	
		/* Get details of conversion (Arguments may be NULL if info not needed) */
		su.in.luo->spaces(su.in.luo, &su.ins, &su.id, NULL, NULL, &su.in.alg, NULL, NULL, NULL);

		/* Get native PCS space */
		su.in.luo->lutspaces(su.in.luo, NULL, NULL, NULL, NULL, &natpcs);
	
		if (natpcs == icSigXYZData) {
			su.icombine = 1;			/* XYZ is to non-linear to be a benefit */
		}

		/* Open up the output device profile for reading */
		if ((su.out.fp = new_icmFileStd_name(su.out.name,"r")) == NULL)
			error ("Can't open file '%s'",su.out.name);
		
		if ((su.out.c = new_icc()) == NULL)
			error ("Creation of Output profile ICC object failed");
	
		/* Read header etc. */
		if ((rv = su.out.c->read(su.out.c,su.out.fp,0)) != 0)
			error ("%d, %s on file '%s'",rv,su.out.c->err,su.out.name);
		su.out.h = su.out.c->header;
	
		/* Check that it is a suitable device output icc */
		if (su.out.h->deviceClass != icSigInputClass
		 && su.out.h->deviceClass != icSigDisplayClass
		 && su.out.h->deviceClass != icSigOutputClass
		 && su.out.h->deviceClass != icSigColorSpaceClass)	/* For sRGB etc. */
			error("Output profile isn't a device profile");
	
		/* Get a conversion object */
		if ((su.out.luo = su.out.c->get_luobj(su.out.c, icmBwd, su.out.intent,
		                                             icSigLabData, icmLuOrdNorm)) == NULL)
			error ("%d, %s for profile '%s'",su.out.c->errc, su.out.c->err, su.out.name);
	
		/* Get details of conversion (Arguments may be NULL if info not needed) */
		su.out.luo->spaces(su.out.luo, NULL, NULL, &su.outs, &su.od, &su.out.alg, NULL, NULL, NULL);

		/* Get native PCS space */
		su.out.luo->lutspaces(su.out.luo, NULL, NULL, NULL, NULL, &natpcs);
	
		if (natpcs == icSigXYZData) {
			su.ocombine = 1;			/* XYZ is to non-linear to be a benefit */
		}

		/* See discussion in imdi/imdi_gen.c for ideal numbers */
		/* Use "high quality" resolution numbers */
		switch (su.id) {
			case 0:
				error ("Illegal number of input chanels");
			case 1:
	  		  	clutres = 256;
				break;
			case 2:
	  		  	clutres = 256;
				break;
			case 3:
	  		  	clutres = 33;
				break;
			case 4:
  		  		clutres = 18;
				break;
			case 5:
  		  		clutres = 16;
				break;
			case 6:
  		  		clutres = 9;
				break;
			case 7:
  		  		clutres = 7;
				break;
			case 8:
  		  		clutres = 6;
				break;
			default: /* > 8 chan */
				clutres = 3;
				break;
		}	

	} else {
		icmLut *lut;						/* ICC LUT table */
		icmLuLut *luluo;					/* LUT lookup object */

		/* Open up the device link profile for reading */
		if ((su.dev.fp = new_icmFileStd_name(su.dev.name,"r")) == NULL)
			error ("Can't open file '%s'",su.dev.name);
	
		if ((su.dev.c = new_icc()) == NULL)
			error ("Creation of ICC object failed");
	
		if ((rv = su.dev.c->read(su.dev.c, su.dev.fp, 0)) != 0)
			error ("%d, %s",rv,su.dev.c->err);
		su.dev.h = su.dev.c->header;

		if (su.verb) {
			icmFile *op;
			if ((op = new_icmFileStd_fp(stdout)) == NULL)
				error ("Can't open stdout");
			su.dev.h->dump(su.dev.h, op, 1);
			op->del(op);
		}

		/* Check that the profile is appropriate */
		if (su.dev.h->deviceClass != icSigLinkClass)
			error("Profile isn't a device link profile");

		/* Get a conversion object */
		if ((su.dev.luo = su.dev.c->get_luobj(su.dev.c, icmFwd, icmDefaultIntent,
		                                             icmSigDefaultData, icmLuOrdNorm)) == NULL)
			error ("%d, %s",su.dev.c->errc, su.dev.c->err);
	
		/* Get details of conversion (Arguments may be NULL if info not needed) */
		su.dev.luo->spaces(su.dev.luo, &su.ins, &su.id, &su.outs, &su.od, &su.dev.alg, NULL, NULL, NULL);

		if (su.dev.alg != icmLutType)
			error ("DeviceLink profile doesn't have Lut !");

		luluo = (icmLuLut *)su.dev.luo;		/* Safe to coerce */
		luluo->get_info(luluo, &lut, NULL, NULL, NULL);	/* Get some details */
		clutres = lut->clutPoints;			/* Desired table resolution */
	}

	/* - - - - - - - - - - - - - - - */
	/* Open up input tiff file ready for reading */
	/* Got arguments, so setup to process the file */
	if ((rh = TIFFOpen(in_name, "r")) == NULL)
		error("error opening read file '%s'",in_name);

	TIFFGetField(rh, TIFFTAG_IMAGEWIDTH,  &width);
	TIFFGetField(rh, TIFFTAG_IMAGELENGTH, &height);

	TIFFGetField(rh, TIFFTAG_BITSPERSAMPLE, &bitspersample);
	if (bitspersample != 8 && bitspersample != 16) {
		error("TIFF Input file must be 8 or 16 bit/channel");
	}

	TIFFGetField(rh, TIFFTAG_PHOTOMETRIC, &photometric);
	if  ((no_pmtc = ColorSpaceSignature2TiffPhotometric(pmtc, su.ins)) == 0)
		error("ICC  input colorspace '%s' can't be handled by a TIFF file!",
		      icm2str(icmColorSpaceSignature, su.ins));
	for (i = 0; i < no_pmtc; i++) {
		if (pmtc[i] == photometric)
			break;				/* Matches */
	}
	if (i >= no_pmtc) {
		/* These error reports are a bit sloppy */
		switch (no_pmtc) {
			case 1:
				error("TIFF colorspace '%s' doesn't match ICC colorspace '%s'!",
			      Photometric2str(photometric), Photometric2str(pmtc[0]));
			case 2:
				error("TIFF colorspace '%s' doesn't match ICC colorspace '%s' or '%s'!",
			      Photometric2str(photometric), Photometric2str(pmtc[0]),
			      Photometric2str(pmtc[1]));
			default:
				error("TIFF colorspace '%s' doesn't match ICC colorspace '%s', '%s' or '%s'!",
			      Photometric2str(photometric), Photometric2str(pmtc[0]),
			      Photometric2str(pmtc[1]), Photometric2str(pmtc[2]));
		}
	}

	TIFFGetField(rh, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
	if (su.id != samplesperpixel)
		error ("TIFF Input file has %d input channels mismatched to colorspace '%s'",
		       samplesperpixel, icm2str(icmColorSpaceSignature, su.ins));

	TIFFGetField(rh, TIFFTAG_PLANARCONFIG, &pconfig);
	if (pconfig != PLANARCONFIG_CONTIG)
		error ("TIFF Input file must be planar");

	TIFFGetField(rh, TIFFTAG_RESOLUTIONUNIT, &resunits);
	TIFFGetField(rh, TIFFTAG_XRESOLUTION, &resx);
	TIFFGetField(rh, TIFFTAG_YRESOLUTION, &resy);

	/* - - - - - - - - - - - - - - - */
	if ((wh = TIFFOpen(out_name, "w")) == NULL)
		error("Can\'t create TIFF file '%s'!",out_name);
	
	TIFFSetField(wh, TIFFTAG_IMAGEWIDTH,  width);
	TIFFSetField(wh, TIFFTAG_IMAGELENGTH, height);
	TIFFSetField(wh, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
	TIFFSetField(wh, TIFFTAG_SAMPLESPERPIXEL, su.od);
	TIFFSetField(wh, TIFFTAG_BITSPERSAMPLE, bitspersample);
	TIFFSetField(wh, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
	if  ((no_pmtc = ColorSpaceSignature2TiffPhotometric(pmtc, su.outs)) == 0)
		error("TIFF file can't handle output colorspace '%s'!",
		      icm2str(icmColorSpaceSignature, su.outs));
	TIFFSetField(wh, TIFFTAG_PHOTOMETRIC, pmtc[0]);	/* Use first returned */
	if (pmtc[0] == PHOTOMETRIC_SEPARATED) {
		int iset;
		int inlen;
		char *inames;
		iset = ColorSpaceSignature2TiffInkset(su.outs, &inlen, &inames);
		if (iset != 0xffff && inlen > 0 && inames != NULL) {
			TIFFSetField(wh, TIFFTAG_INKSET, iset);
			if (inames != NULL) {
				TIFFSetField(wh, TIFFTAG_INKNAMES, inlen, inames);
			}
		}
	}
	TIFFSetField(wh, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
	if (resunits) {
		TIFFSetField(wh, TIFFTAG_RESOLUTIONUNIT, resunits);
		TIFFSetField(wh, TIFFTAG_XRESOLUTION, resx);
		TIFFSetField(wh, TIFFTAG_YRESOLUTION, resy);
	}
	TIFFSetField(wh, TIFFTAG_IMAGEDESCRIPTION, "Color corrected by Argyll");

	/* - - - - - - - - - - - - - - - */
	/* Setup the imdi */

	if (!slow) {
		s = new_imdi(
			su.id,			/* Number of input dimensions */
			su.od,			/* Number of output dimensions */
							/* Input pixel representation */
			bitspersample == 8 ? pixint8 : pixint16,
							/* Output pixel representation */
			0x0,			/* Treat every channel as unsigned */
			NULL,			/* No raster to callback mapping */
			prec_min,		/* Minimum of input and output precision */
			bitspersample == 8 ? pixint8 : pixint16,
			0x0,			/* Treat every channel as unsigned */
			NULL,			/* No raster to callback mapping */
			clutres,		/* Desired table resolution */
			oopts_none,		/* Desired per channel output options */
			NULL,			/* Output channel check values */
			opts_none,		/* Desired processing direction and stride support */
			input_curves,	/* Callback functions */
			md_table,
			output_curves,
			(void *)&su		/* Context to callbacks */
		);
	
		if (s == NULL)
			error("new_imdi failed");
	}

	/* - - - - - - - - - - - - - - - */
	/* Process colors to translate */
	/* (Should fix this to process a group of lines at a time ?) */

	inbuf  = _TIFFmalloc(TIFFScanlineSize(rh));
	outbuf = _TIFFmalloc(TIFFScanlineSize(wh));
	if (check)
		checkbuf = _TIFFmalloc(TIFFScanlineSize(wh));

	inp[0] = (unsigned char *)inbuf;
	outp[0] = (unsigned char *)outbuf;

	if (!slow) {		/* Fast */
		for (y = 0; y < height; y++) {

			/* Read in the next line */
			if (TIFFReadScanline(rh, inbuf, y, 0) < 0)
				error ("Failed to read TIFF line %d",y);

			/* Do fast conversion */
			s->interp(s, (void **)outp, 0, (void **)inp, 0, width);
			
			if (check) {
				/* Do floating point conversion */
				for (x = 0; x < width; x++) {
					int i;
					double in[MAX_CHAN], out[MAX_CHAN];
					
					if (bitspersample == 8)
						for (i = 0; i < su.id; i++)
							in[i] = ((unsigned char *)inbuf)[x * su.id + i]/255.0;
					else
						for (i = 0; i < su.id; i++)
							in[i] = ((unsigned short *)inbuf)[x * su.id + i]/65535.0;
					
#ifdef NEVER
					if (su.dolink) {
						if ((rv = su.in.luo->lookup(su.in.luo, out, in)) > 1)
							error ("%d, %s",su.dev.c->errc,su.dev.c->err);
						if ((rv = su.out.luo->lookup(su.out.luo, out, out)) > 1)
							error ("%d, %s",su.dev.c->errc,su.dev.c->err);
					} else {
						if ((rv = su.dev.luo->lookup(su.dev.luo, out, in)) > 1)
							error ("%d, %s",su.dev.c->errc,su.dev.c->err);
					}
#else
					/* Apply the reference conversion */
					input_curves((void *)&su, out, in);
					md_table((void *)&su, out, out);
					output_curves((void *)&su, out, out);
#endif
					if (bitspersample == 8)
						for (i = 0; i < su.od; i++)
							((unsigned char *)checkbuf)[x * su.od + i] = (int)(out[i] * 255.0 + 0.5);
					else
						for (i = 0; i < su.od; i++)
							((unsigned short *)checkbuf)[x * su.od + i] = (int)(out[i] * 65535.0 + 0.5);
				}
				/* Compute the errors */
				for (x = 0; x < (width * su.od); x++) {
					int err;
					if (bitspersample == 8)
						err = ((unsigned char *)outbuf)[x] - ((unsigned char *)checkbuf)[x];
					else
						err = ((unsigned short *)outbuf)[x] - ((unsigned short *)checkbuf)[x];
					if (err < 0)
						err = -err;
					if (err > mxerr)
						mxerr = err;
					avgerr += (double)err;
					avgcount++;
				}
			}
				
			if (TIFFWriteScanline(wh, outbuf, y, 0) < 0)
				error ("Failed to write TIFF line %d",y);

		}

	} else {	/* Slow but precise */
		if (bitspersample == 8) {
			for (y = 0; y < height; y++) {

				/* Read in the next line */
				if (TIFFReadScanline(rh, inbuf, y, 0) < 0)
					error ("Failed to read TIFF line %d",y);

				/* Do floating point conversion */
				for (x = 0; x < width; x++) {
					int i;
					double in[MAX_CHAN], out[MAX_CHAN];
					
					for (i = 0; i < su.id; i++) {
						in[i] = ((unsigned char *)inbuf)[x * su.id + i]/255.0;
					}
					
#ifdef NEVER
					if (su.dolink) {
						if ((rv = su.in.luo->lookup(su.in.luo, out, in)) > 1)
							error ("%d, %s",su.dev.c->errc,su.dev.c->err);
						if ((rv = su.out.luo->lookup(su.out.luo, out, out)) > 1)
							error ("%d, %s",su.dev.c->errc,su.dev.c->err);
					} else {
						if ((rv = su.dev.luo->lookup(su.dev.luo, out, in)) > 1)
							error ("%d, %s",su.dev.c->errc,su.dev.c->err);
					}
#else
					/* Apply the reference conversion */
					input_curves((void *)&su, out, in);
					md_table((void *)&su, out, out);
					output_curves((void *)&su, out, out);
#endif

					for (i = 0; i < su.od; i++) {
						double outi = out[i];
						if (outi < 0.0)			/* Protect against sillies */
							outi = 0.0;
						else if (outi > 1.0)
							outi = 1.0;
						((unsigned char *)outbuf)[x * su.od + i] = (int)(outi * 255.0 + 0.5);
					}
				}
				if (TIFFWriteScanline(wh, outbuf, y, 0) < 0)
					error ("Failed to write TIFF line %d",y);
			}
		} else if (bitspersample == 16) {
			for (y = 0; y < height; y++) {

				/* Read in the next line */
				if (TIFFReadScanline(rh, inbuf, y, 0) < 0)
					error ("Failed to read TIFF line %d",y);

				/* Do floating point conversion */
				for (x = 0; x < width; x++) {
					int i;
					double in[MAX_CHAN], out[MAX_CHAN];
					
					for (i = 0; i < su.id; i++) {
						in[i] = ((unsigned short *)inbuf)[x * su.id + i]/65535.0;
					}
					
#ifdef NEVER
					if (su.dolink) {
						if ((rv = su.in.luo->lookup(su.in.luo, out, in)) > 1)
							error ("%d, %s",su.dev.c->errc,su.dev.c->err);
						if ((rv = su.out.luo->lookup(su.out.luo, out, out)) > 1)
							error ("%d, %s",su.dev.c->errc,su.dev.c->err);
					} else {
						if ((rv = su.dev.luo->lookup(su.dev.luo, out, in)) > 1)
							error ("%d, %s",su.dev.c->errc,su.dev.c->err);
					}
#else
					/* Apply the reference conversion */
					input_curves((void *)&su, out, in);
					md_table((void *)&su, out, out);
					output_curves((void *)&su, out, out);
#endif

					for (i = 0; i < su.od; i++) {
						double outi = out[i];
						if (outi < 0.0)			/* Protect against sillies */
							outi = 0.0;
						else if (outi > 1.0)
							outi = 1.0;
						((unsigned short *)outbuf)[x * su.od + i] = (int)(outi * 65535.0 + 0.5);
					}
				}
				if (TIFFWriteScanline(wh, outbuf, y, 0) < 0)
					error ("Failed to write TIFF line %d",y);
			}
		}
	}

	if (check) {
		printf("Worst error = %d bits, average error = %f bits\n", mxerr, avgerr/avgcount);
		if (bitspersample == 8)
			printf("Worst error = %f%%, average error = %f%%\n",
			       mxerr/2.55, avgerr/(2.55 * avgcount));
		else
			printf("Worst error = %f%%, average error = %f%%\n",
			       mxerr/655.35, avgerr/(655.35 * avgcount));
	}

	/* Done with lookup object */
	if (s != NULL)
		s->del(s);

	if (su.dolink) {
		su.in.luo->del(su.in.luo);
		su.in.c->del(su.in.c);
		su.in.fp->del(su.in.fp);
		su.out.luo->del(su.out.luo);
		su.out.c->del(su.out.c);
		su.out.fp->del(su.out.fp);
	} else {
		su.dev.luo->del(su.dev.luo);
		su.dev.c->del(su.dev.c);
		su.dev.fp->del(su.dev.fp);
	}

	_TIFFfree(inbuf);
	_TIFFfree(outbuf);
	if (check)
		_TIFFfree(checkbuf);

	TIFFClose(rh);		/* Close Input file */
	TIFFClose(wh);		/* Close Output file */

	return 0;
}
예제 #30
0
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++ = (unsigned char) rmap[ibuf[x]];
				*pp++ = (unsigned char) gmap[ibuf[x]];
				*pp++ = (unsigned char) 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++ = (unsigned char) rmap[ibuf[x]];
			if (!TIFFWriteScanline(out, obuf, row, 0))
				goto done;
			for (pp = obuf, x = 0; x < imagewidth; x++)
				*pp++ = (unsigned char) gmap[ibuf[x]];
			if (!TIFFWriteScanline(out, obuf, row, 0))
				goto done;
			for (pp = obuf, x = 0; x < imagewidth; x++)
				*pp++ = (unsigned char) 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);
}