2012-04-11 68 views
3

要重現此問題,請在Microsoft Paint中創建一個2x2像素黑色圖像,並保存爲D:\small.png。然後在Visual Studio中創建一個新的WinForms應用程序,並帶有無邊距的PictureBox。然後使用下面的代碼:我遇到意外的結果Graphics.DrawImage

void f6(Graphics g) 
{ 
    var img = Image.FromFile(@"d:\small3.png"); 
    var srcRect = new Rectangle(0, 0, img.Width, img.Height); 
    int factor = 400; 
    var destRect = new Rectangle(0, 0, img.Width * factor, img.Height * factor); 
    g.DrawRectangle(new Pen(Color.Blue), destRect); 
    g.DrawImage(img, destRect, srcRect, GraphicsUnit.Pixel); 
} 

void pictureBox1_Paint(object sender, PaintEventArgs e) 
{ 
    f6(e.Graphics); 
} 

我希望藍邊距之內的整個矩形是黑色的,而輸出如下:

enter image description here

這究竟是爲什麼?


好的,謝謝。我不知道插值。現在,讓我們來改變代碼如下:

void f6(Graphics g) 
{ 
    var img = Image.FromFile(@"d:\small3.png"); 
    var srcRect = new Rectangle(0, 0, img.Width, img.Height); 
    int factor = 200; 
    var destRect = new Rectangle(0, 0, img.Width * factor, img.Height * factor); 
    g.FillRectangle(new SolidBrush(Color.DarkCyan), pictureBox1.ClientRectangle); 
    g.InterpolationMode = InterpolationMode.NearestNeighbor; 
    g.DrawRectangle(new Pen(Color.Blue), destRect); 
    g.DrawImage(img, destRect, srcRect, GraphicsUnit.Pixel); 
} 

它產生以下結果:

Result3

這仍然是不能接受的。 我也嘗試過60x60圖片。這個問題並不是因爲它是一張2x2圖片。它們產生相同的效果。問題是爲什麼GDI +決定不用整個srcRect填充整個destRect?! 原來的問題是,我有一個大的圖像平鋪在較小的。我需要相鄰的瓷磚既不重疊也不接縫。在C++中,StretchBlt可以正常工作。但它不會產生平滑的拉伸圖像。

+1

我已將您的後續帖子合併到此問題的*編輯* – 2012-04-11 07:38:00

回答

5

的GDI +源矩形的定義是有點奇怪。

(0,0)在源圖像中實際上是圖像中左上像素的中心。 (寬度-1,高度-1)是圖像中右下像素的中心。

這意味着左上像素是從(-0.5,-0.5)到(0.5,0.5)的矩形,而右下像素是從(寬度-1.5,高度-1.5)到(寬度-0.5,高度0.5)。因此,源矩形實際上是在圖像的右邊和底部0.5個像素之外。

所以,你實際上需要一個源矩形(-0.5,-0.5,img.Width,img.Height)。

我想你也可以嘗試按照Hans的說法設置PixelOffsetMode。這實際上會理解行爲,但我不希望它適用於源矩形。

+0

哇,就是這樣。 非常感謝。 這正是我正在尋找的答案。 :) – hamidi 2012-04-12 07:35:34

+0

爲什麼GDI是這樣的? – jjxtra 2014-01-21 05:02:31

+0

@jjxtra我讀了一些它幫助旋轉變換的地方。 – 2016-04-03 04:12:57

4

看起來像使用雙三次插值調整圖像大小。正常的Bicubic尺寸算法通常需要16個像素來插入一個,但在圖像中只有4個像素,所以其餘12個像素從不設置,保持白色。

嘗試將調整大小的方法更改爲最近鄰居。這是由你的圖形對象克的InterpolationMode屬性設置爲InterpolationMode.NearestNeighbor完成:

void f6(Graphics g) 
{ 
    var img = Image.FromFile(@"d:\small3.png"); 
    var srcRect = new Rectangle(0, 0, img.Width, img.Height); 
    int factor = 400; 
    var destRect = new Rectangle(0, 0, img.Width * factor, img.Height * factor); 
    g.ImterpolatonMode = InterpolationMode.NearestNeighbor; 
    g.DrawRectangle(new Pen(Color.Blue), destRect); 
    g.DrawImage(img, destRect, srcRect, GraphicsUnit.Pixel); 
} 
+3

將PixelOffsetMode設置爲Half。 – 2012-04-11 09:00:09