2011-04-20 74 views
6

如何從JPEG壓縮的TIFF文件中提取圖像?Jpeg from Tiff(jpeg-compressed)

我已經根據StripOffests和StripBytesCount字段讀取字節,但我無法從它們加載圖像。

+0

您是否在尋找壓縮圖片的數據,或者您正在尋找真實圖片? – plinth 2011-04-20 17:24:09

+0

我在尋找實際的圖片 – user393679 2011-04-20 18:33:16

回答

3

舊式TIFF-JPEG(壓縮類型6)基本上在TIFF包裝器內填充了一個普通的JFIF文件。新型TIFF-JPEG(壓縮類型7)允許將JPEG表格數據(Huffman,量化)存儲在單獨的標籤(0x015B JPEGTables)中。這允許您在文件中放入帶有SOI/EOI標記的JPEG數據條,而無需重複Huffman和Quantization表。這可能是你看到你的文件。單條開始於序列FFD8,但缺少霍夫曼和量化表。這是Photoshop產品通常寫入文件的方式。

+0

我試圖在圖像數據的開頭添加量化表,但它沒有幫助。我必須在哪裏插入該表格? – user393679 2011-04-21 22:21:57

+0

霍夫曼表怎麼樣?圖像是否分成多個條。你想每個帶1 JPEG文件?添加更多細節。 – BitBank 2011-04-22 04:34:21

+0

有1個JPEG分成多個條。 – user393679 2011-04-22 05:28:20

1

如果您試圖從TIFF,JPEG或其他文件中提取實際圖像,最好使用庫如libtiff這樣做。 TIFF是一個非常複雜的規範,雖然你自己也可以做到這一點,並獲得一到兩類圖像,但你可能無法處理經常出現的其他情況,特別是「舊式」JPEG是在TIFF中加入的子格式,並且不適合整體。

我的公司,Atalasoft,使.NET產品,包括一個非常好的TIFF編解碼器。如果您只需要擔心單頁圖像,我們的免費產品將適合您。

在.NET領域,你也可以看看Bit Miracle的libtiff的託管版本。這是一個相當不錯的圖書館港口。

+0

謝謝你的回答。我無法使用任何庫。我只在解析新式JPEG壓縮的TIFF時很有趣。你能告訴我,根據StripOffests和StripBytesCount字段,我從TIFF文件中檢索到的JPEG壓縮數據有什麼問題? – user393679 2011-04-21 13:17:37

+0

我看到它包含jpeg的開始標記:X0FFD8,但爲什麼它不能打開。我必須用這些數據來操作什麼來獲得圖像? – user393679 2011-04-21 13:25:17

2

使用JAI:

int TAG_COMPRESSION    = 259; 
int TAG_JPEG_INTERCHANGE_FORMAT = 513; 

int COMP_JPEG_OLD = 6; 
int COMP_JPEG_TTN2 = 7; 

SeekableStream stream = new ByteArraySeekableStream(imageData); 
TIFFDirectory tdir = new TIFFDirectory(stream, 0); 
int  compression = tdir.getField(TAG_COMPRESSION).getAsInt(0); 

// Decoder name 
String decoder2use = "tiff"; 
if (compression == COMP_JPEG_OLD) { 
    // Special handling for old/unsupported JPEG-in-TIFF format: 
    // {@link: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4929147 } 
    stream.seek(tdir.getField(TAG_JPEG_INTERCHANGE_FORMAT).getAsLong(0)); 
    decoder2use = "jpeg"; 
} 

// Decode image 
ImageDecoder dec = ImageCodec.createImageDecoder(decoder2use, stream, null); 
RenderedImage img = dec.decodeAsRenderedImage(); 

的最佳解決方案,對我幫助很大。 只需添加,如果您在TIFF中有多個頁面,則必須重複讀取流,並在TIFFDirectory對象中定義不同的目錄號,然後重複上述所有操作。

TIFFDirectory tdir = new TIFFDirectory(stream, 1); 
+0

非凡。謝謝你的救星。 – Adrian 2014-10-14 12:11:56

2

與提到的庫的libtiff的問題是,它提取圖像和然後將其保存再壓縮,這意味着在JPG的情況下的另一質量損失。這就是說,即使不使用第三方庫,也可以通過調用NET Framework的GDI +方法來完成相同的任務。

此線程的初始作者嘗試獲取jpeg二進制文件而無需重新壓縮它,這正是我所要做的。

這是一個可能的解決方案,如果你能提供優質的損失住,不想使用幹啥,但.NET類庫:

