位置指定の描画 – プログラミング – Home

通知
すべてクリア

[解決済] 位置指定の描画


おあ
 おあ
(@おあ)
ゲスト
結合: 18年前
投稿: 7
Topic starter  

今まで1000x1000サイズのビットマップを使用していたのですが
今回から3500x1000サイズを使用しなければならなくなりました。
ただ、必要な(表示されている)部分はDCの左上(1500,0)から右下(3500.1000)までなの
です。
メモリが危ういので左上(1500,0)から2000x1000サイズを使用したいのですが
どうすればいいのか分からない状態です。

現在使用しているソースは以下のような感じです。

CDC m_DC;
CDC* pDC = GetDC();
CBitmap m_Bitmap;

m_DC.CreateCompatibleDC(pDC);
m_Bitmap.CreateCompatibleBitmap(pDC, 1000, 1000);
m_DC.SelectObject(&m_Bitmap);

:

m_DC.BitBlt(0, 0, 1000, 1000, pDC, 0, 0, SRCCOPY);

BitBltを1500, 0, 2000, 1000にするのは分かるのですが・・・。
ご存知の方がいらっしゃいましたらご教示願います。


引用未解決
トピックタグ
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

文章的におかしな感じがする部分がありますが、
必要な部分と言うのは用意されているビットマップの内、
(1500,0)-(3500,1000)の矩形で表現される部分という理解で良いでしょうか?

ソースの見る限りでは用途が良くわかりませんが、m_Bitmapなる物があり、
これは1000×1000で作成されているようですが、これで良いのでしょうか?
あと、肝心のビットマップをロードする部分が無いようですが、
その部分とはどう繋がるのでしょう?

あと、BitBltの使い方は本当にこれで良いのでしょうか?
これだと表示されている内容をメモリDC上のビットマップにコピーしている事に
なりそうですけれど。


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

元々の処理がどのような事をしていて今回の修正でどうしたいのか
をきちんと説明で来ていないので今の状態では想像でしかレスが付けられません。
質問内容を見直して説明する必要がある部分はきちんと説明してください。

あと、開発環境に関する記述が全く無いようなのでこれもきちんと提示してください。
解決方法に影響が出る場合がありますので。


返信引用
おあ
 おあ
(@おあ)
ゲスト
結合: 18年前
投稿: 7
Topic starter  

説明不足で申し訳ありません。

>元々の処理
GetDC()先自体に画像があり、その画像をコピーしたビットマップを作成し
GetDC()の上に表示しています。
実際にはこのコピーしたビットマップ上に他の描画をしてからですが。

ソースは1000x1000サイズで処理していた時のを抜粋で書いています。

>必要な部分と言うのは用意されているビットマップの内、
>(1500,0)-(3500,1000)の矩形で表現される部分という理解で良いでしょうか?
正確にはGetDC()先の(1500,0)-(3500,1000)です。

単にm_Bitmap.CreateCompatibleBitmap(pDC, 2000, 1000);とした場合に
(0,0)-(2000,1000)までの範囲になっているので何か方法はないかと思い
質問させていただきました。

開発環境は WinXP(SP2) VC++.NET MFC です。
分かりにくい点が多いと思いますがよろしくお願いします。


返信引用
Kerry
 Kerry
(@Kerry)
ゲスト
結合: 20年前
投稿: 192
 

転送元DCに3500x1000の大きさのビットマップが選択されていて、
そこから(1500,0)-(3500,1000)の範囲を別のビットマップに
コピーしたいということであれば、

m_DC.BitBlt(0, 0, 2000, 1000, pDC, 1500, 0, SRCCOPY);

こうすればいかがですか?


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

>> 必要な部分と言うのは用意されているビットマップの内、
>> (1500,0)-(3500,1000)の矩形で表現される部分という理解で良いでしょうか?
> 正確にはGetDC()先の(1500,0)-(3500,1000)です。

いえ、ビットマップも左上を基準に考えれば、同じ事になると思いますけれど。
基本的に作成したビットマップをDCに選択状態にする場合、
強制的にビットマップの左上が原点(0,0)になるはずです。
DCにビットマップを選択すると言う行為は、描画に使用する準備として
行っているのであって表示そのものではありませんから問題にはならないはずです。
一般的な方法を挙げておきますが、
貼り付けたいビットマップは通常、メモリDC側選択状態にするのが普通です。
この時、メモリDC上ではビットマップの左上がDCの原点に位置するように
選択されていますから、メモリDCから通常のクライアントDCへ切り出して
貼り付けます。
ですからロードしたビットマップをメモリDC(コンパチブルDC)に選択状態にしておき、
クライアントDCのBitBltでメモリDCから貼り付けるのが普通でしょう。

