質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MFC

MFC (Microsoft Fouondation Class)とは、MicrosoftがVC++用に開発したWindows用アプリケーションのフレームワークです。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1672閲覧

クリップボードからBMP画像データを取得し、画像上のあるピクセルの色情報を抜き出せるようにしたい

notgoodpg

総合スコア37

MFC

MFC (Microsoft Fouondation Class)とは、MicrosoftがVC++用に開発したWindows用アプリケーションのフレームワークです。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/01/31 08:13

編集2018/01/31 08:18

前提・実現したいこと

クリップボードから画像データを取得し、画像上のあるピクセルの色情報を抜き出せるようにしたい。

  • クリップボードにBMP形式で抜き出せる画像をコピー(抜き出せる と書きましたができない画像データが有るか無いかも分かりません)
  • プログラムでクリップボードの情報を読み出す
  • 要素単位にピクセル単位のRGB情報を持った2次元配列で画像データを取得[質問箇所]
  • ある1ピクセルの色を取り出す

上記のことをしたいのですが、[質問箇所]の処理がうまく行えません。
ビットマップイメージの扱いについて知識がほぼ無い状態で進めているためまるで的外れな事を書いているかも知れないですが指摘していただければ大変助かります。
よろしくお願いいたします。

該当のソースコード

c++

1 // クリップボードからDIBを取得 2 if (!::OpenClipboard(NULL)) return; 3 HANDLE hData = ::GetClipboardData(CF_DIB); 4 5 if (hData == NULL) { 6 ::CloseClipboard(); 7 return; 8 } 9 10 HANDLE *hDib = (HANDLE *)GlobalLock(hData); 11 12 ::GlobalUnlock(hData); 13 ::CloseClipboard(); 14 15 BITMAPINFOHEADER bitHead; 16 memcpy(&bitHead, hDib, sizeof(BITMAPINFOHEADER)); // BITMAPINFOHEADERを取得 17 18 if (bitHead.biBitCount != 32) { 19 // 念のため32bit画像じゃなければ抜け 20 ::GlobalFree(hData); 21 return; 22 } 23 // ピクセルごとの色情報を取りたい 24 int bitFieldMask = 12; 25 void* beginBMPData = &bitHead + bitHead.biSize + bitFieldMask; // 画像のビット情報の開始アドレス 26 int width = bitHead.biWidth, height = bitHead.biHeight, bitCnt = bitHead.biBitCount; 27 std::vector< std::vector< RGBQUAD>> picData; // RGBQUAD構造体の動的2次元配列 28 29 std::vector< RGBQUAD> picRow; 30 RGBQUAD* curPnt; // 現在指しているポインタ 31 for (int h = height -1 ; h >= 0; --h) { // 左下から右上へ並ぶデータを左上から右下へ並び変えつつ取得 32 curPnt = (RGBQUAD *)beginBMPData + (width * (h-1) * sizeof(RGBQUAD)); 33 34 picRow.clear(); 35 36 for (int w = 0; w < width; ++w) { 37 RGBQUAD tmp; 38 memcpy(&tmp, curPnt, sizeof(RGBQUAD)); 39 picRow.push_back(tmp); 40 41 curPnt += sizeof(RGBQUAD); 42 } 43 44 picData.push_back(picRow); // 何かしら値は取れているが同じデータをMSPaintにペーストして見比べると同じ座標のRGB値が違う 45 } 46 47 48 ::GlobalFree(hData);

補足情報(FW/ツールのバージョンなど)

  • Windows7/64bit SP1
  • VisualStudio2015SP
  • VC++/MFC

参考情報

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こういうのはサンプルコードがないと難しいですよね。

こんな感じでできます。エラー処理は適宜実装してください。

C++

1#include <atlimage.h> 2 3// クリップボードからビットマップを取得する関数 4void SampleClipboard() 5{ 6 if(!::IsClipboardFormatAvailable(CF_BITMAP)) 7 { 8 return; 9 } 10 11 if(!::OpenClipboard(NULL)) 12 { 13 return; 14 } 15 16 CImage image; 17 HBITMAP hBitmap = (HBITMAP)::GetClipboardData(CF_BITMAP); 18 if(hBitmap == NULL) 19 { 20 ::CloseClipboard(); 21 return; 22 } 23 24 CImage clip; 25 clip.Attach(hBitmap); 26 image.Create(clip.GetWidth(), clip.GetHeight(), 32); 27 HDC hdc = image.GetDC(); 28 clip.BitBlt(hdc, 0, 0); 29 clip.Detach(); 30 image.ReleaseDC(); 31 32 ::CloseClipboard(); 33 34 for(int y = 0; y < image.GetHeight(); y++) 35 { 36 for(int x = 0; x < image.GetWidth(); x++) 37 { 38 COLORREF color = image.GetPixel(x, y); 39 BYTE r = GetRValue(color); 40 BYTE g = GetGValue(color); 41 BYTE b = GetBValue(color); 42 43 // 何かの処理 44 } 45 } 46 47 // そのままファイルに保存することも可能 48 image.Save(L"sample.png"); 49}

ビットマップ処理の簡略化のためATLCImageクラスを利用しています。詳しい使い方は当該クラスのリファレンスを参照してください。

投稿2018/01/31 12:17

編集2018/01/31 12:26
catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

notgoodpg

2018/02/01 02:03

お忙しい中コードまで用意していただきありがとうございました。 おかげさまで求めていた情報が取得できました。
guest

0

openCVなどの画像処理ライブラリの使用はいかがでしょうか?
BMPに限らず、いろいろな画像に適用できますし扱いやすいですよ

投稿2018/01/31 09:35

iwanote

総合スコア295

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

notgoodpg

2018/02/01 02:19 編集

ご回答ありがとうございます。 OpenCVを利用するのはもっともなご提案とは思いますが、今回サードパーティのライブラリを出来れば避けたいため最後の手段と考えています またOpenCVのC++版にWindows7/64bitでクリップボードを扱う関数は少し調べた限りでは無いようなのですが、存在するのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問