public static int SplitMultiPage(string sourceFileName, string targetPath) 
    { 
     using (Image multipageTIFF = Image.FromFile(sourceFileName)) 
     { 
      int pageCount = multipageTIFF.GetFrameCount(FrameDimension.Page); 

      if (pageCount > 1) 
      { 
       string sFileName = Path.GetFileNameWithoutExtension (sourceFileName); 
       for (int i = 0; i < pageCount; i++) 
       {       
        multipageTIFF.SelectActiveFrame(FrameDimension.Page, i); 

        // ein einzelner Frame könnte auch ein anderes Format haben, z.B. JPG, PNG, BMP, etc. 
        // Damit die Datei die korrekte Endung bekommt, holen wir uns eine Endung aus der Beschreibung des Codecs 
        // Interessanterweise liefert uns das RawFormat im Fall TIFF (der einzige Multiframefall) immer den Codec für TIFF, 
        // statt den des Frames 
        ImageCodecInfo codec = Helpers.GetEncoder(multipageTIFF.RawFormat); 
        string sExtension = codec.FilenameExtension.Split(new char[] { ';' })[0]; 
        sExtension = sExtension.Substring(sExtension.IndexOf('.') + 1); 
        string newFileName = Path.Combine(targetPath, string.Format("{0}_{1}.{2}", sFileName, i + 1, sExtension)); 

        EncoderParameters encoderParams = new EncoderParameters(2); 
        encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.LastFrame); 

        // für TIF 1 Bit machen wir CompressionCCITT4 Kompression, da das die besten Ergebnisse liefert 
        switch (GetCompressionType(multipageTIFF)) 
        { 

         case 1: // No compression -> BMP? 
          encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionNone); 
          break; 
         case 2: // CCITT modified Huffman RLE 32773 = PackBits compression, aka Macintosh RLE 
          encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionRle); 
          break; 
         case 3: // CCITT Group 3 fax encoding 
          encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT3); 
          break; 
         case 4: // CCITT Group 4 fax encoding 
          encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT4); 
          break; 
         case 5: // LZW 
          encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW); 
          break; 
         case 6: //JPEG ('old-style' JPEG, later overriden in Technote2) 
         case 7: // Technote2 overrides old-style JPEG compression, and defines 7 = JPEG ('new-style' JPEG) 
          { 
           codec = Helpers.GetEncoder(ImageFormat.Jpeg); 
           encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 90); 
          } 
          break; 
        } 

        multipageTIFF.Save(newFileName, codec, encoderParams); 
       } 
      } 

      return pageCount; 
     } 
    } 

所使用的輔助方法:

public static ImageCodecInfo GetEncoder(ImageFormat format) 
    { 

     ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); 

     foreach (ImageCodecInfo codec in codecs) 
     { 
      if (codec.FormatID == format.Guid) 
      { 
       return codec; 
      } 
     } 
     return null; 
    } 

讀壓縮標誌:

public static int GetCompressionType(Image image) 
    { 
     /* TIFF Tag Compression 
      IFD  Image 
      Code  259 (hex 0x0103) 
      Name  Compression 
      LibTiff name  TIFFTAG_COMPRESSION 
      Type  SHORT 
      Count  1 
      Default  1 (No compression) 
      Description 

      Compression scheme used on the image data. 

      The specification defines these values to be baseline: 

      1 = No compression 
      2 = CCITT modified Huffman RLE 
      32773 = PackBits compression, aka Macintosh RLE 

      Additionally, the specification defines these values as part of the TIFF extensions: 

      3 = CCITT Group 3 fax encoding 
      4 = CCITT Group 4 fax encoding 
      5 = LZW 
      6 = JPEG ('old-style' JPEG, later overriden in Technote2) 

      Technote2 overrides old-style JPEG compression, and defines: 

      7 = JPEG ('new-style' JPEG) 

      Adobe later added the deflate compression scheme: 

      8 = Deflate ('Adobe-style') 

      The TIFF-F specification (RFC 2301) defines: 

      9 = Defined by TIFF-F and TIFF-FX standard (RFC 2301) as ITU-T Rec. T.82 coding, using ITU-T Rec. T.85 (which boils down to JBIG on black and white). 
      10 = Defined by TIFF-F and TIFF-FX standard (RFC 2301) as ITU-T Rec. T.82 coding, using ITU-T Rec. T.43 (which boils down to JBIG on color). 
     */ 
     int compressionTagIndex = Array.IndexOf(image.PropertyIdList, 0x103); 

     PropertyItem compressionTag = image.PropertyItems[compressionTagIndex]; 

     return BitConverter.ToInt16(compressionTag.Value, 0); 
    } 
+0

此方法:public static int GetCompressionType(Image image)應以「返回BitConverter.ToUInt16(compressionTag.Value,0);」結尾因爲您不需要由於返回的16位數組而產生有符號整數。 – 2013-03-08 18:36:54

相關問題