2010-08-26 17 views
5

Recentemente mi sono spostato in una nuova finestra di sviluppo da Windows XP 32 Bit a Windows 7 a 64 bit. Entrambe le macchine sono in esecuzione .Net Framework versione 4.0 per lo sviluppo con Visual Studio 2010.Divisione di Tiff multipagina in Tiff singolo su Windows 7/.Net 4.0

Dopo l'aggiornamento a Windows 7 a 64 bit, il mio codice per dividere un'immagine Tiff su più pagine in immagini separate è ora rotto (funzionava bene in precedenza su XP 32 bit, ad eccezione del bug di ordine di riempimento MS). Dopo il debug, i metadati bitmap sembrano essere letti correttamente da .Net Framework, tuttavia, alcuni componenti dello stack persistono in modo errato alcuni tag Tiff (273, 278 e 279). Ho provato diversi metodi per realizzare lo split, incluso GDI + e la libreria FreeImage, ma tutti falliscono all'interno di .Net. Sono riuscito a dividere il Tiff con Image Magick e un altro strumento di terze parti con valori di tag validi.

In particolare, Tag Tiff 273, 278 (deve corrispondere a 257 ma non lo è) e 279 hanno valori errati.

Si tratta di un problema noto di Microsoft? C'è una soluzione? Sto facendo questo compito in modo sbagliato? Molto frustrato dal fatto che funzionasse su XP 32 e che OS non fosse un'opzione di implementazione.

// Copy bytes into our memory 
using (MemoryStream ms = new MemoryStream()) 
{ 
    using (BinaryWriter bw = new BinaryWriter(ms)) 
    { 
     // Get the multi page tiff image's size, and allocate a place to put it. 
     int size = RdmInstance.ImageSize; 
     byte[] imgContents = new byte[size + 1]; 

     // Create the pointer and assign the Rdm image address to it 
     IntPtr pointerToImage = new IntPtr(RdmInstance.ImageData); 

     // Copy the bytes from unmanaged memory to managed memory 
     Marshal.Copy(pointerToImage, imgContents, 0, size); 

     // Now, write that contents into our memory stream 
     bw.Write(imgContents); 


     // Check for multiple tiff pages, split them out and write them out correctly for the Fed 
     TiffBitmapDecoder decoder = new TiffBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); 

     if (decoder.Frames.Count > 0) 
     { 

      // check for multi page tiff 
      for (int i = 0; i < decoder.Frames.Count; i++) 
      { 
       log.InfoFormat("Loading Multi Page Tiff Frame [{0}]... to bitmap", i); 

       // First is front, second is back 
       // TODO - it would be better to get this out of tiff tag RDM sets with the page info 
       string fileName = (i == 0) ? frontFileName : backFileName; 
       BitmapSource bmSrc = decoder.Frames[i]; 
       TiffBitmapEncoder encoder = new TiffBitmapEncoder(); 

       encoder.Compression = TiffCompressOption.Ccitt4; 
       encoder.Frames.Add(BitmapFrame.Create(bmSrc)); 

       log.InfoFormat("Saving Multi Page Tiff Frame [{0}]... to file {1}.", i, fileName); 
       using (var fs = new FileStream(fileName, FileMode.Create)) 
       { 
        encoder.Save(fs); 
       } 

       /* 
       * jknipp - 6/4/2010 
       * Microsoft has a bug in their TiffBitmapEncoder where 
       * they incorrectly set tag 266 (Fill Order) to 0, where the TIFF 
       * spec says it should be 1 or 2. We fix this here. 
       * Reopen the stupid file and fix the fill order 
       */ 
       using (var file = new FileStream(fileName, FileMode.Open)) 
       { 
        TiffBitmapDecoder output = new TiffBitmapDecoder(file, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); 
        InPlaceBitmapMetadataWriter metadata = output.Frames[0].CreateInPlaceBitmapMetadataWriter(); 

        var fillOrder = metadata.GetQuery("/ifd/{ushort=266}"); 
        log.DebugFormat("Read Fill Order Metadata tag as {0}", fillOrder); 

        // If .Net added a bogus fill order, correct it 
        if (fillOrder != null && (ushort)fillOrder == 0) 
        { 
         log.InfoFormat("Correcting FILL ORDER in file {0}", fileName); 
         metadata.SetQuery("/ifd/{ushort=266}", (ushort)1); 

         // Try to save new metadata 
         if (metadata.TrySave()) 
         { 
          fillOrder = metadata.GetQuery("/ifd/{ushort=266}"); 
          log.Info("Fill order correction successful!"); 
          log.DebugFormat("Read New Fill Order Metadata tag as {0}", fillOrder); 
         } 
        } 
       } 
      } 
     } 
    } 
} 

risposta

3

Si può provare la libreria LibTiff.Net per questo. È gratuito e open-source (licenza BSD).

La libreria viene fornita con l'utilità tiffcp che può essere utilizzata dal codice per dividere/fondere immagini TIFF. Oppure puoi usare il codice sorgente di quell'utilità come esempio.

LibTiff.Net contiene anche esempi per l'unione e la suddivisione di immagini TIFF utilizzando tiffcp dall'applicazione.

Disclaimer: Sono uno dei manutentori della biblioteca.

+0

avevo guardato con LibTiff.Net ieri, ma ha deciso di essere pigro. Dopo aver hackerato il codice TiffCP nella mia applicazione, sta funzionando di nuovo! –

+0

Grande che LibTiff.Net ti ha aiutato :-) – Bobrovsky

3

A giudicare dal codice iniziale, la mia risposta qui può essere ingenuo rispetto per le esigenze specifiche, ma comunque, per me funziona:

public static MyImage New(string filePath, ImageFormat imageFormat, 
    int imageSequence = 0) 
{ 
    byte[] imageBytes; 

    using (FileStream imageStream = File.OpenRead(filePath)) 
    { 
     Image tmpImg = Image.FromStream(imageStream); 
     if (imageSequence > 0) 
     { 
      tmpImg.SelectActiveFrame(FrameDimension.Page, imageSequence); 
     } 
     imageBytes = ToByteArray(tmpImg, imageFormat); 
     //FileStream must be open for entire lifetime of the Image 
     imageStream.Close(); 
    } 
    return new MyImage(filePath, imageBytes); 
} 

public static byte[] ToByteArray(Image image, ImageFormat imageFormat) 
{ 
    using (MemoryStream ms = new MemoryStream()) 
    { 
     image.Save(ms, imageFormat); 
     byte[] bytes = ms.ToArray(); 
     ms.Close(); 
     return bytes; 
    } 
} 
Problemi correlati