2011-11-23 7 views
9

現在、非常に大きな画像を処理していますが、基本的にはパノラマやフォトモザイクなどの小さな画像を多数つなぎ合わせて生成します。メモリ不足の例外を防ぐために、小さな画像を整理する方法の「マップ」だけがメモリです)、BinaryWriterとLockBitsを使ってビットマップとしてこれらの画像を1行ずつ保存するコードを書きました。ここまでは順調ですね。c#非常に大きなビットマップをjpegs(または他の圧縮形式)として保存する

問題は、これらの画像をJpeg(またはPNG)として保存することになりました。私はかなり新しいので、私は今のところ2つの方法しか考えることができません。

1)ビットマップ保存手順と似ています。いくつかのjpegヘッダーを生成し、大きなイメージを1行ずつ保存し、前に何らかの形でそれらを圧縮します。私はどのように圧縮を実行するか分かりません。

2)すでに保存されているビットマップをメモリにストリーミングし、エンコードされたjpegとして保存します。

FileStream fsr = 
    new FileStream("input.bmp", FileMode.Open, FileAccess.Read); 
FileStream fsw = 
    new FileStream("output.jpg", FileMode.CreateNew, FileAccess.Write); 

EncoderParameters encoderParameters = new EncoderParameters(1); 
encoderParameters.Param[0] = 
    new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 80L); 

Bitmap bmp = new Bitmap(fsr); 
bmp.Save(fsw, GetEncoder(ImageFormat.Jpeg), encoderParameters); 
bmp.Dispose(); 

問題はメモリ不足を引き起こし、保存法が完全に最初のメモリにビットマップをロードしようということになりました。第二のアプローチは容易に見えたので

は、私はこのような何かを試してみました例外。

私は、この問題を解決する方法や迂回する方法に関する提案に満足しています。

+1

OutOfMemoryException - この日および年齢ではありませんか?あなたのビットマップの大きさはどれくらいですか? – zmbq

+2

はい、あなたは簡単にメモリの問題に遭遇することができます。私は適切に処分していたとしても、約10Kのイメージのサイズを変更して、 'OutOfMemoryException'に頻繁に走っていました。 – DarthVader

+1

ビットマップからのOOMは非常に疑わしいです。このクラスは、悪いパラメータなどを含む間違ったものについてメモリ例外をスローします。 –

答えて

0

私はこれを.NETで行うことはできないと思っていますが、Cライブラリを呼び出すことでいつも重い作業をすることができます。私は自分で使ったことはありませんが、GraphicsMagickライブラリを見ることをお勧めします。これは、オープンソースと商用の両方を可能にするライセンス付きのCライブラリであり、必要とするように見えます。 JPEG圧縮は、いくつかの重要な非自明な欠点を持っていることを

+0

ありがとう、私はそれを見ていきます。しかし、私は実際に余分なライブラリを避けることを好むでしょう。 – mgulde

+0

GraphicsMagickのlibをチェックアウトしましたが、jpeg(またはpng)をチャンクで書く方法について何も見つかりませんでした。 – mgulde

1

注:

1)あなたが同じイメージを再生成しませんので、JPEGは、非可逆です。これは完全に受け入れられるかもしれませんが、ソースイメージを正確に再生成する必要がある場合は、PNGを使用してください。

2)JPEGは8ピクセル境界で整列されます。あなたが一緒にサイズが8の倍数ではない画像をシュティッヒ、いずれかの幅または高さで、あなたのユースケースを考慮すると、画像の境界

でいくつかの強力なアーティファクトを取得する場合、私はむしろ一緒にないステッチ画像に推薦する、とPNGまたはZlibなどの標準圧縮アルゴリズムを使用して、それぞれの小さな画像に適用します。圧縮されたストリームを1つのファイルに保存することはできます。利点は、抽出したい小さな画像の位置で直接「ジャンプ」することができるため、メモリを大量に節約できます。

デメリットは、大きな画像にすべての小さな画像を「視覚的にプレビュー」することができないことです(この用途にはプログラムを作成する必要があります)。

+0

まずは、ありがとうございます。 大きな画像を行単位で保存せずに8x8pxの塊で保存するようにコードを変更することは問題ありません。また、jpegとして保存することによるわずかな情報の損失は問題になりません。 今私の問題は、ブロックごとにjpeg(またはpng)というファイルを書く方法についての全くの手がかりがないことです。 – mgulde

+0

「大きなイメージ」の方法を採用したい場合は、8行のバンドで保存することをお勧めします。次に、幅x 8ピクセルのビットマップをメモリに格納します。これにより、フルイメージと比較してメモリ要件が減少します。 – Cyan

+0

コードを修正して、8行のバンドで画像を保存しています。しかし、それでもjpegとして保存する方法がわからないという問題があります。bmpsの場合は、ヘッダーを書き、ARGBバイト値を1つずつストリーミングしました。私はjpegヘッダーを書くことができるいくつかの関数が必要です - これは私がトリッキーな部分であると考えるものです - バンドをjpeg形式にエンコードし、それらをチャンクで既存のファイル塊に追加します。 – mgulde

0

(タイトルは言う「または任意の他の圧縮形式」以降)

TIFF形式は、タイルやストライプの概念を持っています。どちらも、いつでも大きな画像をメモリに保存するのを避けるために使用できます。たぶんあなたが小さな画像を綴じているのでタイルがあなたのために便利になるでしょう。

タスクのLibTiff.Net(無料、商用フレンドリー、オープンソース、C#のみ)を試してみることもできます。

記事Basic introduction to the capabilities of the libraryには、ストリップとタイル指向の画像IOに関する情報が記事の第2部にあります。

免責事項:私は同社の仕事をしています。

+0

ありがとう、私はそれを試してみます。 jpegs、pngs、asoについても同様のことがあるかどうか知っていますか?通常、私はいつもjpegsのために行くだろう。 – mgulde

+0

私が知る限り、JPEGの場合はこのようなものはありません。残念ながら、私はPNGのためのこのようなものがあるかどうかわかりません。 – Bobrovsky

関連する問題