将多页TIFF转换为PNG .Net

8

我能够利用.Net将单页TIFF转换为PNG,但是,如果要处理多页TIFF文件该怎么做呢?

5个回答

9

感谢 @Tom Halladay

我将提供一个C#版本的您的代码。

private static Bitmap ConvertTiffToBitmapStream(byte[] tiffImage){
    System.Drawing.Image ImageBitmap = Bitmap.FromStream(new MemoryStream(tiffImage));
    int FrameCount = ImageBitmap.GetFrameCount(FrameDimension.Page);
    int RunningHeight = 0;
    int MaxWidth = 0;

    for (int MeasurementFrameIndex = 0; MeasurementFrameIndex <= FrameCount - 1; MeasurementFrameIndex++){
        ImageBitmap.SelectActiveFrame(FrameDimension.Page, MeasurementFrameIndex);
        RunningHeight += ImageBitmap.Height;
        MaxWidth = Math.Max(MaxWidth, ImageBitmap.Width);
    }

    Bitmap CombinedBitmap = new Bitmap(MaxWidth, RunningHeight);
    int RunningVerticalPosition = 0;

    for (int CombinationFrameIndex = 0; CombinationFrameIndex <= FrameCount - 1; CombinationFrameIndex++){
        ImageBitmap.SelectActiveFrame(FrameDimension.Page, CombinationFrameIndex);
        EmbedBitmap(new Bitmap(ImageBitmap), ref CombinedBitmap, RunningVerticalPosition);
        RunningVerticalPosition += ImageBitmap.Height + 1;
    }
    return CombinedBitmap;
}

private static void EmbedBitmap(Bitmap SourceBitmap, ref Bitmap DestinationBitmap, int VerticalPosition){
    Rectangle SourceRectangle = new Rectangle(new Point(0, 0), new Size(SourceBitmap.Width, SourceBitmap.Height));
    Rectangle DestinationRectangle = new Rectangle(new Point(0, VerticalPosition), new Size(SourceBitmap.Width, SourceBitmap.Height));

    using (Graphics Canvas = Graphics.FromImage(DestinationBitmap)){
        Canvas.DrawImage(SourceBitmap, DestinationRectangle, SourceRectangle, GraphicsUnit.Pixel);
    }
}

作为C#转换,这里的命名约定真的很笨拙,我相当确定仍有未明确处理的IDisposable元素(如ImageBitmapMemoryStream等)。 - CajunCoding

6
你应该在循环中选择活动帧(页面),并将每个tiff页面转换为png格式。
int pageCount = 1;
try
{
    pageCount = bmp.GetFrameCount(FrameDimension.Page);
}
catch (Exception)
{
    // sometimes GDI+ throws internal exceptions.
    // just ignore them.
}

for (int page = 0; page < pageCount; page++)
{
    bmp.SelectActiveFrame(FrameDimension.Page, page);
    // save or otherwise process tiff page
}

这段代码假设您可以在System.Drawing.Bitmap对象中加载Tiff图像。


3

不需要第三方程序集的完整示例:

' MAIN CODE '

Dim ImageBitmap = Bitmap.FromStream(ImageStream)

Dim FrameCount = ImageBitmap.GetFrameCount(FrameDimension.Page)

Dim RunningHeight As Integer = 0
Dim MaxWidth As Integer = 0

For MeasurementFrameIndex As Integer = 0 To FrameCount - 1
    ImageBitmap.SelectActiveFrame(FrameDimension.Page, MeasurementFrameIndex)

    RunningHeight += ImageBitmap.Height
    MaxWidth = Math.Max(MaxWidth, ImageBitmap.Width)
Next

Dim CombinedBitmap As New Bitmap(MaxWidth, RunningHeight)
Dim RunningVerticalPosition As Integer = 0

For CombinationFrameIndex As Integer = 0 To FrameCount - 1
    ImageBitmap.SelectActiveFrame(FrameDimension.Page, CombinationFrameIndex)

    EmbedBitmap(ImageBitmap, CombinedBitmap, RunningVerticalPosition)

    RunningVerticalPosition += ImageBitmap.Height + 1
Next



    ' SUPPORT ROUTINES '

Private Shared Sub EmbedBitmap(
        SourceBitmap As Bitmap,
        ByRef DestinationBitmap As Bitmap,
        VerticalPosition As Integer)

    Dim SourceRectangle As New Rectangle(
        New Point(0, 0),
        New Size(SourceBitmap.Width, SourceBitmap.Height))

    Dim DestinationRectangle As New Rectangle(
        New Point(0, VerticalPosition),
        New Size(SourceBitmap.Width, SourceBitmap.Height))

    Using Canvas As Graphics = Graphics.FromImage(DestinationBitmap)
        Canvas.DrawImage(
            SourceBitmap,
            DestinationRectangle,
            SourceRectangle,
            GraphicsUnit.Pixel)
    End Using
End Sub

2
我知道这是一个老问题,但在.NET Core、.NET5+等世界中,它需要不同的解决方案,因为本地的.NET库,如System.Drawing.Image,只能在Windows平台上工作,而不能在其他部署,如Linux上工作。
因此,现在第三方选项实际上是正确的选择,ImageSharp是一个很棒的开源选项... 它轻松支持以下操作:

    using (var image = ImageSharp.Load(imageBytes))
    {
        //Process all possible Frames -- this same flow supports single images as well as Multi-page TIFF Images!
        for (var frameIndex = 0; frameIndex < image.Frames.Count; frameIndex++)
        {
            var clonedImageFrame = image.Frames.CloneFrame(frameIndex);
            await using var extractedImageStream = new MemoryStream();
            
            //There are a variety of overloads to extract in any format you like...
            //await clonedImageFrame.SaveAsTiffAsync(extractedImageStream).ConfigureAwait(false);
            //await clonedImageFrame.SaveAsJpegAsync(extractedImageStream, new JpegEncoder() { Quality = 80 }).ConfigureAwait(false);
            await clonedImageFrame.SaveAsPngAsync(extractedImageStream).ConfigureAwait(false);
            
            //Now you can do what you like with the extractedImageFrame. . . .
            var extractedImageFrameBytes = extractedImageStream.ToArray();
        
        }
    }

1

Imagemagick 可以处理几乎所有与图像相关的事情,但由于可供选择的选项数量庞大,可能需要一些时间才能掌握它。您可以使用 interop 直接与 Imagemagick 进行交互,也可以使用 .NET 封装器。我只使用过 interop,所以不知道 封装器 的好坏。

private readonly ImageMagickObject.MagickImageClass _imageMagick = new ImageMagickObject.MagickImageClass();

var parameters = new object[] {sourcePath, destPath};
_imageMagick.Convert(ref parameters);

你需要自己在ImageMagick网站上找到相应的参数。查看命令行参数的帮助并搜索多页tiff的论坛。我假设你想将tiff文件拆分成多个png文件?那么可以尝试使用以下命令:

convert multipage.tif single%d.png


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