MFCでネガポジ変換

このQ&Aのポイント
  • MFCを使用してネガポジ変換を行うプログラムを作成しました。
  • プロジェクトのCChildView.cppのOnPaint関数に実装しました。
  • VC++2008ではウィンドウが白黒の縞模様になり、VC++2005ではウィンドウが真っ黒になる違いがあります。
回答を見る
  • ベストアンサー

MFCでネガポジ変換

以下のプログラムはネガポジ変換をするプログラムです。MFCで最初に作られるプロジェクトのCChildView.cppのOnPaint関数に実装しました。デバッグするとウィンドウ全体が真っ黒になるはずです。が、なぜか添付のファイルのように白黒の縞模様になってしまします。ちなみに私はVC++2008を使っています。知人にも相談して、VC++2005で全く同じプログラムで試してもらいましたが、そちらではウィンドウが真っ黒になって成功しました。違いはおそらく2008か2005かということだけ何のです。 何か原因をご存知の方がいらしたら教えてもらえないでしょうか。 void CChildView::OnPaint() { CPaintDC dc(this); // 描画のデバイス コンテキスト int w = dc.GetDeviceCaps(HORZRES); //DCの幅を得る int h = dc.GetDeviceCaps(VERTRES); //DCの高さを得る int i, j; for(j=0; j<h; j++) { for(i=0; i<w; i++) { //DCの(i,j)位置から色を得る COLORREF c = dc.GetPixel(i, j); //色を取得 if(c!=CLR_INVALID) { //反転したr,g,b値を取得 int r = 255- GetRValue(c); int g = 255- GetGValue(c); int b = 255- GetBValue(c); c = RGB(r, g, b); //その画素を置く dc.SetPixel(i, j, 0); } } } }

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

OnPaintで何もしなかった場合は 真っ白になるのでしょうか? if ( c != COLOR_INVALID )をコメントアウトしても同じですか? OnPaintがはじめて呼ばれたときは真っ白に塗るだけにして Invalidateをかけてみるとか ・・・

nikoru222
質問者

補足

>OnPaintで何もしなかった場合は 真っ白になるのでしょうか? 真っ白になります。 >if ( c != COLOR_INVALID )をコメントアウトしても同じですか? 同じです。

その他の回答 (2)

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.3

>自分のPCで(2008)作ったプロジェクトを知人のPC(2005)で実行してもらいましたが、知人のPCではうまくいったみたいです。 だとすると、VCの問題ではなくて、他の環境(OSとかグラフィックボードとか)の問題のように思えます。 いずれにせよ、OnPaint内で、PaintDCからGetPixelして同じ場所にSetPixelしても、プログラムとしては意味がない(真っ黒が画面を作るのが目的ではないでしょう?)ので、そこの設計を直すほうが、原因を追求するより早いように思えます。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.2

paintDCからGetPixelするのがそもそも間違いなのかも。 >違いはおそらく2008か2005かということだけ何のです。 知人の方のPCで、あなたのPCで作ったプログラムを実行したり、知人の方のPCで作られたプログラムをあなたのPCで実行したりはしてみましたでしょうか?

nikoru222
質問者

補足

自分のPCで(2008)作ったプロジェクトを知人のPC(2005)で実行してもらいましたが、知人のPCではうまくいったみたいです。

関連するQ&A

  • CreateCompatibleDCを初期化時にしたい(MFC)

    MFCでJPEG画像を表示するプログラムを OnPaint() の中に書いていたのですが・・・  : bool m_bImageMemDCInit; CImage m_Image; CBitmap *m_pImageBitmap; CDC m_ImageMemDC;  :  : void CChildView::OnPaint() {  CPaintDC dc(this);  if(!m_bImageMemDCInit){   m_bImageMemDCInit = true;   // イメージをロード   m_Image.Load("test.jpg");   m_pImageBitmap = CBitmap::FromHandle(m_Image);   m_ImageMemDC.CreateCompatibleDC(&dc);   m_ImageMemDC.SelectObject(m_pImageBitmap);  }  // 描画  dc.BitBlt(0, 0, 256, 256, &m_ImageMemDC, 0, 0, SRCCOPY); } このように、Load や CreateCompatibleDC などの初期化にあたる処理を、起動時に1度しか処理しないように書いています。 しかし、このプログラムではあまりに汚い。どうにかして PreCreateWindow などの初期化関数内に書きたいのですが、CreateCompatibleDC 関数で CPaintDC* を渡す必要があるので、OnPaint 関数内に書かざるを得ないのです。 (Loadだけなら初期化関数内に移せるのですが・・・) いっそ CreateCompatibleDC を再描画のたびに呼んでもいいのでは? と思い、やってみると異常終了してしまいました。 また、CPaintDC dc(this); を PreCreateWindow 関数内に書いても異常終了しました。 どなたかスマートな方法をご存知でしたら、ご指導願います m(_ _)m

  • 非クライアント領域への描画について

    非クライアント領域に文字を書こうとしました。 以下の(2)では書けますが、(1)では書いてくれません。 CPaintDCはクライアント領域でないとダメなのですか? void CMainFrame::OnPaint() { CPaintDC dc(this); // 描画用のデバイス コンテキスト dc.TextOut(0,0,"こんにちは"); ・・・(1) CDC* pDC = GetWindowDC(); pDC->TextOut(100,0,"こんにちは"); ・・・(2) 環境 WIN98 VC++6.0 MFC

  • dc.TextOut(0 ,0 , *str) ;について

    環境 WIN98 VC++6.0 MFC にて パターンBはOKですが、パターンAだと不正な処理で落ちてしまいます。 どうしてなのかお教えください。 void CFffView::OnPaint() { CPaintDC dc(this); //パターンA CString* str ; str = (CString*)("999"); dc.TextOut(0 ,0 , *str) ; //パターンB CString aaa ; aaa = (CString)("999"); dc.TextOut(0 ,0 , aaa) ; }

  • 幾何学変換

    Windowsアプリケーションでボタン一つで画像を45度回転させるプログラムを作りたいのですが、プログラムがよく分かりません。どなたか教えていただけないでしょうか。あと、回転変化後の画像には線形補間法(バイリニア法)を使っての補間処理をして表示させたいのですがよろしいでしょうか。言語はC#です。 自分で色々プログラム組んでるのですがなかなか出来ないです。今組んでるプログラムを実行すると変な風に実行されます。 組んでる途中のプログラム↓↓ private Color[,] SpinImage(Color[,] colImage) { int iHeight = colImage.GetLength(0); int iWidth = colImage.GetLength(1); //Console.WriteLine(iHeight + "\t" + iWidth); double X = 45.0 * Math.PI / 180.0; int iHeight2 = (int)(iWidth * Math.Cos(X) + iHeight * Math.Sin(X)); int iWidth2 = (int)(iWidth * Math.Sin(X) + iHeight * Math.Cos(X)); Color[,] colImage2 = new Color[iHeight2, iWidth2]; //Console.WriteLine(iHeight +"\t" +iWidth); for (int j = 0; j < iHeight-1; j++) { for (int i = 0; i < iWidth-1; i++) { int m = (int)(i * Math.Cos(X) + j * Math.Sin(X)); int n = (int)(-1 * i * Math.Sin(X) + j * Math.Cos(X)) + 100; int iRed = 0; int iGreen = 0; int iBlue = 0; // Console.WriteLine("y:"+ j +"\t i:"+i+"\t m:" +m + "\tn:" + n); iRed = colImage[j, i].R; iGreen = colImage[j, i].G; iBlue = colImage[j, i].B; #region a //if ((j >= 0) && (j < iWidth) && (i >= 0) && (i < iHeight)) //{ // iRed = colImage[i, j].R; // iGreen = colImage[i, j].G; // iBlue = colImage[i, j].B; // colImage[m, n] = Color.FromArgb(iRed, iGreen, iBlue); //} //else //{ // colImage[m, n] = Color.FromArgb(0, 0, 0); //} #endregion if (m < iHeight && n >= 0) { colImage2[m, n] = Color.FromArgb(iRed, iGreen, iBlue); } } } return colImage2; }

  • MFC C++

    MFCでソリューションを新規作成した時に作られるプログラムにちょこちょこと手を加えています。 以下のプログラムは、画面の中心に黒い円を描くプログラムの一部です。 void CChildView::OnPaint() { CPaintDC dc(this); // 描画のデバイス コンテキスト CRect rect; GetClientRect(&rect); CPoint center = rect.CenterPoint(); const int sizeCircle = 60; CSize offset(sizeCircle / 2, sizeCircle / 2); CSize size(sizeCircle, sizeCircle); CRect rectCircle(center - offset, size); CBrush brush(RGB(0, 0, 0)); CBrush* pBrushOrg = dc.SelectObject(&brush); dc.Ellipse(rectCircle); dc.SelectObject(pBrushOrg); } どなたか以下のことを教もらえないでしょうか。 (1)CSize size(sizeCircle, sizeCircle);の部分ですが、size()はCSizeのメンバ変数ではないと思うのですが、size()の型がCSizeになっているのはどうしてでしょうか? (2)上の続きで、size()関数は見る限りどこにも定義されていなかったのですが、どこかに元々定義があるのでしょうか?(元々というのは、Microsoft側で定義してくれているということです。) (3)dc.Ellipse(rectCircle);の部分で、dc.とはどういう意味でしょうか? どなたかお願いします。

  • 画像の抽出

    今、VB2008を用いて、原画像と原画像に落書きをした画像の2枚を用いて、 落書きのみを抽出するプログラムを作っているのですが、 RGBの演算がどうも上手く出来ません。 コードは Dim r1#, g1#, b1#, r2#, g2#, b2#, r3#, g3#, b3#      Dim i%, j%, nx%, ny%      Dim col1, col2 As Color '略     For j = 0 To ny - 1      For i = 0 To nx - 1       col1 = bmp1.GetPixel(i, j)'落書きした画像         r1 = col1.R         g2 = col1.G         b3 = col1.B      col2 = bmp2.GetPixel(i, j)'落書き前の原画像         r2 = col2.R         g2 = col2.G         b2 = col2.B      r3 = r1 - r2       g3 = g1 - g2     b3 = b1 - b2    bmp3.SetPixel(i, j, Color.FromArgb(Int(r3), Int(g3), Int(b3)))'落書きのみ抽出された画像の書き込み     Next    Next Form1.Picturebox1.Image = bmp3 としてみたのですが、gやbの値が - になってしまい、エラーが出て しまいます。If(g3<255) then g3 =255 などと記載してみたのですが上手くいきませんでした。 どこを修正、加筆すればうまく抽出が出来る様になるのでしょうか。

  • 外積のプログラムについて質問があります

    ベクトルの外積のプログラムについて質問があります 環境はリナックスです 問題は2つの実ベクトルa,bをキーボードから入力しその外積を求めるプログラムです i<jである組み合わせに対してai*bj-aj*biを並べたものです 次元nについてはキーボードから入力します wedge内で外積を求める計算をします #include <stdio.h> int *wedge(int *a, int *b, int *c); int main() { int n; int a[100]; int b[100]; int i; int j; printf(" nの値を入力" ); scanf("%d", &n); for(i = 0; i < n; i++){ scanf("%d",&a[i]); } for(i = 0; i < n; i++){ scanf("%d",&b[i]); } for(i = 0; i < n; i++){ printf("a[%d]=%d\n",i, a[i]); } for(i = 0; i < n; i++){ printf("b[%d]=%d\n",i, b[i]); } } int *wedge(int *a, int *b, int *c) { int i; int j; *c = a[i] * b[j] - a[j] * b[i]; if ( i < j ){ *c = a[i] * b[j] - a[j] * b[i]; } else { *c = 0 ; } printf("*c = %d",a[i] * b[j] - a[j] * b[i]); } このようなプログラムを作ったのですが外積を表示させることができません。 修正したプログラムをおしえていただけないでしょうか

  • ちらつきについて

    ゲームをつくっているのですが、画面がちらつくのが気になり、直そうと、ネットで調べたのですが、裏画面に一度、ビットマップを表示させて、それをデバイスコンテキストに転送する?ってやりかたがよくわかりません。 CMyFrameWnd::OnPaint(){ CPaintDC dc(this); CDC MemDC; CBitmap bitmap1; bitmap1.LoadBitmap("IDB_BITMAP1"); ...略 for(j=0;j<30;j++){ for(k=0;k<30;k++){ MemDC.SelectObject(&bitmap1); dc.Blt(j*32,k*32,32,32,&MemDC,0,0,SRCCOPY); } } } 見たいな感じです。なにぶんc,c++始めたばっかりでデバイスコンテキストとかもよくわかってないんでわかりやすい説明お願いします。

  • 2次元配列にポインタを格納

    http://www.okweb.ne.jp/kotaeru.php3?q=505241の訂正版の質問です。 VC++6.0を使っております。 下のようなプログラムを作ってみました。 #include <stdio.h> #include <vector> using namespace std; class c{ public: c(); virtual ~c(); int get(){return j;}; void set(int i){j=i;}; private: c(const c &right); const c &operator=(const c &right); int j; }; void main(){ vector <vector<c*> > a; c *b; for(int n=0;n<10;n++){ for(int i=0;i<10;i++){ b=new c; a[n].push_back(b); } } for(int j=0;j<10;j++){ for(int i=0;i<9;i++){ a[i][j] -> set(i+j); } } for(j=0;j<10;j++){ for(int i=0;i<9;i++){ printf("%d ",a[i][j] -> get()); } printf("%d\n",a[9][j] -> get()); } for(int i=0;i<10;i++){ for(int j=0;j<10;j++){ delete a[i][j]; } } } すると、コンパイルには成功するのですが、実行は出来ません。 その理由は、「外部参照1が未解決」だそうです。 アドバイスをお願いいたします。

  • クライアント領域をCBitmapに取り込みたい

    VC6.0MFCで クライアント領域(みたまま)を CBitmapに取り込みたいのですがどうすればよいのでしょうか? ためしにダイアログの領域をクリップボードに取り込むコード OnPaint書いたのですが真っ黒の画像しか取り込めていませんでした。 根本的に使うAPIが違うのでしょうか? void CCaptureDlg::OnPaint() {  CPaintDC dc(this); // 描画用のデバイス コンテキスト  CRect cr;  GetClientRect(&cr);  dc.TextOut(0,0,"テスト");  CDC* pDC = new CDC();  pDC->CreateCompatibleDC(&dc);  CBitmap img;  img.CreateCompatibleBitmap(pDC, cr.Width(), cr.Height());  OpenClipboard();  ::EmptyClipboard();  ::SetClipboardData(CF_BITMAP, img.GetSafeHandle());  ::CloseClipboard();  pDC->DeleteDC();  delete pDC;  CDialog::OnPaint(); }