2

異なる画像形式に変換する必要がある大きな画像ファイルがいくつかあります。これを行うには、次のコードを使用しています。

using (Image img =new Bitmap(inputImageName))
        {
            img.Save(outputImageName, imageFormat);
        } 

会話を行いますが、画像が大きいため、メモリ不足の例外が発生します。LOH の断片化を克服する方法についての記事をいくつか読みましたが、この場合はどれも使用できません。

私に何ができる?

画像は約 100MByte で、3 つまたは 4 つの画像を開いた後に発生します。

4

3 に答える 3

3

この記事に従って、GDI を使用しない WPF 画像操作クラスをご覧ください。次のソース コードは、出発点として適しています。

public static void Resize(string input, string output)
{
    using (var inputStream = File.OpenRead(input))
    {
        var photoDecoder = BitmapDecoder.Create(inputStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);

        var frame = photoDecoder.Frames[0];

        using (var ouputStream = File.Create(output))
        {
            var targetEncoder = new PngBitmapEncoder();
            targetEncoder.Frames.Add(frame);
            targetEncoder.Save(ouputStream);
        }
    }    
}
于 2013-01-18T15:22:48.403 に答える
3

ここで質問する必要があるのは、「これを .NET や C# で行う必要がありますか?」ということです。

多くの人々にとって、C# のような柔軟な言語が多くのタスクを実行するための答えである理由は理解できますが、「ハンマーしかない場合、すべての問題は釘のように見える」とも言わざるを得ません。

これが 1 回限りの変換で、1 つのプロジェクトにのみ使用する必要がある場合は、ジョブにより適したスタンドアロン ツールを使用することをお勧めします。

次のような有料アプリケーションに至るまで、たくさんあります。

AcdSee フォト マネージャー

http://www.acdsee.com/

などのツールを解放する

Ifran View とその画像変換関数

http://www.bleepingcomputer.com/forums/topic50519.html

コマンド ライン スクリプトがゲームの場合は、ImageMagik などのツール セットを使用します。

http://www.imagemagick.org/script/index.php

Iamage Magik には .NET バインディングも含まれているため、プロジェクトでプログラム コード内でオンザフライでこれらを変換する必要がある場合は、その機能を .NET プロジェクトや他の多くのプロジェクト内から使用できます。

http://www.imagemagick.org/script/api.php

このようなシナリオでは、車輪を再発明する理由はまったくありません。この問題は以前に何度も解決されているため、決定を下す必要はありません。

于 2013-01-18T14:41:43.207 に答える
2

ラージオブジェクトヒープとは何の関係もありません。BitmapクラスはGDI+のマネージラッパーであり、GDI+はアンマネージコードの大きな塊です。アンマネージメモリにピクセルデータバッファを割り当てます。コードが使用する管理メモリの量は非常に少ないです。

100メガバイトのイメージファイルは、必要なアンマネージメモリの量についてはあまり説明していません。おそらく、JPEGやPNGなどの圧縮画像形式です。これは、圧縮解除された後、より多くのアンマネージメモリを必要とします。したがって、簡単に数百メガバイトが必要になる可能性があります。

これは、32ビットオペレーティングシステムでコードを実行する場合、またはEXEのプラットフォームターゲット設定としてx86を選択した場合(VS2010以降のデフォルト)に問題になります。プログラムは、コードのチャンクとすでにロードされているデータの間にある穴から仮想メモリを割り当てます。GDI +は、ピクセルデータをロードするために連続したメモリのチャンクを必要とします。プログラムに使用可能な仮想メモリがたくさんあるが、それが多くの穴に分散している場合、それを実現するのは難しい場合があります。追加の問題は、アドレス空間の断片化です。DLLのロードまたはメモリの割り当てにより、大きな穴のサイズが2つに削減される可能性があります。

この問題には簡単な修正があります。64ビットオペレーティングシステムでコードを実行してください。利用可能な仮想メモリの塊、大きな穴があります。32ビットオペレーティングシステムで現在の問題について何でもできる可能性はほとんどありません。メモリマネージャを直接制御することはできません。

于 2013-01-18T15:14:21.513 に答える