2010-08-26 22 views
5

Recientemente me mudé a una nueva caja de desarrollo de Windows XP de 32 bits a Windows 7 de 64 bits. Ambas máquinas ejecutan .Net Framework versión 4.0 para desarrollo con Visual Studio 2010.División de Tiff de varias páginas en Single Tiff's en Windows 7/.Net 4.0

Después de actualizar a Windows 7 64 Bit, mi código para dividir una imagen Tiff de varias páginas en imágenes separadas ahora está roto (funcionó bien previamente en XP 32 bits, excepto por el error de orden de relleno MS). Después de la depuración, la Metadatos de mapa de bits parece ser leída correctamente por .Net Framework, sin embargo, algunos componentes en la pila persisten incorrectamente algunas etiquetas Tiff (273, 278 y 279). He intentado varios métodos para lograr la división, incluidos GDI +, y la biblioteca FreeImage, pero todos fallan en .Net. Pude dividir exitosamente el Tiff usando Image Magick y otra herramienta de terceros con valores de etiqueta válidos.

Específicamente, Tiff Tags 273, 278 (debe coincidir con 257 pero no lo hace), y 279 tienen valores incorrectos.

¿Es este un problema conocido de Microsoft? ¿Hay alguna solución? ¿Estoy haciendo esta tarea mal? Muy frustrado ya que esto estaba funcionando en XP 32 muy bien y que el sistema operativo no es una opción de implementación.

// 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); 
         } 
        } 
       } 
      } 
     } 
    } 
} 

Respuesta

3

Puede probar la biblioteca LibTiff.Net para esto. Es gratis y de código abierto (Licencia BSD).

La biblioteca viene con la utilidad tiffcp que se puede utilizar desde su código para dividir/fusionar imágenes TIFF. O puede usar el código fuente de esa utilidad como muestra.

LibTiff.Net también contiene muestras para fusionar y dividir imágenes TIFF usando tiffcp desde su aplicación.

Descargo de responsabilidad: soy uno de los administradores de la biblioteca.

+0

me había basado en el uso de LibTiff.Net ayer, pero decidió ser flojo. Después de piratear el código TiffCP en mi aplicación, ¡está funcionando de nuevo! –

+0

Genial que LibTiff.Net te ayudó :-) – Bobrovsky

3

A juzgar por su código inicial, mi respuesta aquí puede ser ingenuo con respecto a sus necesidades específicas, pero no obstante, que funciona para mí:

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; 
    } 
} 
Cuestiones relacionadas