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); }
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 ); }
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; }
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; }
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; }
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; }
/** 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); }
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); }
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); }
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); }
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//////// }
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; }
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; }
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; }
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; }
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; }
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; }
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."); }
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); }
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; }
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; }
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; }
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++; } } } }
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; }
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; }
/// 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)); }
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); }
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; }
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; }
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); }