// Set open file's clientdata, and return previous value. public static Stream TIFFSetClientdata(TIFF tif, Stream newvalue) { Stream m = tif.tif_clientdata; tif.tif_clientdata = newvalue; return(m); }
// Set open file's I/O descriptor, and return previous value. public static Stream TIFFSetFileno(TIFF tif, Stream fd) { Stream old_fd = tif.tif_fd; tif.tif_fd = fd; return(old_fd); }
// Set the file name. public static string TIFFSetFileName(TIFF tif, string name) { string old_name = tif.tif_name; tif.tif_name = name; return(old_name); }
// Similar to TIFFWriteDirectory(), but if the directory has already // been written once, it is relocated to the end of the file, in case it // has changed in size. Note that this will result in the loss of the // previously used directory space. public static bool TIFFRewriteDirectory(TIFF tif) { string module="TIFFRewriteDirectory"; // We don't need to do anything special if it hasn't been written. if(tif.tif_diroff==0) return TIFFWriteDirectory(tif); // Find and zero the pointer to this directory, so that TIFFLinkDirectory // will cause it to be added after this directories current pre-link. // Is it the first directory in the file? if(tif.tif_header.tiff_diroff==tif.tif_diroff) { tif.tif_header.tiff_diroff=0; tif.tif_diroff=0; TIFFSeekFile(tif, (uint)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE), SEEK.SET); if(!WriteOK(tif, tif.tif_header.tiff_diroff)) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "Error updating TIFF header"); return true; } } else { uint nextdir=tif.tif_header.tiff_diroff; do { ushort dircount; if(!SeekOK(tif, nextdir)||!ReadOK(tif, out dircount)) { TIFFErrorExt(tif.tif_clientdata, module, "Error fetching directory count"); return false; } if((tif.tif_flags&TIF_FLAGS.TIFF_SWAB)!=0) TIFFSwab(ref dircount); TIFFSeekFile(tif, (uint)dircount*12, SEEK.CUR); if(!ReadOK(tif, out nextdir)) { TIFFErrorExt(tif.tif_clientdata, module, "Error fetching directory link"); return false; } if((tif.tif_flags&TIF_FLAGS.TIFF_SWAB)!=0) TIFFSwab(ref nextdir); } while(nextdir!=tif.tif_diroff&&nextdir!=0); uint off=TIFFSeekFile(tif, 0, SEEK.CUR); // get current offset TIFFSeekFile(tif, off-4, SEEK.SET); tif.tif_diroff=0; if(!WriteOK(tif, tif.tif_diroff)) { TIFFErrorExt(tif.tif_clientdata, module, "Error writing directory link"); return false; } } // Now use TIFFWriteDirectory() normally. return TIFFWriteDirectory(tif); }
// Return read/write mode. public static O TIFFSetMode(TIFF tif, O mode) { O old_mode = tif.tif_mode; tif.tif_mode = mode; return(old_mode); }
static bool ZIPSetupDecode(TIFF tif) { ZIPState sp = tif.tif_data as ZIPState; string module = "ZIPSetupDecode"; #if DEBUG if (sp == null) { throw new Exception("sp==null"); } #endif // if we were last encoding, terminate this mode if ((sp.state & ZSTATE.INIT_ENCODE) == ZSTATE.INIT_ENCODE) { zlib.deflateEnd(sp.stream); sp.state = ZSTATE.None; } if (zlib.inflateInit(sp.stream) != zlib.Z_OK) { TIFFErrorExt(tif.tif_clientdata, module, "{0}: {1}", tif.tif_name, sp.stream.msg); return(false); } else { sp.state |= ZSTATE.INIT_DECODE; return(true); } }
// Return the number of bytes to read/write in a call to // one of the scanline-oriented i/o routines. Note that // this number may be 1/samples-per-pixel if data is // stored as separate planes. // The ScanlineSize in case of YCbCrSubsampling is defined as the // strip size divided by the strip height, i.e. the size of a pack of vertical // subsampling lines divided by vertical subsampling. It should thus make // sense when multiplied by a multiple of vertical subsampling. // Some stuff depends on this newer version of TIFFScanlineSize // TODO: resolve this public static int TIFFNewScanlineSize(TIFF tif) { TIFFDirectory td=tif.tif_dir; uint scanline; if(td.td_planarconfig==PLANARCONFIG.CONTIG) { if(td.td_photometric==PHOTOMETRIC.YCBCR&&!isUpSampled(tif)) { object[] ap=new object[2]; TIFFGetField(tif, TIFFTAG.YCBCRSUBSAMPLING, ap); ushort[] ycbcrsubsampling=new ushort[2]; ycbcrsubsampling[0]=__GetAsUshort(ap, 0); ycbcrsubsampling[1]=__GetAsUshort(ap, 1); if(ycbcrsubsampling[0]*ycbcrsubsampling[1]==0) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "Invalid YCbCr subsampling"); return 0; } return (int)(((((td.td_imagewidth+ycbcrsubsampling[0]-1)/ycbcrsubsampling[0])*(ycbcrsubsampling[0]*ycbcrsubsampling[1]+2)*td.td_bitspersample+7)/8)/ycbcrsubsampling[1]); } else scanline=multiply(tif, td.td_imagewidth, td.td_samplesperpixel, "TIFFScanlineSize"); } else scanline=td.td_imagewidth; return (int)TIFFhowmany8(multiply(tif, scanline, td.td_bitspersample, "TIFFScanlineSize")); }
public static bool _TIFFMergeFieldInfo(TIFF tif, List <TIFFFieldInfo> info) { string module = "_TIFFMergeFieldInfo"; tif.tif_foundfield = null; try { foreach (TIFFFieldInfo fi in info) { TIFFFieldInfo fip = TIFFFindFieldInfo(tif, fi.field_tag, fi.field_type); if (fip == null) { tif.tif_fieldinfo.Add(fi); } } } catch { TIFFErrorExt(tif.tif_clientdata, module, "Failed to allocate field info array"); return(false); } // Sort the field info by tag number tif.tif_fieldinfo.Sort(tagCompare); return(true); }
static TIFFFieldInfo TIFFFindFieldInfo(TIFF tif, TIFFTAG tag, TIFFDataType dt) { if (tif.tif_foundfield != null && tif.tif_foundfield.field_tag == tag && (dt == TIFFDataType.TIFF_ANY || dt == tif.tif_foundfield.field_type)) { return(tif.tif_foundfield); } // If we are invoked with no field information, then just return. if (tif.tif_fieldinfo == null || tif.tif_fieldinfo.Count == 0) { return(null); } #if !USE_TIFFFindFieldInfoSearch foreach (TIFFFieldInfo fip in tif.tif_fieldinfo) { if (fip.field_tag == tag && (dt == TIFFDataType.TIFF_ANY || fip.field_type == dt)) { return(tif.tif_foundfield = fip); } } return(null); #else return(TIFFFindFieldInfoSearch(tif, tag, dt, 0, tif.tif_fieldinfo.Count)); #endif }
public static void TIFFMergeFieldInfo(TIFF tif, List <TIFFFieldInfo> info) { if (!_TIFFMergeFieldInfo(tif, info)) { TIFFErrorExt(tif.tif_clientdata, "TIFFMergeFieldInfo", "Merging block of %d fields failed", info.Count); } }
// Compute how many tiles are in an image. public static uint TIFFNumberOfTiles(TIFF tif) { TIFFDirectory td = tif.tif_dir; uint dx = td.td_tilewidth; uint dy = td.td_tilelength; uint dz = td.td_tiledepth; uint ntiles; if (dx == 0xffffffff) { dx = td.td_imagewidth; } if (dy == 0xffffffff) { dy = td.td_imagelength; } if (dz == 0xffffffff) { dz = td.td_imagedepth; } ntiles = (dx == 0 || dy == 0 || dz == 0)?0: multiply(tif, multiply(tif, TIFFhowmany(td.td_imagewidth, dx), TIFFhowmany(td.td_imagelength, dy), "TIFFNumberOfTiles"), TIFFhowmany(td.td_imagedepth, dz), "TIFFNumberOfTiles"); if (td.td_planarconfig == PLANARCONFIG.SEPARATE) { ntiles = multiply(tif, ntiles, td.td_samplesperpixel, "TIFFNumberOfTiles"); } return(ntiles); }
//********************************************************************* // // Public Routines // //********************************************************************* // Given an open TIFF file, look for GTIF keys and values and return GTIF structure. // // This function creates a GeoTIFF information interpretation handle // (GTIF) based on a passed in TIFF handle originally from // XTIFFOpen(). // // The returned GTIF handle can be used to read or write GeoTIFF tags // using the various GTIF functions. The handle should be destroyed using // GTIFFree() before the file is closed with TIFFClose(). // // If the file accessed has no GeoTIFF keys, an valid (but empty) GTIF is // still returned. GTIFNew() is used both for existing files being read, and // for new TIFF files that will have GeoTIFF tags written to them. public static GTIF GTIFNew(TIFF tif) { TIFFMethod default_methods=new TIFFMethod(); _GTIFSetDefaultTIFF(default_methods); return GTIFNewWithMethods(tif, default_methods); }
// Check an (x,y,z,s) coordinate against the image bounds. public static bool TIFFCheckTile(TIFF tif, uint x, uint y, uint z, ushort s) { TIFFDirectory td=tif.tif_dir; if(x>=td.td_imagewidth) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Col out of range, max {1}", x, td.td_imagewidth-1); return false; } if(y>=td.td_imagelength) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Row out of range, max {1}", y, td.td_imagelength-1); return false; } if(z>=td.td_imagedepth) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Depth out of range, max {1}", z, td.td_imagedepth-1); return false; } if(td.td_planarconfig==PLANARCONFIG.SEPARATE&&s>=td.td_samplesperpixel) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Sample out of range, max {1}", s, td.td_samplesperpixel-1); return false; } return true; }
// Compute which tile an (x,y,z,s) value is in. public static uint TIFFComputeTile(TIFF tif, uint x, uint y, uint z, ushort s) { TIFFDirectory td=tif.tif_dir; uint dx=td.td_tilewidth; uint dy=td.td_tilelength; uint dz=td.td_tiledepth; if(td.td_imagedepth==1) z=0; if(dx==0xffffffff) dx=td.td_imagewidth; if(dy==0xffffffff) dy=td.td_imagelength; if(dz==0xffffffff) dz=td.td_imagedepth; if(dx!=0&&dy!=0&&dz!=0) { uint xpt=TIFFhowmany(td.td_imagewidth, dx); uint ypt=TIFFhowmany(td.td_imagelength, dy); uint zpt=TIFFhowmany(td.td_imagedepth, dz); if(td.td_planarconfig==PLANARCONFIG.SEPARATE) return xpt*ypt*zpt*s+xpt*ypt*(z/dz)+xpt*(y/dy)+x/dx; return xpt*ypt*(z/dz)+xpt*(y/dy)+x/dx; } return 1; }
static bool _notConfigured(TIFF tif) { TIFFCodec c = TIFFFindCODEC(tif.tif_dir.td_compression); TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0} compression support is not configured", (c != null?c.name:tif.tif_dir.td_compression.ToString())); return(false); }
static bool TIFFInitNeXT(TIFF tif, COMPRESSION scheme) { tif.tif_decoderow = NeXTDecode; tif.tif_decodestrip = NeXTDecode; tif.tif_decodetile = NeXTDecode; return(true); }
static int TIFFReadRawTile1(TIFF tif, uint tile, byte[] buf, int size, string module) { TIFFDirectory td = tif.tif_dir; #if DEBUG if ((tif.tif_flags & TIF_FLAGS.TIFF_NOREADRAW) != 0) { throw new Exception("(tif.tif_flags&TIF_FLAGS.TIFF.NOREADRAW)==0"); } #endif if (!SeekOK(tif, td.td_stripoffset[tile])) { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Seek error at row {1}, col {2}, tile {3}", tif.tif_name, tif.tif_row, tif.tif_col, tile); return(-1); } int cc = TIFFReadFile(tif, buf, size); if (cc != size) { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Read error at row {1}, col {2}; got {3} bytes, expected {4}", tif.tif_name, tif.tif_row, tif.tif_col, cc, size); return(-1); } return(size); }
static void ZIPCleanup(TIFF tif) { ZIPState sp = tif.tif_data as ZIPState; #if DEBUG if (sp == null) { throw new Exception("sp==null"); } #endif TIFFPredictorCleanup(tif); tif.tif_tagmethods.vgetfield = sp.vgetparent; tif.tif_tagmethods.vsetfield = sp.vsetparent; if ((sp.state & ZSTATE.INIT_ENCODE) == ZSTATE.INIT_ENCODE) { zlib.deflateEnd(sp.stream); sp.state = ZSTATE.None; } else if ((sp.state & ZSTATE.INIT_DECODE) == ZSTATE.INIT_DECODE) { zlib.inflateEnd(sp.stream); sp.state = ZSTATE.None; } tif.tif_data = null; TIFFSetDefaultCompressionState(tif); }
// Finish off an encoded strip by flushing the last // string and tacking on an End Of Information code. static bool ZIPPostEncode(TIFF tif) { ZIPState sp = tif.tif_data as ZIPState; string module = "ZIPPostEncode"; int state; sp.stream.avail_in = 0; do { state = zlib.deflate(sp.stream, zlib.Z_FINISH); switch (state) { case zlib.Z_STREAM_END: case zlib.Z_OK: if ((int)sp.stream.avail_out != (int)tif.tif_rawdatasize) { tif.tif_rawcc = tif.tif_rawdatasize - sp.stream.avail_out; TIFFFlushData1(tif); sp.stream.out_buf = tif.tif_rawdata; sp.stream.next_out = 0; sp.stream.avail_out = tif.tif_rawdatasize; } break; default: TIFFErrorExt(tif.tif_clientdata, module, "{0}: zlib error: {1}", tif.tif_name, sp.stream.msg); return(false); } } while(state != zlib.Z_STREAM_END); return(true); }
// Check an (x,y,z,s) coordinate against the image bounds. public static bool TIFFCheckTile(TIFF tif, uint x, uint y, uint z, ushort s) { TIFFDirectory td = tif.tif_dir; if (x >= td.td_imagewidth) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Col out of range, max {1}", x, td.td_imagewidth - 1); return(false); } if (y >= td.td_imagelength) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Row out of range, max {1}", y, td.td_imagelength - 1); return(false); } if (z >= td.td_imagedepth) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Depth out of range, max {1}", z, td.td_imagedepth - 1); return(false); } if (td.td_planarconfig == PLANARCONFIG.SEPARATE && s >= td.td_samplesperpixel) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Sample out of range, max {1}", s, td.td_samplesperpixel - 1); return(false); } return(true); }
// Decode a tile/strip and apply the predictor routine. // Note that horizontal differencing must be done on a // row-by-row basis. The width of a "row" has already // been calculated at pre-decode time according to the // strip/tile dimensions. static bool PredictorDecodeTile(TIFF tif, byte[] op0, int occ0, ushort s) { TIFFPredictorState sp = (TIFFPredictorState)tif.tif_data; if (sp.decodetile(tif, op0, occ0, s)) { int rowsize = sp.rowsize; #if DEBUG if (rowsize <= 0) { throw new Exception("rowsize<=0"); } #endif int op0_offset = 0; while (occ0 > 0) { sp.decodepfunc(tif, op0, op0_offset, rowsize); occ0 -= rowsize; op0_offset += rowsize; } return(true); } return(false); }
// Return the number of bytes to read/write in a call to // one of the scanline-oriented i/o routines. Note that // this number may be 1/samples-per-pixel if data is // stored as separate planes. public static int TIFFScanlineSize(TIFF tif) { TIFFDirectory td = tif.tif_dir; uint scanline; if (td.td_planarconfig == PLANARCONFIG.CONTIG) { if (td.td_photometric == PHOTOMETRIC.YCBCR && !isUpSampled(tif)) { object[] ap = new object[2]; TIFFGetField(tif, TIFFTAG.YCBCRSUBSAMPLING, ap); ushort ycbcrsubsampling0 = __GetAsUshort(ap, 0); //ushort ycbcrsubsampling1=__GetAsUshort(ap, 1); // not needed if (ycbcrsubsampling0 == 0) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "Invalid YCbCr subsampling"); return(0); } scanline = TIFFroundup(td.td_imagewidth, ycbcrsubsampling0); scanline = TIFFhowmany8(multiply(tif, scanline, td.td_bitspersample, "TIFFScanlineSize")); return((int)summarize(tif, scanline, multiply(tif, 2, scanline / ycbcrsubsampling0, "TIFFVStripSize"), "TIFFVStripSize")); } scanline = multiply(tif, td.td_imagewidth, td.td_samplesperpixel, "TIFFScanlineSize"); } else { scanline = td.td_imagewidth; } return((int)TIFFhowmany8(multiply(tif, scanline, td.td_bitspersample, "TIFFScanlineSize"))); }
// Read a tile of data and decompress the specified // amount into the user-supplied buffer. public static int TIFFReadEncodedTile(TIFF tif, uint tile, byte[] buf, int size) { TIFFDirectory td = tif.tif_dir; int tilesize = tif.tif_tilesize; if (!TIFFCheckRead(tif, true)) { return(-1); } if (tile >= td.td_nstrips) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Tile out of range, max {1}", tile, td.td_nstrips); return(-1); } if (size == -1) { size = tilesize; } else if (size > tilesize) { size = tilesize; } if (TIFFFillTile(tif, tile) && tif.tif_decodetile(tif, buf, size, (ushort)(tile / td.td_stripsperimage))) { tif.tif_postdecode(tif, buf, 0, size); return(size); } return(-1); }
public static int TIFFReadScanline(TIFF tif, byte[] buf, uint row, ushort sample) { if (!TIFFCheckRead(tif, false)) { return(-1); } bool e = TIFFSeek(tif, buf, row, sample); if (e) { // Decompress desired row into user buffer. e = tif.tif_decoderow(tif, buf, (int)tif.tif_scanlinesize, sample); // we are now poised at the beginning of the next row tif.tif_row = row + 1; if (e) { tif.tif_postdecode(tif, buf, 0, (int)tif.tif_scanlinesize); } } return(e?1:-1); }
// Set state to appear as if a // tile has just been read in. static bool TIFFStartTile(TIFF tif, uint tile) { TIFFDirectory td = tif.tif_dir; if ((tif.tif_flags & TIF_FLAGS.TIFF_CODERSETUP) == 0) { if (!tif.tif_setupdecode(tif)) { return(false); } tif.tif_flags |= TIF_FLAGS.TIFF_CODERSETUP; } tif.tif_curtile = tile; tif.tif_row = (tile % TIFFhowmany(td.td_imagewidth, td.td_tilewidth)) * td.td_tilelength; tif.tif_col = (tile % TIFFhowmany(td.td_imagelength, td.td_tilelength)) * td.td_tilewidth; if ((tif.tif_flags & TIF_FLAGS.TIFF_NOREADRAW) == TIF_FLAGS.TIFF_NOREADRAW) { tif.tif_rawdata = null; // ????? tif.tif_rawcp = 0; tif.tif_rawcc = 0; } else { tif.tif_rawcp = 0; //was tif.tif_rawdata; tif.tif_rawcc = td.td_stripbytecount[tile]; } return(tif.tif_predecode(tif, (ushort)(tile / td.td_stripsperimage))); }
// Set state to appear as if a // strip has just been read in. static bool TIFFStartStrip(TIFF tif, uint strip) { TIFFDirectory td = tif.tif_dir; if ((tif.tif_flags & TIF_FLAGS.TIFF_CODERSETUP) == 0) { if (!tif.tif_setupdecode(tif)) { return(false); } tif.tif_flags |= TIF_FLAGS.TIFF_CODERSETUP; } tif.tif_curstrip = strip; tif.tif_row = (strip % td.td_stripsperimage) * td.td_rowsperstrip; if ((tif.tif_flags & TIF_FLAGS.TIFF_NOREADRAW) == TIF_FLAGS.TIFF_NOREADRAW) { tif.tif_rawdata = null; // ????? tif.tif_rawcp = 0; tif.tif_rawcc = 0; } else { tif.tif_rawcp = 0; //was tif.tif_rawdata; tif.tif_rawcc = td.td_stripbytecount[strip]; } return(tif.tif_predecode(tif, (ushort)(strip / td.td_stripsperimage))); }
public static TIFFTAG TIFFGetTagListEntry(TIFF tif, int tag_index) { TIFFDirectory td=tif.tif_dir; if(tag_index<0||tag_index>=td.td_customValueCount) return (TIFFTAG)(-1); else return td.td_customValues[tag_index].info.field_tag; }
static bool TIFFPredictorInit(TIFF tif) { TIFFPredictorState sp = (TIFFPredictorState)tif.tif_data; // Merge codec-specific tag information. if (!_TIFFMergeFieldInfo(tif, predictFieldInfo)) { TIFFErrorExt(tif.tif_clientdata, "TIFFPredictorInit", "Merging Predictor codec-specific tags failed"); return(false); } // Override parent get/set field methods. sp.vgetparent = tif.tif_tagmethods.vgetfield; tif.tif_tagmethods.vgetfield = PredictorVGetField; // hook for predictor tag sp.vsetparent = tif.tif_tagmethods.vsetfield; tif.tif_tagmethods.vsetfield = PredictorVSetField; // hook for predictor tag sp.printdir = tif.tif_tagmethods.printdir; tif.tif_tagmethods.printdir = PredictorPrintDir; // hook for predictor tag sp.setupdecode = tif.tif_setupdecode; tif.tif_setupdecode = PredictorSetupDecode; sp.setupencode = tif.tif_setupencode; tif.tif_setupencode = PredictorSetupEncode; sp.predictor = PREDICTOR.NONE; // default value sp.encodepfunc = null; // no predictor routine sp.decodepfunc = null; // no predictor routine return(true); }
public static void TIFFMergeFieldInfo(TIFF tif, TIFFFieldInfo info) { if (!_TIFFMergeFieldInfo(tif, info)) { TIFFErrorExt(tif.tif_clientdata, "TIFFMergeFieldInfo", "Merging block of 1 fields failed"); } }
static bool PackBitsPreEncode(TIFF tif, ushort sampleNumber) { PackBitsState state = null; try { tif.tif_data = state = new PackBitsState(); } catch { return(false); } // Calculate the scanline/tile-width size in bytes. if (isTiled(tif)) { state.data = TIFFTileRowSize(tif); } else { state.data = TIFFScanlineSize(tif); } return(true); }
// Seek forwards nrows in the current strip. static bool DumpModeSeek(TIFF tif, uint nrows) { tif.tif_rawcp += nrows * tif.tif_scanlinesize; tif.tif_rawcc -= nrows * tif.tif_scanlinesize; return(true); }
// Read a tile of data from the file. public static int TIFFReadRawTile(TIFF tif, uint tile, byte[] buf, int size) { string module = "TIFFReadRawTile"; TIFFDirectory td = tif.tif_dir; if (!TIFFCheckRead(tif, true)) { return(-1); } if (tile >= td.td_nstrips) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Tile out of range, max {1}", tile, td.td_nstrips); return(-1); } if ((tif.tif_flags & TIF_FLAGS.TIFF_NOREADRAW) == TIF_FLAGS.TIFF_NOREADRAW) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "Compression scheme does not support access to raw uncompressed data"); return(-1); } // FIXME: butecount should have tsize_t type, but for now libtiff // defines tsize_t as a signed 32-bit integer and we are losing // ability to read arrays larger than 2^31 bytes. So we are using // uint32 instead of tsize_t here. uint bytecount = td.td_stripbytecount[tile]; if (size != -1 && (uint)size < bytecount) { bytecount = (uint)size; } return(TIFFReadRawTile1(tif, tile, buf, (int)bytecount, module)); }
// Allocate downsampled-data buffers needed for downsampled I/O. // We use values computed in jpeg_start_compress or jpeg_start_decompress. // We use libjpeg's allocator so that buffers will be released automatically // when done with strip/tile. // This is also a handy place to compute samplesperclump, bytesperline. static bool alloc_downsampled_buffers(TIFF tif, jpeg_component_info[] comp_info, int num_components) { JPEGState sp=tif.tif_data as JPEGState; byte[][] buf; int samples_per_clump=0; for(int ci=0; ci<num_components; ci++) { jpeg_component_info compptr=comp_info[ci]; samples_per_clump+=compptr.h_samp_factor*compptr.v_samp_factor; try { buf=TIFFjpeg_alloc_sarray(sp, compptr.width_in_blocks*libjpeg.DCTSIZE, (uint)compptr.v_samp_factor*libjpeg.DCTSIZE); } catch { return false; } sp.ds_buffer[ci]=buf; } sp.samplesperclump=samples_per_clump; return true; }
public static bool 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:(uint)TIFFNumberOfStrips(tif); td.td_nstrips=td.td_stripsperimage; if(td.td_planarconfig==PLANARCONFIG.SEPARATE) td.td_stripsperimage/=td.td_samplesperpixel; try { td.td_stripoffset=new uint[td.td_nstrips]; td.td_stripbytecount=new uint[td.td_nstrips]; } catch { return false; } // Place data at the end-of-file // (by setting offsets to zero). TIFFSetFieldBit(tif, FIELD.STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD.STRIPBYTECOUNTS); // FIX: Some tools don't like images without ROWSPERSTRIP set. if(!TIFFFieldSet(tif, FIELD.ROWSPERSTRIP)) { td.td_rowsperstrip=td.td_imagelength; TIFFSetFieldBit(tif, FIELD.ROWSPERSTRIP); } return true; }
static bool PackBitsDecode(TIFF tif, byte[] op, int occ, ushort s) { uint bp = tif.tif_rawcp; int cc = (int)tif.tif_rawcc; uint op_ind = 0; while (cc > 0 && (long)occ > 0) { int n = tif.tif_rawdata[bp++]; cc--; // Watch out for compilers that // don't sign extend chars... if (n >= 128) { n -= 256; } if (n < 0) { // replicate next byte -n+1 times if (n == -128) { continue; // nop } n = -n + 1; if (occ < n) { TIFFWarningExt(tif.tif_clientdata, tif.tif_name, "PackBitsDecode: discarding {0} bytes to avoid buffer overrun", n - occ); n = occ; } occ -= n; byte b = tif.tif_rawdata[bp++]; cc--; while ((n--) > 0) { op[op_ind++] = b; } } else { // copy next n+1 bytes literally if (occ < n + 1) { TIFFWarningExt(tif.tif_clientdata, tif.tif_name, "PackBitsDecode: discarding {0} bytes to avoid buffer overrun", n - occ + 1); n = occ - 1; } n++; Array.Copy(tif.tif_rawdata, bp, op, op_ind, n); op_ind += (uint)n; occ -= n; bp += (uint)n; cc -= n; } } tif.tif_rawcp = bp; tif.tif_rawcc = (uint)cc; if (occ > 0) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "PackBitsDecode: Not enough data for scanline {0}", tif.tif_row); return(false); } return(true); }
static bool TIFFInitZIP(TIFF tif, COMPRESSION scheme) { string module = "TIFFInitZIP"; #if DEBUG if (scheme != COMPRESSION.DEFLATE && scheme != COMPRESSION.ADOBE_DEFLATE) { throw new Exception("scheme!=COMPRESSION.DEFLATE&&scheme!=COMPRESSION.ADOBE_DEFLATE"); } #endif // Merge codec-specific tag information. if (!_TIFFMergeFieldInfo(tif, zipFieldInfo)) { TIFFErrorExt(tif.tif_clientdata, module, "Merging Deflate codec-specific tags failed"); return(false); } // Allocate state block so tag methods have storage to record values. ZIPState sp = null; try { tif.tif_data = sp = new ZIPState(); sp.stream = new zlib.z_stream(); } catch { TIFFErrorExt(tif.tif_clientdata, module, "No space for ZIP state block"); return(false); } // Override parent get/set field methods. sp.vgetparent = tif.tif_tagmethods.vgetfield; tif.tif_tagmethods.vgetfield = ZIPVGetField; // hook for codec tags sp.vsetparent = tif.tif_tagmethods.vsetfield; tif.tif_tagmethods.vsetfield = ZIPVSetField; // hook for codec tags // Default values for codec-specific fields sp.zipquality = zlib.Z_DEFAULT_COMPRESSION; // default comp. level sp.state = ZSTATE.None; // Install codec methods. tif.tif_setupdecode = ZIPSetupDecode; tif.tif_predecode = ZIPPreDecode; tif.tif_decoderow = ZIPDecode; tif.tif_decodestrip = ZIPDecode; tif.tif_decodetile = ZIPDecode; tif.tif_setupencode = ZIPSetupEncode; tif.tif_preencode = ZIPPreEncode; tif.tif_postencode = ZIPPostEncode; tif.tif_encoderow = ZIPEncode; tif.tif_encodestrip = ZIPEncode; tif.tif_encodetile = ZIPEncode; tif.tif_cleanup = ZIPCleanup; // Setup predictor setup. TIFFPredictorInit(tif); return(true); }
// Tile-oriented Read Support // Contributed by Nancy Cam (Silicon Graphics). // Read and decompress a tile of data. The // tile is selected by the (x,y,z,s) coordinates. public static int TIFFReadTile(TIFF tif, byte[] buf, uint x, uint y, uint z, ushort s) { if (!TIFFCheckRead(tif, true) || !TIFFCheckTile(tif, x, y, z, s)) { return(-1); } return(TIFFReadEncodedTile(tif, TIFFComputeTile(tif, x, y, z, s), buf, -1)); }
public static object TIFFGetClientInfo(TIFF tif, string name) { foreach(TIFFClientInfoLink link in tif.tif_clientinfo) { if(link.name==name) return link.data; } return null; }
static bool NotConfigured(TIFF tif, COMPRESSION scheme) { tif.tif_decodestatus = false; tif.tif_setupdecode = _notConfigured; tif.tif_encodestatus = false; tif.tif_setupencode = _notConfigured; return(false); }
// Similar to TIFFWriteDirectory(), writes the directory out // but leaves all data structures in memory so that it can be // written again. This will make a partially written TIFF file // readable before it is successfully completed/closed. public static bool TIFFCheckpointDirectory(TIFF tif) { // Setup the strips arrays, if they haven't already been. if(tif.tif_dir.td_stripoffset==null) TIFFSetupStrips(tif); bool rc=TIFFWriteDirectory(tif, false); TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK.END)); return rc; }
static bool TIFFInitZIP(TIFF tif, COMPRESSION scheme) { string module="TIFFInitZIP"; #if DEBUG if(scheme!=COMPRESSION.DEFLATE&&scheme!=COMPRESSION.ADOBE_DEFLATE) throw new Exception("scheme!=COMPRESSION.DEFLATE&&scheme!=COMPRESSION.ADOBE_DEFLATE"); #endif // Merge codec-specific tag information. if(!_TIFFMergeFieldInfo(tif, zipFieldInfo)) { TIFFErrorExt(tif.tif_clientdata, module, "Merging Deflate codec-specific tags failed"); return false; } // Allocate state block so tag methods have storage to record values. ZIPState sp=null; try { tif.tif_data=sp=new ZIPState(); sp.stream=new zlib.z_stream(); } catch { TIFFErrorExt(tif.tif_clientdata, module, "No space for ZIP state block"); return false; } // Override parent get/set field methods. sp.vgetparent=tif.tif_tagmethods.vgetfield; tif.tif_tagmethods.vgetfield=ZIPVGetField; // hook for codec tags sp.vsetparent=tif.tif_tagmethods.vsetfield; tif.tif_tagmethods.vsetfield=ZIPVSetField; // hook for codec tags // Default values for codec-specific fields sp.zipquality=zlib.Z_DEFAULT_COMPRESSION; // default comp. level sp.state=ZSTATE.None; // Install codec methods. tif.tif_setupdecode=ZIPSetupDecode; tif.tif_predecode=ZIPPreDecode; tif.tif_decoderow=ZIPDecode; tif.tif_decodestrip=ZIPDecode; tif.tif_decodetile=ZIPDecode; tif.tif_setupencode=ZIPSetupEncode; tif.tif_preencode=ZIPPreEncode; tif.tif_postencode=ZIPPostEncode; tif.tif_encoderow=ZIPEncode; tif.tif_encodestrip=ZIPEncode; tif.tif_encodetile=ZIPEncode; tif.tif_cleanup=ZIPCleanup; // Setup predictor setup. TIFFPredictorInit(tif); return true; }
// Compute which strip a (row, sample) value is in. public static int TIFFComputeStrip(TIFF tif, uint row, ushort sample) { TIFFDirectory td=tif.tif_dir; uint strip; strip=row/td.td_rowsperstrip; if(td.td_planarconfig==PLANARCONFIG.SEPARATE) { if(sample>=td.td_samplesperpixel) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Sample out of range, max {1}", sample, td.td_samplesperpixel); return 0; } strip+=sample*td.td_stripsperimage; } return (int)strip; }
// Floating point predictor accumulation routine. static unsafe void fpAcc(TIFF tif, byte[] cp0, int cp0_offset, int cc) { int stride=((TIFFPredictorState)tif.tif_data).stride; int bps=tif.tif_dir.td_bitspersample/8; int wc=cc/bps; int count=cc; byte[] tmp=null; try { tmp=new byte[cc]; } catch { return; } fixed(byte* cp0_=cp0) { byte* cp=cp0_+cp0_offset; while(count>stride) { //was REPEAT4(stride, cp[stride]+=*(cp++)); switch(stride) { default: for(int i=stride-4; i>0; i--) cp[stride]+=*(cp++); goto case 4; case 4: cp[stride]+=*(cp++); goto case 3; case 3: cp[stride]+=*(cp++); goto case 2; case 2: cp[stride]+=*(cp++); goto case 1; case 1: cp[stride]+=*(cp++); break; case 0: break; } count-=stride; } Array.Copy(cp0, cp0_offset, tmp, 0, cc); cp=cp0_+cp0_offset; for(count=0; count<wc; count++) { for(uint b=0; b<bps; b++) cp[bps*count+b]=tmp[(bps-b-1)*wc+count]; } } }
public static void TIFFSetClientInfo(TIFF tif, object data, string name) { // Do we have an existing link with this name? If so, just // set it. foreach(TIFFClientInfoLink link in tif.tif_clientinfo) { if(link.name==name) { link.data=data; return; } } // Create a new link. TIFFClientInfoLink newlink=new TIFFClientInfoLink(); newlink.name=name; newlink.data=data; tif.tif_clientinfo.Add(newlink); }
const uint NOTILE = 0xffffffff; // undefined state #endregion Fields #region Methods // Read the specified strip and setup for decoding. // The data buffer is expanded, as necessary, to // hold the strip's data. public static bool TIFFFillStrip(TIFF tif, uint strip) { string module="TIFFFillStrip"; TIFFDirectory td=tif.tif_dir; if((tif.tif_flags&TIF_FLAGS.TIFF_NOREADRAW)==0) { // FIXME: butecount should have tsize_t type, but for now // libtiff defines tsize_t as a signed 32-bit integer and we // are losing ability to read arrays larger than 2^31 bytes. // So we are using uint32 instead of tsize_t here. uint bytecount=td.td_stripbytecount[strip]; if(bytecount<=0) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "{0}: Invalid strip byte count, strip {1}", bytecount, strip); return false; } // Expand raw data buffer, if needed, to // hold data strip coming from file // (perhaps should set upper bound on // the size of a buffer we'll use?). if(bytecount>tif.tif_rawdatasize) { tif.tif_curstrip=NOSTRIP; if((tif.tif_flags&TIF_FLAGS.TIFF_MYBUFFER)==0) { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Data buffer too small to hold strip {1}", tif.tif_name, strip); return false; } if(!TIFFReadBufferSetup(tif, null, (int)TIFFroundup(bytecount, 1024))) return false; } if((uint)TIFFReadRawStrip1(tif, strip, tif.tif_rawdata, (int)bytecount, module)!=bytecount) return false; if(!isFillOrder(tif, td.td_fillorder)&&(tif.tif_flags&TIF_FLAGS.TIFF_NOBITREV)==0) TIFFReverseBits(tif.tif_rawdata, (uint)bytecount); } return TIFFStartStrip(tif, strip); }
// Read the specified image into an ABGR-format rastertaking in account // specified orientation. public static bool TIFFReadRGBAImageOriented(TIFF tif, uint rwidth, uint rheight, uint[] raster, ORIENTATION orientation, bool stop) { string emsg=""; TIFFRGBAImage img=new TIFFRGBAImage(); bool ok; if(TIFFRGBAImageOK(tif, out emsg)&&TIFFRGBAImageBegin(img, tif, stop, out emsg)) { img.req_orientation=orientation; // XXX verify rwidth and rheight against width and height ok=TIFFRGBAImageGet(img, raster, (rheight-img.height)*rwidth, rwidth, img.height); TIFFRGBAImageEnd(img); } else { TIFFErrorExt(tif.tif_clientdata, TIFFFileName(tif), emsg); ok=false; } return ok; }
static TIFFFieldInfo TIFFCreateAnonFieldInfo(TIFF tif, TIFFTAG tag, TIFFDataType field_type) { try { // ??? TIFFFieldInfo fld=new TIFFFieldInfo(tag, TIFF_VARIABLE2, TIFF_VARIABLE2, field_type, FIELD.CUSTOM, true, true, "Tag "+tag); TIFFFieldInfo fld=new TIFFFieldInfo(tag, TIFF_VARIABLE, TIFF_VARIABLE, field_type, FIELD.CUSTOM, true, true, "Tag "+tag); return fld; } catch { return null; } }
static TIFFFieldInfo TIFFFieldWithName(TIFF tif, string field_name) { TIFFFieldInfo fip=TIFFFindFieldInfoByName(tif, field_name, TIFFDataType.TIFF_ANY); if(fip==null) { TIFFErrorExt(tif.tif_clientdata, "TIFFFieldWithName", "Internal error, unknown tag {0}", field_name); #if DEBUG throw new Exception("fip==null"); #endif // NOTREACHED } return fip; }
static TIFFFieldInfo TIFFFindOrRegisterFieldInfo(TIFF tif, TIFFTAG tag, TIFFDataType dt) { TIFFFieldInfo fld=TIFFFindFieldInfo(tif, tag, dt); if(fld==null) { fld=TIFFCreateAnonFieldInfo(tif, tag, dt); if(!_TIFFMergeFieldInfo(tif, fld)) return null; } return fld; }
static TIFFFieldInfo TIFFFindFieldInfoByName(TIFF tif, string field_name, TIFFDataType dt) { if(tif.tif_foundfield!=null&&tif.tif_foundfield.field_name==field_name&& (dt==TIFFDataType.TIFF_ANY||dt==tif.tif_foundfield.field_type)) return tif.tif_foundfield; // If we are invoked with no field information, then just return. if(tif.tif_fieldinfo==null||tif.tif_fieldinfo.Count==0) return null; foreach(TIFFFieldInfo fip in tif.tif_fieldinfo) { if(fip.field_name==field_name&&(dt==TIFFDataType.TIFF_ANY||fip.field_type==dt)) return tif.tif_foundfield=fip; } return null; }
static TIFFFieldInfo TIFFFieldWithTag(TIFF tif, TIFFTAG tag) { TIFFFieldInfo fip=TIFFFindFieldInfo(tif, tag, TIFFDataType.TIFF_ANY); if(fip==null) { TIFFErrorExt(tif.tif_clientdata, "TIFFFieldWithTag", "Internal error, unknown tag 0x{0:X}", tag); #if DEBUG throw new Exception("fip==null"); #endif // NOTREACHED } return fip; }
static TIFFFieldInfo TIFFFindFieldInfo(TIFF tif, TIFFTAG tag, TIFFDataType dt) { if(tif.tif_foundfield!=null&&tif.tif_foundfield.field_tag==tag&& (dt==TIFFDataType.TIFF_ANY||dt==tif.tif_foundfield.field_type)) return tif.tif_foundfield; // If we are invoked with no field information, then just return. if(tif.tif_fieldinfo==null||tif.tif_fieldinfo.Count==0) return null; #if !USE_TIFFFindFieldInfoSearch foreach(TIFFFieldInfo fip in tif.tif_fieldinfo) { if(fip.field_tag==tag&&(dt==TIFFDataType.TIFF_ANY||fip.field_type==dt)) return tif.tif_foundfield=fip; } return null; #else return TIFFFindFieldInfoSearch(tif, tag, dt, 0, tif.tif_fieldinfo.Count); #endif }
static TIFFFieldInfo TIFFFindFieldInfoSearch(TIFF tif, TIFFTAG tag, TIFFDataType dt, int min, int num) { if(num==0) return null; TIFFFieldInfo fip=tif.tif_fieldinfo[min+num/2]; if(fip.field_tag==tag) { int pos=min+num/2; if(dt==TIFFDataType.TIFF_ANY) { for(; ; ) // Find first { if(pos==0) break; if(tif.tif_fieldinfo[pos-1].field_tag!=tag) break; pos--; fip=tif.tif_fieldinfo[pos]; } return tif.tif_foundfield=fip; } if(fip.field_type==dt) return tif.tif_foundfield=fip; //if(fip.field_type>dt) return TIFFFindFieldInfoSearch(tif, tag, dt, min, num/2); //return TIFFFindFieldInfoSearch(tif, tag, dt, min+num/2+1, num-(num/2+1)); for(; ; ) // preceding fieldinfos and exit if found DataType { if(pos==0) break; if(tif.tif_fieldinfo[pos-1].field_tag!=tag) break; pos--; fip=tif.tif_fieldinfo[pos]; if(fip.field_type==dt) return tif.tif_foundfield=fip; } pos=min+num/2; for(; ; ) // succeding fieldinfos first and exit if found DataType { if(pos==(tif.tif_fieldinfo.Count-1)) break; if(tif.tif_fieldinfo[pos+1].field_tag!=tag) break; pos++; fip=tif.tif_fieldinfo[pos]; if(fip.field_type==dt) return tif.tif_foundfield=fip; } return null; } if(fip.field_tag>tag) return TIFFFindFieldInfoSearch(tif, tag, dt, min, num/2); return TIFFFindFieldInfoSearch(tif, tag, dt, min+num/2+1, num-(num/2+1)); }
public static void TIFFPrintFieldInfo(TIFF tif, StreamWriter fd) { fd.WriteLine("{0}: ", tif.tif_name); int i=0; foreach(TIFFFieldInfo fip in tif.tif_fieldinfo) fd.WriteLine("field[{0, 2}] {1, 5}, {2, 2}, {3, 2}, {4}, {5, 2}, {6}, {7}, {8}", i++, fip.field_tag, fip.field_readcount, fip.field_writecount, fip.field_type, fip.field_bit, fip.field_oktochange?"TRUE ":"FALSE", fip.field_passcount?"TRUE ":"FALSE", fip.field_name); }
// Return nearest TIFFDataType to the sample type of an image. static TIFFDataType TIFFSampleToTagType(TIFF tif) { uint bps=TIFFhowmany8(tif.tif_dir.td_bitspersample); switch(tif.tif_dir.td_sampleformat) { case SAMPLEFORMAT.IEEEFP: return (bps==4?TIFFDataType.TIFF_FLOAT:TIFFDataType.TIFF_DOUBLE); case SAMPLEFORMAT.INT: return (bps<=1?TIFFDataType.TIFF_SBYTE:bps<=2?TIFFDataType.TIFF_SSHORT:TIFFDataType.TIFF_SLONG); case SAMPLEFORMAT.UINT: return (bps<=1?TIFFDataType.TIFF_BYTE:bps<=2?TIFFDataType.TIFF_SHORT:TIFFDataType.TIFF_LONG); case SAMPLEFORMAT.VOID: return TIFFDataType.TIFF_UNDEFINED; } // NOTREACHED return TIFFDataType.TIFF_UNDEFINED; }
public static bool _TIFFMergeFieldInfo(TIFF tif, List<TIFFFieldInfo> info) { string module="_TIFFMergeFieldInfo"; tif.tif_foundfield=null; try { foreach(TIFFFieldInfo fi in info) { TIFFFieldInfo fip=TIFFFindFieldInfo(tif, fi.field_tag, fi.field_type); if(fip==null) tif.tif_fieldinfo.Add(fi); } } catch { TIFFErrorExt(tif.tif_clientdata, module, "Failed to allocate field info array"); return false; } // Sort the field info by tag number tif.tif_fieldinfo.Sort(tagCompare); return true; }
public static void TIFFMergeFieldInfo(TIFF tif, List<TIFFFieldInfo> info) { if(!_TIFFMergeFieldInfo(tif, info)) { TIFFErrorExt(tif.tif_clientdata, "TIFFMergeFieldInfo", "Merging block of %d fields failed", info.Count); } }
public static void TIFFMergeFieldInfo(TIFF tif, TIFFFieldInfo info) { if(!_TIFFMergeFieldInfo(tif, info)) { TIFFErrorExt(tif.tif_clientdata, "TIFFMergeFieldInfo", "Merging block of 1 fields failed"); } }
public static void TIFFSetupFieldInfo(TIFF tif, List<TIFFFieldInfo> info) { tif.tif_fieldinfo.Clear(); if(!_TIFFMergeFieldInfo(tif, info)) TIFFErrorExt(tif.tif_clientdata, "TIFFSetupFieldInfo", "Setting up field info failed"); }
static void TIFFSwab64BitData(TIFF tif, byte[] buf, int buf_offset, int cc) { #if DEBUG if((cc&7)!=0) throw new Exception("cc&7!=0"); #endif TIFFSwabArrayOfDouble(buf, buf_offset, (uint)(cc/8)); }