Access DB でイメージデータを扱う方法

タグの編集
投稿者 N88-BASIC  (社会人) 投稿日時 2018/7/19 10:49:36
Windows 10 & Visual Stduio 2017 Community にて Access2000 形式の DB を扱う計画です。

上記条件にて DB 上のイメージデータを処理(表示、保存)を計画しております。
現状はファイル名を DB に保存する方法で、必要に応じてイメージファイルを作成して処理していました。
クリックボード経由で入力したイメージを処理場合などでファイルと保存するのが面倒なのと、当該データベースを他のPCで処理する場合にイメージファイルをコピーするのが手間なので、DB にイメージそのものを組み込めないかと考えましたが、恥ずかしながら処理イメージが思いつきません。

※処理イメージ
 レコード内にイメージの取り出し PictureBox 上に表示するのと PictureBox 上の一部のイメージをレコードに埋め込む(基本的には数個のイメージ)

※Access2013 でのデザイン
 ID      整数型
 image OLEオブジェクト型

※テスト用としてのサンプルをAccess で直接入力
 ID     10                (キーボードで入力)
 image  BitmapImage (Access で オブジェクトの挿入-> Bitmapを選択 -> 起動したペイントで入力

※VB 上でDbRecords.Columns(i).DataType.ToString にて状況の確認
 ID     : System.Int32
 image : System.Byte[]

処理方法に関して情報をお持ちでしたらご教授ください。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2018/7/19 13:14:02
> 恥ずかしながら処理イメージが思いつきません。
データベースの読み書きは、以前実施しているので大丈夫ですよね。
http://rucio.cloudapp.net/ThreadDetail.aspx?ThreadId=27032

DataAdapter や TableAdapter を用いているのなら、
Byte 配列な列を持つ DataTable を通じて読み書きできます。

'画像ファイルを Byte 配列にする方法 
Dim bin As Byte() = System.IO.File.ReadAllBytes("C:\temp\test.bmp")

'Byte 配列な画像を PictureBox に表示する方法 
Dim img As Image = Image.FromStream(New System.IO.MemoryStream(bin))
PictureBox1.Image = img




> ※Access2013 でのデザイン
Access 2007-2013 の .accdb なら「添付ファイル型」というものもあるのですけれどね。
https://dekiru.net/article/14897/


今回は 2000 形式(Jet 4.0 世代)なので、画像保持に使える型としては
 ① バイナリ型
 ② OLEオブジェクト型
の 2 種類が存在します。


そして下記のテーブルで言うと、
X1~X2 が ① のバイナリ型を表しており、
Y1~Y4 が ② の OLE オブジェクト型です。

CREATE TABLE SampleTable
( Id INT
, X1 BINARY
, X2 VARBINARY
, Y1 IMAGE
, Y2 LONGBINARY
, Y3 GENERAL
, Y4 OLEOBJECT
)


上記 Y1 列の型定義を見ると分かるように、Jet にとって IMAGE は予約語ですので、
> ID     10                (キーボードで入力)
> image  BitmapImage (Access で オブジェクトの挿入-> Bitmapを選択 -> 起動したペイントで入力
のように列名に [image] という名を付けることは避けましょう。



> PictureBox 上に表示するのと
Access の 「連結オブジェクトフレーム」に表示させるなら ② で良いのですが、
VB の「PictureBox」に表示させるなら ① を使います。


① の バイナリ型は、バイナリデータそのものを管理するものですが、
② の OLEオブジェクト型は、OLE ドキュメントの保持を目的としています。
http://atata.sakura.ne.jp/net/


② は画像形式で保存するわけではないので、二次利用には向きません。
使うとすれば、生のバイナリを無加工で格納可能な ① の「バイナリ型」です。

ただし Access は、① に対してファイルを添付したり、内容をファイルに
保存したりする機能を有していないのでご注意ください。
(VB から読み書きする分には問題ありません)
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2018/7/19 18:17:14
なお、バイナリ型のフィールドのかわりに、OLEオブジェクト型のフィールドに対して
生のバイナリデータを保持させることもできます。

ただし、Access の「オブジェクトの挿入」からでは、コンテンツの埋め込みまたはリンクしか
行えないので、生バイナリを入出力するためのコードは、どちらにせよ自作が必要です。


一応、OLE オブジェクトから、画像データを切り出す方法としてこういう資料もありますが…。
https://support.microsoft.com/en-us/help/175261/

今回のケースだと、「オブジェクトの挿入」を用いず、
生のバイナリーをそのまま保持させた方が扱い易いと思います。
投稿者 N88-BASIC  (社会人) 投稿日時 2018/7/20 19:26:28
魔界の仮面弁士 さま、ご回答ありがとうございます。

ご紹介いただいた内容を参考にバイナリーデータで対応することにしました。

現状は書き込みを試してみました。
Access ではバイナリーとしての指定はできないのでOLEオブジェクト型のままで試してみました。
下記の様に Byte() を代入してみました。

Dim bin As Byte() = System.IO.File.ReadAllBytes("C:\temp\test.bmp")
Dim DbRow as DataRow
DbRow("Gazou")=bin

一応、実行時のエラーはなく、DBのファイルサイズも変化しており、 Access 上では”バイナリー”となっていましたので書き込みは完了していると考えています(ご案内どうり Access では内容の確認は不可でした)。

ご案内いただいた下記のコードなど初めてことが多く、読み出しやクリップボードなど壁は高そうです。

Dim img As Image = Image.FromStream(New System.IO.MemoryStream(bin))

今後ともよろしくお願いいたします。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2018/7/21 11:53:22
> Access ではバイナリーとしての指定はできないので
これは SQL 文でしか作成できないフィールド型ですね。
利用はできますが、Access のデザイナーからの作成はできません。

その逆に SQL では指定できず、Access からでないと指定できない型も
あります(添付ファイル型やハイパーリンク型など)。*.mdb ではなく *.accdb ですが。


ちなみに、バイナリデータの登録や更新は、SQL 文を用いて行うこともできます。

UPDATE TABLE1
 SET TABLE1.IMG = 0x549B4C756E30EE4E6297015FEB58
WHERE ID = 1



ただしバイナリデータから 16 進数への変換は、自前で行う必要があります。
Dim bin As Byte() = System.IO.File.ReadAllBytes("C:\temp\test.bmp")
Dim hexString As String = "0x" & System.BitConverter.ToString(bin).Replace("-""")




> クリックボード経由で入力したイメージ
クリップボードには、同じデータに対する複数のデータフォーマットを保持できます。
Excel で右クリックした時に、『形式を選択して貼り付け』が行えるのも、この機能によるものですね。

たとえば、背景透過な PNG 形式と、Windows で一般的な Bitmap 形式の両方が
同時にクリップボードに転送されることなどもあります。

※クリップボードでの PNG は標準的なものではないので、サポートしているソフトは少ないです。
※背景透過な Bitmap も仕様としてはあるのですが、通常は不透明 Bitmap のことが多いです。
※クリップボード形式として標準的なもののうち、背景透過に対応しているものとしては、Metafile 形式があります。


> 読み出しやクリップボードなど壁は高そうです。
参考資料として。

【クリップボードの画像を表示する、クリップボードに画像をコピーする】
https://dobon.net/vb/dotnet/graphics/getclipboarddata.html

【クリップボードのデータの形式を取得する】
https://dobon.net/vb/dotnet/system/clipboardformats.html

【クリップボードのデータの取得、設定がうまくいかないときは】
https://dobon.net/vb/dotnet/system/nostaclipboard.html
投稿者 N88-BASIC  (社会人) 投稿日時 2018/7/26 12:38:27
魔界の仮面弁士 さま、追加のご説明をありがとうございました。

報告が遅くなりました。

情報を参考にクリックボードからの画像をデータベースに保存するために Byte() に変換するのに難儀しておりました。
ネットなどで検索したところ、 ImageConverter を使用する例があったので参考にして、変換→保存→読み出しを実現することができ、無事解決できました。
Byte() 処理についてのサンプルをいただいていなければ諦めていたところでした。

今後ともよろしくお願いいたします。

PS。
システムの無理解上の結果だと思うのですが、画像の読み込みに dobon.net さんで紹介のありました「表示中の画像ファイルが削除できない問題の解決法」を参考にしていたのですが、読み込んだ直後にに ImageConverter で変換したときにエラーが出たので戸惑っていました。