ですから、おあさんのコードからすると
pDC->BitBlt(0, 0, 2000, 1000, &m_DC, 1500, 0, SRCCOPY);
となるのではないでしょうか?

なぜ、クライアントDCに元のビットマップが選択されているのかが疑問です。
何か理由があるんでしょうか?


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

> なぜ、クライアントDCに元のビットマップが選択されているのかが疑問です。
> 何か理由があるんでしょうか?

単純な話で二度手間になっているような気がします。
あと、画像処理で気をつけないといけないのはコピーすると
その時点でその分だけ余計にメモリを食います。
例えば、3500x1000の画像をロードしてこれをメモリDC上に2000×1000のサイズに
切り出した時、3500x1000の画像と2000×1000の画像が両方存在する状態になっています。
ここで3500x1000の画像を破棄したとして2000×1000の画像をクライアントDCに
1000×1000に切り出して貼り付けるとこの状態でも画像は二つ存在する事になります。
要するにそれだけメモリを食うと言う話です。
描画時のスピード等を考えると描画に使用する画像は必要最小限メモリ上に置いて
おきたいのが普通ですからこれは致し方ないでしょう。
基本的に他のウインドウが重なったりした時の再描画用に画像を保持しておく必要が
ありますから画像を使用するならメモリを食ってしまうのは覚悟するしか無いと思います。


返信引用
おあ
 おあ
(@おあ)
ゲスト
結合: 18年前
投稿: 7
Topic starter  

PATIOさん、Kerryさん、ありがとうございます。

元々外部コントロール、アプリの画像を表示しており、
その上に描画を行いたい(行っているように見せたい)ので
このような処理にしております。
正確には

m_DC.BitBlt(0, 0, 1000, 1000, pDC, 0, 0, SRCCOPY);

: m_DCに対し他の描画処理を行う

pDC->BitBlt(0, 0, 1000, 1000, &m_DC, 0, 0, SRCCOPY);

になっています。

試してみた所、処理的にはうまくいっているようですがメモリ的には厳しいみたいです。
そこでまた質問なのですが、
CreateCompatibleBitmapを処理した時点で指定したサイズのビットマップが作成される。
作成したビットマップの左上は作成元の原点(0,0)の位置になっている。
で、正しいのでしょうか。
また、CreateCompatibleBitmapのサイズを減らし原点以外から指定したサイズ分の描画は
できるのでしょうか。

描画等々があまり分かっていないので基本的な質問になってきましたがよろしくお願いし
ます。


返信引用
ryo
 ryo
(@ryo)
ゲスト
結合: 23年前
投稿: 252
 

>元々外部コントロール、アプリの画像を表示しており、
>その上に描画を行いたい(行っているように見せたい)ので
これは
「別のアプリケーションの画像をとってきて、
作成してるアプリケーションに表示してる。さらにそれを加工したい」
って意味でしょうか?それとも、
「作成してるアプリケーションに表示機能はなく、
別のアプリケーションに横入りする形でその表示を操作したい」
ということでしょうか?
GetDCの結果に対し、入出力してるから、後者だとは思うのですが。

>試してみた所、処理的にはうまくいっているようですがメモリ的には厳しいみたいで
す。
メモリが厳しいとは?
・メモリ不足エラーがでる
・タスクマネージャなどで使用メモリがでっかくて気にいらない
・表示だけじゃなく処理そのものが重い
・画面がちらつく
などなど

>CreateCompatibleBitmapを処理した時点で指定したサイズのビットマップが作成され
る。
>作成したビットマップの左上は作成元の原点(0,0)の位置になっている。
作成元が、Create~の第一パラメータで渡したpDCのことをさしてるなら、
「位置関係は無関係」です。
画像内容をコピーするときに「位置関係」を指定するのがBitBltのパラメータ。


返信引用
おあ
 おあ
(@おあ)
ゲスト
結合: 18年前
投稿: 7
Topic starter  

ryoさん、返信が遅くなり申し訳ございません。

>これは
後者ですね。

