2013-01-14 23 views
0

情況:我有一個包含文本數據和許多二進制TIFF圖像的文件。有幾個tiff屬性標籤需要更改,因爲它們在放入該文件之前最初創建時,它們的配置是錯誤的。因此,我將二進制數據轉儲到byte [],然後轉儲到MemoryStream,然後轉儲到Image,然後繼續從Image.PropertyItems中刪除所有PropertyItem,然後通過Image.SetPropertyItem()重新創建我自己的標記。最後,我使用正確的編碼器信息和編碼器參數執行Image.Save()。.NET Image.Save()忽略已更改的TIFF屬性項目

問題:創建的文件不包含我創建的所有屬性項目,而且我更改的一些項目已被完全忽略。屬性項中的數據類型也被忽略(短被改爲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); 

回答

0

好了,我才知道,也許是.NET框架是不是最終的權威TIFFs,它實際上可以做任何想做的事情。而且你無法控制它。我結束了學習使用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();