将多个多页 tiff 图像合并为单个 tiff C#

8

在我的场景中,我有3个或更多的多页tiff图像,需要将它们合并成一个单独的tiff图像。

以下是我尝试过的代码。它可以将所有tiff图像的第一页合并成一个单独的tiff图像。

private static void MergeTiff(string[] sourceFiles)
{
    string[] sa = sourceFiles;
    //get the codec for tiff files
    ImageCodecInfo info = null;
    foreach (ImageCodecInfo ice in ImageCodecInfo.GetImageEncoders())
        if (ice.MimeType == "image/tiff")
            info = ice;

    //use the save encoder
    Encoder enc = Encoder.SaveFlag;

    EncoderParameters ep = new EncoderParameters(1);
    ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.MultiFrame);

    Bitmap pages = null;

    int frame = 0;

    foreach (string s in sa)
    {
        if (frame == 0)
        {
            MemoryStream ms = new MemoryStream(File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, @"C:\Data_Warehouse\SVNRepository\CD.BNS.W5555.LT45555C.D180306.T113850.Z0101\", s)));
            pages = (Bitmap)Image.FromStream(ms);

            var appDataPath = @"C:\Data_Warehouse\SVNRepository\Tiffiles\";
            var filePath = Path.Combine(appDataPath, Path.GetRandomFileName() + ".tif");

            //save the first frame
            pages.Save(filePath, info, ep);
        }
        else
        {
            //save the intermediate frames
            ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.FrameDimensionPage);

            try
            {
                MemoryStream mss = new MemoryStream(File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, @"C:\Data_Warehouse\SVNRepository\CD.BNS.W5555.LT45555C.D180306.T113850.Z0101\", s)));
                Bitmap bm = (Bitmap)Image.FromStream(mss);
                pages.SaveAdd(bm, ep);
            }
            catch (Exception e)
            {
                //LogError(e, s);
            }
        }

        if (frame == sa.Length - 1)
        {
            //flush and close.
            ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.Flush);
            pages.SaveAdd(ep);

        }

        frame++;
    }

}

我需要合并多个tiff图像,并包含每个tiff图像的所有页面。请给予建议!
谢谢
编辑:从下面的答案更新
if (frame == 0)
            {
                MemoryStream ms = new MemoryStream(File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, @"C:\OMTest\Working\", s)));
                pages = (Bitmap)Image.FromStream(ms);

                var appDataPath = @"C:\Data_Warehouse\SVNRepository\Tiffiles\";
                var filePath = Path.Combine(appDataPath, Path.GetRandomFileName() + ".tif");

                //save the first frame
                pages.Save(filePath, info, ep);

                //Save the second frame if any
                int frameCount1 = pages.GetFrameCount(FrameDimension.Page);
                if (frameCount1 > 1)
                {
                    for (int i = 1; i < frameCount1; i++)
                    {
                        ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.FrameDimensionPage);
                        pages.SelectActiveFrame(FrameDimension.Page, i);
                        pages.SaveAdd(pages, ep);
                    }
                }
            }
            else
            {
                //save the intermediate frames
                ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.FrameDimensionPage);
                try
                {
                    MemoryStream mss = new MemoryStream(File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, @"C:\OMTest\Working\", s)));
                    Bitmap bm = (Bitmap)Image.FromStream(mss);
                    int frameCount = bm.GetFrameCount(FrameDimension.Page);
                    for (int i = 0; i < frameCount; i++)
                    {
                        bm.SelectActiveFrame(FrameDimension.Page, i);
                        pages.SaveAdd(bm, ep);
                    }
                }
                catch (Exception e)
                {
                    //LogError(e, s);
                }
            }
2个回答

9
你需要选择活动框架以确保获取TIFF上的所有页面。在你的代码中,你需要获取帧数并循环处理
你的else块中的代码可能如下所示:
MemoryStream mss = new MemoryStream(File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, @"C:\Data_Warehouse\SVNRepository\CD.BNS.W5555.LT45555C.D180306.T113850.Z0101\", s)));
Bitmap bm = (Bitmap)Image.FromStream(mss);
int frameCount = bm.GetFrameCount(FrameDimension.Page);
for(int i=0;i<frameCount;i++){
    bm.SelectActiveFrame(FrameDimension.Page, i);
    pages.SaveAdd(bm, ep);
}

您可能需要进行微调,因为我还没有测试过它。

非常感谢。您的代码完美地运行了,尽管我不得不稍作调整。为了方便其他人参考,我在编辑部分添加了修改后的代码。 - crony

1
给定的代码可以将单页TIFF文件合并为一个多页TIFF,但是如果源文件是多页TIFF,则在生成的TIFF文件中只会合并它们的第一页:其他页面将被丢弃。
由于我们找不到任何能解决这个问题的工作示例,所以我们最终编写了一个小的C#帮助类,后来成为一个完整的跨平台控制台应用程序,使用.NET Core 2和C#编写。我们称之为项目MergeTIFF,并在GitHub上以GNU v3许可证发布了整个源代码,以便其他人也可以使用它;我们还发布了Windows和Linux(32位和64位)的二进制文件。
以下是C#代码的相关摘录:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace MergeTiff.NET
{
    /// <summary>
    /// A small helper class to handle TIFF files
    /// </summary>
    public static class TiffHelper
    {
        /// <summary>
        /// Merges multiple TIFF files (including multipage TIFFs) into a single multipage TIFF file.
        /// </summary>
        public static byte[] MergeTiff(params byte[][] tiffFiles)
        {
            byte[] tiffMerge = null;
            using (var msMerge = new MemoryStream())
            {
                //get the codec for tiff files
                ImageCodecInfo ici = null;
                foreach (ImageCodecInfo i in ImageCodecInfo.GetImageEncoders())
                    if (i.MimeType == "image/tiff")
                        ici = i;

                Encoder enc = Encoder.SaveFlag;
                EncoderParameters ep = new EncoderParameters(1);

                Bitmap pages = null;
                int frame = 0;

                foreach (var tiffFile in tiffFiles)
                {
                    using (var imageStream = new MemoryStream(tiffFile))
                    {
                        using (Image tiffImage = Image.FromStream(imageStream))
                        {
                            foreach (Guid guid in tiffImage.FrameDimensionsList)
                            {
                                //create the frame dimension 
                                FrameDimension dimension = new FrameDimension(guid);
                                //Gets the total number of frames in the .tiff file 
                                int noOfPages = tiffImage.GetFrameCount(dimension);

                                for (int index = 0; index < noOfPages; index++)
                                {
                                    FrameDimension currentFrame = new FrameDimension(guid);
                                    tiffImage.SelectActiveFrame(currentFrame, index);
                                    using (MemoryStream tempImg = new MemoryStream())
                                    {
                                        tiffImage.Save(tempImg, ImageFormat.Tiff);
                                        {
                                            if (frame == 0)
                                            {
                                                //save the first frame
                                                pages = (Bitmap)Image.FromStream(tempImg);
                                                ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.MultiFrame);
                                                pages.Save(msMerge, ici, ep);
                                            }
                                            else
                                            {
                                                //save the intermediate frames
                                                ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.FrameDimensionPage);
                                                pages.SaveAdd((Bitmap)Image.FromStream(tempImg), ep);
                                            }
                                        }
                                        frame++;
                                    }
                                }
                            }
                        }
                    }
                }
                if (frame >0)
                {
                    //flush and close.
                    ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.Flush);
                    pages.SaveAdd(ep);
                }

                msMerge.Position = 0;
                tiffMerge = msMerge.ToArray();
            }
            return tiffMerge;
        }
    }
}

如果您需要更多信息和/或下载,请查看我们发布的以下资源以更好地记录整个项目:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接