>メモリが厳しいとは?
開発用メインマシンでは普通に表示されるのですが
サブマシン(メインより高性能)では真っ黒になってしまっているのです。
CreateCompatibleBitmapでのサイズを減らすと普通に表示されるので
メモリ系統かなと。ただ、GetLastError()で確認した所、
「このコマンドを実行するのに十分な記憶領域がありません。」と出るのですが、
出ても普通に表示される場合や、出ないで表示されない場合もあるので直接的な原因は
分からないのですが・・・。

>「位置関係は無関係」です。
>画像内容をコピーするときに「位置関係」を指定するのがBitBltのパラメータ。
CreateCompatibleBitmap(2000,1000)とし、
BitBlt(1500, 0, 2000, 1000, 元DC, 1500, 0, SRCCOPY)とした場合、
コピー元の左上(1500,0)から幅2000、高さ1000分コピーし、(右下(3500,1000)まで)
コピー先の左上(1500,0)から幅2000、高さ1000分を貼り付け(右下(3500,1000)まで)
といった動作にならないのでしょうか。
やってみても右下(2000,1000)を超えてコピー、貼り付けを行わないので・・・。
私自身が何か根本的に勘違いしてしまっているのかも知れませんが。

もう少しの間、よろしくお願いします。


返信引用
Kerry
 Kerry
(@Kerry)
ゲスト
結合: 20年前
投稿: 192
 

> CreateCompatibleBitmap(2000,1000)

このビットマップを介した時点で、(0,0)-(1999,999)までの範囲
しかコピーできないのだから当然の結果かと思われます。

やるなら、

// 元DCの(1500,0)から2000x1000の範囲をメモリDCの(0,0)に転送
m_DC.BitBlt(0, 0, 2000, 1000, pDC, 1500, 0, SRCCOPY);

// ..何か処理..

// メモリDCの(0,0)から2000x1000の範囲を、元DCの(1500,0)に転送
pDC->BitBlt(1500, 0, 2000, 1000, &m_DC, 0, 0, SRCCOPY);

こうすべきでは?


返信引用
ryo
 ryo
(@ryo)
ゲスト
結合: 23年前
投稿: 252
 

>CreateCompatibleBitmap(2000,1000)とし、
>BitBlt(1500, 0, 2000, 1000, 元DC, 1500, 0, SRCCOPY)とした場合、
>コピー元の左上(1500,0)から幅2000、高さ1000分コピーし、(右下(3500,1000)まで)
>コピー先の左上(1500,0)から幅2000、高さ1000分を貼り付け(右下(3500,1000)まで)
>といった動作にならないのでしょうか。
なってます。
なってますが、それがおかしい
コピー先はX方向が2000しか幅しかないのに、
「1500の位置からスタートして2000の幅を貼り付け」したら
2000以降はどこに描かれるのでしょうか?

>やってみても右下(2000,1000)を超えてコピー、貼り付けを行わないので・・・。
超えてるからです。

たとえば、
横幅20cmの画用紙に対し、左から15cm位置を起点に右方向20cmの線を書いたら、
画用紙を飛び出して床か机に線を書くことになります
おあさんが、なさっているのはこういうことです

元DCを横幅35cmの紙とした場合、この紙を左から15cmから右側20cm分を切り取ります。
で、コピー先として用意した20cm幅の画用紙に、切り取ったものを貼り付けるとき
コピー先の画用紙にぴったりあわせることになります。
つまり、コピー先の(0,0)-(2000,1000)にあわせるのです(これがBitBltの1~4
番目のパラメータ)。

このとき、元画像の1500の位置にあった色は、コピー先では0の位置に描かれますが
「元画像の1500の位置」という情報はもうありません
BitBltは、色をコピーするだけであって、元画像の位置情報はコピーしないのです
ですから、BitBltしたことによって、コピー先のビットマップが
(1500,0)-(3500,1000)という位置情報をもった2000×1000の大きさのビットマップになっ
たりはしないのです。

おまけ:
「元画像でx方向2000の位置の色を変えたい」と思った場合
コピー先では 2000-1500=500の位置の色を変えることになります。
このように、「画像の一部切り出し」の場合は、
元画像の位置とコピー先の位置関係を覚えておいて、計算する必要があります。


返信引用
おあ
 おあ
(@おあ)
ゲスト
結合: 18年前
投稿: 7
Topic starter  

Kerryさん、ryoさん、ありがとうございます。

「外部をビットマップにコピー」と「ビットマップを外部に貼り付け」が
混ざっていたみたいですね・・・。
説明通りにやるとサブマシンでも普通に表示してくれました。
これでとりあえずは一安心です。

本当にありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました