C# 图像不';Don’不要把整个图片盒都盖上

C# 图像不';Don’不要把整个图片盒都盖上,c#,image,image-processing,picturebox,C#,Image,Image Processing,Picturebox,我正在使用C#创建一个图像查看器,但在缩放(缩放)PictureBox方面有一个小问题 我在面板中有一个图片盒,我可以使用左上角的控件和鼠标滚轮对图像进行缩放(缩放)。但是,在某些特定的缩放比例下,图像无法覆盖整个PictureBox 例如,100%和200%时的SO徽标(100x116像素): 右边的图像是199x131像素,而PictureBox是200x132像素 我已将PictureBox的背景色设置为红色,以使问题变得明显 这并不总是发生,只是在特定的缩放级别。为什么呢?我做错什么

我正在使用C#创建一个图像查看器,但在缩放(缩放)
PictureBox
方面有一个小问题

我在
面板中有一个
图片盒
,我可以使用左上角的控件和鼠标滚轮对图像进行缩放(缩放)。但是,在某些特定的缩放比例下,图像无法覆盖整个
PictureBox

例如,100%和200%时的SO徽标(100x116像素):

右边的图像是199x131像素,而
PictureBox
是200x132像素

我已将
PictureBox
背景色设置为
红色
,以使问题变得明显

这并不总是发生,只是在特定的缩放级别。为什么呢?我做错什么了吗

我可以将
PictureBox
BackColor
设置为
面板的
BackColor
,以产生图像覆盖整个
PictureBox
的错觉,但我宁愿解决这个问题。如果我做不到,我将采用棘手的解决方案

相关代码:

float zoom = 1;
Image image = null;

public MainForm(string[] args)
{
    InitializeComponent();
    image = ImageBox.Image;
    this.ImageBox.MouseWheel += ImageBox_MouseWheel;
    if (args.Length > 0)
    {
        LoadImage(args[0]);
    }
}

private void ImageBox_Paint(object sender, PaintEventArgs e)
{
    // disable interpolation (sharper pixels)
    e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
    // https://msdn.microsoft.com/en-us/library/ms142046(v=vs.110).aspx
    e.Graphics.DrawImage(image,
        new Rectangle(0, 0, ImageBox.Width, ImageBox.Height),
        0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
}

private void LoadImage(string path)
{
    image = Image.FromFile(path);
    ImageBox.Width = (int)(image.Width * zoom);
    ImageBox.Height = (int)(image.Height * zoom);
    ImageBox.Image = image;
    CenterImage();
}

private void ScaleImage()
{
    ImageBox.Image = null;
    ImageBox.Width = (int)(image.Width * zoom);
    ImageBox.Height = (int)(image.Height * zoom);
    ImageBox.Image = image;
    CenterImage();
}

我还创建了一个,以防有人想实时查看应用程序。

您需要调整
ImageBox\u Paint
中的矩形。试试这个:

private void ImageBox_Paint(object sender, PaintEventArgs e)
{
    int add = ImageBox.Width / 200; 

    // disable interpolation (sharper pixels)
    e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
    // https://msdn.microsoft.com/en-us/library/ms142046(v=vs.110).aspx
    e.Graphics.DrawImage(image,
        new Rectangle(0, 0, ImageBox.Width + add, ImageBox.Height + add),
        0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
}

只需将PictureBox的
SizeMode
属性设置为
Zoom
。然后调整picturebox的大小将自动使图像拉伸到其完整大小


您甚至不需要绘制事件侦听器;这是内置的功能。只需将PictureBox的尺寸更改为计算出的图像缩放尺寸,即可完成操作。

这是一个基本的浮点精度问题,由将浮点值截断为int引起。这很容易产生off-by-1错误。由zoom变量引起的,它不完全是2.0,但或多或少有点小。反过来,与1.1f相乘会导致该值不能在基数2中准确表示。使用十进制而不是浮点避免了这一点,但PictureBox本身使用浮点数学,您无法改变这一点。设置背景色是目前为止最简单的解决方案。@HansPassant没有办法解决这个问题吗?我是否可以假设偏移量总是小于1,这样我就可以将1添加到不足的变量中?我更改了数学,使用了固定的缩放值
int zoom=2
,并绘制了图像。我仍然可以看到丢失的像素(红色背景)。。。我见过几个图像查看器似乎没有这个问题。他们要么使用
背景色
技巧,要么有真正的解决方案。我想我必须检查他们的源代码.Nvm。他们似乎都有相同的问题。我想知道Windows照片查看器是如何工作的。这是一种常见的方法吗?我现在就试过了,虽然它似乎有效,但也引起了一些问题。首先,这只适用于SO徽标,或者至少适用于具有类似尺寸的图像。如何将
200
更改为动态值,以便它可以处理任何图像?另外,在宽度和高度上添加
add
是否明智?他们不应该接受不同的价值观吗?你能详细说明一下你的方法吗?现在,我正在使用
intaddw=ImageBox.Width/(image.Width*2);int addH=ImageBox.Height/(image.Height*2)并且它正在生成正确的。我需要一个更新:)这是如何工作的?有点希望我在2009年发布了这个答案。最近的邻居应该只用于缩放完美的整数因子,虽然。。。对于这种像素缩放,还应将Graphics.PixelOffsetMode设置为PixelOffsetMode.Half。它的记录不正确,但如果不这样做,图像将移动半个(缩放)像素。