2020年5月2日土曜日

VB WPF 内容の異なる同一ファイル名から画像を断続的に表示

一体 何のこっちゃ?。  ですね、 このタイトル!。
SD カード等のメディアに記録された写真なのですが、
何時も、同じ番号から始まるカメラ設定の場合、
複数枚のカードを対象にすると、変な事が起こります。


メディア( SD カード等 )から画像表示するプログラムがあります。
ファイル全部では無く、最初と最後だけ、表示しています。
通常は1枚のメディアを扱うケースが多いのですが、
時折、複数枚を差し替えて、連続的に表示する事もあります。
WPF ですから、該当 Window を閉じて、再び、開き直しています。
でも、
差し替えたのに、 古い画像がお出ましに ... 。  X(

その、不可解な出来事で ずっと 悩んでいました。

はい。  Image Control の挙動が少し変なのです。
最初の分だけ、画像が切り替わらないのです。
そう、差し替える前の 最初のメディアのものが表示されます。
どうして?。

推測するに、
メディアを入れ替えても、その番号の振り方から、
最初のものはファイルパスが全く同じになって仕舞うので、
キャッシュが活きていて、読み直さないのであろう、 と勘繰っていました。
或いは、 コンパイル時若しくは実行時の最適化段階で、そんなロジックが組み込まれているのかも知れない、と。

最初と異なり、
最後はメディアによって記録可能枚数にばらつきが生じるので、
最後は、概ね、正確に表示されています。
はい。  最後の番号そのものが異なるのですね。  まぁ、偶然 ... ですが。

ソフトそのものを終了させ、再度実行すれば、目的は叶います。
或いは、不調に眼を瞑り、黙々と実行する、 とか。
幸いかな、 数多の文字情報は正確に表示してくれていますので。
例えば、画像の撮影時間とか。

しかし、 どうも、スッキリしない ... 。


でも、ようやく、出口の灯りが見えました!。


原因は、
Bitmap を ファイル Uri から生成している事でした。  恐らく。
(場所をも含むフルパス名は、メディアを交換しても、全く、同一なので。 )
これを、Stream に切り替えて、目的達成です。

この方法は、
ファイルのハンドリングを掴まれて、削除等の作業が出来ない時の対処法なのですが、
それが、目的の異なる、今回の対策でも有用でした。

メディア交換で、
ファイルパスが完全に同一になるとしても、
その内容 (Stream) は、皆、異なりますから。


さて、
搔い摘んだコード部分を一部抜粋します。
Image.Source に用意した BitmapImage 生成の部分です。
  fp は String で 画像ファイルパス。.
  緑部分 が Uri から読み出す書き方。.
  赤部分 が Stream を使って読む書き方。  最後に閉じるのをお忘れ無く!。.
      Dim bi As New BitmapImage()
      bi.BeginInit()
      bi.CacheOption = BitmapCacheOption.OnLoad

      ''bi.UriSource = New System.Uri(fp)
      'bi.UriSource = New System.Uri(fp, UriKind.RelativeOrAbsolute)

      Dim stream As IO.FileStream = IO.File.OpenRead(fp)
      bi.StreamSource = stream
      bi.DecodePixelHeight = CInt(imageControl.Height)
      RenderOptions.SetBitmapScalingMode(imageControl, BitmapScalingMode.NearestNeighbor)
      bi.EndInit()

      stream.Close()

これって、稀な例だと思います。
検証用に、
メディアでは無く、Directory を3つ用意し、
そのひとつ(メディアドライブに相当)から読み出し、
別途、残りのふたつの何れかから其処へファイル群をコピー出来る様にして 、
メディア差し替え を再現したものを作りました。
Uri と Stream の違いをご覧下さい。



最初、解決策を見出せず、
msdn に質問する心算で、Project ごとアップ出来る様に、と作ったものです。
もしや! と思い、試したのが、 今回の方法です。
その過程で、自己解決に至れました。  ふぅ。  :)



0 件のコメント:

コメントを投稿