为什么GDI +会切断缩放图像?

时间:2010-12-19 06:51:44

标签: c# gdi+ image-manipulation

我正在使用GDI +(C#)进行一些图像缩放,并注意到我正在缩放的​​图像沿着左边和上边缘切割的问题。

http://zctut.com/cutoff.png

要重现这一点,请创建一个新的表单项目,将this image保存到bin \ debug文件夹中,并将以下代码添加到表单(以及相应的事件):

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
    }

    int scale = 1;
    Image img = Image.FromFile("circle.png");

    private void Form1_Paint(object sender, PaintEventArgs e) {
        //this makes the glitch easier to see
        e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;

        RectangleF srcRect = new RectangleF(0f, 0f, img.Width, img.Height);
        RectangleF destRect = new RectangleF(0f, 0f, img.Width * scale, img.Height * scale);

        e.Graphics.DrawImage(img, destRect, srcRect, GraphicsUnit.Pixel);
    }

    private void Form1_Click(object sender, EventArgs e) {
        scale++;
        if (scale > 8) scale = 1;
        Invalidate();
    }
}

正如您所看到的那样,左侧和最顶部的像素行被切除,就像缩放矩形在像素中间开始一样。

编辑:注意,我也尝试使用Scale变换而不是如上所述使用矩形,并且渲染完全相同。

现在,那说,我确实发现了一个解决方法。如果您更改上面示例中的矩形声明,如下所示:

RectangleF srcRect = new RectangleF(-0.5f, -0.5f, img.Width, img.Height);

因此我们纠正“中途”事物,然后图像呈现正确。

基本上,虽然这很容易解决,但我做错了什么,还是这种正常行为?

编辑:根据Andrei Pana的建议,我尝试在绘图调用之前添加此代码:

e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;

不幸的是,它并没有影响渲染。边缘仍被切断。

3 个答案:

答案 0 :(得分:14)

尝试将PixelOffsetMode设置为PixelOffsetMode.Half。默认情况下,对于高速抗锯齿,像素偏移-0.5

答案 1 :(得分:0)

将图像的大小设置为比其包含的图形大2个像素(在每个维度中)。我也遇到过这种情况,并且发现抗锯齿过度拍摄的每一面都不超过1个像素。

换句话说,要么关闭抗锯齿(这将解决这个问题),要么更改代码的这一部分:

RectangleF destRect = new RectangleF(0f, 0f, img.Width * scale, img.Height * scale);

到此:

RectangleF destRect = new RectangleF(1f, 1f, img.Width * scale -2, img.Height * scale -2);

(或使用使用srcRect的等效变通方法)

是的,这是正常行为,是GDI + / .Net。

的已知问题

答案 2 :(得分:0)