C# 在 .NET 2.0 中将位图转换为一个多页 TIFF 图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/398388/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert bitmaps to one multipage TIFF image in .NET 2.0
提问by mirezus
How can i convert an array of bitmaps into a brand new image of TIFF format, adding all the bitmaps as frames in this new tiff image?
如何将位图数组转换为全新的 TIFF 格式图像,将所有位图添加为这个新 tiff 图像中的帧?
using .NET 2.0.
使用 .NET 2.0。
采纳答案by Otávio Décio
Start with the first bitmap by putting it into an Image object
从第一个位图开始,将其放入 Image 对象中
Bitmap bitmap = (Bitmap)Image.FromFile(file);
Save the bitmap to memory as tiff
将位图保存为 tiff
MemoryStream byteStream = new MemoryStream();
bitmap.Save(byteStream, ImageFormat.Tiff);
Put Tiff into another Image object
将 Tiff 放入另一个 Image 对象
Image tiff = Image.FromStream(byteStream)
Prepare encoders:
准备编码器:
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);
Save to file:
保存到文件:
tiff.Save(sOutFilePath, encoderInfo, encoderParams);
For subsequent pages, prepare encoders:
对于后续页面,准备编码器:
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);
Finally flush the file:
最后刷新文件:
EncoderParameter SaveEncodeParam = new EncoderParameter(
Encoder.SaveFlag, (long)EncoderValue.Flush);
EncoderParams = new EncoderParameters(1);
EncoderParams.Param[0] = SaveEncodeParam;
tiff.SaveAdd(EncoderParams);
That should get you started.
这应该让你开始。
回答by Sparr
Not being a fan of Microsoft's track record when it comes to handling and creating files of standardized formats, I would suggest using ImageMagick, available as a .Net library in the form of MagickNet(beware, http://midimick.com/magicknet/currently has a spyware popup, I have alerted the site owner).
在处理和创建标准化格式的文件时,我不喜欢 Microsoft 的跟踪记录,我建议使用 ImageMagick,它以MagickNet的形式作为 .Net 库提供(注意,http: //midimick.com/magicknet/目前有一个间谍软件弹出窗口,我已通知网站所有者)。
回答by Skadoosh
Came across this post after a bit of searching on Google. I tried the code that was in the post by a'b'c'd'e'f'g'h', but that didn't work for me. Perhaps, I was not doing something correctly.
在谷歌上搜索了一下后发现了这篇文章。我尝试了 a'b'c'd'e'f'g'h' 帖子中的代码,但这对我不起作用。也许,我没有做正确的事情。
In any case, I found another post that saved images to multi page tiffs. Here is the link to the post: http://www.bobpowell.net/addframes.htm
无论如何,我发现了另一篇将图像保存到多页 tiff 的帖子。这是帖子的链接:http: //www.bobpowell.net/addframes.htm
Also, here is the code that worked for me. It should be identical to that post.
另外,这是对我有用的代码。它应该与那个帖子相同。
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);
回答by cihata87
Here is the split operation of multi-tiff file. It works just like string substring function. The first index of image will be your MasterBitMap and you will keep adding frame to the MasterBitmap till the end of index.
这里是多 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;
}
}
}
回答by Karshan
helpful topic. thanks for the info. I had a need to stitch a multipage image from an array of base64 encoded strings. This is what i put together based on the information in this thread. I dont quite underststand why i have to create a memory stream with the image format specified explicitly but this is what ended up working, if there is a better way to deal with this please let me know. thanks
有用的话题。谢谢(你的)信息。我需要从 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);
}
}
回答by Stefan Steiger
Necromancing
The accepted answer is a bit vague.
Here's full working code:
死灵法师
接受的答案有点含糊。
这是完整的工作代码:
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;
}
}
回答by Igor Krupitsky
Here is how to do this in vb.net:
以下是在 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