• 締切済み

DrawImageでビットマップを拡大したときの表示について

今、画像を拡大して表示する処理を作成しています。 実際の処理としては以下のような感じです。 Graphics^ g = Graphics::FromImage(picView->Image); g->InterpolationMode = Drawing2D::InterpolationMode::NearestNeighbor; g->DrawImage(imgTemp, 0, 0, nWidth * nScale, nHeight * nScale); 画像を拡大して表示すること自体はできているのですが、 拡大の基準点?がずれているような表示になるのが気になります。 たとえば、拡大前の画像が市松模様だったとして、拡大後は □□■■□□■■□□■■ □□■■□□■■□□■■ ■■□□■■□□■■□□ ■■□□■■□□■■□□ □□■■□□■■□□■■ □□■■□□■■□□■■ ■■□□■■□□■■□□ ■■□□■■□□■■□□(図1) のように表示して欲しいのですが、実際の表示は □■■□□■■□□■■ ■□□■■□□■■□□ ■□□■■□□■■□□ □■■□□■■□□■■ □■■□□■■□□■■ ■□□■■□□■■□□ ■□□■■□□■■□□(図2) のような感じで、左端と上端が半分くらいしか見えてない感じです。 (8倍に拡大したとして、4ピクセルの白、8ピクセルの黒…となっている感じです) (図1)のように表示されるにはどのようにすればいいでしょうか?

みんなの回答

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

GDI+で組んでも ドット欠けが起きるようですよ

回答No.2

 こんばんは。補足頂きました。  すんません、思いっきり的外れな事を書いてしまいました。Visual Studio 2008 C++/CLIで以下のコードで試して見ました。  見事に1ピクセル分ずれました。Graphics::DrawImage()メソッドのバグである可能性が濃厚です。  まともに等価倍率コピーが出来ないのですから、ルーペ表示的な機能を実装する上では、使い物にならないと思います。 private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { this->pictureBox1->Image = gcnew Bitmap("test.bmp"); this->pictureBox1->Image->Save("kakunin.bmp"); const int nWidth = this->pictureBox1->Image->Width; const int nHeight= this->pictureBox1->Image->Height; const int nScale = 2; Bitmap^ imgTemp = gcnew Bitmap(nWidth * nScale, nHeight * nScale, this->pictureBox1->Image->PixelFormat); Graphics^ g = Graphics::FromImage(imgTemp); g->InterpolationMode = Drawing2D::InterpolationMode::NearestNeighbor; g->DrawImage(this->pictureBox1->Image, 0, 0, nWidth * nScale, nHeight * nScale); imgTemp->Save("stretch.bmp");//此処で出力されたビットマップファイルもズレている this->pictureBox1->Image = imgTemp; this->pictureBox1->Invalidate(); }  win32 apiの出番かもしれません。以下でまともに出力されました。以下参考程度に。 #include<windows.h> #pragma comment(lib, "gdi32.lib") private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { this->pictureBox1->Image = gcnew Bitmap("test.bmp"); this->pictureBox1->Image->Save("kakunin.bmp"); const int nWidth = this->pictureBox1->Image->Width; const int nHeight= this->pictureBox1->Image->Height; const int nScale = 2; Bitmap^ imgTemp = gcnew Bitmap(nWidth * nScale, nHeight * nScale, this->pictureBox1->Image->PixelFormat); IntPtr iPtrDst = imgTemp->GetHbitmap(); IntPtr iPtrSrc = static_cast<Bitmap^>(this->pictureBox1->Image)->GetHbitmap(); HDC hDCDst = ::CreateCompatibleDC(NULL); HDC hDCSrc = ::CreateCompatibleDC(NULL); HBITMAP hBmpDst = static_cast<HBITMAP>(iPtrDst.ToPointer()); HBITMAP hBmpSrc = static_cast<HBITMAP>(iPtrSrc.ToPointer()); HGDIOBJ hBmpDstOld = ::SelectObject(hDCDst, hBmpDst); HGDIOBJ hBmpSrcOld = ::SelectObject(hDCSrc, hBmpSrc); ::StretchBlt(hDCDst, 0, 0, nWidth * nScale, nHeight * nScale, hDCSrc, 0, 0, nWidth, nHeight, SRCCOPY); ::SelectObject(hDCDst, hBmpDstOld); ::SelectObject(hDCSrc, hBmpSrcOld); ::DeleteDC(hDCDst); ::DeleteDC(hDCSrc); imgTemp = Bitmap::FromHbitmap(iPtrDst); imgTemp->Save("stretch.bmp"); ::DeleteObject(hBmpDst); ::DeleteObject(hBmpSrc); this->pictureBox1->Image = imgTemp; this->pictureBox1->Invalidate(); }

kis_red
質問者

お礼

どうもDrawImageを使う限り、この「ずれ」からは逃れられないみたいですね。 調べてみたところ、バグというよりは補間をした結果の「ずれ」みたいな感じです。 考え方の違いというか。 拡大前の座標が 0.5000~1.4999 になる範囲に 1.0000 の座標の色が拡大されている感じで。 言葉では説明しにくいんですが、  元々の画素を拡大後の座標に配置    ↓  開いた隙間を、配置した画素の色(の範囲)を広げて埋める みたいな感じですかね? それぞれの画素から滲み出した色が(混ざらないで)広がった結果、こうなった的な。 Win32APIを使う方法は今までもやったことはあるんですが、あまりC++的じゃないというか、純粋なCっぽいので避けてました。 今回はWin32APIのお世話になるのが正解なんでしょうかね。 ひとまずDrawImageはやめてWin32APIでやってみます。 ありがとうございました。

回答No.1

 こんにちは。  恐らく、  g->InterpolationMode = Drawing2D::InterpolationMode::NearestNeighbor;  辺りが原因かもしれません。  http://msdn.microsoft.com/ja-jp/library/system.drawing.drawing2d.interpolationmode(VS.80).aspx  上記の、  g->InterpolationMode = Drawing2D::InterpolationMode::Default;  又は、  g->InterpolationMode = Drawing2D::InterpolationMode::Invalid;  辺りで試されて見ては如何でしょうか。

kis_red
質問者

補足

~::Defaultなどでは拡大したときに補完をしてしまいます。 今回やりたいのは、ルーペツールなどのように「そのまま」拡大する処理なんです。 こういった処理はDrawImageではできないんでしょうか?

関連するQ&A