- 締切済み
重いグラフィックス処理
Windows VisualC++/MFC でのご質問です。 大きなグラフィックスデータをSDIアプリケーションで表示しているのですが、データが重く描画に10数秒時間を要してしまいます。1mil1画素といった具合に割り当てているのですが、あまりにも重過ぎます。描画を早くしたいのですが、何か良い手はありますでしょうか? 現在はDCに直接描画しています。メモリDCも試しましたが、サイズが大きすぎてbitmapが作れまずあきらめました。 以上、ご指導よろしくお願いします。
- みんなの回答 (6)
- 専門家の回答
みんなの回答
- titokani
- ベストアンサー率19% (341/1726)
>Windowのビュー/マップモードに頼らないで..メモリDC+自分でスケーリングというのが近道でしょうか? >..でもマッピングモードに頼って広大なDCを使っているのが間違いなのかもしれません。ただ、全景を表示したときつぶれなく表示され、拡大はかなり高速にそして滑らかに表示されたので...その点は良いと考えていました。 はい、マッピングモードには問題はないです。 >MoveTo,LineToで書いている以上、論理サイズの大きさは、速度にあまり影響ありません。BitBltとかStretchBltとかしていると別ですが。 と、書いたとおりです。 とにかく、無断な線を引かないのが一番効果があります。 >データ解析 : 確かに遅く。試行覚悟していますが、ダメですね。 >中間ファイルに落として...というのも試しましたが、更にデータ数が増えてしまうという情け無い結果に終わったり...してしまいました。 でも、現状でも、ファイルを読み込んでMoveTo,LineToにしているわけですよね? でしたら、そのMoveTo、LineToに与えているパラメータを予め計算して配列かなんかに保存しておくだけです。メモリは使うでしょうが、スピードは速くなるはずです。 >他にも手法はあるとのことですが...私にはなかなか手の届く範囲では無いような気がします。 無駄な線を引かないだけなら難しいことではありません。 例えば、一本の線の始点と終点がウィンドウの上端よりも上にあるのなら、その線は画面に表示されません。なので、その線を引く必要はありません。同様の処理を、ウィンドウの左と右と下についても行えば、大きく拡大したときなどは引く線の数を大きく減らすことができます。 「手の届く範囲では無い」とおっしゃいますが、一つ一つの技術はそう難しいものではないですよ。
- titokani
- ベストアンサー率19% (341/1726)
#1です。 なるほど、だいたいわかりました。 MoveTo,LineToで書いている以上、論理サイズの大きさは、速度にあまり影響ありません。BitBltとかStretchBltとかしていると別ですが。 MoveTo,LineToで線を何本書いているのでしょうか?その数が非常に多いのであれば、速度が遅いのは仕方がないですね。 ただ、工夫はできます。 ウィンドウと同じ大きさのビットマップを用意して、一度そのビットマップに描いてからBitBltします。これなら、一度目は同じ時間がかかりますが、2回目以降はBitBltの時間だけで済みます。 また、一部を拡大して表示する場合は、すべての線を引く必要はないですよね?画面に表示される線だけを引くようにすれば、これも早くなります。 同様にスクロールの際も、必要がある部分のみ描画します。 当然、 >データファイルの読み込み解析に時間が掛かっていることが判明しました こんなロスは論外です。解析なんぞはファイル読み込んだその一回きりにとどめましょう。 あと、遅くてもあまりストレスに感じさせない方法としては、WM_PAINTで一気に描画するのではなく、アイドルループや別スレッドなどで書く方法があります。これだと、スクロールの際に、画面を全部書き終えるまえに、さらにスクロールを続けたりとできます。拡大縮小なんかでも同様。 とにかく、いろいろと工夫の余地はありますので、頑張りましょう。
- jjk65536
- ベストアンサー率59% (66/111)
過去に仕事で大きい画像の表示に関するプログラムを書いたことがあります。 ドット単位の画像アクセスをしながら数十ミリ秒くらいで描画できて いました。 (当時は質問者様と同じくWindows VisualC++/MFC環境でした) そのときは参考URLのページをみながらDIBを作って、ドットアクセスは 自分で確保したメモリにアクセスしつつ、矩形転送などは StreatchBltなどを使ってハードウェアアクセラレーションきかせて 描画、みたいにいいトコどりで作ったと記憶してます。 1mil1画素、という単位は私も知りませんが、高速な描画は参考URLの 方のサンプルコードで実現できている気がします。
補足
ありがとうございます。 その昔何かの機会でこのDIBの方法は使ったような気もします。 いつもその場しのぎで対応しているので... でもこのDIBというのを使っても今回の画像を表現できないというかサイズに制限があったような気がします。StrechDIBかSetDIBなるAPIを試した気がします。
- penta1331
- ベストアンサー率64% (16/25)
画像全体をタイル状に分割して、画面表示にはタイルを組み合わせて表示する、と考えてはどうですか? 表示領域サイズのメモリDCを複数個用意して、表示している領域付近の表示用データをメモリDCに先読みして作成する。 画面には複数のメモリDCを組み合わせて表示する。 裏読みなどテクニックが必要になってきますが、パフォーマンスは上がると思います。 元のデータが画像ではないようですから、そのフォーマットによっては実現できないかもしれません。
補足
ありがとうございます。 メモリDCを使いたいのは山々なんです。 というのもレイヤが使えるので、表示する対象物を要素毎にレイヤ分けして重ねて表示したりしたいのです。 なるほど並べてという手法ですが... 部分ズーミングなどする際に...その時はどうすれば良いか? 思い浮かびません。メモリDCって自分のディスプレイサイズ程度しか確保できないようで、困ってます。
- php504
- ベストアンサー率42% (926/2160)
なじみのない単位ですが1mil=1/1,000in =0.0254mm のことかな ソース見ないとなぜ重いのかはわかりません ボトルネックになってる処理を探して最適化してください
補足
ありがとうございます。 グラフィックスが重いのもさることながら、データファイルの読み込み解析に時間が掛かっていることが判明しました。グラフィックですが、領域が大きすぎるためメモリDCをあきらめたこともあり、直接DCに描いています。このこともあり、要素に応じて何度が上書きしています。 たとえば、パターンを描いたあと、穴を上書きするとか... とりあえず、ファイル読み込み解析の無駄を無くして時間を短縮する意向です。ただ、描画の方も... 高速?にスケーリング(拡大縮小)をしたくて、WINDOW/VIEWの座標系を変更して瞬時にできるマップモードを使っているのがダメ?なのでしょうか?(確かMM_ISO....だったような?) それからゴメンナサイ1mil = 1/10000inchと勘違いしていました。 ゆえに5000000* 5000000のサイズが対象です。 以上、よろしくお願いいたします。
- titokani
- ベストアンサー率19% (341/1726)
>大きなグラフィックスデータ 具体的にどんな大きさなのでしょうか?ピクセル数および色数は? >1mil1画素 意味がわかりません。「1ミリ1画素」・・だとしても不明です。 >現在はDCに直接描画 使用しているAPI、関数等は何でしょうか? 以上、補足お願いします。
補足
すみません。 内容不足で.. 不具合的に 1mil = 1/1000inchです。 ここに意味はなく、データの単位系がmilです。 データ上1000という座標には1000画素を割り当てるようにしています。 そして全体の大きさは500000mil * 500000milを想定しています。 MFCを使っていて.. MoveTo,LineToです。(Poly...も使ってみたりしましたが大差ありませんでした。) 具体的には、プリント板のパターンを描画しています。
補足
ありがとうございます。 確かに数えきれないくらいのMoveTo/LineToを呼び出しています。 Windowのビュー/マップモードに頼らないで..メモリDC+自分でスケーリングというのが近道でしょうか? ..でもマッピングモードに頼って広大なDCを使っているのが間違いなのかもしれません。ただ、全景を表示したときつぶれなく表示され、拡大はかなり高速にそして滑らかに表示されたので...その点は良いと考えていました。 ちなみに印刷DCとなると解像度の関係でおなじような状況となります。 データ解析 : 確かに遅く。試行覚悟していますが、ダメですね。 中間ファイルに落として...というのも試しましたが、更にデータ数が増えてしまうという情け無い結果に終わったり...してしまいました。 他にも手法はあるとのことですが...私にはなかなか手の届く範囲では無いような気がします。 読みながら描画して無駄をなくすとか???を考えたりもしましたが... もう少し悪戦苦闘してみます。 ありがとうございました。 他に何かありましたらご支援お願いいたします。