Incorrect image interpolation in .Net

I have a simple test. When it is resolved, my problem is also resolved. When working with small images, graphical interpolation does not work well.

Please check if you know how to fix the problem that the result image in the following code ignores the second half of the image for drawing. Draw something on the image using loadimage from JPG or whatever.

Dim GrayImage as system.drawing.Bitmap(640,480) Dim bmTmp As New System.Drawing.Bitmap(GrayImage.Width, 1) Using gr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmTmp) gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear gr.DrawImage(GrayImage, New System.Drawing.Rectangle(0, 0, bmTmp.Width, bmTmp.Height), New System.Drawing.Rectangle(0, 0, GrayImage.Width - 0, GrayImage.Height - 0), System.Drawing.GraphicsUnit.Pixel) End Using GrayImage = New System.Drawing.Bitmap(GrayImage.Width, GrayImage.Height, GrayImage.PixelFormat) Using gr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(GrayImage) gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor gr.DrawImage(bmTmp, New System.Drawing.Rectangle(0, 0, GrayImage.Width, GrayImage.Height ), New System.Drawing.Rectangle(0, 0, bmTmp.Width - 0, bmTmp.Height - 0), System.Drawing.GraphicsUnit.Pixel) End Using 

Source stretched to let you view it Download the original Source here: http://www.goldengel.ch/temp/Source01%20one%20Pixel.jpg (one image height image)

Destination image without fully drawing in half The second half of the vertical is not drawn using the DrawImage method. I want the image to be the result, as you see in the first shot. Stretched image with source text for all content.

* DOWNLOAD * Download here the full working VS2010 demo project VB.Net:

VS2010 Scaling Project with description - Timo Böhme

+3
source share
4 answers

Try adding:

 gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality 

at your last point. GDI magic I think :)

Hope this helps!

+2
source

I had a similar problem that I solved by resizing the original image. I assume this is the expected behavior and not an error (the usual explanation is MS, but for this case it may be correct :)). Some interpolation algorithms require more than one row of pixels (for both axes) to work properly. If there is no second line, they can interpolate to an empty line, which causes this problem above. You can change the width / height of the image by at least 2 pixels or use the correct interpolation methods for single-line images.

+2
source

As @EmirAkaydin said in his answer, your problem lies in interpolation. I suspect that his answer about this, only one pixel, contrary to Microsoft's resizing algorithm, is correct.

I have a two-story solution for you. If you don’t want to write your own resizing code (I don’t want), which will change the way you want, you can still use the Graphics.DrawImage function to at least resize the width of your image, but only the width. Then you can directly manipulate the pixel data and copy every first valid row for the entire height of the image.

You can replace the DoDemo code DoDemo following (I don't use VB, so I'm not sure about the coding style, but it works):

  Call CreateSampleImage() 'scale the image to only one single row Dim bm As New Bitmap(450, 1) Using gr As Graphics = Graphics.FromImage(bm) Dim RDst As New Rectangle(0, 0, bm.Width, bm.Height) Dim RSrc As New Rectangle(0, 0, Me.PictureBox1.Image.Width, Me.PictureBox1.Image.Height) gr.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor gr.SmoothingMode = Drawing2D.SmoothingMode.None gr.DrawImage(Me.PictureBox1.Image, RDst, RSrc, GraphicsUnit.Pixel) End Using Me.PictureBox2.Image = bm 'stretch now the single row image back to original width Dim bm2 As New Bitmap(Me.PictureBox1.Image.Width, Me.PictureBox1.Image.Height) Using gr As Graphics = Graphics.FromImage(bm2) Dim RDst As New Rectangle(0, 0, bm2.Width, 1) Dim RSrc As New Rectangle(0, 0, Me.PictureBox2.Image.Width, Me.PictureBox2.Image.Height) gr.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor gr.SmoothingMode = Drawing2D.SmoothingMode.None gr.DrawImage(Me.PictureBox2.Image, RDst, RSrc, GraphicsUnit.Pixel) End Using ' use our own custom height stretch code Dim rrc As New Rectangle(0, 0, bm2.Width, bm2.Height) Dim bmd As BitmapData bmd = bm2.LockBits(rrc, ImageLockMode.ReadWrite, bm2.PixelFormat) ' stride is the width of the image in pixels Dim ba(bmd.Stride - 1) As Byte Marshal.Copy(bmd.Scan0, ba, 0, bmd.Stride) ' copy pixel data to each line For y = 1 To bmd.Height - 1 Marshal.Copy(ba, 0, bmd.Scan0 + (y * bmd.Stride), ba.Length) Next bm2.UnlockBits(bmd) Me.PictureBox3.Image = bm2 

EDIT:

Interestingly, @FredrikJohansson's code also published a paper:

 gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality 

before you draw an image. I'm going to leave this code and answer here if someone wants to see it, but it looks like it answered your question in a simpler way :)

+1
source

Have you tried NearestNeighbor interpolation?

0
source

Source: https://habr.com/ru/post/958385/


All Articles