【问题标题】:Convert bitmaps to one multipage TIFF image in .NET 2.0在 .NET 2.0 中将位图转换为一个多页 TIFF 图像
【发布时间】:2008-12-29 19:19:56
【问题描述】:

如何将位图数组转换为全新的 TIFF 格式图像,并将所有位图作为帧添加到这个新的 tiff 图像中?

使用 .NET 2.0。

【问题讨论】:

  • 最新.net版本的解决方案?

标签: c# .net .net-2.0 drawing tiff


【解决方案1】:

从第一个位图开始,将其放入 Image 对象中

Bitmap bitmap = (Bitmap)Image.FromFile(file);

将位图以 tiff 格式保存到内存

MemoryStream byteStream = new MemoryStream();
bitmap.Save(byteStream, ImageFormat.Tiff);

将 Tiff 放入另一个 Image 对象中

Image tiff = Image.FromStream(byteStream)

准备编码器:

var encoderInfo = ImageCodecInfo.GetImageEncoders().First(i => i.MimeType == "image/tiff");

EncoderParameters encoderParams = new EncoderParameters(2);
encoderParams.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionNone);
encoderParams.Param[1] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.MultiFrame);

保存到文件:

tiff.Save(sOutFilePath, encoderInfo, encoderParams);

对于后续页面,准备编码器:

EncoderParameters EncoderParams = new EncoderParameters(2);
EncoderParameter SaveEncodeParam = new EncoderParameter(
     Encoder.SaveFlag, 
     (long)EncoderValue.FrameDimensionPage);
EncoderParameter CompressionEncodeParam = new EncoderParameter(
     Encoder.Compression, (long)EncoderValue.CompressionNone);
EncoderParams.Param[0] = CompressionEncodeParam;
EncoderParams.Param[1] = SaveEncodeParam;
tiff.SaveAdd(/* next image as tiff - do the same as above with memory */, EncoderParams);

最后刷新文件:

EncoderParameter SaveEncodeParam = new EncoderParameter(
     Encoder.SaveFlag, (long)EncoderValue.Flush);
EncoderParams = new EncoderParameters(1);
EncoderParams.Param[0] = SaveEncodeParam;
tiff.SaveAdd(EncoderParams);

这应该让你开始。

【讨论】:

  • 优秀的答案。如果你描述你是如何得到它的(如果不是从试错中学到的),只会更完整,因为 MSDN 文档几乎无法理解。
  • @alabamasucks - 这是一个返回指定 mime 类型的 ImageCodecInfo 对象的函数。可以替换为:ImageCodecInfo.GetImageEncoders().First(i => i.MimeType == "image/tiff");
  • 我遇到了同样的黑色图像问题,原来我在调用 tiff 上的 write 之前关闭了位图流。
  • 它将图像转换为 TIFF 但输出文件是黑白的。有什么理由吗?
  • 优秀的答案。我想补充一点,GetEncoderInfo() 方法记录在 MSDN 上的 msdn.microsoft.com/en-us/library/… 并且 Encoder.SaveFlag 可能需要完全限定——System.Drawing.Imaging.Encoder.SaveFlag。
【解决方案2】:

在谷歌上搜索了一下后发现了这篇文章。我尝试了 a'b'c'd'e'f'g'h' 在帖子中的代码,但这对我不起作用。也许,我做的不对。

无论如何,我发现另一篇将图像保存到多页 tiff 的帖子。这是帖子的链接:Adding frames to a Multi-Frame TIFF

另外,这是对我有用的代码。它应该与那个帖子相同。

Encoder encoder = Encoder.SaveFlag;
ImageCodecInfo encoderInfo = ImageCodecInfo.GetImageEncoders().First(i => i.MimeType == "image/tiff");
EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.MultiFrame);
            
// Save the first frame of the multi page tiff
Bitmap firstImage = (Bitmap) _scannedPages[0].RawContent;
firstImage.Save(fileName, encoderInfo, encoderParameters);

encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.FrameDimensionPage);

