- PR -

VB PoitureBoxで表示時にOutOfMemoryException

投稿者投稿内容
こばさん
大ベテラン
会議室デビュー日: 2004/03/17
投稿数: 147
投稿日時: 2006-11-17 11:11
 ちょうど今、画像処理系のPGやってますもので、後学も兼ねて手元で大雑把にコーディングしてみました。


Dim original As New System.Drawing.Bitmap(OpenFileDialog.FileName)

Dim aspect As Decimal = (original.HorizontalResolution * original.Height) / (original.VerticalResolution * original.Width)

Dim thumnail As System.Drawing.Bitmap = original.GetThumbnailImage(Me.PictureBox.Width, Me.PictureBox.Width * aspect, Nothing, System.IntPtr.Zero)

Me.PictureBox.Image = thumnail

※GetThumbnailImage は 800×600 規模のサイズには不向きらしいですが1行で縮小できるのは便利でして(笑)


 thumnail と original の縮尺比を考慮しつつ、UI(thumnail)上でのトリミング結果を original に適用して保存、と。
みかげ☆
会議室デビュー日: 2006/11/14
投稿数: 9
投稿日時: 2006-11-17 11:46
こば様、コメントありがとうございました。

最初のサンプルコードでは、ファイル入力については下記のスレッドを
参考に、FileStreamで入力しております。

件名:ImageクラスのFileStreamで読み込んだ画像の保存

こば様のコードをそのまま流用させていただいた場合、入力できていたファイルD
(140MBくらい)もGetThumbnailImage部分でOutOfMemoryExceptionとなって
しまいました

そこで以下のようにしますと、ファイルDは○ですが、やはりファイルAは
thumnailのコンストラクタでOutOfMemoryExceptionとなってしまいました。
やっぱり200MB超はだめなんでしょうか…

●サンプルコード2
Dim original As Bitmap

Private Sub LoadFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LoadFile.Click

Dim OpenFileDialog1 As New OpenFileDialog()

OpenFileDialog1.Filter = "TIFF ファイル|*.tif"

If OpenFileDialog1.ShowDialog() = DialogResult.OK Then

  Dim hStream As New System.IO.FileStream(OpenFileDialog1.FileName, System.IO.FileMode.Open)

  original = System.Drawing.Bitmap.FromStream(hStream)
  hStream.Close()

  Dim aspect As Decimal = (original.HorizontalResolution * original.Height) / (original.VerticalResolution * original.Width)

  Dim thumnail As Bitmap = New Bitmap(original, Me.PictureBox1.Width, Me.PictureBox1.Width * aspect)

  Me.PictureBox1.Image = thumnail
  thumnail.Dispose()

End If

OpenFileDialog1.Dispose()

End Sub
みかげ☆
会議室デビュー日: 2006/11/14
投稿数: 9
投稿日時: 2006-11-17 16:23
重ねて記載いたしますが、サンプルファイルが以下のURLにございます。
もしお手間でなければサンプルとしてご使用いただければと存じます。

ファイルA(× 208MB)とファイルD(○ 137MB)に相当するものを
圧縮して同梱してあります。画像はまっしろです。

#ファイルサイズは400KB弱ですが、解凍すると合計350MBくらいに
 なります。ご注意ください。
http://www.dekaino.net/~mikage/largewhite.zip
みかげ☆
会議室デビュー日: 2006/11/14
投稿数: 9
投稿日時: 2006-11-17 16:33
根本的な問題に、甕星様にコメントいただきました

引用:
32bitのWindowsアプリケーションで利用可能なメモリ空間は2GB。連続して確保できるのは、実質1GB程度。



という部分があるかと思いました。
これを確認するために、現在のアプリケーション上での総空きメモリ空間や
連続空きメモリ空間を確認するような手法はあるのでしょうか?

[ メッセージ編集済み 編集者: みかげ☆ 編集日時 2006-11-17 16:34 ]
ryuuji
ベテラン
会議室デビュー日: 2003/07/10
投稿数: 53
お住まい・勤務地: 東京都
投稿日時: 2006-11-20 13:32
何がどうメモリを使っているか調べるなら
CLRプロファイラ
を試されてはいかがでしょう。

ところでなんらかの方法で200MBの読み込みが成功したとして今度は300MBでOufOfMemoryExceptionが発生した場合はどうするのでしょうか。なので何MBの画像を読み込んでも(解像度を変えたり、圧縮したりして)表示できるようにすることを考えた方が良いのではないでしょうか。
みかげ☆
会議室デビュー日: 2006/11/14
投稿数: 9
投稿日時: 2006-11-20 14:20
ryuuji様、コメントありがとうございます。

CLRプロファイラをお教えいただき、ありがとうございます。
早速試してみます。

引用文が前後します。

引用:

なので何MBの画像を読み込んでも(解像度を変えたり、圧縮したりして)表示できるようにすることを考えた方が良いのではないでしょうか。



こば様にお教えいただいたコードを元に、サンプルコード2で
画像サイズをかえてから表示しようとおもったのですが、
表示前の変換する部分でOufOfMemoryExceptionとなってしまいました。

Dim thumnail As Bitmap = New Bitmap(original, Me.PictureBox1.Width, Me.PictureBox1.Width * aspect)

が発生場所です。
WWWを検索しても画像の拡大縮小はおおよそ似たり寄ったりな手法が多く、
他にどのような解像度を変えたり、圧縮したりする方法があるのかが
わかっていません…

引用:

ところでなんらかの方法で200MBの読み込みが成功したとして今度は300MBでOufOfMemoryExceptionが発生した場合はどうするのでしょうか。



そういうわけでして方法が分からないので、とりあえず現状としては
「限界を知る」、という感じでしょうか。
どうも当初予定の500Mはとても無理そうなので、それならばとりあえず
どこまでいけるのかを知りたいといったところです。
ryuuji
ベテラン
会議室デビュー日: 2003/07/10
投稿数: 53
お住まい・勤務地: 東京都
投稿日時: 2006-11-21 13:16
理解しました。200MBを既定のライブラリ(Bitmap)で読み込む、ということにはこだわってはないのですね。

コード:

Dim thumnail As Bitmap = New Bitmap(original, Me.PictureBox1.Width, Me.PictureBox1.Width * aspect)



このコードの厳密な意味は知りませんが、リサイズなり解像度の変更なりがBitmapオブジェクトへの操作ならば、そもそもメモリが足りなくてBitmapオブジェクトを作れない事が例外の原因なので無理な気がします(鶏が先か、卵が先かみたいな?)。

Webを探してみると同じような問題を抱えている方が沢山いるようです。CompactFramework向けのオープンソースライブラリでOpenNETCF.orgというものがあるそうです。CF向けですがオープンソースなのでソースコードを参考にしてみてはどうでしょうか。

追記:
OutOfMemoryExceptionが発生するか事前に調べる方法が.NET 2.0で追加された、と聞いた気がします。限界が何MBか調べるより、こっちでチェックした方がいいのでは(そんなメソッドがあるならですが・・・)。

[ メッセージ編集済み 編集者: ryuuji 編集日時 2006-11-21 13:19 ]

スキルアップ/キャリアアップ(JOB@IT)