dポイントプレゼントキャンペーン実施中!

今、画像を拡大して表示する処理を作成しています。
実際の処理としては以下のような感じです。

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)のように表示されるにはどのようにすればいいでしょうか?

A 回答 (3件)

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

    • good
    • 0

 こんばんは。

補足頂きました。
 すんません、思いっきり的外れな事を書いてしまいました。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();
}
    • good
    • 0
この回答へのお礼

どうもDrawImageを使う限り、この「ずれ」からは逃れられないみたいですね。

調べてみたところ、バグというよりは補間をした結果の「ずれ」みたいな感じです。
考え方の違いというか。
拡大前の座標が 0.5000~1.4999 になる範囲に 1.0000 の座標の色が拡大されている感じで。
言葉では説明しにくいんですが、
 元々の画素を拡大後の座標に配置
   ↓
 開いた隙間を、配置した画素の色(の範囲)を広げて埋める
みたいな感じですかね?
それぞれの画素から滲み出した色が(混ざらないで)広がった結果、こうなった的な。

Win32APIを使う方法は今までもやったことはあるんですが、あまりC++的じゃないというか、純粋なCっぽいので避けてました。
今回はWin32APIのお世話になるのが正解なんでしょうかね。

ひとまずDrawImageはやめてWin32APIでやってみます。

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

お礼日時:2009/10/14 18:58

 こんにちは。



 恐らく、
 g->InterpolationMode = Drawing2D::InterpolationMode::NearestNeighbor;
 辺りが原因かもしれません。

 http://msdn.microsoft.com/ja-jp/library/system.d …

 上記の、
 g->InterpolationMode = Drawing2D::InterpolationMode::Default;
 又は、
 g->InterpolationMode = Drawing2D::InterpolationMode::Invalid;
 辺りで試されて見ては如何でしょうか。

この回答への補足

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

こういった処理はDrawImageではできないんでしょうか?

補足日時:2009/10/14 12:03
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!