Convert multipage TIFF to PNG .Net
I am able to convert a single page TIFF to a PNG in .Net, however, how would I do this for a multipag开发者_如何学Ce TIFF?
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);
}
}
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.
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
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
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();
}
}
精彩评论