/* * Grow the strip data structures by delta strips. */ static int TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module) { TIFFDirectory *td = &tif->tif_dir; uint64* new_stripoffset; uint64* new_stripbytecount; assert(td->td_planarconfig == PLANARCONFIG_CONTIG); new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset, (td->td_nstrips + delta) * sizeof (uint64)); new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount, (td->td_nstrips + delta) * sizeof (uint64)); if (new_stripoffset == NULL || new_stripbytecount == NULL) { if (new_stripoffset) _TIFFfree(new_stripoffset); if (new_stripbytecount) _TIFFfree(new_stripbytecount); td->td_nstrips = 0; TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays"); return (0); } td->td_stripoffset = new_stripoffset; td->td_stripbytecount = new_stripbytecount; _TIFFmemset(td->td_stripoffset + td->td_nstrips, 0, delta*sizeof (uint64)); _TIFFmemset(td->td_stripbytecount + td->td_nstrips, 0, delta*sizeof (uint64)); td->td_nstrips += delta; tif->tif_flags |= TIFF_DIRTYDIRECT; return (1); }
/* * Grow the strip data structures by delta strips. This routine assumes entire * offsets / byte counts arrays are in memory. */ static int TIFFGrowStrips(TIFF* tif, int delta, const char* module) { TIFFDirectory *td = &tif->tif_dir; toff_t *new_stripoffs; uint32 *new_stripbcs; assert(td->td_planarconfig == PLANARCONFIG_CONTIG); /* failure if have already placed offsets array in file */ if (td->td_stripoffsoff) { td->td_nstrips = 0; TIFFErrorExt(tif->tif_clientdata, module, "%s: Can't expand strip array", tif->tif_name); return (0); } new_stripoffs = (toff_t*)_TIFFrealloc(td->td_stripoffsbuf, (td->td_nstrips + delta) * sizeof (toff_t)); new_stripbcs = (uint32*)_TIFFrealloc(td->td_stripbcsbuf, (td->td_nstrips + delta) * sizeof (uint32)); if (new_stripoffs == NULL || new_stripbcs == NULL) { _TIFFfree(new_stripoffs); _TIFFfree(new_stripbcs); td->td_nstrips = 0; TIFFErrorExt(tif->tif_clientdata, module, "%s: No space to expand strip arrays", tif->tif_name); return (0); } td->td_stripoffsbuf = new_stripoffs; td->td_stripbcsbuf = new_stripbcs; _TIFFmemset(td->td_stripoffsbuf + td->td_nstrips, 0, delta * sizeof(toff_t)); _TIFFmemset(td->td_stripbcsbuf + td->td_nstrips, 0, delta * sizeof(uint32)); td->td_nstrips += delta; td->td_stripbufmax = TIFFmax(td->td_stripbufmax, td->td_nstrips); return (1); }
static int TIFFSetupStrips(TIFF* tif) { #define isUnspecified(td, v) \ (td->v == (uint32) -1 || (td)->td_imagelength == 0) register TIFFDirectory *td = &tif->tif_dir; if (!isTiled(tif)) td->td_stripsperimage = isUnspecified(td, td_rowsperstrip) ? 1 : howmany(td->td_imagelength, td->td_rowsperstrip); else td->td_stripsperimage = isUnspecified(td, td_tilelength) ? 1 : TIFFNumberOfTiles(tif); td->td_nstrips = td->td_stripsperimage; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_nstrips *= td->td_samplesperpixel; td->td_stripoffset = (uint32 *) _TIFFmalloc(td->td_nstrips * sizeof (uint32)); td->td_stripbytecount = (uint32 *) _TIFFmalloc(td->td_nstrips * sizeof (uint32)); if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) return (0); /* * Place data at the end-of-file * (by setting offsets to zero). */ _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32)); _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32)); TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); return (1); #undef isUnspecified }
int TIFFSetupStrips(TIFF* tif) { TIFFDirectory* td = &tif->tif_dir; if (isTiled(tif)) td->td_stripsperimage = isUnspecified(tif, FIELD_TILEDIMENSIONS) ? td->td_samplesperpixel : TIFFNumberOfTiles(tif); else td->td_stripsperimage = isUnspecified(tif, FIELD_ROWSPERSTRIP) ? td->td_samplesperpixel : TIFFNumberOfStrips(tif); td->td_nstrips = td->td_stripsperimage; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_stripsperimage /= td->td_samplesperpixel; td->td_stripoffset = (uint64 *) _TIFFmalloc(td->td_nstrips * sizeof (uint64)); td->td_stripbytecount = (uint64 *) _TIFFmalloc(td->td_nstrips * sizeof (uint64)); if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) return (0); /* * Place data at the end-of-file * (by setting offsets to zero). */ _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64)); _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64)); TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); return (1); }
/* * Grow the strip data structures by delta strips. */ static int TIFFGrowStrips(TIFF* tif, int delta, const char* module) { TIFFDirectory* td = &tif->tif_dir; uint32* new_stripoffset, *new_stripbytecount; assert(td->td_planarconfig == PLANARCONFIG_CONTIG); new_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset, (td->td_nstrips + delta) * sizeof(uint32)); new_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount, (td->td_nstrips + delta) * sizeof(uint32)); if (new_stripoffset == NULL || new_stripbytecount == NULL) { if (new_stripoffset) { _TIFFfree(new_stripoffset); } if (new_stripbytecount) { _TIFFfree(new_stripbytecount); } td->td_nstrips = 0; TIFFError(module, "%s: No space to expand strip arrays", tif->tif_name); return (0); } td->td_stripoffset = new_stripoffset; td->td_stripbytecount = new_stripbytecount; _TIFFmemset(td->td_stripoffset + td->td_nstrips, 0, delta * sizeof(uint32)); _TIFFmemset(td->td_stripbytecount + td->td_nstrips, 0, delta * sizeof(uint32)); td->td_nstrips += delta; return (1); }
static void _XTIFFDefaultDirectory(TIFF *tif) { xtiff *xt; /* Allocate Directory Structure if first time, and install it */ if (!(tif->tif_flags & XTIFF_INITIALIZED)) { xt = _TIFFmalloc(sizeof(xtiff)); if (!xt) { /* handle memory allocation failure here ! */ return; } _TIFFmemset(xt,0,sizeof(xtiff)); /* * Install into TIFF structure. */ TIFFMEMBER(tif,clientdir) = (tidata_t)xt; tif->tif_flags |= XTIFF_INITIALIZED; /* dont do this again! */ } /* set up our own defaults */ _XTIFFLocalDefaultDirectory(tif); /* Since an XTIFF client module may have overridden * the default directory method, we call it now to * allow it to set up the rest of its own methods. */ if (_ParentExtender) (*_ParentExtender)(tif); }
TIFFFieldInfo* _TIFFCreateAnonFieldInfo(TIFF *tif, ttag_t tag, TIFFDataType field_type) { TIFFFieldInfo *fld; (void) tif; fld = (TIFFFieldInfo *) _TIFFmalloc(sizeof (TIFFFieldInfo)); if (fld == NULL) return NULL; _TIFFmemset( fld, 0, sizeof(TIFFFieldInfo) ); fld->field_tag = tag; fld->field_readcount = TIFF_VARIABLE2; fld->field_writecount = TIFF_VARIABLE2; fld->field_type = field_type; fld->field_bit = FIELD_CUSTOM; fld->field_oktochange = TRUE; fld->field_passcount = TRUE; fld->field_name = (char *) _TIFFmalloc(32); if (fld->field_name == NULL) { _TIFFfree(fld); return NULL; } /* * note that this name is a special sign to TIFFClose() and * _TIFFSetupFieldInfo() to free the field */ sprintf(fld->field_name, "Tag %d", (int) tag); return fld; }
static int cpData(TIFF *in, TIFF *out, const uint32_t nrow) { tsize_t scSize = TIFFScanlineSize(in); tdata_t buf = _TIFFmalloc(scSize); if (!buf) return 0; _TIFFmemset(buf, 0, scSize); for (uint32_t irow = 0; irow < nrow; irow++) { try { if (TIFFReadScanline(in, buf, irow, 0) < 0) { throw -1; } if (TIFFWriteScanline(out, buf, irow, 0) < 0) { throw -2; } } catch (int err) { if (err == -1) { std::cerr << "Cannot read scanline " << irow; std::cerr << " from " << TIFFFileName(in) << std::endl; } else if (err == -2) { std::cerr << "Cannot write scanline " << irow; std::cerr << " to " << TIFFFileName(out) << std::endl; } else { std::cerr << "Unknown error during row copy" << std::endl; } _TIFFfree(buf); return 0; } } _TIFFfree(buf); return 1; }
static toff_t _tiffSeekProc(thandle_t fd, off_t off, int whence) { char buf[256]; long current_off, expected_off, new_off; if (whence == SEEK_END || off <= 0) return Fseek(off, (int) fd, whence); current_off = Fseek(0, (int) fd, SEEK_CUR); /* find out where we are */ if (whence == SEEK_SET) expected_off = off; else expected_off = off + current_off; new_off = Fseek(off, (int) fd, whence); if (new_off == expected_off) return new_off; /* otherwise extend file -- zero filling the hole */ if (new_off < 0) /* error? */ new_off = Fseek(0, (int) fd, SEEK_END); /* go to eof */ _TIFFmemset(buf, 0, sizeof(buf)); while (expected_off > new_off) { off = expected_off - new_off; if (off > sizeof(buf)) off = sizeof(buf); if ((current_off = Fwrite((int) fd, off, buf)) != off) return (current_off > 0) ? new_off + current_off : new_off; new_off += off; } return new_off; }
static void _XTIFFLocalDefaultDirectory(TIFF *tif) { xtiff *xt = XTIFFDIR(tif); XTIFFDirectory* xd = &xt->xtif_dir; /* Install the extended Tag field info */ _TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo)); /* * free up any dynamically allocated arrays * before the new directory is read in. */ _XTIFFFreeDirectory(xt); _TIFFmemset(xt,0,sizeof(xtiff)); /* Override the tag access methods */ PARENT(xt,vsetfield) = TIFFMEMBER(tif,vsetfield); TIFFMEMBER(tif,vsetfield) = _XTIFFVSetField; PARENT(xt,vgetfield) = TIFFMEMBER(tif,vgetfield); TIFFMEMBER(tif,vgetfield) = _XTIFFVGetField; /* * XXX Set up any default values here. */ xd->xd_example_single = 234; }
int TIFFInitJBIG(TIFF* tif, int scheme) { JBIGState* codec = NULL; assert(scheme == COMPRESSION_JBIG); /* * Merge codec-specific tag information. */ if (!_TIFFMergeFieldInfo(tif, jbigFieldInfo, TIFFArrayCount(jbigFieldInfo))) { TIFFErrorExt(tif->tif_clientdata, "TIFFInitJBIG", "Merging JBIG codec-specific tags failed"); return 0; } /* Allocate memory for the JBIGState structure.*/ tif->tif_data = (tdata_t)_TIFFmalloc(sizeof(JBIGState)); if (tif->tif_data == NULL) { TIFFError("TIFFInitJBIG", "Not enough memory for JBIGState"); return 0; } _TIFFmemset(tif->tif_data, 0, sizeof(JBIGState)); codec = GetJBIGState(tif); /* Initialize codec private fields */ codec->recvparams = 0; codec->subaddress = NULL; codec->faxdcs = NULL; codec->recvtime = 0; /* * Override parent get/set field methods. */ codec->vgetparent = tif->tif_tagmethods.vgetfield; codec->vsetparent = tif->tif_tagmethods.vsetfield; tif->tif_tagmethods.vgetfield = JBIGVGetField; tif->tif_tagmethods.vsetfield = JBIGVSetField; tif->tif_tagmethods.printdir = JBIGPrintDir; /* * These flags are set so the JBIG Codec can control when to reverse * bits and when not to and to allow the jbig decoder and bit reverser * to write to memory when necessary. */ tif->tif_flags |= TIFF_NOBITREV; tif->tif_flags &= ~TIFF_MAPPED; /* Setup the function pointers for encode, decode, and cleanup. */ tif->tif_setupdecode = JBIGSetupDecode; tif->tif_decodestrip = JBIGDecode; tif->tif_setupencode = JBIGSetupEncode; tif->tif_encodestrip = JBIGEncode; tif->tif_cleanup = JBIGCleanup; return 1; }
int copyFaxFile(TIFF* tifin, TIFF* tifout) { uint32 row; uint16 badrun; int ok; tifin->tif_rawdatasize = TIFFGetFileSize(tifin); tifin->tif_rawdata = _TIFFmalloc(tifin->tif_rawdatasize); if (!ReadOK(tifin, tifin->tif_rawdata, tifin->tif_rawdatasize)) { TIFFError(tifin->tif_name, "%s: Read error at scanline 0"); return (0); } tifin->tif_rawcp = tifin->tif_rawdata; tifin->tif_rawcc = tifin->tif_rawdatasize; (*tifin->tif_setupdecode)(tifin); (*tifin->tif_predecode)(tifin, (tsample_t) 0); tifin->tif_row = 0; badfaxlines = 0; badfaxrun = 0; _TIFFmemset(refbuf, 0, sizeof (refbuf)); row = 0; badrun = 0; /* current run of bad lines */ while (tifin->tif_rawcc > 0) { ok = (*tifin->tif_decoderow)(tifin, rowbuf, sizeof (rowbuf), 0); if (!ok) { badfaxlines++; badrun++; /* regenerate line from previous good line */ _TIFFmemcpy(rowbuf, refbuf, sizeof (rowbuf)); } else { if (badrun > badfaxrun) badfaxrun = badrun; badrun = 0; _TIFFmemcpy(refbuf, rowbuf, sizeof (rowbuf)); } tifin->tif_row++; if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) { fprintf(stderr, "%s: Write error at row %ld.\n", tifout->tif_name, (long) row); break; } row++; if (stretch) { if (TIFFWriteScanline(tifout, rowbuf, row, 0) < 0) { fprintf(stderr, "%s: Write error at row %ld.\n", tifout->tif_name, (long) row); break; } row++; } } if (badrun > badfaxrun) badfaxrun = badrun; _TIFFfree(tifin->tif_rawdata); return (row); }
static int LZWSetupDecode(TIFF* tif) { static const char module[] = "LZWSetupDecode"; LZWCodecState* sp = DecoderState(tif); int code; if( sp == NULL ) { /* * Allocate state block so tag methods have storage to record * values. */ tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZWCodecState)); if (tif->tif_data == NULL) { TIFFErrorExt(tif->tif_clientdata, module, "No space for LZW state block"); return (0); } DecoderState(tif)->dec_codetab = NULL; DecoderState(tif)->dec_decode = NULL; /* * Setup predictor setup. */ (void) TIFFPredictorInit(tif); sp = DecoderState(tif); } assert(sp != NULL); if (sp->dec_codetab == NULL) { sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t)); if (sp->dec_codetab == NULL) { TIFFErrorExt(tif->tif_clientdata, module, "No space for LZW code table"); return (0); } /* * Pre-load the table. */ code = 255; do { sp->dec_codetab[code].value = (unsigned char)code; sp->dec_codetab[code].firstchar = (unsigned char)code; sp->dec_codetab[code].length = 1; sp->dec_codetab[code].next = NULL; } while (code--); /* * Zero-out the unused entries */ _TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0, (CODE_FIRST - CODE_CLEAR) * sizeof (code_t)); } return (1); }
/* * Initialize the YCbCr->RGB conversion tables. The conversion * is done according to the 6.0 spec: * * R = Y + Cr*(2 - 2*LumaRed) * B = Y + Cb*(2 - 2*LumaBlue) * G = Y * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen * * To avoid floating point arithmetic the fractional constants that * come out of the equations are represented as fixed point values * in the range 0...2^16. We also eliminate multiplications by * pre-calculating possible values indexed by Cb and Cr (this code * assumes conversion is being done for 8-bit samples). */ static void TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, TIFF* tif) { TIFFRGBValue* clamptab; float* coeffs; int i; clamptab = (TIFFRGBValue*)( (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))); _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */ ycbcr->clamptab = (clamptab += 256); for (i = 0; i < 256; i++) clamptab[i] = i; _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */ TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS, &coeffs); _TIFFmemcpy(ycbcr->coeffs, coeffs, 3*sizeof (float)); { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1); float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2); float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3); float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4); int x; ycbcr->Cr_r_tab = (int*) (clamptab + 3*256); ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256; ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256); ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256; /* * i is the actual input pixel value in the range 0..255 * Cb and Cr values are in the range -128..127 (actually * they are in a range defined by the ReferenceBlackWhite * tag) so there is some range shifting to do here when * constructing tables indexed by the raw pixel data. * * XXX handle ReferenceBlackWhite correctly to calculate * Cb/Cr values to use in constructing the tables. */ for (i = 0, x = -128; i < 256; i++, x++) { ycbcr->Cr_r_tab[i] = (int)((D1*x + ONE_HALF)>>SHIFT); ycbcr->Cb_b_tab[i] = (int)((D3*x + ONE_HALF)>>SHIFT); ycbcr->Cr_g_tab[i] = D2*x; ycbcr->Cb_g_tab[i] = D4*x + ONE_HALF; } } }
// Write a 6x4 test tiff consisting of two directories void writeStripTiff(const char* fileName) { uint32 height = 4; uint32 width = 6; uint32 rowsPerStrip = height/2; uint16 samplesPerPixel = 3; uint16 bitsPerSample = 8; const unsigned char red[] = {0xFF, 0, 0}; const unsigned char blue[] = {0, 0, 0xFF}; //TIFF* outFile = TIFFStreamOpen("stream", &outStream); TIFF* outFile = TIFFOpen(fileName, "w"); setTiffFields(outFile, width, height, samplesPerPixel, bitsPerSample); TIFFSetField(outFile, TIFFTAG_ROWSPERSTRIP, rowsPerStrip); TIFFSetField(outFile, TIFFTAG_IMAGEDESCRIPTION, "Strip-allocated tiff for unit tests"); tsize_t bufSize = TIFFStripSize(outFile); unsigned char* buf = reinterpret_cast<unsigned char*>(_TIFFmalloc(bufSize)); // first directory is a red strip and a blue strip. setBufToColor(buf, bufSize/samplesPerPixel, red, samplesPerPixel); TIFFWriteEncodedStrip(outFile, 0, buf, bufSize); setBufToColor(buf, bufSize/samplesPerPixel, blue, samplesPerPixel); TIFFWriteEncodedStrip(outFile, 1, buf, bufSize); TIFFWriteDirectory(outFile); setTiffFields(outFile, width, height, samplesPerPixel, bitsPerSample); TIFFSetField(outFile, TIFFTAG_ROWSPERSTRIP, rowsPerStrip); // second directory is a white strip and a black strip _TIFFmemset(buf, 0xFF, bufSize); TIFFWriteEncodedStrip(outFile, 0, buf, bufSize); _TIFFmemset(buf, 0x00, bufSize); TIFFWriteEncodedStrip(outFile, 1, buf, bufSize); TIFFClose(outFile); _TIFFfree(buf); //TIFFSetField(outFile, TIFFTAG_TILEWIDTH, tileWidth); //TIFFSetField(outFile, TIFFTAG_TILELENGTH, tileHeight); }
/* * Decode a string of 32-bit pixels. */ static int LogLuvDecode32(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) { LogLuvState* sp; int shft, i, npixels; unsigned char* bp; uint32* tp; uint32 b; int cc, rc; assert(s == 0); sp = DecoderState(tif); assert(sp != NULL); npixels = occ / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_RAW) { tp = (uint32*) op; } else { assert(sp->tbuflen >= npixels); tp = (uint32*) sp->tbuf; } _TIFFmemset((tdata_t) tp, 0, npixels * sizeof(tp[0])); bp = (unsigned char*) tif->tif_rawcp; cc = tif->tif_rawcc; /* get each byte string */ for (shft = 4 * 8; (shft -= 8) >= 0;) { for (i = 0; i < npixels && cc > 0;) if (*bp >= 128) { /* run */ rc = *bp++ + (2 - 128); b = (uint32) * bp++ << shft; cc -= 2; while (rc-- && i < npixels) { tp[i++] |= b; } } else { /* non-run */ rc = *bp++; /* nul is noop */ while (--cc && rc-- && i < npixels) { tp[i++] |= (uint32) * bp++ << shft; } } if (i != npixels) { TIFFError(tif->tif_name, "LogLuvDecode32: Not enough data at row %d (short %d pixels)", tif->tif_row, npixels - i); tif->tif_rawcp = (tidata_t) bp; tif->tif_rawcc = cc; return (0); } } (*sp->tfunc)(sp, op, npixels); tif->tif_rawcp = (tidata_t) bp; tif->tif_rawcc = cc; return (1); }
void Ascii85Flush(FILE* fd) { if (ascii85count > 0) { char* res; _TIFFmemset(&ascii85buf[ascii85count], 0, 3); res = Ascii85Encode(ascii85buf); fwrite(res[0] == 'z' ? "!!!!" : res, ascii85count + 1, 1, fd); } fputs("~>\n", fd); }
/* Variant of TIFFReadEncodedTile() that does * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillTile() has * succeeded. This avoid excessive memory allocation in case of truncated * file. * * calls regular TIFFReadEncodedTile() if *buf != NULL */ tmsize_t _TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, void **buf, tmsize_t bufsizetoalloc, tmsize_t size_to_read) { static const char module[] = "_TIFFReadEncodedTileAndAllocBuffer"; TIFFDirectory *td = &tif->tif_dir; tmsize_t tilesize = tif->tif_tilesize; if( *buf != NULL ) { return TIFFReadEncodedTile(tif, tile, *buf, size_to_read); } if (!TIFFCheckRead(tif, 1)) return ((tmsize_t)(-1)); if (tile >= td->td_nstrips) { TIFFErrorExt(tif->tif_clientdata, module, "%lu: Tile out of range, max %lu", (unsigned long) tile, (unsigned long) td->td_nstrips); return ((tmsize_t)(-1)); } if (!TIFFFillTile(tif,tile)) return((tmsize_t)(-1)); *buf = _TIFFmalloc(bufsizetoalloc); if (*buf == NULL) { TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); return((tmsize_t)(-1)); } _TIFFmemset(*buf, 0, bufsizetoalloc); if (size_to_read == (tmsize_t)(-1)) size_to_read = tilesize; else if (size_to_read > tilesize) size_to_read = tilesize; if( (*tif->tif_decodetile)(tif, (uint8*) *buf, size_to_read, (uint16)(tile/td->td_stripsperimage))) { (*tif->tif_postdecode)(tif, (uint8*) *buf, size_to_read); return (size_to_read); } else return ((tmsize_t)(-1)); }
TIFFCodec* TIFFGetConfiguredCODECs() { int i = 1; codec_t *cd; const TIFFCodec* c; TIFFCodec* codecs = NULL; TIFFCodec* new_codecs; for (cd = registeredCODECS; cd; cd = cd->next) { new_codecs = (TIFFCodec *) _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); if (!new_codecs) { _TIFFfree (codecs); return NULL; } codecs = new_codecs; _TIFFmemcpy(codecs + i - 1, cd, sizeof(TIFFCodec)); i++; } for (c = _TIFFBuiltinCODECS; c->name; c++) { if (TIFFIsCODECConfigured(c->scheme)) { new_codecs = (TIFFCodec *) _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); if (!new_codecs) { _TIFFfree (codecs); return NULL; } codecs = new_codecs; _TIFFmemcpy(codecs + i - 1, (const void*)c, sizeof(TIFFCodec)); i++; } } new_codecs = (TIFFCodec *) _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); if (!new_codecs) { _TIFFfree (codecs); return NULL; } codecs = new_codecs; _TIFFmemset(codecs + i - 1, 0, sizeof(TIFFCodec)); return codecs; }
// Write a 4x5 tiled test tiff intended to have the correct sizes for a mipmap void writeTiledTiff(const char* fileName) { uint32 height = 5; uint32 width = 4; uint16 samplesPerPixel = 3; uint16 bitsPerSample = 8; uint32 tileWidth = 16; uint32 tileHeight = 16; //TIFF* outFile = TIFFStreamOpen("stream", &outStream); TIFF* outFile = TIFFOpen(fileName, "w"); setTiffFields(outFile, width, height, samplesPerPixel, bitsPerSample); TIFFSetField(outFile, TIFFTAG_TILEWIDTH, tileWidth); TIFFSetField(outFile, TIFFTAG_TILELENGTH, tileHeight); tsize_t bufSize = TIFFTileSize(outFile); char* buf = reinterpret_cast<char*>(_TIFFmalloc(bufSize)); _TIFFmemset(buf, 0x00, bufSize); // first directory TIFFWriteEncodedTile(outFile, 0, buf, bufSize); TIFFWriteDirectory(outFile); // rest of the directories while(width > 1 || height > 1) { width = std::max<uint32>((width+1)/2, 1); height = std::max<uint32>((height+1)/2, 1); setTiffFields(outFile, width, height, samplesPerPixel, bitsPerSample); TIFFSetField(outFile, TIFFTAG_TILEWIDTH, tileWidth); TIFFSetField(outFile, TIFFTAG_TILELENGTH, tileHeight); TIFFWriteEncodedTile(outFile, 0, buf, bufSize); TIFFWriteDirectory(outFile); } TIFFClose(outFile); _TIFFfree(buf); }
/* * Decode a string of 24-bit pixels. */ static int LogLuvDecode24(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) { LogLuvState* sp = DecoderState(tif); int cc, i, npixels; u_char* bp; uint32* tp; assert(s == 0); assert(sp != NULL); npixels = occ / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_RAW) tp = (uint32 *)op; else { assert(sp->tbuflen >= npixels); tp = (uint32 *) sp->tbuf; } _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0])); /* copy to array of uint32 */ bp = (u_char*) tif->tif_rawcp; cc = tif->tif_rawcc; for (i = 0; i < npixels && cc > 0; i++) { tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2]; bp += 3; cc -= 3; } tif->tif_rawcp = (tidata_t) bp; tif->tif_rawcc = cc; if (i != npixels) { TIFFError(tif->tif_name, "LogLuvDecode24: Not enough data at row %d (short %d pixels)", tif->tif_row, npixels - i); return (0); } (*sp->tfunc)(sp, op, npixels); return (1); }
//header of the TIFF snaphot - - to be passed as a function pointer (snapshotHeader) void printTiffHeader(Grid *g, Orientation direction, int slice) { sprintf(filename, "%s-x.%d.tif", basename, frameX++); tif = TIFFOpen(filename, "w"); if (!tif) { perror("printTiffHeader: impossible to open "); exit(-1); } switch (direction) { case XY: width = g->sizeX; height = g->sizeY; break; case XZ: width = g->sizeX; height = g->sizeZ; break; case YZ: width = g->sizeY; height = g->sizeZ; break; } TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width); // set the width of the image TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height); // set the height of the image TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); // set number of channels per pixel TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32); // set the size of the channels TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); //floating point tiff image TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); // set the origin of the image. TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); //row buffer (scanline write tiff) buf = (float *)_TIFFmalloc(width * sizeof(float)); _TIFFmemset(buf, 0, width*sizeof(float)); }
/* Variant of TIFFReadEncodedStrip() that does * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillStrip() has * succeeded. This avoid excessive memory allocation in case of truncated * file. * * calls regular TIFFReadEncodedStrip() if *buf != NULL */ tmsize_t _TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, void **buf, tmsize_t bufsizetoalloc, tmsize_t size_to_read) { tmsize_t this_stripsize; uint16 plane; if( *buf != NULL ) { return TIFFReadEncodedStrip(tif, strip, *buf, size_to_read); } this_stripsize=TIFFReadEncodedStripGetStripSize(tif, strip, &plane); if (this_stripsize==((tmsize_t)(-1))) return((tmsize_t)(-1)); if ((size_to_read!=(tmsize_t)(-1))&&(size_to_read<this_stripsize)) this_stripsize=size_to_read; if (!TIFFFillStrip(tif,strip)) return((tmsize_t)(-1)); *buf = _TIFFmalloc(bufsizetoalloc); if (*buf == NULL) { TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); return((tmsize_t)(-1)); } _TIFFmemset(*buf, 0, bufsizetoalloc); if ((*tif->tif_decodestrip)(tif,*buf,this_stripsize,plane)<=0) return((tmsize_t)(-1)); (*tif->tif_postdecode)(tif,*buf,this_stripsize); return(this_stripsize); }
TIFFField* _TIFFCreateAnonField(TIFF *tif, uint32 tag, TIFFDataType field_type) { TIFFField *fld; (void) tif; fld = (TIFFField *) _TIFFmalloc(sizeof (TIFFField)); if (fld == NULL) return NULL; _TIFFmemset(fld, 0, sizeof(TIFFField)); fld->field_tag = tag; fld->field_readcount = TIFF_VARIABLE2; fld->field_writecount = TIFF_VARIABLE2; fld->field_type = field_type; fld->reserved = 0; switch (field_type) { case TIFF_BYTE: case TIFF_UNDEFINED: fld->set_field_type = TIFF_SETGET_C32_UINT8; fld->get_field_type = TIFF_SETGET_C32_UINT8; break; case TIFF_ASCII: fld->set_field_type = TIFF_SETGET_C32_ASCII; fld->get_field_type = TIFF_SETGET_C32_ASCII; break; case TIFF_SHORT: fld->set_field_type = TIFF_SETGET_C32_UINT16; fld->get_field_type = TIFF_SETGET_C32_UINT16; break; case TIFF_LONG: fld->set_field_type = TIFF_SETGET_C32_UINT32; fld->get_field_type = TIFF_SETGET_C32_UINT32; break; case TIFF_RATIONAL: case TIFF_SRATIONAL: case TIFF_FLOAT: fld->set_field_type = TIFF_SETGET_C32_FLOAT; fld->get_field_type = TIFF_SETGET_C32_FLOAT; break; case TIFF_SBYTE: fld->set_field_type = TIFF_SETGET_C32_SINT8; fld->get_field_type = TIFF_SETGET_C32_SINT8; break; case TIFF_SSHORT: fld->set_field_type = TIFF_SETGET_C32_SINT16; fld->get_field_type = TIFF_SETGET_C32_SINT16; break; case TIFF_SLONG: fld->set_field_type = TIFF_SETGET_C32_SINT32; fld->get_field_type = TIFF_SETGET_C32_SINT32; break; case TIFF_DOUBLE: fld->set_field_type = TIFF_SETGET_C32_DOUBLE; fld->get_field_type = TIFF_SETGET_C32_DOUBLE; break; case TIFF_IFD: case TIFF_IFD8: fld->set_field_type = TIFF_SETGET_C32_IFD8; fld->get_field_type = TIFF_SETGET_C32_IFD8; break; case TIFF_LONG8: fld->set_field_type = TIFF_SETGET_C32_UINT64; fld->get_field_type = TIFF_SETGET_C32_UINT64; break; case TIFF_SLONG8: fld->set_field_type = TIFF_SETGET_C32_SINT64; fld->get_field_type = TIFF_SETGET_C32_SINT64; break; default: fld->set_field_type = TIFF_SETGET_UNDEFINED; fld->get_field_type = TIFF_SETGET_UNDEFINED; break; } fld->field_bit = FIELD_CUSTOM; fld->field_oktochange = TRUE; fld->field_passcount = TRUE; fld->field_name = (char *) _TIFFmalloc(32); if (fld->field_name == NULL) { _TIFFfree(fld); return NULL; } fld->field_subfields = NULL; /* * note that this name is a special sign to TIFFClose() and * _TIFFSetupFields() to free the field */ #if defined(_MSC_VER) && _MSC_VER < 1900 // classical problem with sprintf on Windows(JLM) (void) sprintf_s(fld->field_name, 32, "Tag %d", (int) tag); #else (void) snprintf(fld->field_name, 32, "Tag %d", (int) tag); #endif return fld; }
TIFF* TIFFClientOpen( const char* name, const char* mode, thandle_t clientdata, TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc, TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc ) { static const char module[] = "TIFFClientOpen"; TIFF *tif; int m; const char* cp; /* The following are configuration checks. They should be redundant, but should not * compile to any actual code in an optimised release build anyway. If any of them * fail, (makefile-based or other) configuration is not correct */ assert(sizeof(uint8)==1); assert(sizeof(int8)==1); assert(sizeof(uint16)==2); assert(sizeof(int16)==2); assert(sizeof(uint32)==4); assert(sizeof(int32)==4); assert(sizeof(uint64)==8); assert(sizeof(int64)==8); assert(sizeof(tmsize_t)==sizeof(void*)); { union{ uint8 a8[2]; uint16 a16; } n; n.a8[0]=1; n.a8[1]=0; #ifdef WORDS_BIGENDIAN assert(n.a16==256); #else assert(n.a16==1); #endif } m = _TIFFgetMode(mode, module); if (m == -1) goto bad2; tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1)); if (tif == NULL) { TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name); goto bad2; } _TIFFmemset(tif, 0, sizeof (*tif)); tif->tif_name = (char *)tif + sizeof (TIFF); strcpy(tif->tif_name, name); tif->tif_mode = m &~ (O_CREAT|O_TRUNC); tif->tif_curdir = (uint16) -1; /* non-existent directory */ tif->tif_curoff = 0; tif->tif_curstrip = (uint32) -1; /* invalid strip */ tif->tif_row = (uint32) -1; /* read/write pre-increment */ tif->tif_clientdata = clientdata; if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) { TIFFErrorExt(clientdata, module, "One of the client procedures is NULL pointer."); goto bad2; } tif->tif_readproc = readproc; tif->tif_writeproc = writeproc; tif->tif_seekproc = seekproc; tif->tif_closeproc = closeproc; tif->tif_sizeproc = sizeproc; if (mapproc) tif->tif_mapproc = mapproc; else tif->tif_mapproc = _tiffDummyMapProc; if (unmapproc) tif->tif_unmapproc = unmapproc; else tif->tif_unmapproc = _tiffDummyUnmapProc; _TIFFSetDefaultCompressionState(tif); /* setup default state */ /* * Default is to return data MSB2LSB and enable the * use of memory-mapped files and strip chopping when * a file is opened read-only. */ tif->tif_flags = FILLORDER_MSB2LSB; if (m == O_RDONLY ) tif->tif_flags |= TIFF_MAPPED; #ifdef STRIPCHOP_DEFAULT if (m == O_RDONLY || m == O_RDWR) tif->tif_flags |= STRIPCHOP_DEFAULT; #endif /* * Process library-specific flags in the open mode string. * The following flags may be used to control intrinsic library * behaviour that may or may not be desirable (usually for * compatibility with some application that claims to support * TIFF but only supports some braindead idea of what the * vendor thinks TIFF is): * * 'l' use little-endian byte order for creating a file * 'b' use big-endian byte order for creating a file * 'L' read/write information using LSB2MSB bit order * 'B' read/write information using MSB2LSB bit order * 'H' read/write information using host bit order * 'M' enable use of memory-mapped files when supported * 'm' disable use of memory-mapped files * 'C' enable strip chopping support when reading * 'c' disable strip chopping support * 'h' read TIFF header only, do not load the first IFD * '4' ClassicTIFF for creating a file (default) * '8' BigTIFF for creating a file * * The use of the 'l' and 'b' flags is strongly discouraged. * These flags are provided solely because numerous vendors, * typically on the PC, do not correctly support TIFF; they * only support the Intel little-endian byte order. This * support is not configured by default because it supports * the violation of the TIFF spec that says that readers *MUST* * support both byte orders. It is strongly recommended that * you not use this feature except to deal with busted apps * that write invalid TIFF. And even in those cases you should * bang on the vendors to fix their software. * * The 'L', 'B', and 'H' flags are intended for applications * that can optimize operations on data by using a particular * bit order. By default the library returns data in MSB2LSB * bit order for compatibiltiy with older versions of this * library. Returning data in the bit order of the native cpu * makes the most sense but also requires applications to check * the value of the FillOrder tag; something they probably do * not do right now. * * The 'M' and 'm' flags are provided because some virtual memory * systems exhibit poor behaviour when large images are mapped. * These options permit clients to control the use of memory-mapped * files on a per-file basis. * * The 'C' and 'c' flags are provided because the library support * for chopping up large strips into multiple smaller strips is not * application-transparent and as such can cause problems. The 'c' * option permits applications that only want to look at the tags, * for example, to get the unadulterated TIFF tag information. */ for (cp = mode; *cp; cp++) switch (*cp) { case 'b': #ifndef WORDS_BIGENDIAN if (m&O_CREAT) tif->tif_flags |= TIFF_SWAB; #endif break; case 'l': #ifdef WORDS_BIGENDIAN if ((m&O_CREAT)) tif->tif_flags |= TIFF_SWAB; #endif break; case 'B': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_MSB2LSB; break; case 'L': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_LSB2MSB; break; case 'H': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | HOST_FILLORDER; break; case 'M': if (m == O_RDONLY) tif->tif_flags |= TIFF_MAPPED; break; case 'm': if (m == O_RDONLY) tif->tif_flags &= ~TIFF_MAPPED; break; case 'C': if (m == O_RDONLY) tif->tif_flags |= TIFF_STRIPCHOP; break; case 'c': if (m == O_RDONLY) tif->tif_flags &= ~TIFF_STRIPCHOP; break; case 'h': tif->tif_flags |= TIFF_HEADERONLY; break; case '8': if (m&O_CREAT) tif->tif_flags |= TIFF_BIGTIFF; break; } /* * Read in TIFF header. */ if ((m & O_TRUNC) || !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeaderClassic))) { if (tif->tif_mode == O_RDONLY) { TIFFErrorExt(tif->tif_clientdata, name, "Cannot read TIFF header"); goto bad; } /* * Setup header and write. */ #ifdef WORDS_BIGENDIAN tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN; #else tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN; #endif if (!(tif->tif_flags&TIFF_BIGTIFF)) { tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC; tif->tif_header.classic.tiff_diroff = 0; if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&tif->tif_header.common.tiff_version); tif->tif_header_size = sizeof(TIFFHeaderClassic); } else { tif->tif_header.common.tiff_version = TIFF_VERSION_BIG; tif->tif_header.big.tiff_offsetsize = 8; tif->tif_header.big.tiff_unused = 0; tif->tif_header.big.tiff_diroff = 0; if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.common.tiff_version); TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); } tif->tif_header_size = sizeof (TIFFHeaderBig); } /* * The doc for "fopen" for some STD_C_LIBs says that if you * open a file for modify ("+"), then you must fseek (or * fflush?) between any freads and fwrites. This is not * necessary on most systems, but has been shown to be needed * on Solaris. */ TIFFSeekFile( tif, 0, SEEK_SET ); if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) { TIFFErrorExt(tif->tif_clientdata, name, "Error writing TIFF header"); goto bad; } /* * Setup the byte order handling. */ if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) { #ifndef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } else { #ifdef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } /* * Setup default directory. */ if (!TIFFDefaultDirectory(tif)) goto bad; tif->tif_diroff = 0; tif->tif_dirlist = NULL; tif->tif_dirlistsize = 0; tif->tif_dirnumber = 0; return (tif); } /* * Setup the byte order handling. */ if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN && tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN #if MDI_SUPPORT && #if HOST_BIGENDIAN tif->tif_header.common.tiff_magic != MDI_BIGENDIAN #else tif->tif_header.common.tiff_magic != MDI_LITTLEENDIAN #endif ) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF or MDI file, bad magic number %d (0x%x)", #else ) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad magic number %d (0x%x)", #endif tif->tif_header.common.tiff_magic, tif->tif_header.common.tiff_magic); goto bad; } if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) { #ifndef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } else { #ifdef WORDS_BIGENDIAN tif->tif_flags |= TIFF_SWAB; #endif } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&tif->tif_header.common.tiff_version); if ((tif->tif_header.common.tiff_version != TIFF_VERSION_CLASSIC)&& (tif->tif_header.common.tiff_version != TIFF_VERSION_BIG)) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad version number %d (0x%x)", tif->tif_header.common.tiff_version, tif->tif_header.common.tiff_version); goto bad; } if (tif->tif_header.common.tiff_version == TIFF_VERSION_CLASSIC) { if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&tif->tif_header.classic.tiff_diroff); tif->tif_header_size = sizeof(TIFFHeaderClassic); } else { if (!ReadOK(tif, ((uint8*)(&tif->tif_header) + sizeof(TIFFHeaderClassic)), (sizeof(TIFFHeaderBig)-sizeof(TIFFHeaderClassic)))) { TIFFErrorExt(tif->tif_clientdata, name, "Cannot read TIFF header"); goto bad; } if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); TIFFSwabLong8(&tif->tif_header.big.tiff_diroff); } if (tif->tif_header.big.tiff_offsetsize != 8) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad BigTIFF offsetsize %d (0x%x)", tif->tif_header.big.tiff_offsetsize, tif->tif_header.big.tiff_offsetsize); goto bad; } if (tif->tif_header.big.tiff_unused != 0) { TIFFErrorExt(tif->tif_clientdata, name, "Not a TIFF file, bad BigTIFF unused %d (0x%x)", tif->tif_header.big.tiff_unused, tif->tif_header.big.tiff_unused); goto bad; } tif->tif_header_size = sizeof(TIFFHeaderBig); tif->tif_flags |= TIFF_BIGTIFF; } tif->tif_flags |= TIFF_MYBUFFER; tif->tif_rawcp = tif->tif_rawdata = 0; tif->tif_rawdatasize = 0; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = 0; switch (mode[0]) { case 'r': if (!(tif->tif_flags&TIFF_BIGTIFF)) tif->tif_nextdiroff = tif->tif_header.classic.tiff_diroff; else tif->tif_nextdiroff = tif->tif_header.big.tiff_diroff; /* * Try to use a memory-mapped file if the client * has not explicitly suppressed usage with the * 'm' flag in the open mode (see above). */ if (tif->tif_flags & TIFF_MAPPED) { toff_t n; if (TIFFMapFileContents(tif,(void**)(&tif->tif_base),&n)) { tif->tif_size=(tmsize_t)n; assert((toff_t)tif->tif_size==n); } else tif->tif_flags &= ~TIFF_MAPPED; } /* * Sometimes we do not want to read the first directory (for example, * it may be broken) and want to proceed to other directories. I this * case we use the TIFF_HEADERONLY flag to open file and return * immediately after reading TIFF header. */ if (tif->tif_flags & TIFF_HEADERONLY) return (tif); /* * Setup initial directory. */ if (TIFFReadDirectory(tif)) { tif->tif_rawcc = (tmsize_t)-1; tif->tif_flags |= TIFF_BUFFERSETUP; return (tif); } break; case 'a': /* * New directories are automatically append * to the end of the directory chain when they * are written out (see TIFFWriteDirectory). */ if (!TIFFDefaultDirectory(tif)) goto bad; return (tif); } bad: tif->tif_mode = O_RDONLY; /* XXX avoid flush */ TIFFCleanup(tif); bad2: return ((TIFF*)0); }
TIFF* TIFFClientOpen( const char* name, const char* mode, void* clientdata, TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc, TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc, void* pdflib_opaque, TIFFmallocHandler malloc_h, TIFFreallocHandler realloc_h, TIFFfreeHandler free_h, TIFFErrorHandler error_h, TIFFErrorHandler warn_h ) { static const char module[] = "TIFFClientOpen"; TIFF pdftiff; TIFF *tif = &pdftiff; int m; int bigendian; const char* cp; (void) mapproc; (void) unmapproc; { union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; } m = _TIFFgetMode(mode, module); if (m == -1) goto bad2; /* PDFlib: preset tiff structure so that the first malloc works */ tif->pdflib_opaque = pdflib_opaque; tif->pdflib_malloc = malloc_h; tif->pdflib_realloc = realloc_h; tif->pdflib_free = free_h; tif->pdflib_error = error_h; tif->pdflib_warn = warn_h; tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + (tsize_t) strlen(name) + 1); if (tif == NULL) { _TIFFError(tif, module, "%s: Out of memory (TIFF structure)", name); goto bad2; } _TIFFmemset(tif, 0, sizeof (*tif)); /* PDFlib: add own mallochandling */ tif->pdflib_opaque = pdflib_opaque; tif->pdflib_malloc = malloc_h; tif->pdflib_realloc = realloc_h; tif->pdflib_free = free_h; tif->pdflib_error = error_h; tif->pdflib_warn = warn_h; tif->tif_name = (char *)tif + sizeof (TIFF); strcpy(tif->tif_name, name); tif->tif_mode = m &~ (O_CREAT|O_TRUNC); tif->tif_curdir = (tdir_t) -1; /* non-existent directory */ tif->tif_curoff = 0; tif->tif_curstrip = (tstrip_t) -1; /* invalid strip */ tif->tif_row = (uint32) -1; /* read/write pre-increment */ tif->tif_clientdata = clientdata; #ifdef PDFlib_NOT_USED if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) { _TIFFError(tif, module, "One of the client procedures is NULL pointer."); goto bad2; } #endif /* PDFLIB_TIFFWRITE_SUPPORT */ tif->tif_readproc = readproc; tif->tif_writeproc = writeproc; tif->tif_seekproc = seekproc; tif->tif_closeproc = closeproc; tif->tif_sizeproc = sizeproc; #ifdef HAVE_MMAP if (mapproc) tif->tif_mapproc = mapproc; else tif->tif_mapproc = _tiffDummyMapProc; if (unmapproc) tif->tif_unmapproc = unmapproc; else tif->tif_unmapproc = _tiffDummyUnmapProc; #endif _TIFFSetDefaultCompressionState(tif); /* setup default state */ /* * Default is to return data MSB2LSB and enable the * use of memory-mapped files and strip chopping when * a file is opened read-only. */ tif->tif_flags = FILLORDER_MSB2LSB; #ifdef HAVE_MMAP if (m == O_RDONLY ) tif->tif_flags |= TIFF_MAPPED; #endif #ifdef STRIPCHOP_DEFAULT if (m == O_RDONLY || m == O_RDWR) tif->tif_flags |= STRIPCHOP_DEFAULT; #endif /* * Process library-specific flags in the open mode string. * The following flags may be used to control intrinsic library * behaviour that may or may not be desirable (usually for * compatibility with some application that claims to support * TIFF but only supports some braindead idea of what the * vendor thinks TIFF is): * * 'l' use little-endian byte order for creating a file * 'b' use big-endian byte order for creating a file * 'L' read/write information using LSB2MSB bit order * 'B' read/write information using MSB2LSB bit order * 'H' read/write information using host bit order * 'M' enable use of memory-mapped files when supported * 'm' disable use of memory-mapped files * 'C' enable strip chopping support when reading * 'c' disable strip chopping support * 'h' read TIFF header only, do not load the first IFD * * The use of the 'l' and 'b' flags is strongly discouraged. * These flags are provided solely because numerous vendors, * typically on the PC, do not correctly support TIFF; they * only support the Intel little-endian byte order. This * support is not configured by default because it supports * the violation of the TIFF spec that says that readers *MUST* * support both byte orders. It is strongly recommended that * you not use this feature except to deal with busted apps * that write invalid TIFF. And even in those cases you should * bang on the vendors to fix their software. * * The 'L', 'B', and 'H' flags are intended for applications * that can optimize operations on data by using a particular * bit order. By default the library returns data in MSB2LSB * bit order for compatibiltiy with older versions of this * library. Returning data in the bit order of the native cpu * makes the most sense but also requires applications to check * the value of the FillOrder tag; something they probably do * not do right now. * * The 'M' and 'm' flags are provided because some virtual memory * systems exhibit poor behaviour when large images are mapped. * These options permit clients to control the use of memory-mapped * files on a per-file basis. * * The 'C' and 'c' flags are provided because the library support * for chopping up large strips into multiple smaller strips is not * application-transparent and as such can cause problems. The 'c' * option permits applications that only want to look at the tags, * for example, to get the unadulterated TIFF tag information. */ for (cp = mode; *cp; cp++) switch (*cp) { case 'b': if ((m&O_CREAT) && !bigendian) tif->tif_flags |= TIFF_SWAB; break; case 'l': if ((m&O_CREAT) && bigendian) tif->tif_flags |= TIFF_SWAB; break; case 'B': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_MSB2LSB; break; case 'L': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | FILLORDER_LSB2MSB; break; #ifdef PDFlib_NOT_USED /* PDFlib GmbH */ case 'H': tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | HOST_FILLORDER; break; #endif #ifdef HAVE_MMAP case 'M': if (m == O_RDONLY) tif->tif_flags |= TIFF_MAPPED; break; case 'm': if (m == O_RDONLY) tif->tif_flags &= ~TIFF_MAPPED; break; #endif case 'C': if (m == O_RDONLY) tif->tif_flags |= TIFF_STRIPCHOP; break; case 'c': if (m == O_RDONLY) tif->tif_flags &= ~TIFF_STRIPCHOP; break; case 'h': tif->tif_flags |= TIFF_HEADERONLY; break; } /* * Read in TIFF header. */ if (tif->tif_mode & O_TRUNC || !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { if (tif->tif_mode == O_RDONLY) { _TIFFError(tif, name, "Cannot read TIFF header"); goto bad; } /* * Setup header and write. */ tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN) : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN); tif->tif_header.tiff_version = TIFF_VERSION; if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&tif->tif_header.tiff_version); tif->tif_header.tiff_diroff = 0; /* filled in later */ /* * The doc for "fopen" for some STD_C_LIBs says that if you * open a file for modify ("+"), then you must fseek (or * fflush?) between any freads and fwrites. This is not * necessary on most systems, but has been shown to be needed * on Solaris. */ TIFFSeekFile( tif, 0, SEEK_SET ); if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { _TIFFError(tif, name, "Error writing TIFF header"); goto bad; } /* * Setup the byte order handling. */ TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); /* * Setup default directory. */ if (!TIFFDefaultDirectory(tif)) goto bad; tif->tif_diroff = 0; tif->tif_dirlist = NULL; tif->tif_dirnumber = 0; return (tif); } /* * Setup the byte order handling. */ if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN && tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) { _TIFFError(tif, name, "Not a TIFF file, bad magic number %d (0x%x)", tif->tif_header.tiff_magic, tif->tif_header.tiff_magic); goto bad; } TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); /* * Swap header if required. */ if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.tiff_version); TIFFSwabLong(&tif->tif_header.tiff_diroff); } /* * Now check version (if needed, it's been byte-swapped). * Note that this isn't actually a version number, it's a * magic number that doesn't change (stupid). */ if (tif->tif_header.tiff_version == TIFF_BIGTIFF_VERSION) { _TIFFError(tif, name, "This is a BigTIFF file. This format not supported\n" "by this version of libtiff." ); goto bad; } if (tif->tif_header.tiff_version != TIFF_VERSION) { _TIFFError(tif, name, "Not a TIFF file, bad version number %d (0x%x)", tif->tif_header.tiff_version, tif->tif_header.tiff_version); goto bad; } tif->tif_flags |= TIFF_MYBUFFER; tif->tif_rawcp = tif->tif_rawdata = 0; tif->tif_rawdatasize = 0; /* * Sometimes we do not want to read the first directory (for example, * it may be broken) and want to proceed to other directories. I this * case we use the TIFF_HEADERONLY flag to open file and return * immediately after reading TIFF header. */ if (tif->tif_flags & TIFF_HEADERONLY) return (tif); /* * Setup initial directory. */ switch (mode[0]) { case 'r': tif->tif_nextdiroff = tif->tif_header.tiff_diroff; #ifdef HAVE_MMAP /* * Try to use a memory-mapped file if the client * has not explicitly suppressed usage with the * 'm' flag in the open mode (see above). */ if ((tif->tif_flags & TIFF_MAPPED) && !TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size)) tif->tif_flags &= ~TIFF_MAPPED; #endif if (TIFFReadDirectory(tif)) { tif->tif_rawcc = -1; tif->tif_flags |= TIFF_BUFFERSETUP; return (tif); } break; case 'a': /* * New directories are automatically append * to the end of the directory chain when they * are written out (see TIFFWriteDirectory). */ if (!TIFFDefaultDirectory(tif)) goto bad; return (tif); } bad: tif->tif_mode = O_RDONLY; /* XXX avoid flush */ TIFFCleanup(tif); bad2: return ((TIFF*)0); }
static int LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) { static const char module[] = "LZWDecodeCompat"; LZWCodecState *sp = DecoderState(tif); char *op = (char*) op0; long occ = (long) occ0; char *tp; unsigned char *bp; int code, nbits; long nextbits, nextdata, nbitsmask; code_t *codep, *free_entp, *maxcodep, *oldcodep; (void) s; assert(sp != NULL); /* Fail if value does not fit in long. */ if ((tmsize_t) occ != occ0) return (0); /* * Restart interrupted output operation. */ if (sp->dec_restart) { long residue; codep = sp->dec_codep; residue = codep->length - sp->dec_restart; if (residue > occ) { /* * Residue from previous decode is sufficient * to satisfy decode request. Skip to the * start of the decoded string, place decoded * values in the output buffer, and return. */ sp->dec_restart += occ; do { codep = codep->next; } while (--residue > occ); tp = op + occ; do { *--tp = codep->value; codep = codep->next; } while (--occ); return (1); } /* * Residue satisfies only part of the decode request. */ op += residue; occ -= residue; tp = op; do { *--tp = codep->value; codep = codep->next; } while (--residue); sp->dec_restart = 0; } bp = (unsigned char *)tif->tif_rawcp; #ifdef LZW_CHECKEOS sp->dec_bitsleft = (((uint64)tif->tif_rawcc) << 3); #endif nbits = sp->lzw_nbits; nextdata = sp->lzw_nextdata; nextbits = sp->lzw_nextbits; nbitsmask = sp->dec_nbitsmask; oldcodep = sp->dec_oldcodep; free_entp = sp->dec_free_entp; maxcodep = sp->dec_maxcodep; while (occ > 0) { NextCode(tif, sp, bp, code, GetNextCodeCompat); if (code == CODE_EOI) break; if (code == CODE_CLEAR) { do { free_entp = sp->dec_codetab + CODE_FIRST; _TIFFmemset(free_entp, 0, (CSIZE - CODE_FIRST) * sizeof (code_t)); nbits = BITS_MIN; nbitsmask = MAXCODE(BITS_MIN); maxcodep = sp->dec_codetab + nbitsmask; NextCode(tif, sp, bp, code, GetNextCodeCompat); } while (code == CODE_CLEAR); /* consecutive CODE_CLEAR codes */ if (code == CODE_EOI) break; if (code > CODE_CLEAR) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "LZWDecode: Corrupted LZW table at scanline %d", tif->tif_row); return (0); } *op++ = (char)code; occ--; oldcodep = sp->dec_codetab + code; continue; } codep = sp->dec_codetab + code; /* * Add the new entry to the code table. */ if (free_entp < &sp->dec_codetab[0] || free_entp >= &sp->dec_codetab[CSIZE]) { TIFFErrorExt(tif->tif_clientdata, module, "Corrupted LZW table at scanline %d", tif->tif_row); return (0); } free_entp->next = oldcodep; if (free_entp->next < &sp->dec_codetab[0] || free_entp->next >= &sp->dec_codetab[CSIZE]) { TIFFErrorExt(tif->tif_clientdata, module, "Corrupted LZW table at scanline %d", tif->tif_row); return (0); } free_entp->firstchar = free_entp->next->firstchar; free_entp->length = free_entp->next->length+1; free_entp->value = (codep < free_entp) ? codep->firstchar : free_entp->firstchar; if (++free_entp > maxcodep) { if (++nbits > BITS_MAX) /* should not happen */ nbits = BITS_MAX; nbitsmask = MAXCODE(nbits); maxcodep = sp->dec_codetab + nbitsmask; } oldcodep = codep; if (code >= 256) { /* * Code maps to a string, copy string * value to output (written in reverse). */ if(codep->length == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Wrong length of decoded " "string: data probably corrupted at scanline %d", tif->tif_row); return (0); } if (codep->length > occ) { /* * String is too long for decode buffer, * locate portion that will fit, copy to * the decode buffer, and setup restart * logic for the next decoding call. */ sp->dec_codep = codep; do { codep = codep->next; } while (codep->length > occ); sp->dec_restart = occ; tp = op + occ; do { *--tp = codep->value; codep = codep->next; } while (--occ); break; } assert(occ >= codep->length); op += codep->length; occ -= codep->length; tp = op; do { *--tp = codep->value; } while( (codep = codep->next) != NULL ); } else { *op++ = (char)code; occ--; } } tif->tif_rawcc -= (tmsize_t)( (uint8*) bp - tif->tif_rawcp ); tif->tif_rawcp = (uint8*) bp; sp->lzw_nbits = (unsigned short)nbits; sp->lzw_nextdata = nextdata; sp->lzw_nextbits = nextbits; sp->dec_nbitsmask = nbitsmask; sp->dec_oldcodep = oldcodep; sp->dec_free_entp = free_entp; sp->dec_maxcodep = maxcodep; if (occ > 0) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Not enough data at scanline %d (short %I64d bytes)", tif->tif_row, (unsigned __int64) occ); #else TIFFErrorExt(tif->tif_clientdata, module, "Not enough data at scanline %d (short %llu bytes)", tif->tif_row, (unsigned long long) occ); #endif return (0); } return (1); }
/* * Setup state for decoding a strip. */ static int LZWPreDecode(TIFF* tif, uint16 s) { static const char module[] = "LZWPreDecode"; LZWCodecState *sp = DecoderState(tif); (void) s; assert(sp != NULL); if( sp->dec_codetab == NULL ) { tif->tif_setupdecode( tif ); if( sp->dec_codetab == NULL ) return (0); } /* * Check for old bit-reversed codes. */ if (tif->tif_rawcc >= 2 && tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) { #ifdef LZW_COMPAT if (!sp->dec_decode) { TIFFWarningExt(tif->tif_clientdata, module, "Old-style LZW codes, convert file"); /* * Override default decoding methods with * ones that deal with the old coding. * Otherwise the predictor versions set * above will call the compatibility routines * through the dec_decode method. */ tif->tif_decoderow = LZWDecodeCompat; tif->tif_decodestrip = LZWDecodeCompat; tif->tif_decodetile = LZWDecodeCompat; /* * If doing horizontal differencing, must * re-setup the predictor logic since we * switched the basic decoder methods... */ (*tif->tif_setupdecode)(tif); sp->dec_decode = LZWDecodeCompat; } sp->lzw_maxcode = MAXCODE(BITS_MIN); #else /* !LZW_COMPAT */ if (!sp->dec_decode) { TIFFErrorExt(tif->tif_clientdata, module, "Old-style LZW codes not supported"); sp->dec_decode = LZWDecode; } return (0); #endif/* !LZW_COMPAT */ } else { sp->lzw_maxcode = MAXCODE(BITS_MIN)-1; sp->dec_decode = LZWDecode; } sp->lzw_nbits = BITS_MIN; sp->lzw_nextbits = 0; sp->lzw_nextdata = 0; sp->dec_restart = 0; sp->dec_nbitsmask = MAXCODE(BITS_MIN); #ifdef LZW_CHECKEOS sp->dec_bitsleft = 0; #endif sp->dec_free_entp = sp->dec_codetab + CODE_FIRST; /* * Zero entries that are not yet filled in. We do * this to guard against bogus input data that causes * us to index into undefined entries. If you can * come up with a way to safely bounds-check input codes * while decoding then you can remove this operation. */ _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t)); sp->dec_oldcodep = &sp->dec_codetab[-1]; sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1]; return (1); }
/* * Decode a string of 32-bit pixels. */ static int LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { static const char module[] = "LogLuvDecode32"; LogLuvState* sp; int shft; tmsize_t i; tmsize_t npixels; unsigned char* bp; uint32* tp; uint32 b; tmsize_t cc; int rc; assert(s == 0); sp = DecoderState(tif); assert(sp != NULL); npixels = occ / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_RAW) tp = (uint32*) op; else { assert(sp->tbuflen >= npixels); tp = (uint32*) sp->tbuf; } _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0])); bp = (unsigned char*) tif->tif_rawcp; cc = tif->tif_rawcc; /* get each byte string */ for (shft = 4*8; (shft -= 8) >= 0; ) { for (i = 0; i < npixels && cc > 0; ) if (*bp >= 128) { /* run */ rc = *bp++ + (2-128); b = (uint32)*bp++ << shft; cc -= 2; /* TODO: potential input buffer overrun when decoding corrupt or truncated data */ while (rc-- && i < npixels) tp[i++] |= b; } else { /* non-run */ rc = *bp++; /* nul is noop */ while (--cc && rc-- && i < npixels) tp[i++] |= (uint32)*bp++ << shft; } if (i != npixels) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Not enough data at row %lu (short %I64d pixels)", (unsigned long) tif->tif_row, (unsigned __int64) (npixels - i)); #else TIFFErrorExt(tif->tif_clientdata, module, "Not enough data at row %lu (short %llu pixels)", (unsigned long) tif->tif_row, (unsigned long long) (npixels - i)); #endif tif->tif_rawcp = (uint8*) bp; tif->tif_rawcc = cc; return (0); } } (*sp->tfunc)(sp, op, npixels); tif->tif_rawcp = (uint8*) bp; tif->tif_rawcc = cc; return (1); }
/* * Floyd-Steinberg error propragation with threshold. * This code is stolen from tiffmedian. */ static void fsdither(TIFF* in, TIFF* out) { unsigned char *outline, *inputline, *inptr; short *thisline, *nextline, *tmpptr; register unsigned char *outptr; register short *thisptr, *nextptr; register uint32 i, j; uint32 imax, jmax; int lastline, lastpixel; int bit; tsize_t outlinesize; imax = imagelength - 1; jmax = imagewidth - 1; inputline = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(in)); thisline = (short *)_TIFFmalloc(imagewidth * sizeof (short)); nextline = (short *)_TIFFmalloc(imagewidth * sizeof (short)); outlinesize = TIFFScanlineSize(out); outline = (unsigned char *) _TIFFmalloc(outlinesize); /* * Get first line */ if (TIFFReadScanline(in, inputline, 0, 0) <= 0) return; inptr = inputline; nextptr = nextline; for (j = 0; j < imagewidth; ++j) *nextptr++ = *inptr++; for (i = 1; i < imagelength; ++i) { tmpptr = thisline; thisline = nextline; nextline = tmpptr; lastline = (i == imax); if (TIFFReadScanline(in, inputline, i, 0) <= 0) break; inptr = inputline; nextptr = nextline; for (j = 0; j < imagewidth; ++j) *nextptr++ = *inptr++; thisptr = thisline; nextptr = nextline; _TIFFmemset(outptr = outline, 0, outlinesize); bit = 0x80; for (j = 0; j < imagewidth; ++j) { register int v; lastpixel = (j == jmax); v = *thisptr++; if (v < 0) v = 0; else if (v > 255) v = 255; if (v > threshold) { *outptr |= bit; v -= 255; } bit >>= 1; if (bit == 0) { outptr++; bit = 0x80; } if (!lastpixel) thisptr[0] += v * 7 / 16; if (!lastline) { if (j != 0) nextptr[-1] += v * 3 / 16; *nextptr++ += v * 5 / 16; if (!lastpixel) nextptr[0] += v / 16; } } if (TIFFWriteScanline(out, outline, i-1, 0) < 0) break; } _TIFFfree(inputline); _TIFFfree(thisline); _TIFFfree(nextline); _TIFFfree(outline); }