2016-12-16 9 views
4

Я сшиваю несколько изображений вместе вертикально и горизонтально, чтобы создать одно большее изображение (в котором общая ширина и высота являются суммой ширины и высоты отдельных изображений) с использованием Bitmap и System.Drawing.Graphics в C#. Размер отдельных изображений составляет 256 px на 256 px.DrawImage весы исходное изображение

Когда я использую DrawImage от System.Drawing.Graphics, почему я получаю масштабированную и/или увеличенную версию исходного изображения?


Вот оригинальное изображение:

original image


Когда я получить изображение программно и записать в файл в коде, я получаю следующее:

var result = httpClient.GetStreamAsync(/* url */); 
var bitmap = new Bitmap(await result); 
... 
using (var memory = new MemoryStream()) 
{ 
    using (var fs = new FileStream(/* path */, FileMode.OpenOrCreate, FileAccess.ReadWrite)) 
    { 
     bitmap.Save(memory, ImageFormat.Png); // I save to .png if that makes a difference 
     var bytes = memory.ToArray(); 
     await fs.WriteAsync(bytes, 0, bytes.Length); 
    } 
} 

programmatic retrieval of image in code

Я не вижу разницы. Все идет нормально.


Однако, когда я пытаюсь сшить изображения по горизонтали, я получаю следующее:

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

horizontally stitched image

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


Вот код, я использую, чтобы объединить изображения:

Примечание: Если byWidth является true, я сшить изображения по горизонтали.

private Bitmap MergeImages(IEnumerable<Bitmap> images, bool byWidth) 
{ 
    var enumerable = images as IList<Bitmap> ?? images.ToList(); 

    var width = 0; 
    var height = 0; 

    foreach (var image in enumerable) 
    { 
     if (byWidth) 
     { 
      width += image.Width; 
      height = image.Height; 
     } 
     else 
     { 
      width = image.Width; 
      height += image.Height; 
     } 
    } 

    var bitmap = new Bitmap(width, height); 
    using (var g = Graphics.FromImage(bitmap)) 
    { 
     var localWidth = 0; 
     var localHeight = 0; 

     foreach (var image in enumerable) 
     { 
      if (byWidth) 
      { 
       g.DrawImage(image, localWidth, 0); 
       localWidth += image.Width; 
      } 
      else 
      { 
       g.DrawImage(image, 0, localHeight); 
       localHeight += image.Height; 
      } 
     } 
    } 

    return bitmap; 
} 

ответ

4

Да, DrawImage масштабирует изображение, выводимое на основании настройки DPI изображения втягиваются. Растровое изображение, сохраненное в 72 DPI, будет масштабироваться в соответствии с 96 DPI экрана, на который вы его рисуете (или любого другого DPI, на котором на самом деле установлен ваш экран). Идея здесь заключается в том, что исходное разрешение (ДОИ) должно быть сделано для соответствия разрешению адресата (ДОИ), чтобы поддерживать независимость от разрешения.

Смысл, даже метод DrawImageUnscaled использует эту логику масштабирования на основе DPI. Практически это связано с тем, что метод DrawImageUnscaled является простой оболочкой вокруг одной из перегрузок DrawImage. Концептуально это кажется мне ошибкой.

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

g.DrawImage(img, 0, 0, img.Width, img.Height); 

Это квази-документированы в KB317174.