c# - DrawImage 缩放原始图像

标签 c# image-manipulation system.drawing

我正在使用 Bitmap 将多张图像垂直和水平拼接在一起以创建一个更大的图像(其中总宽度和高度是各个图像的宽度和高度之和)。和 System.Drawing.Graphics在 C# 中。单个图像的大小为 256 像素 x 256 像素。

当我使用 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

它看起来经过缩放、放大,绝对不像上面的原始图像或以编程方式检索的单个图像。


这是我用来将图像拼接在一起的代码:

注:如果byWidthtrue , 我水平拼接图像。

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;
}

最佳答案

是的,DrawImage 根据所绘制图像的 DPI 设置缩放图像输出。以 72 DPI 保存的位图图像将被缩放以匹配您正在绘制它的屏幕的 96 DPI(或您的屏幕实际设置的任何 DPI)。这里的想法是源分辨率 (DPI) 应该与目标分辨率 (DPI) 相匹配,以保持分辨率独立性。

令人困惑的是,即使是 DrawImageUnscaled 方法也使用这种基于 DPI 的缩放逻辑。实际上,这是因为 DrawImageUnscaled 方法只是对 DrawImage 重载之一的简单包装。从概念上讲,这对我来说似乎是一个错误。

无论哪种方式,解决方案都很简单:将所需的图像大小显式传递给 DrawImage 调用。本质上,您是在强制它缩放到所需的大小:

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

这在 KB317174 中有准记录.

关于c# - DrawImage 缩放原始图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41188689/

相关文章:

c# - 我无法摆脱我的 ClipRectangle 我想哭

c# - 如何创建对现有对象的引用?特别是对于 Get-Service 对象之一?

c# - 我可以通过 SQL Server 触发器调用 C# 函数吗?

c# - 如何使用 Matlab 创建偏振 3D 图像?

ruby - 我如何使用 ImageMagick 检测水平黑线?

android - Android ColorMatrix setSaturation() 是否支持大于 1 的值?

C# 检查当前日期是该月的 1 日、2 日还是 3 日,忽略周末和附加 List<DateTime>

c# - 如何在控制流图中表达 Try/Catch?

c# - 图形对象到图像文件