将多页 TIFF 转换为 PNG .Net

发布于 2024-09-16 13:22:16 字数 58 浏览 9 评论 0原文

我可以将单页 TIFF 转换为 .Net 中的 PNG,但是,对于多页 TIFF,我该如何执行此操作?

I am able to convert a single page TIFF to a PNG in .Net, however, how would I do this for a multipage TIFF?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

久随 2024-09-23 13:22:23

Imagemagick 几乎可以对图像执行任何操作,但可能需要一段时间才能正确执行由于有大量的选项可供选择。您可以使用互操作直接使用 Imagemagick,也可以使用 .NET 包装器。我只使用过互操作,所以我不知道 包装器 有多好或多坏。

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

Imagemagick can do just about anything with images but it might take a while to get it right due to the overwhelming amount of options to choose from. You can use interop to work directly with Imagemagick or you can use a .NET wrapper. I have only used interop so I don't know how good or bad the wrapper is.

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

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

The parameters you'll have to find out for yourself on the ImageMagick website. Look at the help for the command line parameter and search the forum for multipage tiff. I assume you want to split the tiff into multiple pngs? Then maybe something like this:

convert multipage.tif single%d.png

一个人的旅程 2024-09-23 13:22:22

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

' 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

Complete example without the need for 3'rd party assemblies:

' 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
你爱我像她 2024-09-23 13:22:22

我知道这是一个老问题,但在 .NET Core、.NET5+ 等领域,它确实需要不同的解决方案,因为诸如 System.Drawing.Image 之类的本机 .NET 库仅适用于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();
        
        }
    }

I know this is an old question but in the world of .NET Core, .NET5+, etc. it really needs a different solution because native .NET libraries such as System.Drawing.Image will only work on Windows platforms and will not work on other deployments such as Linux.

So third party options are actually the way to go now, and ImageSharp is a great open-source option . . . which easily supports this as follows:


    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();
        
        }
    }
镜花水月 2024-09-23 13:22:21

谢谢@Tom Halladay,

我将提供您的代码的 ac# 版本

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

thanks @Tom Halladay

I'll provide a c# version of your code

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);
    }
}
且行且努力 2024-09-23 13:22:21

您应该循环选择活动帧(页面)并将每个 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 图像。

You should select active frame (page) in a loop and convert each tiff page to a 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
}

This code assumes that you can load Tiff image in System.Drawing.Bitmap object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文