2015-04-12 2 views
2

В большинстве случаев это создает идентичную копию, но если исходный битмап, переданный в Clone, был создан путем рисования раздела из большего растрового изображения, где раздел был расширен до самого крайнего края большего растрового изображения, то копия, которую я получаю, будет иметь слегка измененные пиксели на самом правом краю.Почему этот код не всегда создает идентичную копию растрового изображения?

Что я делаю неправильно?

код, который создает оригинальные выглядит так:

var SmallerImage = new Bitmap(_sqSize, _sqSize); 
using (var gfx = Graphics.FromImage(SmallerImage)) { 
    gfx.InterpolationMode = InterpolationMode.High; 
    gfx.PixelOffsetMode = PixelOffsetMode.None; 
    gfx.DrawImage(LargerImage, 
        new Rectangle(0, 0, _sqSize, _sqSize), 
        new Rectangle(p.X, p.Y, _sqSize, _sqSize), 
        GraphicsUnit.Pixel); 
} 

Важно знать, что есть, что точка р и _sqSize таково, что исходный прямоугольник (второй прямоугольник в вызове DrawImage) идет прямо вплоть до самого правого края LargerImage.

Этот же код будет создавать идентичную копию, если точки p и _sqSize таковы, что исходный прямоугольник не касается правого края LargerImage.

Может ли кто-нибудь сказать мне, почему это происходит?

Или, может ли кто-нибудь сказать мне, как НАДЕЖНО создать ТОЧНЫЙ пиксель-пиксельный дубликат растрового изображения? Похоже, это должно быть легко, но я не могу это сделать.

new Bitmap(bmp) имеет те же проблемы, что и мой метод клонирования. bmp.Clone() действительно работает, но у него есть проблемы под обложками (что-то о том, что это не глубокая копия - совместное использование данных с оригиналом), и использование этого ломает мой код разными способами.

+3

I «Никогда не видел, чтобы конструктор« Bitmap (Image) »создавал нечто иное, чем дубликат входного изображения. Вы уверены, что изображение, которое вы дублируете, не имеет одинаковых артефактов, которые делает объект клонирования? По моему опыту, код, который вы должны создать меньшую версию растрового изображения, скорее всего, приведет к артефактам, особенно когда вы пытаетесь масштабировать из подмножества, выровненного с краем оригинала, как вы здесь. Было бы полезно увидеть [хороший, _minimal_, _complete_ пример кода] (http://stackoverflow.com/help/mcve), который надежно демонстрирует проблему. –

+0

Вы пытались установить PixelOffsetMode.Half? Это действительно важно, поскольку вы не делаете никакого масштабирования, но попытка попробовать не повредит. [MSDN] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms534169%28v=vs.85%29.aspx): _ Рассматривайте пиксель в верхнем левом углу изображения с помощью адрес (0, 0). С PixelOffsetModeNone пиксель покрывает область между -0.5 и 0.5 в обоих направлениях x и y; то есть центр пикселей находится в (0, 0). С PixelOffsetModeHalf пиксель покрывает область между 0 и 1 в направлениях x и y; (0.5, 0.5) ._ – TaW

+0

Для проблем использования Клона и их решения см. [здесь] (http://stackoverflow.com/questions/12709360/whats-the-difference-between-bitmap -clone-and-new-bitmapbitmap) (Прочитайте оба ответа!) – TaW

ответ

0

Прежде всего, убедитесь, что изображение еще не имеет этих артефактов до его клонирования.

Использование Clone() действительно только неполная копия, но я считаю, что Clone(Rectangle, PixelFormat) глубоким клон:

public static Bitmap Clone(Bitmap bmp) { 
    var newbmp = bmp.Clone(new Rectangle(0, 0, bmp.Width, bmp.Height), bmp.PixelFormat); 
    return newbmp; 
} 

Если это не сработает, попробуйте скопировать исходные данные:

[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] 
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); 

public static Bitmap Clone(Bitmap bmp) { 
    var oldData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); 

    var newBmp = new Bitmap(bmp.Width, bmp.Height, oldData.PixelFormat); 
    var newData = newBmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat); 
    CopyMemory(newData.Scan0, oldData.Scan0, (uint)(Math.Abs(oldData.Stride) * oldData.Height)); 
    newBmp.UnlockBits(newData); 

    bmp.UnlockBits(oldData); 
    return newBmp; 
} 
Смежные вопросы