.NET Image.Save()忽略已更改的TIFF属性项

时间:2013-01-14 17:02:30

标签: .net tiff

情况:我有一个包含文本数据的文件和许多二进制的TIFF图像。我需要更改一些tiff属性标记,因为在将tiff放入该文件之前最初创建它们时配置错误。因此,我将二进制数据转储到byte [],然后转储到MemoryStream,然后转储到Image,然后继续从Image.PropertyItems中删除所有PropertyItems,然后通过Image.SetPropertyItem()重新创建我自己的标签。最后,我使用正确的编码器信息和编码器参数进行Image.Save()。

问题:创建的文件不包含我创建的所有属性项,而且我更改的一些项目已被完全忽略。属性项中的数据类型也被忽略(short被改为long等)。它就像Image.Save()重写它想要的任何东西。更具体地说,我将ImageWith和ImageLength属性指定为SHORT,并将它们写为LONG。并且PlanarConfig属性项甚至根本没有写入。

以下是我的一些代码:(知道为什么会发生这种情况以及如何修复它?)

const int SHORT = 3;
const int SHORT_LEN = 2;
const int LONG = 4;
const int LONG_LEN = 4;
const int RATIONAL = 5;
const int RATIONAL_LEN = 8;

byte[] bytesFront = bco.Records[0].Fields[4].Data;
byte[] bytesRear = bco.Records[0].Fields[6].Data;
MemoryStream msFront = new MemoryStream(bytesFront);
Bitmap imgFront = (Bitmap)Image.FromStream(msFront);

PropertyItem pi = imgFront.GetPropertyItem(imgFront.PropertyIdList.First<int>());

foreach (PropertyItem currentPropertyItem in imgFront.PropertyItems)
{
    imgFront.RemovePropertyItem(currentPropertyItem.Id);
}

// SubFile Type
pi.Id = 254;
pi.Type = LONG;
pi.Len = LONG_LEN;
pi.Value = GetBytes((uint)0);
imgFront.SetPropertyItem(pi);

// Image Width
pi.Id = 256;
pi.Type = SHORT;
pi.Len = SHORT_LEN;
pi.Value = GetBytes((ushort)imgFront.Width);
imgFront.SetPropertyItem(pi);

//...

// Planar Config
pi.Id = 284;
pi.Type = SHORT;
pi.Len = SHORT_LEN;
pi.Value = GetBytes((ushort)1);
imgFront.SetPropertyItem(pi);

// Resolution Unit
pi.Id = 296;
pi.Type = SHORT;
pi.Len = SHORT_LEN;
pi.Value = GetBytes((ushort)2);
imgFront.SetPropertyItem(pi);

ImageCodecInfo encoderInfo = ImageCodecInfo.GetImageEncoders().First(i => i.MimeType == "image/tiff");
EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT4);

imgFront.Save(@"C:\Temp\imgFront.tif", encoderInfo, encoderParameters);

1 个答案:

答案 0 :(得分:0)

好的,所以我了解到.NET Framework可能不是TIFF的终极权威,它确实可以做任何想做的事情。你无法控制它。我最终学会使用LibTiff.NET并使用以下代码来完成我需要的工作:

byte[] bytesOriginal = bco.Records[0].Fields[4].Data;
MemoryStream streamOriginal = new MemoryStream(bytesOriginal);

streamOriginal.Seek(0, SeekOrigin.Begin);
Tiff tiffMemory = Tiff.ClientOpen("In-Memory", "r", streamOriginal, new TiffStream());
Tiff tiffFile = Tiff.Open(@"C:\Temp\imgTest2.tif", "w");

tiffFile.SetField(TiffTag.SUBFILETYPE, tiffMemory.GetField(TiffTag.SUBFILETYPE).First());
tiffFile.SetField(TiffTag.IMAGEWIDTH, tiffMemory.GetField(TiffTag.IMAGEWIDTH).First());
tiffFile.SetField(TiffTag.IMAGELENGTH, tiffMemory.GetField(TiffTag.IMAGELENGTH).First());
tiffFile.SetField(TiffTag.BITSPERSAMPLE, tiffMemory.GetField(TiffTag.BITSPERSAMPLE).First());
tiffFile.SetField(TiffTag.COMPRESSION, tiffMemory.GetField(TiffTag.COMPRESSION).First());
tiffFile.SetField(TiffTag.PHOTOMETRIC, tiffMemory.GetField(TiffTag.PHOTOMETRIC).First());
tiffFile.SetField(TiffTag.STRIPOFFSETS, tiffMemory.GetField(TiffTag.STRIPOFFSETS).First());
tiffFile.SetField(TiffTag.ORIENTATION, tiffMemory.GetField(TiffTag.ORIENTATION).First());
tiffFile.SetField(TiffTag.SAMPLESPERPIXEL, tiffMemory.GetField(TiffTag.SAMPLESPERPIXEL).First());
tiffFile.SetField(TiffTag.ROWSPERSTRIP, tiffMemory.GetField(TiffTag.ROWSPERSTRIP).First());
tiffFile.SetField(TiffTag.STRIPBYTECOUNTS, tiffMemory.GetField(TiffTag.STRIPBYTECOUNTS).First());
tiffFile.SetField(TiffTag.XRESOLUTION, tiffMemory.GetField(TiffTag.XRESOLUTION).First());
tiffFile.SetField(TiffTag.YRESOLUTION, tiffMemory.GetField(TiffTag.YRESOLUTION).First());
tiffFile.SetField(TiffTag.PLANARCONFIG, tiffMemory.GetField(TiffTag.PLANARCONFIG).First());
tiffFile.SetField(TiffTag.RESOLUTIONUNIT, tiffMemory.GetField(TiffTag.RESOLUTIONUNIT).First());

tiffFile.CheckpointDirectory();

byte[] bytesNew = new byte[tiffMemory.RawStripSize(0)];
tiffMemory.ReadRawStrip(0, bytesNew, 0, bytesNew.Length);
tiffFile.WriteRawStrip(0, bytesNew, bytesNew.Length);

tiffMemory.Close();
tiffFile.Close();