29

I am using StretchImage because the box is resizable with splitters. It looks like the default is some kind of smooth bilinear filtering, causing my image to be blurry and have moire patterns.

Simon
  • 24,010
  • 36
  • 139
  • 249
Jared Updike
  • 6,806
  • 7
  • 42
  • 67

4 Answers4

37

I needed this functionality also. I made a class that inherits PictureBox, overrides OnPaint and adds a property to allow the interpolation mode to be set:

using System.Drawing.Drawing2D;
using System.Windows.Forms;

/// <summary>
/// Inherits from PictureBox; adds Interpolation Mode Setting
/// </summary>
public class PictureBoxWithInterpolationMode : PictureBox
{
    public InterpolationMode InterpolationMode { get; set; }

    protected override void OnPaint(PaintEventArgs paintEventArgs)
    {
        paintEventArgs.Graphics.InterpolationMode = InterpolationMode;
        base.OnPaint(paintEventArgs);
    }
}
JYelton
  • 32,870
  • 25
  • 119
  • 184
  • Very nice. I think PanAndZoomPictureBox of EmguCV do the same. Are you aware of any performance issue doing it? – Pedro77 May 30 '13 at 22:27
  • I haven't had any measurable performance differences changing the interpolation mode in this way. – JYelton May 30 '13 at 22:30
  • 4
    Lovely answer. I suggest posters be a bit more complete with their code, i.e., add a using `System.Drawing.Drawing2D` or put the full namespace in front of the InterpolationMode declaration. – darda Dec 17 '13 at 14:49
  • 4
    Note that with crisp zoom you'll see that the image, when zoomed, is offset by half a pixel. To fix it, set `paintEventArgs.Graphics.PixelOffsetMode = PixelOffsetMode.Half;` This property is named wrongly; putting it to Half makes it _not_ shift the whole thing up and to the left by half a (zoomed) pixel. – Nyerguds Jan 22 '18 at 22:30
  • @pelesl I added the namespace declarations in using statements for clarity. – JYelton Jun 07 '18 at 18:37
  • And how do we use this class? How can I place a PictureBoxWithInterpolationMode on my form? – Nick_F Jan 21 '20 at 07:41
  • @Nick_F You can either manually change the Designer.cs file (replace PictureBox with the new control) or add the new control to your toolbox. It's been years since I worked in VS but you should be able to find it using the phrase "add custom usercontrol to toolbox." – JYelton Jan 21 '20 at 09:29
  • @JYelton, Thanks. I figured out to edit the designer.cs to include the component, but it would be cool to add this new control as a custom component to the toolbox - it's easier to drag and drop. – Nick_F Jan 21 '20 at 20:37
  • It would be useful to adjust the InterpolationMode` setter to call Invalidate. That way, if you change the InterpolationMode, the PictureBox will update. – Wyck Jun 29 '20 at 00:45
5

I suspect you're going to have to do the resizing manually thru the Image class and DrawImage function and respond to the resize events on the PictureBox.

Joel Lucsy
  • 8,202
  • 1
  • 26
  • 33
3

I did a MSDN search and turns out there's an article on this, which is not very detailed but outlines that you should use the paint event.

http://msdn.microsoft.com/en-us/library/k0fsyd4e.aspx

I edited a commonly available image zooming example to use this feature, see below

Edited from: http://www.dotnetcurry.com/ShowArticle.aspx?ID=196&AspxAutoDetectCookieSupport=1

Hope this helps

    private void Form1_Load(object sender, EventArgs e)
    {
        // set image location
        imgOriginal = new Bitmap(Image.FromFile(@"C:\images\TestImage.bmp"));
        picBox.Image = imgOriginal;

        // set Picture Box Attributes
        picBox.SizeMode = PictureBoxSizeMode.StretchImage;

        // set Slider Attributes
        zoomSlider.Minimum = 1;
        zoomSlider.Maximum = 5;
        zoomSlider.SmallChange = 1;
        zoomSlider.LargeChange = 1;
        zoomSlider.UseWaitCursor = false;

        SetPictureBoxSize();

        // reduce flickering
        this.DoubleBuffered = true;
    }

    // picturebox size changed triggers paint event
    private void SetPictureBoxSize()
    {
        Size s = new Size(Convert.ToInt32(imgOriginal.Width * zoomSlider.Value), Convert.ToInt32(imgOriginal.Height * zoomSlider.Value));
        picBox.Size = s;
    }


    // looks for user trackbar changes
    private void trackBar1_Scroll(object sender, EventArgs e)
    {
        if (zoomSlider.Value > 0)
        {
            SetPictureBoxSize();
        }
    }

    // redraws image using nearest neighbour resampling
    private void picBox_Paint_1(object sender, PaintEventArgs e)
    {
        e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
        e.Graphics.DrawImage(
           imgOriginal,
            new Rectangle(0, 0, picBox.Width, picBox.Height),
            // destination rectangle 
            0,
            0,           // upper-left corner of source rectangle
            imgOriginal.Width,       // width of source rectangle
            imgOriginal.Height,      // height of source rectangle
            GraphicsUnit.Pixel);
    }
Alex D
  • 31
  • 2
  • What event is wired up to your picBox_Paint_1 method? it would be in some other part of your code. – Jared Updike Feb 25 '11 at 03:05
  • Yeah it's in the form designer code: this.picBox.Paint += new System.Windows.Forms.PaintEventHandler(this.picBox_Paint_1); – Alex D Feb 28 '11 at 16:44
-3

When resizing an image in .net, the System.Drawing.Drawing2D.InterpolationMode offers the following resize methods:

  • Bicubic
  • Bilinear
  • High
  • HighQualityBicubic
  • HighQualityBilinear
  • Low
  • NearestNeighbor
  • Default
GateKiller
  • 68,419
  • 71
  • 167
  • 203