0

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

2 に答える 2

1

foreach-loopとfor-loopを1つで使用しています。リストを使用する場合、最後のページはimages.Last()によってアクセスされ、最初のページはimages.First()によってアクセスされ、対応するimage-objectsを返します。

また、現在、すべての画像を自分自身のために保存しているようです。あなたが何ページ持っているかはわかりませんが、それらがたくさんある場合は、時間がかかる可能性があります。それらをすべて処理して、最後にすべてを一度に保存してみましたか?ハードディスクへのアクセスには時間がかかるからです。テキストファイルの特定の行を処理して、それを新しいものに一度保存したときに、その問題が発生しました.....それが「ファイル全体を書き込まずに」という制限で意図したものでない場合。

お役に立てば幸いです。

于 2013-01-15T14:31:55.087 に答える
1

一時ファイルで作業する代わりに、元のファイルで作業し、最後のページのローテーションのみを保存することができます。(編集:うまくいかないようです)


編集:最初のフレームのみを複製し、他のすべてのフレームを追加して最後のフレームを回転させます..

このようなもの :

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;
    }
于 2013-01-15T14:54:59.583 に答える