yTakeといいます。
TWAINドライバーの操作方法がわかる方がおられましたら、ご助言頂けると幸いです。
TWAIN準拠スキャナーでアプリケーションから48ビットカラーでスキャンしデータを取得する事を考えます。
インターネット上で、便利そうな物をみつけました。
url:http://www.kluug.net/delphitwain.php
元々、TWAINドライバーへのI/Fを提供するビジュアルコンポーネントだった様ですが、現在はそのソース部分の提供でプロジェクトのパスにそのソースのフォルダーを追加して使用しています。
サンプルプログラムもあり、比較的簡単にスキャナーを制御できそうです。
24ビットカラーや8ビットグレイスケールでは無事画像を取得できています。
しかしながら、48ビットカラーや16ビットカラーではデータ転送のところでエラーになっている様で、スキャンを開始すると直ぐにエラーになります。
肝心な点として、転送モードが挙げられます。24ビットカラーは、Nativeモード、Memory転送モードのいずれでも転送されますが、48ビットカラーはMemory転送モードのみで転送可能な点です。
しかし、この点も転送モードの変更を事前に行い、少なくともステータスなどから正しく変更されている事を確認の上、48ビットカラーでスキャンしても、エラーになります。
エラーの内容はアドレスに対する書き込み違反です。
当初、自分のこのTWAINのI/Fの使い方が悪いと思っていましたが、このTWAINのI/Fが48ビットカラーや16ビットグレイスケールの転送をサポートしていない気がしています。
自分の使い方の問題なら良いのですが、、、
サンプルプログラムは付属の”DelphiTwainDemo2”を修正して試しました。
もし、48ビットカラーや16ビットグレイスケールの転送の部分を自分で実装させるとなると、TWAINに詳しくないのでご助言を頂けると思います。
DELPHIに対しても未熟なので一筋縄ではいかないかなと考えています。
併せてアドバイス頂けると幸いです。
TWAINドライバーの仕様書やエプソンからのTWAIN開発者向けの資料も当たっています。
TWAIN-2.3-spec.pdf
TwainProgGuideJRevL.pdf
などです。
他に提供すべき情報があればお尋ね下さい。
思うに、48ビットの転送に使うメモリーの確保が、24ビットと違うと思います。
現状の24ビットでは転送メモリーにBitMapを用いている様に見受けられます。
48ビットの場合、RGBで各々配列を確保すべきで、それをTWAINに伝えてそこにスキャンデータを書き込んでもらい、スキャン後その領域をRGB毎に読み出すイメージですが、具体的は模索中です。
TWAINのI/Fに、PrepareMemXfer、TransferImageMemory、などの関数があるのでこの辺を修正するのかな?と思っています。
先ずは、方向性としては正しいでしょうか?
よろしくお願いします。
なお、エプソン純正のスキャンソフトで48ビットカラーや16ビットグレイスケールをTIFFに保存できる事は確認しています。ハードやソフト的に不可能な事へチャレンジしているわけではございません。念の為。
当方、
Windows10、RAD Studio 10.2
EPSON ES-10000G
自己レスです。
中身を確認してみました。
TWAIN I/F ソフトの方では、”prepareMeMXFer”と言う関数で共有メモリ(転送バッファ)を用意している様に思います。
ここで、BITDEPTHによる場合分けがないので、24ビットカラーの転送は可能でも、48ビットカラーの転送でエラーになる様に思います。
ここを修正して、48ビットカラーデータを想定したバッファを用意し、BITDEPTHで場合分けすれば良い様に思います。
TWAINの仕様では、転送バッファに画像のメタデータを含める事が出来ないので、別途、メタ情報の受け渡しが必要な様です。
TWAIN I/Fのソースでは、
{First of all, get information on the image being acquired}
Result := Owner.TwainProc(AppInfo, @Structure, DG_IMAGE, DAT_IMAGEINFO, MSG_GET, @Info);
if Result <> TWRC_SUCCESS then exit;
{Calculate image size}
with Info do
size := ((((ImageWidth * BitsPerPixel + 31) div 32)*4) * info.ImageLength );
{Obtain image buffer transference sizes}
Owner.TwainProc(AppInfo, @Structure, DG_CONTROL, DAT_SETUPMEMXFER,
MSG_GET, @Setup);
blocks := (size div Integer(setup.Preferred));
size := (blocks + 1) * Integer(setup.Preferred);
{Prepare new bitmap}
structsize := size + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
Handle := GlobalAlloc(GHND, StructSize);
Dib := GlobalLock(Handle);
Fillchar(Dib^, structsize, #0);
の様に処理されています。
TWAINの仕様では、トリプレットと言う
DG_IMAGE, DAT_IMAGEINFO, MSG_GET
で、スキャナー側でスキャンされた画像のサイズを得るとしています。
その情報を基に転送バッファのサイズを決めて、
DG_CONTROL, DAT_SETUPMEMXFER, MSG_GET
と言うトリプレットでスキャナーに対し転送メモリを指定する様です。
しかしながら、48ビットカラーの転送バッファを具体的にどの様に指定するか、まだ、把握できていません。
RGB別に各々16ビットの配列を用意するのだと推察しています。
”TW_IMAGEMEMXFER”や”TW_MEMORY”などの構造体を利用する様に読み取れますが、具体的には理解できていません。
もう少し、調べてみようと思います。
ずいぶんと間が空いてしまいました。
色々と試行錯誤をした結果、”DelphiTwain”はよくできたI/Fで主要な操作は提供される手続き・関数でなんとかなりそうです。
操作手順の定石などに慣れる必要があると思います。
また、懸案のメモリー転送モードですが、DIBと言うしくみを使う事が分かってきました。
純粋なDIBとDIBSectionと言う二つの方法がある様です。
現在、24ビットカラーではメモリー転送出来ていると思っています。48ビットカラーでエラーになります。
付属のサンプルではDIBSectionを用いている様で、これはあくまでWindowsのBitmapなので24ビットカラーまでしか扱えないのでは?と思い始めています。
CreateDIBSectionで作成されたBitmapハンドルのサイズ(高さ)が正しくない様に思えます。
48Bitカラーを操作する為には、DIBでなければならないのでしょうか?
サンプルではCreateDIBSectionを使っていますが、スキャン時のデータ転送でアクセスバイオレーションになっています。転送領域が正しく確保されていないと思います。
CreateDIBitmapと言う関数があります。これを使えば48Bitカラーのデータが正しく転送できるのでしょうか?
また、しばらく試行錯誤してみます。
DIB/DIBSection関係はちょっと古いですが中村さんのDelphi Graphic Secrets
http://www.sbcr.jp/products/4797319224.html
が詳しいです。
通りすがり様
ありがとうございます。
早速、当たってみます。
おかげ様で”DELPHI Graphic Secrets”を拝読する事ができました。
大変詳しく又分かり易くビットマップの解説がされています。DDB、DIBSection、DIBについて分かってきました。
それで、やはり48Bitカラーでは、DIBSectionではなくDIBを使う必要があると思います。
ここからはTWAINに大きく関わる点なので、こちらで問い合わせるのが適当か分かりませんが、他に当てもないので、もし分かればご教授下さい。
現在、転送されてくる画像(正しくは画像ではありません)の縦のサイズが分からず困っています。
24ビットカラーや多分32ビットカラー等各色1バイトの画像では、TWAIN上でも@ImageInfoや@DIBSectionなどのオブジェクトに縦横のサイズ情報が得られます。
然しながら、48Bitカラーではこれらに正しいサイズ情報が反映されません。
一方で、48Bitカラーでもデータの転送自体は完了できている様に動作しています。
つまり、転送された画像データから画像の縦サイズを逆算できないか?と言う事です。
転送された画像データの総バイト数が分かれば単純に割れば求まると思いますが、今のところその情報は見当たりません。
幸いにDIBでデータ転送する際の転送バッファ情報から画像の幅は分かります。
又、転送は元画像を縦方向に分割して転送されますがその分割された縦サイズも分かります。つまり、DIB転送が繰り返される回数から、おおよその縦サイズは分かります。
問題は、最後の転送で端数が生じた場合です。(その方が普通と思われます)
サンプルのソースでは、DIBSectionですが、転送バッファからデータをコピーした後、行毎にRGBの順を入れ替えている箇所があります。
ここで行数をカウントして、画像サイズの縦サイズに加味できる様に思っています。
先ずは、24ビットカラーをDIBで転送し、画面へ描画させてみようと思います。
ツイート | ![]() |