Top > Programmingとか > VB / VB.NET > GDI+ in VB6

06 画像ファイルの書き出し→頓挫→迷走

前回PictureBoxへの表示までできたわけですから、当然次の欲としてはPictureBoxからの保存ですよね。

SavePicture Picture1.Image。

いゃいゃ。これではなんのために苦労してGDI+を使っているのかわかりません。
これ、私にとってはVB6が現役の頃から使えねぇステートメントの代表格だったんです。保存形式も指定できない、色数(bit数)もそのマシンの現行の状態に依存してしまうって、何のコントロールもできないではありませんかい。

ので、

好きなbit数と好きな保存形式で保存したい。

ってのを目標に考えてみたかったわけでした。



となると、たぶん画像保存に使用できるAPIはGdipSaveImageToFile
これ、パラメータが全部INでImageオブジェクト、ファイルパス、エンコーダのCLSID、エンコーダのパラメータってことになっています。

えーと、エンコーダのCLSIDはGdipGetImageEncoders APIで引っ張り出せばいいのかな。
って、第3パラメータがEncoders As ImageCodecInfoってことになってる…これ、見つかったすべてのエンコーダ情報を配列にして返してくるはずなんですが…?え?

なんだかGPIPlus.tlbの宣言がおかしいなぁ…要素数不定の状態で返値格納用に変数指定して、APIから返ってきたら要素数が特定された配列になっているなんて芸当、VBからじゃできません(T-T)。

しょうがないのであらかじめGdipGetImageEncodersSize APIで返ってくるはずのImageCodecInfo構造体配列の総バイト数だけ取得して、バッファとしてそのサイズのByte配列を作っといて、それのアドレスをVarPtr関数で取得したものを第3引数としましょうか。
となるとタイプライブラリの宣言では合わなくなりますので、自分で別途第3引数をByVal Longにした形でDeclareし直し。

じゃあ第4パラメータのエンコーダパラメータ用構造体って…構造体の中に要素数不定の配列?引き渡したいパラメータ数に応じて構造体内部の配列を可変にするって…そんな芸当もVBじゃできません(T-T)(T-T)(T-T)。



あー、行き詰まりました。
なんかあちこちヘンです、このGDIPlus.tlb。

で、もぅ一度必死に調べ直してみると。
どぅも作者のDana Seamanさん、初期バージョンの1.05をvbAcceleratorに投稿した後、バージョンアップはご自分のサイトCyberActiveXでひっそりと行っていたみたいなんです。
最新版は1.31(2003.09.11)。
サイトに掲示されている変更履歴を読むと、

* Addition
(追加)
11-Sep-2003GdiAlloc and GdipFree
(GdiAllocとGdipFree。)
* Addition
(追加)
11-Sep-2003Misc. PointerNameStrings
(あちこち。PointerNameStringsとか。)
* Bug Fix
(バグフィックス)
11-Sep-2003Change EncoderParameter in GdipSaveImageToFile, GdipSaveImageToStream, Long pointer. See note to the right concerning this problem.
(GdipSaveImageToFileとGdipSaveImageToStreamのEncoderParameterをLong型のポインタに。この問題に関しては右のメモを参照のこと。)
* Bug Fix
(バグフィックス)
02-Aug-2003Fixed Declares which use IStream. Thanks to Zak Benjamin for pointing out this error.
(IStreamを使った時の宣言の修正。このエラーを指摘してくれたZak Benjamin氏に感謝。)
* Bug Fix
(バグフィックス)
03-Jul-2003Fixed GdipGetImageThumbnail Declare.
(GdipGetImageThumbnail宣言の修正。)
* Bug Fix
(バグフィックス)
03-Jul-2003Updated PictDesc UDT member names to comply with PlatformSDK.
(PictDesc UDTメンバの名前をPlatformSDKと統一。)

えと。2003.09.11のバグフィックス内容がジャストフィットっぽいですね。
じゃ、ってんで「右のメモを参照」してみると。

…あー、すいません、なんだか妙に構文が入り組んでて文意があまりよく辿れませんでした。限界っす(T-T)。
どぅも、「encoderParamsは可変配列を内部に持つ構造体であり、こんなものはVBでもタイプライブラリでも宣言できない。同等の内部イメージを持つメモリ領域を自力で作ってポインタで渡す、という方法が考えられる。」って感じで書いてあると思うんですが。

私もそぅ思います。おーけぃ。
てことで、最新版1.31をDLしてみました。

DLできたのは1.30でした(T-T)。

直ってませんGdipSaveImageToFileの第3パラメータ。つかタイムスタンプが2003.08.02です。当然2003.09.11の修正内容が反映されているはずもなく。
リンクミスかとも思ったんですが、これアップミスですね。サーバに入ってないみたいですもん2003.11のタイムスタンプのファイルなんか。

さすがに、Danaさんに「GDIPlus.tlb 1.31をアップしてくださいなんてメールを打てるほどの英語力が私にはありません。
CyberActiveXにはどーいぅわけか、wpsjrさん(でいいのかな?…どぅも向こうの方は著作権放棄すると記名しない傾向があるので…)作った別のGDI+タイプライブラリもリンクされていますので。…いっそそっちを使っちゃおぅかしらもぅ。でもGraphicやらBitmapやらをわざわざクラスにしてあるあたり、私にはちょっとめんどいんですよねぇ。



ちょっと問題を整理しますと。

GDI+タイプライブラリのバグで画像の保存ができない。

てことですね。で、対応策としては、

  1. Dana Seamanさんにガンバってコンタクトを取り、最新Ver1.31を入手する。
    → 英文での会話ができないんですよね、私。

  2. wpsjrさんのタイプライブラリに乗り換える。
    → もぅ一度タイプライブラリの解析からやり直さなきゃならないかも。

  3. もぅ面倒なので自力Declareに方針を切り替える。
    → これはこれで大変ですし苦労も多そぅ。
のいずれか、といぅことになります。どぅしましょうか…少し考えてみたいと思います。

トラックバック

このエントリーのトラックバックURL:
http://salv.miscnotes.com/mt/mt-tb.cgi/454

コメント

大変参考になりました。既に3年以上経ってもこれ以上の情報はありません。感謝します。おせっかいですがtblの新しいものはこれではないでしょうか?
http://www.cybaractive.com/download/GDI+TLB.zip

> 大変参考になりました。

そう言っていただけると大変嬉しいです。
お教えいただいたタイプライブラリファイルについては、時間のある時に検証してみます。
ちょっと今、別ごとで手一杯なものですから…。

ありがとうございますm(_ _)m。

コメントを投稿