Почему GDI + обрезает масштабированные изображения? - PullRequest
9 голосов
/ 19 декабря 2010

Я выполняю некоторое масштабирование изображения с использованием GDI + (C #) и обнаружил проблему, когда масштабируемое изображение обрезается по левому и верхнему краям.

http://zctut.com/cutoff.png

Чтобы воспроизвести это, создайте новый проект формы, сохраните это изображение в папке 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();
    }
}

Как видите, левый и верхний ряды пикселей обрезаются, как если бы масштабирующий прямоугольник начинался на полпути в пикселе.

Редактировать: для заметки, я также попытался использовать масштабное преобразование вместо прямоугольников, как указано выше, и оно отображалось точно так же.

Теперь, как говорится, я обнаружил работу вокруг. Если вы измените объявления прямоугольника в примере выше, как это:

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

Чтобы мы исправили «наполовину», тогда изображение будет правильно отображено.

В принципе, хотя обойти это легко, я делаю что-то не так или это нормальное поведение?

Редактировать: По предложению Андрея Паны я пытался добавить этот код перед вызовом розыгрыша:

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

И, к сожалению, это не повлияло на рендеринг. Край все еще был обрезан.

Ответы [ 3 ]

14 голосов
/ 19 декабря 2010

Попробуйте установить PixelOffsetMode в PixelOffsetMode.Half. По умолчанию для высокоскоростного сглаживания пиксели смещены на -0,5

.
0 голосов
/ 12 января 2011

Вы также можете проверить этот пост

http://waqarsherbhatti.posterous.com/2010/12/image-scaling-without-cutting-image.html

0 голосов
/ 19 декабря 2010

Установите размер изображения на 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.

...