// Add the remaining images to the tiff
for (int i = 1; i < _scannedPages.Count; i++)
{
   Bitmap img = (Bitmap) _scannedPages[i].RawContent;
   firstImage.SaveAdd(img, encoderParameters);
}

// Close out the file
encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.Flush);
firstImage.SaveAdd(encoderParameters);

【讨论】:

    【解决方案3】:

    死灵法师
    接受的答案有点模糊。
    这是完整的工作代码:

    public class MultiPageTiff
    {
    
    
        private static System.Drawing.Imaging.ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            System.Drawing.Imaging.ImageCodecInfo[] encoders =
                System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
    
            if (encoders != null)
            {
                for (int i = 0; i < encoders.Length; i++)
                {
                    if (encoders[i].MimeType == mimeType)
                    {
                        return encoders[i];
                    } // End if (encoders[i].MimeType == mimeType) 
                } // Next i 
    
            } // End if (encoders != null) 
    
            return null;
        } // End Function GetEncoderInfo 
    
    
        public static System.Drawing.Image Generate(string[] filez)
        {
            System.Drawing.Image multiPageFile = null;
            byte[] ba = null;
    
    
            System.Drawing.Imaging.ImageCodecInfo tiffCodec = GetEncoderInfo("image/tiff");
    
    
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                for (int i = 0; i < filez.Length; ++i)
                {
                    using (System.Drawing.Image inputImage = System.Drawing.Image.FromFile(filez[i]))
                    {
    
                        using (System.IO.MemoryStream byteStream = new System.IO.MemoryStream())
                        {
                            inputImage.Save(byteStream, System.Drawing.Imaging.ImageFormat.Tiff);
    
                            if (i == 0)
                            {
                                multiPageFile = System.Drawing.Image.FromStream(byteStream);
                                multiPageFile = SaveImages(tiffCodec, ms, multiPageFile, null);
                            }
                            else
                            {
    
                                using (System.Drawing.Image tiffImage = System.Drawing.Image.FromStream(byteStream))
                                {
                                    multiPageFile = SaveImages(tiffCodec, ms, tiffImage, multiPageFile);
                                } // End Using tiffImage 
    
                            }
                        } // End Using byteStream 
    
                    } // End Using inputImage 
    
                } // Next i 
    
                ba = ms.ToArray();
            } // End Using ms 
    
            System.IO.File.WriteAllBytes(@"d:\mytiff.tiff", ba);
    
            //if (multiPageFile != null)
            //{
            //    multiPageFile.Dispose();
            //    multiPageFile = null;
            //}
    
            return multiPageFile;
        }
    
    
        private static System.Drawing.Image SaveImages(
              System.Drawing.Imaging.ImageCodecInfo tiffCodec
            , System.IO.MemoryStream outputStream
            , System.Drawing.Image tiffImage, System.Drawing.Image firstImage)
        {
    
    
            using (System.Drawing.Imaging.EncoderParameters encParameters =
                  new System.Drawing.Imaging.EncoderParameters(3))
            {
    
                if (firstImage == null)
                {
                    encParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(
                        System.Drawing.Imaging.Encoder.SaveFlag
                        , (long)System.Drawing.Imaging.EncoderValue.MultiFrame // 18L 
                    );
                }
                else
                {
                    encParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(
                        System.Drawing.Imaging.Encoder.SaveFlag
                        , (long)System.Drawing.Imaging.EncoderValue.FrameDimensionPage // 23L
                    );
                }
    
                encParameters.Param[1] = new System.Drawing.Imaging.EncoderParameter(
                    System.Drawing.Imaging.Encoder.ColorDepth, 24L
                );
    
    
                encParameters.Param[2] = new System.Drawing.Imaging.EncoderParameter(
                    System.Drawing.Imaging.Encoder.Compression
                    , (long)System.Drawing.Imaging.EncoderValue.CompressionLZW
                );
    
    
                if (firstImage == null)
                {
                    firstImage = tiffImage;
    
                    ((System.Drawing.Bitmap)tiffImage).SetResolution(96, 96);
                    firstImage.Save(outputStream, tiffCodec, encParameters);
                }
                else
                {
                    ((System.Drawing.Bitmap)tiffImage).SetResolution(96, 96);
    
                    firstImage.SaveAdd(tiffImage, encParameters);
                }
    
                if (encParameters.Param[0] != null)
                    encParameters.Param[0].Dispose();
    
                if (encParameters.Param[1] != null)
                    encParameters.Param[1].Dispose();
    
                if (encParameters.Param[2] != null)
                    encParameters.Param[2].Dispose();
    
            } // End Using encParameters 
    
            return firstImage;
        }
    
    
    }
    

    【讨论】:

    • 嘿,“string[] filez”这应该是什么类型的文件?我正在向其发送 pdf 文件的路径,但出现错误
    • 任何类型的 System.Drawing.Image 都可以打开,例如 png、bmp、jpg、gif、tiff、wmf、exif 和 memorybmp。换句话说,没有 PDF 也没有 SVG。 docs.microsoft.com/en-us/dotnet/api/…
    【解决方案4】:

    有用的话题。谢谢(你的)信息。我需要从 base64 编码字符串数组中拼接多页图像。这是我根据这个线程中的信息汇总的。我不太明白为什么我必须创建一个明确指定的图像格式的内存流,但这就是最终的工作,如果有更好的方法来处理这个问题,请告诉我。谢谢

    /// <summary>
        /// Takes in an array of base64 encoded strings and creates a multipage tiff.
        /// </summary>
        /// <param name="sOutFile">file to be generated</param>
        /// <param name="pagesbase64Array"></param>
        private void SaevAsMultiPageTiff(string sOutFile, string[] pagesbase64Array)
        {
            System.Drawing.Imaging.Encoder encoder = System.Drawing.Imaging.Encoder.SaveFlag;
            ImageCodecInfo encoderInfo = ImageCodecInfo.GetImageEncoders().First(i => i.MimeType == "image/tiff");
            EncoderParameters encoderParameters = new EncoderParameters(1);
            encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.MultiFrame);
    
            Bitmap firstImage = null;
            try
            {
    
                using (MemoryStream ms1 = new MemoryStream())
                {
                    using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(pagesbase64Array[0])))
                    {
                        Image.FromStream(ms).Save(ms1, ImageFormat.Tiff);
                        firstImage = (Bitmap)Image.FromStream(ms1);
                    }
                    // Save the first frame of the multi page tiff
                    firstImage.Save(sOutFile, encoderInfo, encoderParameters); //throws Generic GDI+ error if the memory streams are not open when this is called
                }
    
    
                encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.FrameDimensionPage);
    
                Bitmap imagePage;
                // Add the remining images to the tiff
                for (int i = 1; i < pagesbase64Array.Length; i++)
                {
    
                    using (MemoryStream ms1 = new MemoryStream())
                    {
                        using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(pagesbase64Array[i])))
                        {
                            Image.FromStream(ms).Save(ms1, ImageFormat.Tiff);
                            imagePage = (Bitmap)Image.FromStream(ms1);
                        }
    
                        firstImage.SaveAdd(imagePage, encoderParameters); //throws Generic GDI+ error if the memory streams are not open when this is called
                    }
                }
    
            }
            catch (Exception)
            {
                //ensure the errors are not missed while allowing for flush in finally block so files dont get locked up.
                throw;
            }
            finally
            {
                // Close out the file
                encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.Flush);
                firstImage.SaveAdd(encoderParameters);
            }
        }   
    

    【讨论】:

      【解决方案5】:

      在处理和创建标准化格式的文件时,我不喜欢 Microsoft 的跟踪记录,我建议使用 ImageMagick,它以 MagickNet 的形式作为 .Net 库提供(请注意,http://midimick.com/magicknet/ 目前有间谍软件弹出窗口,我已通知网站所有者)。

      【讨论】:

        【解决方案6】:

        这里是多tiff文件的拆分操作。它就像字符串子字符串函数一样工作。图像的第一个索引将是您的 MasterBitMap,您将继续向 MasterBitmap 添加帧,直到索引结束。

        public void SaveMultiFrameTiff(int start, int end)
            {            
                string outputFileName = "out.TIF";  
                string inputFileName = "input.TIF";            
        
                try
                {                
        
                    Bitmap MasterBitmap = new Bitmap(inputFileName ); //Start page of document(master)
                    Image imageAdd = Image.FromFile(inputFileName );  //Frame Image that will be added to the master          
                    Guid guid = imageAdd.FrameDimensionsList[0]; //GUID
                    FrameDimension dimension = new FrameDimension(guid);
                    // start index cannot be less than 0 and cannot be greater than frame count        
                    if (start < 1 || end > MasterBitmap.GetFrameCount(dimension)) { return; }        
        
                    EncoderParameters ep = new EncoderParameters(1);
        
                    //Get Image Codec Information
                    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
                    ImageCodecInfo codecInfo = codecs[3]; //image/tiff
        
                    //MultiFrame Encoding format
                    EncoderParameter epMultiFrame = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.MultiFrame);
                    ep.Param[0] = epMultiFrame;
                    MasterBitmap.SelectActiveFrame(dimension, start - 1);
                    MasterBitmap.Save(outputFileName, codecInfo, ep);//create master document
        
                    //FrameDimensionPage Encoding format
                    EncoderParameter epFrameDimensionPage = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.FrameDimensionPage);
                    ep.Param[0] = epFrameDimensionPage;
        
                    for (int i = start; i < end; i++)
                    {
                        imageAdd.SelectActiveFrame(dimension, i);//select next frame
                        MasterBitmap.SaveAdd(new Bitmap(imageAdd), ep);//add it to the master
                    }
        
                    //Flush Encoding format
                    EncoderParameter epFlush = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.Flush);
                    ep.Param[0] = epFlush;
                    MasterBitmap.SaveAdd(ep); //flush the file                   
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
        

        【讨论】:

          【解决方案7】:

          下面是如何在 vb.net 中执行此操作:

          Imports System.Drawing.Imaging
          
          Sub CreateTiff(sOutTiffFile As String, sInFile1 As String, sInFile2 As String)
              Dim bitmap As Bitmap = Image.FromFile(sInFile1)
              Dim byteStream As MemoryStream = New MemoryStream()
              bitmap.Save(byteStream, System.Drawing.Imaging.ImageFormat.Tiff)
          
              Dim tiff As Image = Image.FromStream(byteStream)
          
              Dim oParams As EncoderParameters = New EncoderParameters(2)
              oParams.Param(0) = New EncoderParameter(Imaging.Encoder.Compression, EncoderValue.CompressionCCITT4)
              oParams.Param(1) = New EncoderParameter(Imaging.Encoder.SaveFlag, EncoderValue.MultiFrame)
              tiff.Save(sOutTiffFile, GetEncoderInfo("image/tiff"), oParams)
          
              'Next Page
              Dim bitmap2 As Bitmap = Image.FromFile(sInFile2)
              oParams.Param(1) = New EncoderParameter(Imaging.Encoder.SaveFlag, EncoderValue.FrameDimensionPage)
              tiff.SaveAdd(bitmap2, oParams)
          
              'Flush 
              Dim oFlushParams As EncoderParameters = New EncoderParameters(1)
              oFlushParams.Param(0) = New EncoderParameter(Imaging.Encoder.SaveFlag, EncoderValue.Flush)
              tiff.SaveAdd(oFlushParams)
          End Sub
          
          Private Function GetEncoderInfo(mimeType As String) As System.Drawing.Imaging.ImageCodecInfo
              Dim encoders = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()
              For i As Integer = 0 To encoders.Length - 1
                  If encoders(i).MimeType = mimeType Then
                      Return encoders(i)
                  End If
              Next
              Return Nothing
          End Function
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-01-06
            • 2020-05-16
            • 2019-06-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多