DOBON.NETプログラミング道掲示板

[ 最新記事及び返信フォームをトピックトップへ ]

■34874 / inTopicNo.1)  画像の大きさを取得するには
  
□投稿者/ ペースターズ 一般人(1回)-(2021/08/21(Sat) 16:56:35)
  • アイコン環境/言語:[Windows10 VB.NET2017] 
    分類:[.NET] 

    お世話になります。
    
    VB.NETで画像処理を連続して行うアプリを作成しました。
    これ自体は出来ているのですが、どうにも処理が遅い。
    数枚ならともかく、1000枚単位になると、なかなかバカに出来ない時間がかかっています。
    そこで高速化に着手しようとおもい、まずは画像情報の取得からいこうと思いました。
    現在、画像の縦横サイズを取得するのに、ファイルを開いてヘッダ情報を読み込み、縦横を得ています。
    ↓こんな感じです。
    ----------------------------------
    Dim imagew, imageh As Integer
    Dim fs As System.IO.FileStream
    
    fs = New System.IO.FileStream(ファイル名, IO.FileMode.Open, IO.FileAccess.Read)
    imagew = System.Drawing.Image.FromStream(fs).Width
    imageh = System.Drawing.Image.FromStream(fs).Height
    fs.Close()
    ----------------------------------
    いちいちファイルを開いて読んで閉じる。というのは結構遅いんじゃないかと思います。
    これをもっと手軽に高速に出来る方法はないでしょうか。
    

マルチポストを報告
違反を報告
引用返信 削除キー/
■34875 / inTopicNo.2)  Re[1]: 画像の大きさを取得するには
□投稿者/ Hongliang 大御所(606回)-(2021/08/21(Sat) 20:09:56)
  • アイコンファイルのオープンクローズの時間を気にするレベルだと、ExplorerがThumbs.dbでやってるような「あらかじめ情報を取得しておく」ぐらいしか方法はない気がします。しかしこれはお作りのアプリとは方向性が違うのではないかと思います。

    System.Drawing.Bitmapオブジェクトはインスタンス生成時に画像へのデコードまでやってしまうので、画像の縦横のサイズといったメタデータを読みたいだけなら無駄が多いです。
    // もちろん、画像処理本体には結局画像デコードが必要でしょうが…。
    .NET Framework標準ライブラリの中では、PresentationCore.dllに含まれるSystem.Windows.Media.Imaging.BitmapDecodeクラスを中心としたクラスを使えば、不要な画像デコードを行わなずにすむように記述できます。
    Dim decoder As BitmapDeocder = BitmapDecoder.Create(fs, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None)
    Dim width As Integer = decoder.Frames(0).PixelWidth
    Dim height As Integer = decoder.Frames(0).PixelHeight
違反を報告
引用返信 削除キー/
■34876 / inTopicNo.3)  Re[1]: 画像の大きさを取得するには
□投稿者/ 魔界の仮面弁士 大御所(1389回)-(2021/08/21(Sat) 20:11:43)
  • アイコンNo34874に返信(ペースターズさんの記事)
    > fs = New System.IO.FileStream(ファイル名, IO.FileMode.Open, IO.FileAccess.Read)
    > imagew = System.Drawing.Image.FromStream(fs).Width
    > imageh = System.Drawing.Image.FromStream(fs).Height
    > fs.Close()

    Image オブジェクトのロードを 2 回行っているのは何故でしょうか?
    しかも Dispose もしていないようで…。

    Using img = System.Drawing.Image.FromStream(fs)
     w = img.Width
     h = img.Height
    End Using

    のようにして、かつ、複数ファイルを操作するために
    Parallels.For を併用してみるのはいかがでしょう。
違反を報告
引用返信 削除キー/
■34877 / inTopicNo.4)  Re[2]: 画像の大きさを取得するには
□投稿者/ ペースターズ 一般人(3回)-(2021/08/21(Sat) 23:33:01)
  • アイコン
    Hongliangさん、魔界の仮面弁士さん、アドバイスありがとうございます。
    
    >System.Drawing.Bitmapオブジェクトはインスタンス生成時に画像へのデコードまでやってしまうので、画像の縦横のサイズといったメタデータを読みたいだけなら無駄が多いです。
    
    やっぱりそうですよね。
    とういうわけで、↓のように直してみました。
    ----------------------------------
    Dim imagew, imageh As Integer
    Dim fs As System.IO.FileStream
    
    fs = New System.IO.FileStream(ファイル名, IO.FileMode.Open, IO.FileAccess.Read)
    Using img = System.Drawing.Image.FromStream(fs)
     imagew = img.Width
     imageh = img.Height
    End Using
    fs.Close()
    ----------------------------------
    体感的に速度は変わらないようでした。残念!
    
    >Parallels.For を併用してみるのはいかがでしょう。
     えっ?なにそれ?と思って検索してみたら、並列処理ができるんですね!
    
    単純に
    For i = 0 To files.Length - 1
    ↓
    Parallel.For(0, files.Length,
             Sub(i)
    みたいに変えてみましたが、プログレスバーへの設定とかで
    ProgressBar.Value = i
    なんか挙動不審になっちゃうようです。
    複数のスレッドから操作しようとすれば、そりゃ当然でしょうね。
    でも、これは高速化に効きそうなので、もう少し調べてみます。
    
    ありがとうございました!
    
    

違反を報告
引用返信 削除キー/
■34878 / inTopicNo.5)  Re[3]: 画像の大きさを取得するには
□投稿者/ ペースターズ 一般人(4回)-(2021/08/22(Sun) 09:45:39)
  • アイコン解決済み
解決み!
違反を報告
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

Mode/  Pass/


- Child Tree -