c# - 如何优化此代码以创建 TIFF 文件和/或我应该考虑使用哪些替代库来提高性能?

标签 c# parallel-processing gdi+ tiff parallel.foreach

我正在创建一个进程来提取 TIFF,对其中一个图像执行操作,然后重建 TIFF。中间的操作并不重要,但是,提取和重建在处理方面被证明是非常昂贵的。

const string tifPath = "14 page.TIFF";
MemoryStream[] imageStreams;
var stream = new MemoryStream();

//extract tiff
using (var imageFile = Image.FromFile(tifPath))
{
    var imagePageCount = imageFile.GetFrameCount(FrameDimension.Page);
    imageStreams = new MemoryStream[imagePageCount];
    var frameDimension = new FrameDimension(imageFile.FrameDimensionsList[0]);

    for (var i = 0; i < imagePageCount; i++)
    {
        imageFile.SelectActiveFrame(frameDimension, i);
        var bmp = new Bitmap(imageFile);

        bmp.Save(stream, ImageFormat.Bmp);
        imageStreams[i] = stream;
    }
}

//build tiff
var encoder = Encoder.SaveFlag;
var encoderInfo = ImageCodecInfo.GetImageEncoders().First(i => i.MimeType == "image/tiff");
var encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.MultiFrame);

stream = new MemoryStream();
var firstImage = new Bitmap(Image.FromStream(imageStreams[0]));
firstImage.Save(stream, encoderInfo, encoderParameters);
encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.FrameDimensionPage);

for (var i = 1; i < imageStreams.Length; i++)
{
    var img = Image.FromStream(imageStreams[i]);
    firstImage.SaveAdd(img, encoderParameters);
}

encoderParameters.Param[0] = new EncoderParameter(encoder, (long)EncoderValue.Flush);
firstImage.SaveAdd(encoderParameters);

我发现清除我的流在某些地方有帮助。对于 Microsoft 和其他库(LeadTools 和 LibTiff),平均时间约为 5 秒。我不打算使用 C# 解决方案,但试图找到一种方法来尽可能压缩它。

最佳答案

我找不到并行创建过程的好方法。尝试从在 Parallel.ForEach 之外构建的 MemoryStream 构建图像只会引发一般 GDI+ 错误。

const string tifPath = "14 Page.TIFF";

//extract tiff
var imageFile = Image.FromFile(tifPath);
var imagePageCount = imageFile.GetFrameCount(FrameDimension.Page);
var imageStreams = new Bitmap[imagePageCount];
var rangePartioner = Partitioner.Create(0, imagePageCount);
var frameDimension = new FrameDimension(imageFile.FrameDimensionsList[0]);
imageFile.Dispose();

Parallel.ForEach(rangePartioner, (range, loopState) =>
{
    for (var i = range.Item1; i < range.Item2; i++)
    {
        using (var imageFile2 = Image.FromFile(tifPath))
        {
            imageFile2.SelectActiveFrame(frameDimension, i);
            imageStreams[i] = new Bitmap(imageFile2);
        }
    }
});

//build tiff
var encoder = Encoder.SaveFlag;
var encoderInfo = ImageCodecInfo.GetImageEncoders().First(i => i.MimeType == "image/tiff");
var encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(encoder, (long) EncoderValue.MultiFrame);

var stream2 = new MemoryStream();

using(var firstImage = imageStreams[0])
{
    firstImage.Save(stream2, encoderInfo, encoderParameters);

    encoderParameters.Param[0] = new EncoderParameter(encoder, (long) EncoderValue.FrameDimensionPage);

    for (var i = 1; i < imageStreams.Length; i++)
    {
        firstImage.SaveAdd(imageStreams[i], encoderParameters);
    }

    encoderParameters.Param[0] = new EncoderParameter(encoder, (long) EncoderValue.Flush);
    firstImage.SaveAdd(encoderParameters);
}           

这缩短了大约 2 秒。仍在寻找处理下半年的好方法。

编辑:添加了仅转换图像而不将其保存到流中的建议更改。 编辑:添加了其余修复。

关于c# - 如何优化此代码以创建 TIFF 文件和/或我应该考虑使用哪些替代库来提高性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20668744/

相关文章:

c# - 绘制多条徒手折线或曲线图 - 添加撤消功能

c# - 获取 EXIF 方向标签,旋转到正确的方向,处理图像并以正确的方向保存图像

scala - Spark 作业未在本地并行化(使用本地文件系统中的 Parquet + Avro)

java - 并行处理: class file has wrong version 49. 0,应该是48.0

c - pthread_cond_wait() 实际上是如何工作的?

c# - 重构代码,使顶级实体的行为像一个上下文

C++ GetTextExtentPoint32 未给出正确的大小

c# - 如何在 .NET 中通过 Saxon-HE 9.8 使用 XSLT 3.0

c# - 应用程序退出代码始终返回 0

c# - VB.Net 中的匿名类初始化