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 string field_name; // ASCII name public TIFFFieldInfo(TIFFTAG field_tag, short field_readcount, short field_writecount, TIFFDataType field_type, FIELD field_bit, bool field_oktochange, bool field_passcount, string field_name) { this.field_tag = field_tag; this.field_readcount = field_readcount; this.field_writecount = field_writecount; this.field_type = field_type; this.field_bit = field_bit; this.field_oktochange = field_oktochange; this.field_passcount = field_passcount; this.field_name = field_name; }
static bool _TIFFVGetField(TIFF tif, TIFFTAG tag, object[] ap) { TIFFDirectory td=tif.tif_dir; bool ret_val=true; switch(tag) { case TIFFTAG.SUBFILETYPE: ap[0]=td.td_subfiletype; break; case TIFFTAG.IMAGEWIDTH: ap[0]=td.td_imagewidth; break; case TIFFTAG.IMAGELENGTH: ap[0]=td.td_imagelength; break; case TIFFTAG.BITSPERSAMPLE: ap[0]=td.td_bitspersample; break; case TIFFTAG.COMPRESSION: ap[0]=td.td_compression; break; case TIFFTAG.PHOTOMETRIC: ap[0]=td.td_photometric; break; case TIFFTAG.THRESHHOLDING: ap[0]=td.td_threshholding; break; case TIFFTAG.FILLORDER: ap[0]=td.td_fillorder; break; case TIFFTAG.ORIENTATION: ap[0]=td.td_orientation; break; case TIFFTAG.SAMPLESPERPIXEL: ap[0]=td.td_samplesperpixel; break; case TIFFTAG.ROWSPERSTRIP: ap[0]=td.td_rowsperstrip; break; case TIFFTAG.MINSAMPLEVALUE: ap[0]=td.td_minsamplevalue; break; case TIFFTAG.MAXSAMPLEVALUE: ap[0]=td.td_maxsamplevalue; break; case TIFFTAG.SMINSAMPLEVALUE: ap[0]=td.td_sminsamplevalue; break; case TIFFTAG.SMAXSAMPLEVALUE: ap[0]=td.td_smaxsamplevalue; break; case TIFFTAG.XRESOLUTION: ap[0]=td.td_xresolution; break; case TIFFTAG.YRESOLUTION: ap[0]=td.td_yresolution; break; case TIFFTAG.PLANARCONFIG: ap[0]=td.td_planarconfig; break; case TIFFTAG.XPOSITION: ap[0]=td.td_xposition; break; case TIFFTAG.YPOSITION: ap[0]=td.td_yposition; break; case TIFFTAG.RESOLUTIONUNIT: ap[0]=td.td_resolutionunit; break; case TIFFTAG.PAGENUMBER: ap[0]=td.td_pagenumber[0]; ap[1]=td.td_pagenumber[1]; break; case TIFFTAG.HALFTONEHINTS: ap[0]=td.td_halftonehints[0]; ap[1]=td.td_halftonehints[1]; break; case TIFFTAG.COLORMAP: ap[0]=td.td_colormap[0]; ap[1]=td.td_colormap[1]; ap[2]=td.td_colormap[2]; break; case TIFFTAG.STRIPOFFSETS: case TIFFTAG.TILEOFFSETS: ap[0]=td.td_stripoffset; break; case TIFFTAG.STRIPBYTECOUNTS: case TIFFTAG.TILEBYTECOUNTS: ap[0]=td.td_stripbytecount; break; case TIFFTAG.MATTEING: ap[0]=(td.td_extrasamples==1&&(EXTRASAMPLE)td.td_sampleinfo[0]==EXTRASAMPLE.ASSOCALPHA); break; case TIFFTAG.EXTRASAMPLES: ap[0]=td.td_extrasamples; ap[1]=td.td_sampleinfo; break; case TIFFTAG.TILEWIDTH: ap[0]=td.td_tilewidth; break; case TIFFTAG.TILELENGTH: ap[0]=td.td_tilelength; break; case TIFFTAG.TILEDEPTH: ap[0]=td.td_tiledepth; break; case TIFFTAG.DATATYPE: switch(td.td_sampleformat) { case SAMPLEFORMAT.UINT: ap[0]=DATATYPE_UINT; break; case SAMPLEFORMAT.INT: ap[0]=DATATYPE_INT; break; case SAMPLEFORMAT.IEEEFP: ap[0]=DATATYPE_IEEEFP; break; case SAMPLEFORMAT.VOID: ap[0]=DATATYPE_VOID; break; } break; case TIFFTAG.SAMPLEFORMAT: ap[0]=td.td_sampleformat; break; case TIFFTAG.IMAGEDEPTH: ap[0]=td.td_imagedepth; break; case TIFFTAG.SUBIFD: ap[0]=td.td_nsubifd; ap[1]=td.td_subifd; break; case TIFFTAG.YCBCRPOSITIONING: ap[0]=td.td_ycbcrpositioning; break; case TIFFTAG.YCBCRSUBSAMPLING: ap[0]=td.td_ycbcrsubsampling[0]; ap[1]=td.td_ycbcrsubsampling[1]; break; case TIFFTAG.TRANSFERFUNCTION: ap[0]=td.td_transferfunction[0]; if(td.td_samplesperpixel-td.td_extrasamples>1) { ap[1]=td.td_transferfunction[1]; ap[2]=td.td_transferfunction[2]; } break; case TIFFTAG.REFERENCEBLACKWHITE: ap[0]=td.td_refblackwhite; break; case TIFFTAG.INKNAMES: ap[0]=td.td_inknames; break; default: { TIFFFieldInfo fip=TIFFFindFieldInfo(tif, tag, TIFFDataType.TIFF_ANY); // This can happen if multiple images are open with // different codecs which have private tags. The // global tag information table may then have tags // that are valid for one file but not the other. // If the client tries to get a tag that is not valid // for the image's codec then we'll arrive here. if(fip==null||fip.field_bit!=FIELD.CUSTOM) { TIFFErrorExt(tif.tif_clientdata, "_TIFFVGetField", "{0}: Invalid {1}tag \"{2}\" (not supported by codec)", tif.tif_name, isPseudoTag(tag)?"pseudo-":"", fip!=null?fip.field_name:"Unknown"); ret_val=false; break; } // Do we have a custom value? ret_val=false; for(int i=0; i<td.td_customValueCount; i++) { TIFFTagValue tv=td.td_customValues[i]; if(tv.info.field_tag!=tag) continue; if(fip.field_passcount) { ap[0]=(uint)tv.count; // Assume TIFF_VARIABLE ap[1]=tv.value; ret_val=true; } else { if(fip.field_type==TIFFDataType.TIFF_ASCII||fip.field_readcount==TIFF_VARIABLE||fip.field_readcount==TIFF_SPP) { ap[0]=tv.value; ret_val=true; } else { if(ap.Length<tv.count) break; // maybe Error or Warning? Array a=tv.value as Array; if(a==null) break; // maybe Error or Warning? for(int j=0; j<tv.count; j++) ap[j]=a.GetValue(j); ret_val=true; } } break; } // for } // default break; } return ret_val; }
// Return 1/0 according to whether or not // it is permissible to set the tag's value. // Note that we allow ImageLength to be changed // so that we can append and extend to images. // Any other tag may not be altered once writing // has commenced, unless its value has no effect // on the format of the data that is written. static bool OkToChangeTag(TIFF tif, TIFFTAG tag) { TIFFFieldInfo fip=TIFFFindFieldInfo(tif, tag, TIFFDataType.TIFF_ANY); if(fip==null) { // unknown tag TIFFErrorExt(tif.tif_clientdata, "TIFFSetField", "{0}: Unknown {1}tag {2}", tif.tif_name, isPseudoTag(tag)?"pseudo-":"", tag); return false; } if(tag!=TIFFTAG.IMAGELENGTH&&(tif.tif_flags&TIF_FLAGS.TIFF_BEENWRITING)!=0&&!fip.field_oktochange) { // Consult info table to see if tag can be changed // after we've started writing. We only allow changes // to those tags that don't/shouldn't affect the // compression and/or format of the data. TIFFErrorExt(tif.tif_clientdata, "TIFFSetField", "{0}: Cannot modify tag \"{1}\" while writing", tif.tif_name, fip.field_name); return false; } return true; }
public static bool TIFFVSetField(TIFF tif, TIFFTAG tag, TIFFDataType dt, object[] ap) { return OkToChangeTag(tif, tag)?tif.tif_tagmethods.vsetfield(tif, tag, dt, ap):false; }
// Like TIFFGetField, but taking a varargs // parameter list. This routine is useful // for building higher-level interfaces on // top of the library. public static bool TIFFVGetField(TIFF tif, TIFFTAG tag, object[] ap) { TIFFFieldInfo fip=TIFFFindFieldInfo(tif, tag, TIFFDataType.TIFF_ANY); return (fip!=null&&(isPseudoTag(tag)||TIFFFieldSet(tif, fip.field_bit))?tif.tif_tagmethods.vgetfield(tif, tag, ap):false); }
public static bool TIFFSetField(TIFF tif, TIFFTAG tag, TIFFDataType dt, params object[] ap) { return TIFFVSetField(tif, tag, dt, ap); }
// Print the contents of the current directory // to the specified stdio file stream. public static void TIFFPrintDirectory(TIFF tif, TextWriter fd, TIFFPRINT flags) { TIFFDirectory td = tif.tif_dir; fd.WriteLine("TIFF Directory at offset 0x{0:X} ({0})", tif.tif_diroff); if (TIFFFieldSet(tif, FIELD.SUBFILETYPE)) { fd.Write(" Subfile Type:"); string sep = " "; if ((td.td_subfiletype & FILETYPE.REDUCEDIMAGE) != 0) { fd.Write("{0}reduced-resolution image", sep); sep = "/"; } if ((td.td_subfiletype & FILETYPE.PAGE) != 0) { fd.Write("{0}multi-page document", sep); sep = "/"; } if ((td.td_subfiletype & FILETYPE.MASK) != 0) { fd.Write("{0}transparency mask", sep); } fd.WriteLine(" ({0} = 0x{0:X})", td.td_subfiletype); } if (TIFFFieldSet(tif, FIELD.IMAGEDIMENSIONS)) { fd.Write(" Image Width: {0} Image Length: {1}", td.td_imagewidth, td.td_imagelength); if (TIFFFieldSet(tif, FIELD.IMAGEDEPTH)) { fd.Write(" Image Depth: {0}", td.td_imagedepth); } fd.WriteLine(); } if (TIFFFieldSet(tif, FIELD.TILEDIMENSIONS)) { fd.Write(" Tile Width: {0} Tile Length: {1}", td.td_tilewidth, td.td_tilelength); if (TIFFFieldSet(tif, FIELD.TILEDEPTH)) { fd.Write(" Tile Depth: {0}", td.td_tiledepth); } fd.WriteLine(); } if (TIFFFieldSet(tif, FIELD.RESOLUTION)) { fd.Write(" Resolution: {0}, {1}", td.td_xresolution, td.td_yresolution); if (TIFFFieldSet(tif, FIELD.RESOLUTIONUNIT)) { switch (td.td_resolutionunit) { case RESUNIT.NONE: fd.Write(" (unitless)"); break; case RESUNIT.INCH: fd.Write(" pixels/inch"); break; case RESUNIT.CENTIMETER: fd.Write(" pixels/cm"); break; default: fd.Write(" (unit {0} = 0x{0:X})", td.td_resolutionunit); break; } } fd.WriteLine(); } if (TIFFFieldSet(tif, FIELD.POSITION)) { fd.WriteLine(" Position: {0}, {1}", td.td_xposition, td.td_yposition); } if (TIFFFieldSet(tif, FIELD.BITSPERSAMPLE)) { fd.WriteLine(" Bits/Sample: {0}", td.td_bitspersample); } if (TIFFFieldSet(tif, FIELD.SAMPLEFORMAT)) { fd.Write(" Sample Format: "); switch (td.td_sampleformat) { case SAMPLEFORMAT.VOID: fd.WriteLine("void"); break; case SAMPLEFORMAT.INT: fd.WriteLine("signed integer"); break; case SAMPLEFORMAT.UINT: fd.WriteLine("unsigned integer"); break; case SAMPLEFORMAT.IEEEFP: fd.WriteLine("IEEE floating point"); break; case SAMPLEFORMAT.COMPLEXINT: fd.WriteLine("complex signed integer"); break; case SAMPLEFORMAT.COMPLEXIEEEFP: fd.WriteLine("complex IEEE floating point"); break; default: fd.WriteLine("{0} (0x{0:X})", td.td_sampleformat); break; } } if (TIFFFieldSet(tif, FIELD.COMPRESSION)) { TIFFCodec c = TIFFFindCODEC(td.td_compression); fd.Write(" Compression Scheme: "); if (c != null) { fd.WriteLine(c.name); } else { fd.WriteLine("{0} (0x{0:X})", td.td_compression); } } if (TIFFFieldSet(tif, FIELD.PHOTOMETRIC)) { fd.Write(" Photometric Interpretation: "); if ((int)td.td_photometric < photoNames.Length) { fd.WriteLine(photoNames[(int)td.td_photometric]); } else { switch (td.td_photometric) { case PHOTOMETRIC.LOGL: fd.WriteLine("CIE Log2(L)"); break; case PHOTOMETRIC.LOGLUV: fd.WriteLine("CIE Log2(L) (u',v')"); break; default: fd.WriteLine("{0} (0x{0:X})", td.td_photometric); break; } } } if (TIFFFieldSet(tif, FIELD.EXTRASAMPLES) && td.td_extrasamples != 0) { fd.Write(" Extra Samples: {0}<", td.td_extrasamples); string sep = ""; for (int i = 0; i < td.td_extrasamples; i++) { switch ((EXTRASAMPLE)td.td_sampleinfo[i]) { case EXTRASAMPLE.UNSPECIFIED: fd.Write("{0}unspecified", sep); break; case EXTRASAMPLE.ASSOCALPHA: fd.Write("{0}assoc-alpha", sep); break; case EXTRASAMPLE.UNASSALPHA: fd.Write("{0}unassoc-alpha", sep); break; default: fd.Write("{0}{1} (0x{1:X})", sep, td.td_sampleinfo[i]); break; } sep = ", "; } fd.WriteLine(">"); } if (TIFFFieldSet(tif, FIELD.INKNAMES)) { string[] names = td.td_inknames.Split('\0'); fd.Write(" Ink Names: "); string sep = ""; for (int i = 0; i < td.td_samplesperpixel && i < names.Length; i++) { fd.Write(sep); TIFFprintAscii(fd, names[i]); sep = ", "; } fd.WriteLine(); } if (TIFFFieldSet(tif, FIELD.THRESHHOLDING)) { fd.Write(" Thresholding: "); switch (td.td_threshholding) { case THRESHHOLD.BILEVEL: fd.WriteLine("bilevel art scan"); break; case THRESHHOLD.HALFTONE: fd.WriteLine("halftone or dithered scan"); break; case THRESHHOLD.ERRORDIFFUSE: fd.WriteLine("error diffused"); break; default: fd.WriteLine("{0} (0x{0:X})", td.td_threshholding); break; } } if (TIFFFieldSet(tif, FIELD.FILLORDER)) { fd.Write(" FillOrder: "); switch (td.td_fillorder) { case FILLORDER.MSB2LSB: fd.WriteLine("msb-to-lsb"); break; case FILLORDER.LSB2MSB: fd.WriteLine("lsb-to-msb"); break; default: fd.WriteLine("{0} (0x{0:X})", td.td_fillorder); break; } } if (TIFFFieldSet(tif, FIELD.YCBCRSUBSAMPLING)) { // For hacky reasons (see tif_jpeg.cs - JPEGFixupTestSubsampling), // we need to fetch this rather than trust what is in our structures. object[] ap = new object[2]; TIFFGetField(tif, TIFFTAG.YCBCRSUBSAMPLING, ap); fd.WriteLine(" YCbCr Subsampling: {0}, {1}", __GetAsUshort(ap, 0), __GetAsUshort(ap, 1)); } if (TIFFFieldSet(tif, FIELD.YCBCRPOSITIONING)) { fd.Write(" YCbCr Positioning: "); switch (td.td_ycbcrpositioning) { case YCBCRPOSITION.CENTERED: fd.WriteLine("centered"); break; case YCBCRPOSITION.COSITED: fd.WriteLine("cosited"); break; default: fd.WriteLine("{0} (0x{0:X})", td.td_ycbcrpositioning); break; } } if (TIFFFieldSet(tif, FIELD.HALFTONEHINTS)) { fd.WriteLine(" Halftone Hints: light {0} dark {1}", td.td_halftonehints[0], td.td_halftonehints[1]); } if (TIFFFieldSet(tif, FIELD.ORIENTATION)) { fd.Write(" Orientation: "); if ((int)td.td_orientation < orientNames.Length) { fd.WriteLine(orientNames[(int)td.td_orientation]); } else { fd.WriteLine("{0} (0x{0:X})", td.td_orientation); } } if (TIFFFieldSet(tif, FIELD.SAMPLESPERPIXEL)) { fd.WriteLine(" Samples/Pixel: {0}", td.td_samplesperpixel); } if (TIFFFieldSet(tif, FIELD.ROWSPERSTRIP)) { fd.Write(" Rows/Strip: "); if (td.td_rowsperstrip == uint.MaxValue) { fd.WriteLine("(infinite)"); } else { fd.WriteLine(td.td_rowsperstrip); } } if (TIFFFieldSet(tif, FIELD.MINSAMPLEVALUE)) { fd.WriteLine(" Min Sample Value: {0}", td.td_minsamplevalue); } if (TIFFFieldSet(tif, FIELD.MAXSAMPLEVALUE)) { fd.WriteLine(" Max Sample Value: {0}", td.td_maxsamplevalue); } if (TIFFFieldSet(tif, FIELD.SMINSAMPLEVALUE)) { fd.WriteLine(" SMin Sample Value: {0}", td.td_sminsamplevalue); } if (TIFFFieldSet(tif, FIELD.SMAXSAMPLEVALUE)) { fd.WriteLine(" SMax Sample Value: {0}", td.td_smaxsamplevalue); } if (TIFFFieldSet(tif, FIELD.PLANARCONFIG)) { fd.Write(" Planar Configuration: "); switch (td.td_planarconfig) { case PLANARCONFIG.CONTIG: fd.WriteLine("single image plane"); break; case PLANARCONFIG.SEPARATE: fd.WriteLine("separate image planes"); break; default: fd.WriteLine("{0} (0x{0:X})", td.td_planarconfig); break; } } if (TIFFFieldSet(tif, FIELD.PAGENUMBER)) { fd.WriteLine(" Page Number: {0}-{1}", td.td_pagenumber[0], td.td_pagenumber[1]); } if (TIFFFieldSet(tif, FIELD.COLORMAP)) { fd.Write(" Color Map: "); if ((flags & TIFFPRINT.COLORMAP) != 0) { fd.WriteLine(); uint n = 1u << td.td_bitspersample; for (uint l = 0; l < n; l++) { fd.WriteLine("\t{0}: {1} {2} {3}", l, td.td_colormap[0][l], td.td_colormap[1][l], td.td_colormap[2][l]); } } else { fd.WriteLine("(present)"); } } if (TIFFFieldSet(tif, FIELD.TRANSFERFUNCTION)) { fd.Write(" Transfer Function: "); if ((flags & TIFFPRINT.CURVES) != 0) { fd.WriteLine(); uint n = 1u << td.td_bitspersample; for (uint l = 0; l < n; l++) { fd.Write("\t{0}: {1}", l, td.td_transferfunction[0][l]); for (int i = 1; i < td.td_samplesperpixel; i++) { fd.Write(" {0}", td.td_transferfunction[i][l]); } fd.WriteLine(); } } else { fd.WriteLine("(present)"); } } if (TIFFFieldSet(tif, FIELD.SUBIFD) && td.td_subifd != null && td.td_subifd.Length != 0) { fd.Write(" SubIFD Offsets:"); for (int i = 0; i < td.td_nsubifd; i++) { fd.Write(" {0}", td.td_subifd[i]); } fd.WriteLine(); } // Custom tag support. short count = (short)TIFFGetTagListCount(tif); for (int i = 0; i < count; i++) { TIFFTAG tag = TIFFGetTagListEntry(tif, i); TIFFFieldInfo fip = TIFFFieldWithTag(tif, tag); if (fip == null) { continue; } uint value_count; object raw_data = null; if (fip.field_passcount) { object[] ap = new object[2]; if (!TIFFGetField(tif, tag, ap)) { continue; } value_count = __GetAsUshort(ap, 0); raw_data = ap[1]; } else { if (fip.field_readcount == TIFF_VARIABLE) { value_count = 1; } else if (fip.field_readcount == TIFF_SPP) { value_count = td.td_samplesperpixel; } else { value_count = (ushort)fip.field_readcount; } if (fip.field_type == TIFFDataType.TIFF_ASCII || fip.field_readcount == TIFF_VARIABLE || fip.field_readcount == TIFF_SPP || value_count > 1) { object[] ap = new object[2]; if (!TIFFGetField(tif, tag, ap)) { continue; } raw_data = ap[0]; } else { object[] ap = new object[value_count]; if (!TIFFGetField(tif, tag, ap)) { continue; } switch (fip.field_type) { case TIFFDataType.TIFF_UNDEFINED: case TIFFDataType.TIFF_BYTE: { byte[] raw_data1 = new byte[value_count]; for (int a = 0; a < value_count; a++) { raw_data1[a] = __GetAsByte(ap, a); } raw_data = raw_data1; } break; case TIFFDataType.TIFF_DOUBLE: case TIFFDataType.TIFF_RATIONAL: case TIFFDataType.TIFF_SRATIONAL: { double[] raw_data1 = new double[value_count]; for (int a = 0; a < value_count; a++) { raw_data1[a] = __GetAsDouble(ap, a); } raw_data = raw_data1; } break; case TIFFDataType.TIFF_SBYTE: { sbyte[] raw_data1 = new sbyte[value_count]; for (int a = 0; a < value_count; a++) { raw_data1[a] = __GetAsSbyte(ap, a); } raw_data = raw_data1; } break; case TIFFDataType.TIFF_SHORT: { ushort[] raw_data1 = new ushort[value_count]; for (int a = 0; a < value_count; a++) { raw_data1[a] = __GetAsUshort(ap, a); } raw_data = raw_data1; } break; case TIFFDataType.TIFF_SSHORT: { short[] raw_data1 = new short[value_count]; for (int a = 0; a < value_count; a++) { raw_data1[a] = __GetAsShort(ap, a); } raw_data = raw_data1; } break; case TIFFDataType.TIFF_IFD: case TIFFDataType.TIFF_LONG: { uint[] raw_data1 = new uint[value_count]; for (int a = 0; a < value_count; a++) { raw_data1[a] = __GetAsUint(ap, a); } raw_data = raw_data1; } break; case TIFFDataType.TIFF_SLONG: { int[] raw_data1 = new int[value_count]; for (int a = 0; a < value_count; a++) { raw_data1[a] = __GetAsInt(ap, a); } raw_data = raw_data1; } break; case TIFFDataType.TIFF_FLOAT: { float[] raw_data1 = new float[value_count]; for (int a = 0; a < value_count; a++) { raw_data1[a] = __GetAsFloat(ap, a); } raw_data = raw_data1; } break; } } } // Catch the tags which needs to be specially handled and // pretty print them. If tag not handled in // _TIFFPrettyPrintField() fall down and print it as any other tag. if (TIFFPrettyPrintField(tif, fd, tag, value_count, raw_data)) { continue; } else { TIFFPrintField(fd, fip, value_count, raw_data); } } if (tif.tif_tagmethods.printdir != null) { tif.tif_tagmethods.printdir(tif, fd, flags); } if ((flags & TIFFPRINT.STRIPS) != 0 && TIFFFieldSet(tif, FIELD.STRIPOFFSETS)) { fd.WriteLine(" {0} {1}:", td.td_nstrips, isTiled(tif)?"Tiles":"Strips"); for (uint s = 0; s < td.td_nstrips; s++) { fd.WriteLine("\t{0}: [{1}, {2}]", s, td.td_stripoffset[s], td.td_stripbytecount[s]); } } }
static bool TIFFPrettyPrintField(TIFF tif, TextWriter fd, TIFFTAG tag, uint value_count, object raw_data) { TIFFDirectory td = tif.tif_dir; switch (tag) { case TIFFTAG.INKSET: fd.Write(" Ink Set: "); switch ((INKSET)((ushort[])raw_data)[0]) { case INKSET.CMYK: fd.WriteLine("CMYK"); break; default: fd.WriteLine("{0} (0x{0:X})", ((ushort[])raw_data)[0]); break; } return(true); case TIFFTAG.DOTRANGE: fd.WriteLine(" Dot Range: {0}-{1}", ((ushort[])raw_data)[0], ((ushort[])raw_data)[1]); return(true); case TIFFTAG.WHITEPOINT: fd.WriteLine(" White Point: {0}-{1}", ((double[])raw_data)[0], ((double[])raw_data)[1]); return(true); case TIFFTAG.REFERENCEBLACKWHITE: fd.WriteLine(" Reference Black/White:"); for (ushort i = 0; i < 3; i++) { fd.WriteLine("\t{0}: {1} {2}", i, ((double[])raw_data)[2 * i + 0], ((double[])raw_data)[2 * i + 1]); } return(true); case TIFFTAG.XMLPACKET: fd.WriteLine(" XMLPacket (XMP Metadata):"); for (uint i = 0; i < value_count; i++) { fd.Write((char)((byte[])raw_data)[i]); } fd.WriteLine(); return(true); case TIFFTAG.RICHTIFFIPTC: // XXX: for some weird reason RichTIFFIPTC tag // defined as array of LONG values. fd.WriteLine(" RichTIFFIPTC Data: <present>, {0} bytes", value_count * 4); return(true); case TIFFTAG.PHOTOSHOP: fd.WriteLine(" Photoshop Data: <present>, {0} bytes", value_count); return(true); case TIFFTAG.ICCPROFILE: fd.WriteLine(" ICC Profile: <present>, {0} bytes", value_count); return(true); case TIFFTAG.STONITS: fd.WriteLine(" Sample to Nits conversion factor: {0}", ((double[])raw_data)[0]); return(true); } return(false); }
static bool ZIPVSetField(TIFF tif, TIFFTAG tag, TIFFDataType dt, object[] ap) { ZIPState sp=tif.tif_data as ZIPState; string module="ZIPVSetField"; switch(tag) { case TIFFTAG.ZIPQUALITY: sp.zipquality=__GetAsInt(ap, 0); if((sp.state&ZSTATE.INIT_ENCODE)==ZSTATE.INIT_ENCODE) { if(zlib.deflateParams(sp.stream, sp.zipquality, zlib.Z_DEFAULT_STRATEGY)!=zlib.Z_OK) { TIFFErrorExt(tif.tif_clientdata, module, "{0}: zlib error: {1}", tif.tif_name, sp.stream.msg); return false; } } return true; default: return sp.vsetparent(tif, tag, dt, ap); } //NOTREACHED }
static bool ZIPVGetField(TIFF tif, TIFFTAG tag, object[] ap) { ZIPState sp=tif.tif_data as ZIPState; switch(tag) { case TIFFTAG.ZIPQUALITY: ap[0]=sp.zipquality; break; default: return sp.vgetparent(tif, tag, ap); } return true; }
// Write an array of "type" values for a specified tag (i.e. this is a tag // which is allowed to have different types, e.g. SMaxSampleType). // Internally the data values are represented as double since a double can // hold any of the TIFF tag types (yes, this should really be an abstract // type tany_t for portability). The data is converted into the specified // type in a temporary buffer and then handed off to the appropriate array // writer. static bool TIFFWriteAnyArray(TIFF tif, TIFFDataType type, TIFFTAG tag, TIFFDirEntry dir, uint n, double[] v) { dir.tdir_tag=(ushort)tag; dir.tdir_type=(ushort)type; dir.tdir_count=n; switch(type) { case TIFFDataType.TIFF_BYTE: { byte[] bp=null; try { bp=new byte[n]; } catch { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to write array"); return false; } for(uint i=0; i<n; i++) bp[i]=(byte)v[i]; return TIFFWriteByteArray(tif, dir, bp); } case TIFFDataType.TIFF_SBYTE: { sbyte[] bp=null; try { bp=new sbyte[n]; } catch { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to write array"); return false; } for(uint i=0; i<n; i++) bp[i]=(sbyte)v[i]; return TIFFWriteByteArray(tif, dir, bp); } case TIFFDataType.TIFF_SHORT: { ushort[] bp=null; try { bp=new ushort[n]; } catch { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to write array"); return false; } for(uint i=0; i<n; i++) bp[i]=(ushort)v[i]; return TIFFWriteShortArray(tif, dir, bp); } case TIFFDataType.TIFF_SSHORT: { short[] bp=null; try { bp=new short[n]; } catch { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to write array"); return false; } for(uint i=0; i<n; i++) bp[i]=(short)v[i]; return TIFFWriteShortArray(tif, dir, bp); } case TIFFDataType.TIFF_LONG: { uint[] bp=null; try { bp=new uint[n]; } catch { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to write array"); return false; } for(uint i=0; i<n; i++) bp[i]=(uint)v[i]; return TIFFWriteLongArray(tif, dir, bp); } case TIFFDataType.TIFF_SLONG: { int[] bp=null; try { bp=new int[n]; } catch { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to write array"); return false; } for(uint i=0; i<n; i++) bp[i]=(int)v[i]; return TIFFWriteLongArray(tif, dir, bp); } case TIFFDataType.TIFF_FLOAT: { float[] bp=null; try { bp=new float[n]; } catch { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to write array"); return false; } for(uint i=0; i<n; i++) bp[i]=(float)v[i]; return TIFFWriteFloatArray(tif, dir, bp); } case TIFFDataType.TIFF_DOUBLE: return TIFFWriteDoubleArray(tif, dir, v); default: // TIFF_NOTYPE // TIFF_ASCII // TIFF_UNDEFINED // TIFF_RATIONAL // TIFF_SRATIONAL return false; } }
// Setup a pair of shorts that are returned by // value, rather than as a reference to an array. static bool TIFFSetupShortPair(TIFF tif, TIFFTAG tag, TIFFDirEntry dir) { ushort[] v=null; object[] ap=null; try { v=new ushort[2]; ap=new object[2]; } catch { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to write per-sample shorts"); return false; } TIFFGetField(tif, tag, ap); v[0]=__GetAsUshort(ap, 0); v[1]=__GetAsUshort(ap, 1); dir.tdir_tag=(ushort)tag; dir.tdir_type=(ushort)TIFFDataType.TIFF_SHORT; dir.tdir_count=2; return TIFFWriteShortArray(tif, dir, v); }
// Setup a directory entry with either a SHORT // or LONG type according to the value. static void TIFFSetupShortLong(TIFF tif, TIFFTAG tag, TIFFDirEntry dir, uint v) { dir.tdir_tag=(ushort)tag; dir.tdir_count=1; if(v>0xffff) { dir.tdir_type=(ushort)TIFFDataType.TIFF_LONG; dir.tdir_offset=v; } else { dir.tdir_type=(ushort)TIFFDataType.TIFF_SHORT; //was dir.tdir_offset=TIFFInsertData(tif, (int) TIFF_SHORT, v); dir.tdir_offset=(uint)(tif.tif_header.tiff_magic==TIFF_BIGENDIAN?(v&tif_typemask[(int)TIFFDataType.TIFF_SHORT])<<tif_typeshift[(int)TIFFDataType.TIFF_SHORT]:v&tif_typemask[(int)TIFFDataType.TIFF_SHORT]); } }
// Setup a directory entry for an NxM table of shorts, // where M is known to be 2**bitspersample, and write // the associated indirect data. static bool TIFFWriteShortTable(TIFF tif, TIFFTAG tag, TIFFDirEntry dir, uint n, ushort[][] table) { dir.tdir_tag=(ushort)tag; dir.tdir_type=(ushort)TIFFDataType.TIFF_SHORT; // XXX -- yech, fool TIFFWriteData dir.tdir_count=(uint)(1<<tif.tif_dir.td_bitspersample); uint off=tif.tif_dataoff; byte[] buf=new byte[dir.tdir_count*2]; for(uint i=0; i<n; i++) { for(int a=0; a<dir.tdir_count; a++) BitConverter.GetBytes(table[i][a]).CopyTo(buf, a*2); if(!TIFFWriteData(tif, dir, buf)) return false; } dir.tdir_count*=n; dir.tdir_offset=off; return true; }
static bool _TIFFVSetField(TIFF tif, TIFFTAG tag, TIFFDataType dt, object[] ap) { string module="_TIFFVSetField"; TIFFDirectory td=tif.tif_dir; bool status=true; uint v; switch(tag) { case TIFFTAG.SUBFILETYPE: td.td_subfiletype=(FILETYPE)__GetAsUint(ap, 0); break; case TIFFTAG.IMAGEWIDTH: td.td_imagewidth=__GetAsUint(ap, 0); break; case TIFFTAG.IMAGELENGTH: td.td_imagelength=__GetAsUint(ap, 0); break; case TIFFTAG.BITSPERSAMPLE: td.td_bitspersample=__GetAsUshort(ap, 0); // If the data require post-decoding processing to byte-swap // samples, set it up here. Note that since tags are required // to be ordered, compression code can override this behaviour // in the setup method if it wants to roll the post decoding // work in with its normal work. if((tif.tif_flags&TIF_FLAGS.TIFF_SWAB)!=0) { if(td.td_bitspersample==16) tif.tif_postdecode=TIFFSwab16BitData; else if(td.td_bitspersample==24) tif.tif_postdecode=TIFFSwab24BitData; else if(td.td_bitspersample==32) tif.tif_postdecode=TIFFSwab32BitData; else if(td.td_bitspersample==64) tif.tif_postdecode=TIFFSwab64BitData; else if(td.td_bitspersample==128) tif.tif_postdecode=TIFFSwab64BitData; // two 64's } break; case TIFFTAG.COMPRESSION: v=__GetAsUint(ap, 0)&0xffff; // If we're changing the compression scheme, the notify the // previous module so that it can cleanup any state it's setup. if(TIFFFieldSet(tif, FIELD.COMPRESSION)) { if(td.td_compression==(COMPRESSION)v) break; tif.tif_cleanup(tif); tif.tif_flags&=~TIF_FLAGS.TIFF_CODERSETUP; } // Setup new compression routine state. if(status=TIFFSetCompressionScheme(tif, (COMPRESSION)v)) td.td_compression=(COMPRESSION)v; else status=false; break; case TIFFTAG.PHOTOMETRIC: td.td_photometric=(PHOTOMETRIC)__GetAsUshort(ap, 0); break; case TIFFTAG.THRESHHOLDING: td.td_threshholding=(THRESHHOLD)__GetAsUshort(ap, 0); break; case TIFFTAG.FILLORDER: v=__GetAsUint(ap, 0); if((FILLORDER)v!=FILLORDER.LSB2MSB&&(FILLORDER)v!=FILLORDER.MSB2LSB) goto badvalue; td.td_fillorder=(FILLORDER)v; break; case TIFFTAG.ORIENTATION: v=__GetAsUint(ap, 0); if((ORIENTATION)v<ORIENTATION.TOPLEFT||ORIENTATION.LEFTBOT<(ORIENTATION)v) goto badvalue; td.td_orientation=(ORIENTATION)v; break; case TIFFTAG.SAMPLESPERPIXEL: // XXX should cross check -- e.g. if pallette, then 1 v=__GetAsUint(ap, 0); if(v==0) goto badvalue; td.td_samplesperpixel=(ushort)v; break; case TIFFTAG.ROWSPERSTRIP: v=__GetAsUint(ap, 0); if(v==0) goto badvalue; td.td_rowsperstrip=v; if(!TIFFFieldSet(tif, FIELD.TILEDIMENSIONS)) { td.td_tilelength=v; td.td_tilewidth=td.td_imagewidth; } break; case TIFFTAG.MINSAMPLEVALUE: td.td_minsamplevalue=__GetAsUshort(ap, 0); break; case TIFFTAG.MAXSAMPLEVALUE: td.td_maxsamplevalue=__GetAsUshort(ap, 0); break; case TIFFTAG.SMINSAMPLEVALUE: td.td_sminsamplevalue=__GetAsDouble(ap, 0); break; case TIFFTAG.SMAXSAMPLEVALUE: td.td_smaxsamplevalue=__GetAsDouble(ap, 0); break; case TIFFTAG.XRESOLUTION: td.td_xresolution=__GetAsDouble(ap, 0); break; case TIFFTAG.YRESOLUTION: td.td_yresolution=__GetAsDouble(ap, 0); break; case TIFFTAG.PLANARCONFIG: v=__GetAsUint(ap, 0); if((PLANARCONFIG)v!=PLANARCONFIG.CONTIG&&(PLANARCONFIG)v!=PLANARCONFIG.SEPARATE) goto badvalue; td.td_planarconfig=(PLANARCONFIG)v; break; case TIFFTAG.XPOSITION: td.td_xposition=__GetAsDouble(ap, 0); break; case TIFFTAG.YPOSITION: td.td_yposition=__GetAsDouble(ap, 0); break; case TIFFTAG.RESOLUTIONUNIT: v=__GetAsUint(ap, 0); if((RESUNIT)v<RESUNIT.NONE||RESUNIT.CENTIMETER<(RESUNIT)v) goto badvalue; td.td_resolutionunit=(RESUNIT)v; break; case TIFFTAG.PAGENUMBER: td.td_pagenumber[0]=__GetAsUshort(ap, 0); td.td_pagenumber[1]=__GetAsUshort(ap, 1); break; case TIFFTAG.HALFTONEHINTS: td.td_halftonehints[0]=__GetAsUshort(ap, 0); td.td_halftonehints[1]=__GetAsUshort(ap, 1); break; case TIFFTAG.COLORMAP: v=1u<<td.td_bitspersample; TIFFsetShortArray(ref td.td_colormap[0], (ushort[])ap[0], v); TIFFsetShortArray(ref td.td_colormap[1], (ushort[])ap[1], v); TIFFsetShortArray(ref td.td_colormap[2], (ushort[])ap[2], v); break; case TIFFTAG.EXTRASAMPLES: if(!setExtraSamples(td, ap, out v)) goto badvalue; break; case TIFFTAG.MATTEING: td.td_extrasamples=(ushort)((__GetAsInt(ap, 0)!=0)?1:0); if(td.td_extrasamples!=0) { ushort[] sv=new ushort[] { (ushort)EXTRASAMPLE.ASSOCALPHA }; TIFFsetShortArray(ref td.td_sampleinfo, sv, 1); } break; case TIFFTAG.TILEWIDTH: v=__GetAsUint(ap, 0); if((v%16)!=0) { if(tif.tif_mode!=O.RDONLY) goto badvalue; TIFFWarningExt(tif.tif_clientdata, tif.tif_name, "Nonstandard tile width {0}, convert file", v); } td.td_tilewidth=v; tif.tif_flags|=TIF_FLAGS.TIFF_ISTILED; break; case TIFFTAG.TILELENGTH: v=__GetAsUint(ap, 0); if((v%16)!=0) { if(tif.tif_mode!=O.RDONLY) goto badvalue; TIFFWarningExt(tif.tif_clientdata, tif.tif_name, "Nonstandard tile length {0}, convert file", v); } td.td_tilelength=v; tif.tif_flags|=TIF_FLAGS.TIFF_ISTILED; break; case TIFFTAG.TILEDEPTH: v=__GetAsUint(ap, 0); if(v==0) goto badvalue; td.td_tiledepth=v; break; case TIFFTAG.DATATYPE: v=__GetAsUint(ap, 0); switch(v) { case DATATYPE_VOID: td.td_sampleformat=SAMPLEFORMAT.VOID; break; case DATATYPE_INT: td.td_sampleformat=SAMPLEFORMAT.INT; break; case DATATYPE_UINT: td.td_sampleformat=SAMPLEFORMAT.UINT; break; case DATATYPE_IEEEFP: td.td_sampleformat=SAMPLEFORMAT.IEEEFP; break; default: goto badvalue; } break; case TIFFTAG.SAMPLEFORMAT: v=__GetAsUint(ap, 0); if((SAMPLEFORMAT)v<SAMPLEFORMAT.UINT||SAMPLEFORMAT.COMPLEXIEEEFP<(SAMPLEFORMAT)v) goto badvalue; td.td_sampleformat=(SAMPLEFORMAT)v; // Try to fix up the SWAB function for complex data. if(td.td_sampleformat==SAMPLEFORMAT.COMPLEXINT&&td.td_bitspersample==32&&tif.tif_postdecode==TIFFSwab32BitData) tif.tif_postdecode=TIFFSwab16BitData; else if((td.td_sampleformat==SAMPLEFORMAT.COMPLEXINT||td.td_sampleformat==SAMPLEFORMAT.COMPLEXIEEEFP)&&td.td_bitspersample==64&& tif.tif_postdecode==TIFFSwab64BitData) tif.tif_postdecode=TIFFSwab32BitData; break; case TIFFTAG.IMAGEDEPTH: td.td_imagedepth=__GetAsUint(ap, 0); break; case TIFFTAG.SUBIFD: if((tif.tif_flags&TIF_FLAGS.TIFF_INSUBIFD)==0) { td.td_nsubifd=__GetAsUshort(ap, 0); uint[] tmp=new uint[1]; tmp[0]=(uint)ap[1]; TIFFsetLongArray(ref td.td_subifd, tmp, td.td_nsubifd); } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Sorry, cannot nest SubIFDs", tif.tif_name); status=false; } break; case TIFFTAG.YCBCRPOSITIONING: td.td_ycbcrpositioning=(YCBCRPOSITION)__GetAsUshort(ap, 0); break; case TIFFTAG.YCBCRSUBSAMPLING: td.td_ycbcrsubsampling[0]=__GetAsUshort(ap, 0); td.td_ycbcrsubsampling[1]=__GetAsUshort(ap, 1); break; case TIFFTAG.TRANSFERFUNCTION: v=(uint)((td.td_samplesperpixel-td.td_extrasamples)>1?3:1); for(int i=0; i<v; i++) TIFFsetShortArray(ref td.td_transferfunction[i], (ushort[])ap[i], 1u<<td.td_bitspersample); break; case TIFFTAG.REFERENCEBLACKWHITE: // XXX should check for null range TIFFsetDoubleArray(ref td.td_refblackwhite, (double[])ap[0], 6); break; case TIFFTAG.INKNAMES: v=__GetAsUint(ap, 0); string s=(string)ap[1]; v=checkInkNamesString(tif, v, s); status=v>0; if(v>0) { td.td_inknames=s.Substring(0, (int)v); td.td_inknameslen=(int)v; } break; default: { TIFFFieldInfo fip=TIFFFindFieldInfo(tif, tag, dt); // was TIFFDataType.TIFF_ANY); TIFFTagValue tv; int iCustom; // This can happen if multiple images are open with different // codecs which have private tags. The global tag information // table may then have tags that are valid for one file but not // the other. If the client tries to set a tag that is not valid // for the image's codec then we'll arrive here. This // happens, for example, when tiffcp is used to convert between // compression schemes and codec-specific tags are blindly copied. if(fip==null||fip.field_bit!=FIELD.CUSTOM) { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Invalid {1}tag \"{2}\" (not supported by codec)", tif.tif_name, isPseudoTag(tag)?"pseudo-":"", fip!=null?fip.field_name:"Unknown"); status=false; break; } // Find the existing entry for this custom value. tv=null; for(iCustom=0; iCustom<td.td_customValueCount; iCustom++) { if(td.td_customValues[iCustom].info.field_tag==tag) { tv=td.td_customValues[iCustom]; tv.value=null; break; } } // Grow the custom list if the entry was not found. if(tv==null) { try { td.td_customValueCount++; if(td.td_customValues==null) td.td_customValues=new List<TIFFTagValue>(); tv=new TIFFTagValue(); tv.info=fip; td.td_customValues.Add(tv); } catch { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Failed to allocate space for list of custom values", tif.tif_name); status=false; goto end; } } // Set custom value ... save a copy of the custom tag value. if(TIFFDataSize(fip.field_type)==0) { status=false; TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad field type {1} for \"{2}\"", tif.tif_name, fip.field_type, fip.field_name); goto end; } int apcount=0; if(fip.field_passcount) tv.count=__GetAsInt(ap, apcount++); else if(fip.field_writecount==TIFF_VARIABLE) tv.count=1; else if(fip.field_writecount==TIFF_SPP) tv.count=td.td_samplesperpixel; else tv.count=fip.field_writecount; if(fip.field_type==TIFFDataType.TIFF_ASCII) tv.value=(string)ap[apcount++]; else { if(tv.count<1) { status=false; goto end; } byte[] byteArray=null; sbyte[] sbyteArray=null; ushort[] ushortArray=null; short[] shortArray=null; uint[] uintArray=null; int[] intArray=null; float[] floatArray=null; double[] doubleArray=null; try { switch(fip.field_type) { case TIFFDataType.TIFF_UNDEFINED: case TIFFDataType.TIFF_BYTE: tv.value=byteArray=new byte[tv.count]; break; case TIFFDataType.TIFF_SBYTE: tv.value=sbyteArray=new sbyte[tv.count]; break; case TIFFDataType.TIFF_SHORT: tv.value=ushortArray=new ushort[tv.count]; break; case TIFFDataType.TIFF_SSHORT: tv.value=shortArray=new short[tv.count]; break; case TIFFDataType.TIFF_IFD: case TIFFDataType.TIFF_LONG: tv.value=uintArray=new uint[tv.count]; break; case TIFFDataType.TIFF_SLONG: tv.value=intArray=new int[tv.count]; break; case TIFFDataType.TIFF_FLOAT: tv.value=floatArray=new float[tv.count]; break; case TIFFDataType.TIFF_RATIONAL: case TIFFDataType.TIFF_SRATIONAL: case TIFFDataType.TIFF_DOUBLE: tv.value=doubleArray=new double[tv.count]; break; default: tv.value=null; break; } } catch { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Out of memory.", tif.tif_name); status=false; goto end; } bool done=false; if((fip.field_passcount||fip.field_writecount==TIFF_VARIABLE||fip.field_writecount==TIFF_SPP)) { Array a=ap[apcount] as Array; if(a!=null&&a.Length>=tv.count) { switch(fip.field_type) { case TIFFDataType.TIFF_UNDEFINED: case TIFFDataType.TIFF_BYTE: if(a is byte[]) { Array.Copy(a, byteArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a byte[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_SBYTE: if(a is sbyte[]) { Array.Copy(a, sbyteArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a sbyte[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_SHORT: if(a is ushort[]) { Array.Copy(a, ushortArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a ushort[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_SSHORT: if(a is short[]) { Array.Copy(a, shortArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a short[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_IFD: case TIFFDataType.TIFF_LONG: if(a is uint[]) { Array.Copy(a, uintArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a ulong[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_SLONG: if(a is int[]) { Array.Copy(a, intArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a long[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_FLOAT: if(a is float[]) { Array.Copy(a, floatArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a float[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_RATIONAL: case TIFFDataType.TIFF_SRATIONAL: case TIFFDataType.TIFF_DOUBLE: if(a is double[]) { Array.Copy(a, doubleArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a double[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; default: tv.value=null; break; } // switch } // if(a!=null&&a.Length>=tv.count) else if(a!=null) { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Array has too few elements.", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } } if(!done) { try { Array a=ap[apcount] as Array; if(a!=null&&a.Length>=tv.count) { switch(fip.field_type) { case TIFFDataType.TIFF_UNDEFINED: case TIFFDataType.TIFF_BYTE: if(a is byte[]) { Array.Copy(a, byteArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a byte[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_SBYTE: if(a is sbyte[]) { Array.Copy(a, sbyteArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a sbyte[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_SHORT: if(a is ushort[]) { Array.Copy(a, ushortArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a ushort[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_SSHORT: if(a is short[]) { Array.Copy(a, shortArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a short[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_IFD: case TIFFDataType.TIFF_LONG: if(a is uint[]) { Array.Copy(a, uintArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a ulong[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_SLONG: if(a is int[]) { Array.Copy(a, intArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a long[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_FLOAT: if(a is float[]) { Array.Copy(a, floatArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a float[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; case TIFFDataType.TIFF_RATIONAL: case TIFFDataType.TIFF_SRATIONAL: case TIFFDataType.TIFF_DOUBLE: if(a is double[]) { Array.Copy(a, doubleArray, tv.count); done=true; } else { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument type for \"{2}\" ({1}). Should be a double[].", tif.tif_name, fip.field_type, fip.field_name); status=false; goto end; } break; default: tv.value=null; break; } // switch } else { switch(fip.field_type) { case TIFFDataType.TIFF_UNDEFINED: case TIFFDataType.TIFF_BYTE: for(int i=0; i<tv.count; i++) byteArray[i]=__GetAsByte(ap, apcount++); break; case TIFFDataType.TIFF_SBYTE: for(int i=0; i<tv.count; i++) sbyteArray[i]=__GetAsSbyte(ap, apcount++); break; case TIFFDataType.TIFF_SHORT: for(int i=0; i<tv.count; i++) ushortArray[i]=__GetAsUshort(ap, apcount++); break; case TIFFDataType.TIFF_SSHORT: for(int i=0; i<tv.count; i++) shortArray[i]=__GetAsShort(ap, apcount++); break; case TIFFDataType.TIFF_IFD: case TIFFDataType.TIFF_LONG: for(int i=0; i<tv.count; i++) uintArray[i]=__GetAsUint(ap, apcount++); break; case TIFFDataType.TIFF_SLONG: for(int i=0; i<tv.count; i++) intArray[i]=__GetAsInt(ap, apcount++); break; case TIFFDataType.TIFF_FLOAT: for(int i=0; i<tv.count; i++) floatArray[i]=__GetAsFloat(ap, apcount++); break; case TIFFDataType.TIFF_RATIONAL: case TIFFDataType.TIFF_SRATIONAL: case TIFFDataType.TIFF_DOUBLE: for(int i=0; i<tv.count; i++) doubleArray[i]=__GetAsDouble(ap, apcount++); break; } } } catch { TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad argument({3}) type for \"{2}\" ({1}). Should be an Array anyway!", tif.tif_name, fip.field_type, fip.field_name, apcount); status=false; goto end; } } // if(!done) } // fip.field_type!=TIFFDataType.TIFF_ASCII } // default: break; } // switch() if(status) { TIFFSetFieldBit(tif, TIFFFieldWithTag(tif, tag).field_bit); tif.tif_flags|=TIF_FLAGS.TIFF_DIRTYDIRECT; } end: return status; badvalue: TIFFErrorExt(tif.tif_clientdata, module, "{0}: Bad value {1} for \"{2}\" tag", tif.tif_name, v, TIFFFieldWithTag(tif, tag).field_name); return false; }
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 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)); }
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; }
/// <summary> /// Get .NET 'Bitmap' object from memory DIB via stream constructor. /// This should work for most DIBs. /// </summary> /// <param name="a_platform">Our operating system</param> /// <param name="a_intptrNative">The pointer to something (presumably a BITMAP or a TIFF image)</param> /// <returns>C# Bitmap of image</returns> private Bitmap NativeToBitmap(Platform a_platform, IntPtr a_intptrNative) { ushort u16Magic; IntPtr intptrNative; // We need the first two bytes to decide if we have a DIB or a TIFF. Don't // forget to lock the silly thing... intptrNative = DsmMemLock(a_intptrNative); u16Magic = (ushort)Marshal.PtrToStructure(intptrNative, typeof(ushort)); // Windows uses a DIB, the first usigned short is 40... if (u16Magic == 40) { byte[] bBitmap; BITMAPFILEHEADER bitmapfileheader; BITMAPINFOHEADER bitmapinfoheader; // Our incoming DIB is a bitmap info header... bitmapinfoheader = (BITMAPINFOHEADER)Marshal.PtrToStructure(intptrNative, typeof(BITMAPINFOHEADER)); // Build our file header... bitmapfileheader = new BITMAPFILEHEADER(); bitmapfileheader.bfType = 0x4D42; // "BM" bitmapfileheader.bfSize = (uint)Marshal.SizeOf(typeof(BITMAPFILEHEADER)) + bitmapinfoheader.biSize + (bitmapinfoheader.biClrUsed * 4) + bitmapinfoheader.biSizeImage; bitmapfileheader.bfOffBits = (uint)Marshal.SizeOf(typeof(BITMAPFILEHEADER)) + bitmapinfoheader.biSize + (bitmapinfoheader.biClrUsed * 4); // Copy the file header into our byte array... IntPtr intptr = Marshal.AllocHGlobal(Marshal.SizeOf(bitmapfileheader)); Marshal.StructureToPtr(bitmapfileheader, intptr, true); bBitmap = new byte[bitmapfileheader.bfSize]; Marshal.Copy(intptr, bBitmap, 0, Marshal.SizeOf(bitmapfileheader)); Marshal.FreeHGlobal(intptr); intptr = IntPtr.Zero; // Copy the rest of the DIB into our byte array...... Marshal.Copy(intptrNative, bBitmap, Marshal.SizeOf(typeof(BITMAPFILEHEADER)), (int)bitmapfileheader.bfSize - Marshal.SizeOf(typeof(BITMAPFILEHEADER))); // Now we can turn the in-memory bitmap file into a Bitmap object... MemoryStream memorystream = new MemoryStream(bBitmap); // Unfortunately the stream has to be kept with the bitmap... Bitmap bitmapStream = new Bitmap(memorystream); // So we make a copy (ick)... Bitmap bitmap = new Bitmap(bitmapStream); // Cleanup... //bitmapStream.Dispose(); //memorystream.Close(); bitmapStream = null; memorystream = null; bBitmap = null; // Return our bitmap... DsmMemUnlock(a_intptrNative); return (bitmap); } // Linux and Mac OS X use TIFF. We'll handle a simple Intel TIFF ("II")... else if (u16Magic == 0x4949) { int iTiffSize; ulong u64; ulong u64Pointer; ulong u64TiffHeaderSize; ulong u64TiffTagSize; byte[] abTiff; TIFFHEADER tiffheader; TIFFTAG tifftag; // Init stuff... tiffheader = new TIFFHEADER(); tifftag = new TIFFTAG(); u64TiffHeaderSize = (ulong)Marshal.SizeOf(tiffheader); u64TiffTagSize = (ulong)Marshal.SizeOf(tifftag); // Find the size of the image so we can turn it into a memory stream... iTiffSize = 0; tiffheader = (TIFFHEADER)Marshal.PtrToStructure(intptrNative, typeof(TIFFHEADER)); for (u64 = 0; u64 < 999; u64++) { u64Pointer = (ulong)intptrNative + u64TiffHeaderSize + (u64TiffTagSize * u64); tifftag = (TIFFTAG)Marshal.PtrToStructure((IntPtr)u64Pointer, typeof(TIFFTAG)); // StripOffsets... if (tifftag.u16Tag == 273) { iTiffSize += (int)tifftag.u32Value; } // StripByteCounts... if (tifftag.u16Tag == 279) { iTiffSize += (int)tifftag.u32Value; } } // No joy... if (iTiffSize == 0) { DsmMemUnlock(a_intptrNative); return (null); } // Copy the data to our byte array... abTiff = new byte[iTiffSize]; Marshal.Copy(intptrNative, abTiff, 0, iTiffSize); // Move the image into a memory stream... MemoryStream memorystream = new MemoryStream(abTiff); // Turn the memory stream into an in-memory TIFF image... Image imageTiff = Image.FromStream(memorystream); // Convert the in-memory tiff to a Bitmap object... Bitmap bitmap = new Bitmap(imageTiff); // Cleanup... abTiff = null; memorystream = null; imageTiff = null; // Return our bitmap... DsmMemUnlock(a_intptrNative); return (bitmap); } // Uh-oh... DsmMemUnlock(a_intptrNative); return (null); }
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 bool PredictorVGetField(TIFF tif, TIFFTAG tag, object[] ap) { TIFFPredictorState sp=(TIFFPredictorState)tif.tif_data; switch(tag) { case TIFFTAG.PREDICTOR: ap[0]=(ushort)sp.predictor; break; default: return sp.vgetparent(tif, tag, ap); } return true; }
static bool PredictorVSetField(TIFF tif, TIFFTAG tag, TIFFDataType dt, params object[] ap) { TIFFPredictorState sp=(TIFFPredictorState)tif.tif_data; switch(tag) { case TIFFTAG.PREDICTOR: sp.predictor=(PREDICTOR)__GetAsUshort(ap, 0); TIFFSetFieldBit(tif, FIELD.CODEC); break; default: return sp.vsetparent(tif, tag, dt, ap); } tif.tif_flags|=TIF_FLAGS.TIFF_DIRTYDIRECT; return true; }
static bool Fax3VGetField(TIFF tif, TIFFTAG tag, object[] ap) { Fax3BaseState sp=tif.tif_data as Fax3BaseState; #if DEBUG if(sp==null) throw new Exception("sp==null"); #endif switch(tag) { case TIFFTAG.FAXMODE: ap[0]=sp.mode; break; case TIFFTAG.GROUP3OPTIONS: case TIFFTAG.GROUP4OPTIONS: ap[0]=sp.groupoptions; break; case TIFFTAG.BADFAXLINES: ap[0]=sp.badfaxlines; break; case TIFFTAG.CLEANFAXDATA: ap[0]=sp.cleanfaxdata; break; case TIFFTAG.CONSECUTIVEBADFAXLINES: ap[0]=sp.badfaxrun; break; case TIFFTAG.FAXRECVPARAMS: ap[0]=sp.recvparams; break; case TIFFTAG.FAXSUBADDRESS: ap[0]=sp.subaddress; break; case TIFFTAG.FAXRECVTIME: ap[0]=sp.recvtime; break; case TIFFTAG.FAXDCS: ap[0]=sp.faxdcs; break; default: return sp.vgetparent(tif, tag, ap); } return true; }
static bool JPEGVGetField(TIFF tif, TIFFTAG tag, object[] ap) { JPEGState sp=tif.tif_data as JPEGState; #if DEBUG if(sp==null) throw new Exception("sp==null"); #endif switch(tag) { case TIFFTAG.JPEGTABLES: ap[0]=sp.jpegtables_length; ap[1]=sp.jpegtables; break; case TIFFTAG.JPEGQUALITY: ap[0]=sp.jpegquality; break; case TIFFTAG.JPEGCOLORMODE: ap[0]=sp.jpegcolormode; break; case TIFFTAG.JPEGTABLESMODE: ap[0]=sp.jpegtablesmode; break; case TIFFTAG.YCBCRSUBSAMPLING: JPEGFixupTestSubsampling(tif); return sp.vgetparent(tif, tag, ap); case TIFFTAG.FAXRECVPARAMS: ap[0]=sp.recvparams; break; case TIFFTAG.FAXSUBADDRESS: ap[0]=sp.subaddress; break; case TIFFTAG.FAXRECVTIME: ap[0]=sp.recvtime; break; case TIFFTAG.FAXDCS: ap[0]=sp.faxdcs; break; default: return sp.vgetparent(tif, tag, ap); } return true; }
static bool TIFFPrettyPrintField(TIFF tif, TextWriter fd, TIFFTAG tag, uint value_count, object raw_data) { TIFFDirectory td=tif.tif_dir; switch(tag) { case TIFFTAG.INKSET: fd.Write(" Ink Set: "); switch((INKSET)((ushort[])raw_data)[0]) { case INKSET.CMYK: fd.WriteLine("CMYK"); break; default: fd.WriteLine("{0} (0x{0:X})", ((ushort[])raw_data)[0]); break; } return true; case TIFFTAG.DOTRANGE: fd.WriteLine(" Dot Range: {0}-{1}", ((ushort[])raw_data)[0], ((ushort[])raw_data)[1]); return true; case TIFFTAG.WHITEPOINT: fd.WriteLine(" White Point: {0}-{1}", ((double[])raw_data)[0], ((double[])raw_data)[1]); return true; case TIFFTAG.REFERENCEBLACKWHITE: fd.WriteLine(" Reference Black/White:"); for(ushort i=0; i<3; i++) fd.WriteLine("\t{0}: {1} {2}", i, ((double[])raw_data)[2*i+0], ((double[])raw_data)[2*i+1]); return true; case TIFFTAG.XMLPACKET: fd.WriteLine(" XMLPacket (XMP Metadata):"); for(uint i=0; i<value_count; i++) fd.Write((char)((byte[])raw_data)[i]); fd.WriteLine(); return true; case TIFFTAG.RICHTIFFIPTC: // XXX: for some weird reason RichTIFFIPTC tag // defined as array of LONG values. fd.WriteLine(" RichTIFFIPTC Data: <present>, {0} bytes", value_count*4); return true; case TIFFTAG.PHOTOSHOP: fd.WriteLine(" Photoshop Data: <present>, {0} bytes", value_count); return true; case TIFFTAG.ICCPROFILE: fd.WriteLine(" ICC Profile: <present>, {0} bytes", value_count); return true; case TIFFTAG.STONITS: fd.WriteLine(" Sample to Nits conversion factor: {0}", ((double[])raw_data)[0]); return true; } return false; }
public short field_writecount; // write count/TIFF_VARIABLE #endregion Fields #region Constructors public TIFFFieldInfo(TIFFTAG field_tag, short field_readcount, short field_writecount, TIFFDataType field_type, FIELD field_bit, bool field_oktochange, bool field_passcount, string field_name) { this.field_tag=field_tag; this.field_readcount=field_readcount; this.field_writecount=field_writecount; this.field_type=field_type; this.field_bit=field_bit; this.field_oktochange=field_oktochange; this.field_passcount=field_passcount; this.field_name=field_name; }
// Like TIFFGetField, but return any default // value if the tag is not present in the directory. // // NB: We use the value in the directory, rather than // explicit values so that defaults exist only in one // place in the library -- in TIFFDefaultDirectory. public static bool TIFFVGetFieldDefaulted(TIFF tif, TIFFTAG tag, object[] ap) { TIFFDirectory td=tif.tif_dir; if(TIFFVGetField(tif, tag, ap)) return true; switch(tag) { case TIFFTAG.SUBFILETYPE: ap[0]=td.td_subfiletype; return true; case TIFFTAG.BITSPERSAMPLE: ap[0]=td.td_bitspersample; return true; case TIFFTAG.THRESHHOLDING: ap[0]=td.td_threshholding; return true; case TIFFTAG.FILLORDER: ap[0]=td.td_fillorder; return true; case TIFFTAG.ORIENTATION: ap[0]=td.td_orientation; return true; case TIFFTAG.SAMPLESPERPIXEL: ap[0]=td.td_samplesperpixel; return true; case TIFFTAG.ROWSPERSTRIP: ap[0]=td.td_rowsperstrip; return true; case TIFFTAG.MINSAMPLEVALUE: ap[0]=td.td_minsamplevalue; return true; case TIFFTAG.MAXSAMPLEVALUE: ap[0]=td.td_maxsamplevalue; return true; case TIFFTAG.PLANARCONFIG: ap[0]=td.td_planarconfig; return true; case TIFFTAG.RESOLUTIONUNIT: ap[0]=td.td_resolutionunit; return true; case TIFFTAG.PREDICTOR: TIFFPredictorState sp=(TIFFPredictorState)tif.tif_data; ap[0]=sp.predictor; return true; case TIFFTAG.DOTRANGE: ap[0]=0; ap[1]=(1<<td.td_bitspersample)-1; return true; case TIFFTAG.INKSET: ap[0]=INKSET.CMYK; return true; case TIFFTAG.NUMBEROFINKS: ap[0]=(ushort)4; return true; case TIFFTAG.EXTRASAMPLES: ap[0]=td.td_extrasamples; ap[1]=td.td_sampleinfo; return true; case TIFFTAG.MATTEING: ap[0]=(ushort)((td.td_extrasamples==1&&td.td_sampleinfo[0]==(ushort)EXTRASAMPLE.ASSOCALPHA)?1:0); return true; case TIFFTAG.TILEDEPTH: ap[0]=td.td_tiledepth; return true; case TIFFTAG.DATATYPE: ap[0]=td.td_sampleformat-1; return true; case TIFFTAG.SAMPLEFORMAT: ap[0]=td.td_sampleformat; return true; case TIFFTAG.IMAGEDEPTH: ap[0]=td.td_imagedepth; return true; case TIFFTAG.YCBCRCOEFFICIENTS: // defaults are from CCIR Recommendation 601-1 double[] ycbcrcoeffs=new double[] { 0.299, 0.587, 0.114 }; ap[0]=ycbcrcoeffs; return true; case TIFFTAG.YCBCRSUBSAMPLING: ap[0]=td.td_ycbcrsubsampling[0]; ap[1]=td.td_ycbcrsubsampling[1]; return true; case TIFFTAG.YCBCRPOSITIONING: ap[0]=td.td_ycbcrpositioning; return true; case TIFFTAG.WHITEPOINT: // TIFF 6.0 specification tells that it is no default // value for the WhitePoint, but AdobePhotoshop TIFF // Technical Note tells that it should be CIE D50. ap[0]=new double[] { D50_X0/(D50_X0+D50_Y0+D50_Z0), D50_Y0/(D50_X0+D50_Y0+D50_Z0) }; return true; case TIFFTAG.TRANSFERFUNCTION: if(td.td_transferfunction[0]==null&&!TIFFDefaultTransferFunction(td)) { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space for \"TransferFunction\" tag"); return false; } ap[0]=td.td_transferfunction[0]; if(td.td_samplesperpixel-td.td_extrasamples>1) { ap[1]=td.td_transferfunction[1]; ap[2]=td.td_transferfunction[2]; } return true; case TIFFTAG.REFERENCEBLACKWHITE: { if(td.td_refblackwhite==null&&!TIFFDefaultRefBlackWhite(td)) return false; ap[0]=td.td_refblackwhite; return true; } } return false; }
// Like TIFFGetField, but return any default // value if the tag is not present in the directory. public static bool TIFFGetFieldDefaulted(TIFF tif, TIFFTAG tag, object[] ap) { return TIFFVGetFieldDefaulted(tif, tag, ap); }
static bool JPEGVSetField(TIFF tif, TIFFTAG tag, TIFFDataType dt, object[] ap) { JPEGState sp=tif.tif_data as JPEGState; TIFFDirectory td=tif.tif_dir; #if DEBUG if(sp==null) throw new Exception("sp==null"); #endif switch(tag) { case TIFFTAG.JPEGTABLES: uint v32=__GetAsUint(ap, 0); if(v32==0) return false;// XXX TIFFsetByteArray(ref sp.jpegtables, ap[1] as byte[], v32); sp.jpegtables_length=v32; TIFFSetFieldBit(tif, FIELD.JPEG_JPEGTABLES); break; case TIFFTAG.JPEGQUALITY: sp.jpegquality=__GetAsInt(ap, 0); return true; // pseudo tag case TIFFTAG.JPEGCOLORMODE: sp.jpegcolormode=(JPEGCOLORMODE)__GetAsInt(ap, 0); JPEGResetUpsampled(tif); return true; // pseudo tag case TIFFTAG.JPEGTABLESMODE: sp.jpegtablesmode=(JPEGTABLESMODE)__GetAsInt(ap, 0); return true; // pseudo tag case TIFFTAG.PHOTOMETRIC: bool ret_value=sp.vsetparent(tif, tag, dt, ap); JPEGResetUpsampled(tif); return ret_value; case TIFFTAG.YCBCRSUBSAMPLING: // mark the fact that we have a real ycbcrsubsampling! sp.ycbcrsampling_fetched=true; // should we be recomputing upsampling info here? return sp.vsetparent(tif, tag, dt, ap); case TIFFTAG.FAXRECVPARAMS: sp.recvparams=__GetAsUint(ap, 0); break; case TIFFTAG.FAXSUBADDRESS: sp.subaddress=ap[0] as string; break; case TIFFTAG.FAXRECVTIME: sp.recvtime=__GetAsUint(ap, 0); break; case TIFFTAG.FAXDCS: sp.faxdcs=ap[0] as string; break; default: return sp.vsetparent(tif, tag, dt, ap); } TIFFFieldInfo fip=TIFFFieldWithTag(tif, tag); if(fip!=null) TIFFSetFieldBit(tif, fip.field_bit); else return false; tif.tif_flags|=TIF_FLAGS.TIFF_DIRTYDIRECT; return true; }
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 bool Fax3VSetField(TIFF tif, TIFFTAG tag, TIFFDataType dt, object[] ap) { Fax3BaseState sp=tif.tif_data as Fax3BaseState; #if DEBUG if(sp==null) throw new Exception("sp==null"); if(sp.vsetparent==null) throw new Exception("sp.vsetparent==null"); #endif switch(tag) { case TIFFTAG.FAXMODE: sp.mode=(FAXMODE)__GetAsInt(ap, 0); return true; // NB: pseudo tag case TIFFTAG.GROUP3OPTIONS: // XXX: avoid reading options if compression mismatches. if(tif.tif_dir.td_compression==COMPRESSION.CCITTFAX3) sp.groupoptions=(GROUP3OPT)__GetAsUint(ap, 0); break; case TIFFTAG.GROUP4OPTIONS: // XXX: avoid reading options if compression mismatches. if(tif.tif_dir.td_compression==COMPRESSION.CCITTFAX4) sp.groupoptions=(GROUP3OPT)__GetAsUint(ap, 0); break; case TIFFTAG.BADFAXLINES: sp.badfaxlines=__GetAsUint(ap, 0); break; case TIFFTAG.CLEANFAXDATA: sp.cleanfaxdata=(CLEANFAXDATA)__GetAsUshort(ap, 0); break; case TIFFTAG.CONSECUTIVEBADFAXLINES: sp.badfaxrun=__GetAsUint(ap, 0); break; case TIFFTAG.FAXRECVPARAMS: sp.recvparams=__GetAsUint(ap, 0); break; case TIFFTAG.FAXSUBADDRESS: sp.subaddress=ap[0] as string; break; case TIFFTAG.FAXRECVTIME: sp.recvtime=__GetAsUint(ap, 0); break; case TIFFTAG.FAXDCS: sp.faxdcs=ap[0] as string; break; default: return sp.vsetparent(tif, tag, dt, ap); } TIFFFieldInfo fip=TIFFFieldWithTag(tif, tag); if(fip!=null) TIFFSetFieldBit(tif, fip.field_bit); else return false; tif.tif_flags|=TIF_FLAGS.TIFF_DIRTYDIRECT; return true; }
// Setup a directory entry that references a // samples/pixel array of SHORT values and // (potentially) write the associated indirect // values. static bool TIFFWritePerSampleShorts(TIFF tif, TIFFTAG tag, TIFFDirEntry dir) { ushort samples=tif.tif_dir.td_samplesperpixel; ushort[] w=null; object[] ap=null; try { w=new ushort[samples]; ap=new object[samples]; } catch { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to write per-sample shorts"); return false; } TIFFGetField(tif, tag, ap); for(int i=0; i<samples; i++) w[i]=__GetAsUshort(ap, 0); dir.tdir_tag=(ushort)tag; dir.tdir_type=(ushort)TIFFDataType.TIFF_SHORT; dir.tdir_count=samples; return TIFFWriteShortArray(tif, dir, w); }
// Setup a directory entry of an array of RATIONAL // or SRATIONAL and write the associated indirect values. static bool TIFFWriteRational(TIFF tif, TIFFDataType type, TIFFTAG tag, TIFFDirEntry dir, double fv) { dir.tdir_tag=(ushort)tag; dir.tdir_type=(ushort)type; dir.tdir_count=1; byte[] t=null; try { t=new byte[8]; } catch { TIFFErrorExt(tif.tif_clientdata, tif.tif_name, "No space to write RATIONAL array"); return false; } int sign=1; uint den=1; if(fv<0) { if(type==TIFFDataType.TIFF_RATIONAL) { TIFFWarningExt(tif.tif_clientdata, tif.tif_name, "\"{0}\": Information lost writing value ({1}) as (unsigned) RATIONAL", TIFFFieldWithTag(tif, tag).field_name, fv); fv=0; } else { fv=-fv; sign=-1; } } if(fv>0) { while(fv<(1<<(31-3))&&den<(1<<(31-3))) { fv*=1<<3; den*=1<<3; } } BitConverter.GetBytes((uint)(sign*(fv+0.5))).CopyTo(t, 0); BitConverter.GetBytes(den).CopyTo(t, 4); return TIFFWriteData(tif, dir, t); }