- ベストアンサー
GDI+でアニメPNGの表示
- GDI+を使用してアニメーションPNGを表示する方法を知りたい
- GDI+でアニメーションPNGの表示に関する問題が発生しており、解決方法を知りたい
- GDI+を使用してアニメーションPNGを表示する際にメモリアクセス違反のエラーが発生し、困っている
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
www >>Among all the image formats currently supported by GDI+, the only formats that support multiple-frame images are >>GIF and TIFF. >>When you call the Image::SelectActiveFrame method on a GIF image, you should use FrameDimensionTime. >>When you call the Image::SelectActiveFrame method on a TIFF image, you should use FrameDimensionPage. MSDNで上のように書いてあったのなら単純にPNGアニメは使えないってことですね。 これで解決ではありませんか?w 私はGIFアニメもTIFFアニメも使ずGDI+も使わないのであれですが、本当にそれは必要なのですか? 下位互換性やDirectDraw又はDirect2D非対応環境にも対処するという必要性がないのであれば、いまどきGDI+にこだわる理由もないように思われますが。 いかがでしょう。
その他の回答 (2)
- okdummy001
- ベストアンサー率41% (5/12)
全体のソースが見れないので難ではありますが、ThreadParamsをthreadの引数として渡していますよね。そしてそのThreadParams::imageをthreadの内部で使っています。 おそらくその渡されたThreadParamsインスタンスのポインタはメインスレッドなどで用意されたものかと思われますが、アクセス侵害が起こる関数のどちらとも関係している変数が「ThreadParams::image」です。 つまりメインスレッドで用意したと思われるThreadParams内のimageの扱いになんらかの問題があると私は見ました。 メインスレッドとその子スレッド間でのそういったアクセス侵害はそれほどめずらしくないので一度お調べになられてはいかがでしょうか。 ちなみ例え質問サイトとはいえ、どのような回答が返ってこようとも悪態をとられるのはいかがなものかと。あなたは未熟なのですから。
お礼
回答ありがとうございます。 まずはサンプルプログラムへの訂正です。 済みません、ThreadParamsにImageとIStreamがありますが、 試行錯誤の末に残ってしまった消し忘れで本来要らない(使っていない)ものです。 struct ThreadParams{ HWND hWnd; bool fin; ThreadParams(HWND hWnd):hWnd(hWnd),fin(false){} }; ThreaadParamsの定義は以上で十分です。 処理本体はthread()で、必要なファンクションはGetFrameCount()のみです。 thread()内で >IStream* ist = NULL; >CreateByteStream(&ist,IMAGE_PATH); > >Gdiplus::Graphics g(hdc); >Gdiplus::Image *image = new Gdiplus::Image(ist); という箇所がありますが、この箇所は >Gdiplus::Graphics g(hdc); >Gdiplus::Image *image = new Gdiplus::Image(IMAGE_PATH); と、Gdiplus::Imageのコンストラクタにファイル名を直接指定しても同様の動きをします。 つまり3つのCreateByteStream()とInputFile()ファンクションは使用しなくていいことになります。 (のでファイル読み込み時のサイズ指定ミスという可能性が消えました) ここから、回答への返答なんですが Imageオブジェクトを使用しているのはthread()内部のみなので異なるスレッドから同時にアクセスすることによって起こるアクセス侵害という可能性は低いかなと思います。 (でもその場合はDCに対する操作が複数のスレッドから行われることになるので そこでアクセス違反という可能性は考えられるかもしれませんが) 試しにthread()の処理を、別スレッドで処理する方法をやめてWM_PAINTで処理する方法 (WM_PAINT内で無限ループになるのでメインスレッドをロックしてしまうのですが) でやったみたんですが、やはり同様の原因と思われるアクセス違反が発生しました。 後、いろいろ検証しているうちにわかった事があるので意味があるかどうかわかりませんが書いておきます。 1.Gdiplus::Image::SelectActiveFrame()メソッドで、GIFアニメの何枚目を対象に 操作を行うか、ということを設定するんですが、引数でn枚目を指定した場合 n>1の場合に、n+1回のメモリアクセス違反メッセージが連続して出力されます。 この場合「メモリ破壊っぽいバグり方」はまだ確認していません。 2.静止画像に対してGdiplus::Image::SelectActiveFrame()メソッドを実行した場合、 その場合は必ず1フレーム目を指定するんですが、20~30回ぐらい実行したあたりで 「heap corrupted」というメッセージが出てその後確実に「メモリ破壊っぽいバグり方」が発生します。 メソッド実行は様々な画像フォーマットの別々のImageオブジェクトに対して、各1度ずつ行われました。 これに関してはMSDNの以下の記述に違反しているのが原因かもしれません。 2.に関しては対処可能なのでこのトピックスの質問内容には静止画像は無関係とします。(もともとそうですが) http://msdn.microsoft.com/en-us/library/ms535402%28v=VS.85%29.aspx Among all the image formats currently supported by GDI+, the only formats that support multiple-frame images are GIF and TIFF. When you call the Image::SelectActiveFrame method on a GIF image, you should use FrameDimensionTime. When you call the Image::SelectActiveFrame method on a TIFF image, you should use FrameDimensionPage. メモリ破壊っぽいバグり方とは、 1.他の領域で保持されているメモリ内容が破壊されているっぽい(画面の文字や画像が化けたり消えたりする) 2.プログラムが停止する、または入力を受付なくなる ようなバグりかたです。 GDI+でサポートされているマルチフレーム画像はGIFとTIFFだけなんですね。 マルチフレームのPNGも使えるようにしたいのでGDI+以外のライブラリを使うか、 マルチフレーム画像はあとまわしにして一旦あきらめるか、 マルチフレーム画像を解析・分解して複数のシングルフレーム画像にすることで マルチフレーム関係のメソッドを使用しなくていいようにするか、 みたいな選択肢も脳内にチラつきはじめました。 一応その他の方法も調査しつつ、方針が決まるまではこのトピックでの回答の受付を 継続します。 >ちなみ例え質問サイトとはいえ、どのような回答が返ってこようとも悪態をとられるのはいかがなものかと。あなたは未熟なのですから。 質問した日(=回答にレスした日)は一日中バグ探しやった後で脳みそがぐるんぐるんしていたんですが、 次の日に質問内容とソースコードと私の返信を見直してあまりの痛さに愕然としました。 このひどい内容ではあの回答が返ってきても文句は言えないなと。(これがずっと残ってしまうのがつらい・・・。) 申し訳ありませんでした。調子にのらないように気をつけます。
- okdummy001
- ベストアンサー率41% (5/12)
http://code.msdn.microsoft.com/ERROR-CODE-tips-93491789 アクセス違反エラーなので、確保したPNGデータ領域よりも大きいアドレスを描画処理化何かで読みにいってしまっているというような感じではないでしょうか。上のコードは煩雑なので読んでいませんが、大体画像データサイズをプログラマが把握せずに、描画系関数呼び出しでサイズ指定の間違いとかでよく起こるエラーではあります。 ご参考までに・・・
補足
>アクセス違反エラーなので、確保したPNGデータ領域よりも大きいアドレスを描画処理化何かで読みにいってしまっているというような感じではないでしょうか。 そらそうでしょうよ。 >上のコードは煩雑なので読んでいませんが、 ソース読んでないのに回答しないでくださいよ。何の参考にもならないです。 >大体画像データサイズをプログラマが把握せずに、描画系関数呼び出しでサイズ指定の間違いとかでよく起こるエラーではあります。 >ご参考までに・・・ その可能性はふつうに真っ先に考えるところですよね。 GDI+はIStreamをコンストラクタに与えてやればオブジェクトを作ってくれるんで サイズ指定の間違いだとするとファイル読み込みとか、IStreamを作るあたりなんでしょうが、 アニメーションじゃないPNGは読めたり、アニメPNGでもファイルによって ちゃんと動いたりエラーが出たりするんでどうもそのあたりじゃない気がするんですよね。 どっちにしてもこのソースも100回ぐらい読んで自分では気付けないでいるんで どこか間違っているんだとしたら具体的に指摘して欲しいです。 自分の感触としてはGDI+オブジェクトに何かの指定をしてやらなければならないのを していないとか、そういう間違いの可能性が高いのかなと考えてます(が、わからないです)。
お礼
そうですね。この質問はここで一旦クローズします。 お付き合いいただきありがとうございました。