【问题标题】:Saving multipage tiff without writing the whole file保存多页 tiff 而不写入整个文件
【发布时间】:2013-01-16 21:35:55
【问题描述】:

我面临一个挑战,我需要在 tiff 文件的最后一页上做一些工作。所以我写了下面的示例代码,它确实有效,只是运行缓慢。代码最终会执行很多,我需要加快速度。

我已经尝试过多线程的想法,但我认为结果并不好,因为最终所有数据都必须写入同一个文件,这似乎是耗时的部分。

我希望有一个答案可以告诉我如何只在最后一页上工作,或者我还没有考虑过。

private void rotateLastPage() {
    string inputfile = "C:\\input.tif";
    string tmpfile = inputfile + ".tmp";

    Bitmap bmap = (Bitmap)Image.FromFile(inputfile);
    int max = bmap.GetFrameCount(FrameDimension.Page);

    Image[] images = new Image[max];
    int i;
    for (i = 0; i < max; i++)
    {
            bmap.SelectActiveFrame(FrameDimension.Page, i);
            images[i] = (Image)bmap.Clone();
    }
    bmap.Dispose();

    Bitmap pages = null;
    i = 0;
    foreach(Image image in images)
    {
        try
        {
            if (i == max - 1)
            {
                image.RotateFlip(RotateFlipType.Rotate90FlipNone);
            }
            EncoderParameters encoderParameters = new EncoderParameters(2);
            encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.MultiFrame);

            Int16 c = BitConverter.ToInt16(image.PropertyItems[Array.IndexOf(image.PropertyIdList, 0x103)].Value, 0);

            if (c != 4 && c != 5)
            {
                throw new ArgumentException("Only CCIT4 and LZW compressed images are allowed.");
            }
            else if (c == 4)
            {
                encoderParameters.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT4);
            }
            else if (c == 5)
            {
                encoderParameters.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW);
            }

            if (i == 0)
            {
                pages = (Bitmap)image;
                ImageCodecInfo encoder = getTiffEncoder();
                pages.Save(tmpfile, encoder, encoderParameters);
            }
            else
            {
                encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.FrameDimensionPage);
                pages.SaveAdd(image, encoderParameters);
            }

            if (i == max - 1)
            {
                encoderParameters = new EncoderParameters(1);
                encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)EncoderValue.Flush);
                pages.SaveAdd(encoderParameters);
            }
            i++;
        }
        catch (Exception e)
        {
            Console.WriteLine(String.Format("Unable to rotate page {0} in file {1} due to {2}", (i + 1).ToString(), inputfile, e.Message));
            break;
        }
    }

    foreach (Image image in images) {
        image.Dispose();
    }
    pages.Dispose();

    // eventually overwrite input file with tmp file
}

private static ImageCodecInfo getTiffEncoder()
{
    ImageCodecInfo encoder = null;
    ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
    for (int i = 0; i < encoders.Length; i++)
    {
        if (encoders[i].MimeType == "image/tiff")
        {
            encoder = encoders[i];
        }
    }
    if (encoder == null)
    {
        throw new NotSupportedException("Unable to find a tiff encoder.");
    }
    return encoder;
}

【问题讨论】:

标签: c# tiff multipage


【解决方案1】:

您正在使用一个 foreach 循环和一个 for 循环。如果您要使用 List,则最后一页由 images.Last() 访问,第一个页面由 images.First() 访问,返回相应的图像对象。

此外,现在您似乎正在为自己保存每张图片。我不知道你有多少页,但如果这些是一堆,那可能需要很长时间。您是否尝试过全部处理它们然后最后一次保存它们?因为访问硬盘很费时间。当我处理文本文件的某些行并将其保存到一个新文件时遇到了这个问题.....如果这不是您对“不写入整个文件”的限制的意思。

希望有帮助!

【讨论】:

    【解决方案2】:

    您可以处理原始文件并仅保存最后一页的旋转,而不是处理临时文件。 (编辑:它似乎不起作用)


    编辑:仅克隆第一帧,添加所有其他帧并旋转最后一帧..

    类似这样的:

    public void rotateLastPage()
        {
            string inputfile = @"u:\\input.tiff";
    
            Bitmap bmap = (Bitmap)Image.FromFile(inputfile);
            int max = bmap.GetFrameCount(FrameDimension.Page);
    
            try
            {
                EncoderParameters encoderParameters = GetEncoderParameters(bmap, EncoderValue.MultiFrame);
                ImageCodecInfo encoder = GetTiffEncoder();
                var firstPage = (Image)bmap.Clone();
                firstPage.Save(inputfile+".tmp", encoder, encoderParameters);
                for (int i = 1; i < max - 1; i++)
                {
                    bmap.SelectActiveFrame(FrameDimension.Page, i);
                    encoderParameters = GetEncoderParameters(bmap, EncoderValue.FrameDimensionPage);
                    firstPage.SaveAdd(bmap, encoderParameters);
                }
                bmap.SelectActiveFrame(FrameDimension.Page, max - 1);
                bmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
                encoderParameters = GetEncoderParameters(bmap, EncoderValue.FrameDimensionPage);
                firstPage.SaveAdd(bmap, encoderParameters);
                firstPage.SaveAdd(GetEncoderParameters(EncoderValue.Flush));
            }
            catch (Exception e)
            {
                Console.WriteLine(String.Format("Unable to rotate page {0} in file {1} due to {2}", max.ToString(), inputfile, e.Message));
            }
            bmap.Dispose();
        }
    
        private static EncoderParameters GetEncoderParameters(Image image, EncoderValue encoderValue)
        {
            EncoderParameters encoderParameters = new EncoderParameters(2);
            encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)encoderValue);
            encoderParameters.Param[1] = GetCompressionEncoder(image);
            return encoderParameters;
        }
        private static EncoderParameters GetEncoderParameters(EncoderValue encoderValue)
        {
            EncoderParameters encoderParameters = new EncoderParameters(1);
            encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.SaveFlag, (long)encoderValue);            
            return encoderParameters;
        }
    
        private static EncoderParameter GetCompressionEncoder(Image image)
        {
            Int16 c = BitConverter.ToInt16(image.PropertyItems[Array.IndexOf(image.PropertyIdList, 0x103)].Value, 0);
    
            if (c == 4)
            {
                return new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT4);
            }
            else if (c == 5)
            {
                return new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW);
            }
            throw new ArgumentException("Only CCIT4 and LZW compressed images are allowed.");
        }
    
        private static ImageCodecInfo GetTiffEncoder()
        {
            ImageCodecInfo encoder = null;
            ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
            for (int i = 0; i < encoders.Length; i++)
            {
                if (encoders[i].MimeType == "image/tiff")
                {
                    encoder = encoders[i];
                }
            }
            if (encoder == null)
            {
                throw new NotSupportedException("Unable to find a tiff encoder.");
            }
            return encoder;
        }
    

    【讨论】:

    • 我重写了我的代码以匹配发布的代码,它会旋转文件中的最后一页,但它也会将该文件中的页面减少到最后一页。您是否运行了发布的代码并得到了与我不同的结果?
    • 我已将发布的代码放入一个干净的新项目中并运行它。如果您将 Console.WriteLine(...) 替换为 MessageBox.Show(...),我想您会看到引发的异常,导致旋转后的图像无法保存。如果没有抛出异常,则只剩下最后一页。
    猜你喜欢
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多