3

I have an simple test. When it is solved, my problem is solved too. When working with small images, the graphics interpolation does bad work.

Please check out if you know how to fix the problem that the result image in the following code does ignore second half of image to draw. Draw something on the image by using loadimage from JPG or whatever you want.

    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 original Source here: http://www.goldengel.ch/temp/Source01%20one%20Pixel.jpg (one Pixel height image)

Destination image without fully drawing in half The second half vertical is not drawn by using the DrawImage methode. I want to have the image as result as you see on first picture. Stretched image with source on whole content.

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

VS2010 Scaling Project with description - Timo Böhme

Nasenbaer
  • 4,810
  • 11
  • 53
  • 86
  • 2
    Do your images show the problem? Or are you expecting us to download your code fragment, figure out how to put it into a working program, follow your cryptic instructions, and somehow deduce what the problem is so that we can impress you with our psychic debugging skills? – Jim Mischel Oct 04 '11 at 17:03
  • I added an sample. Hope it should be clear now. The project I made contains demo image and a short description on what happends. – Nasenbaer Oct 05 '11 at 09:01
  • Incredibly unclear. Hardcoding the *bm* bitmap to 450 pixels wide looks wrong, use PictureBox1.Image.Width. – Hans Passant Oct 08 '11 at 16:54
  • Please see the sample again. The size of the image is only as sample and if you will change it into something other it will not solve anything. Ok, perhaps I am wrong and you can tell me how it is solved? – Nasenbaer Oct 08 '11 at 19:17

4 Answers4

2

I had a similar problem which I had solved by resizing the original image. I guess this is an expected behaviour, not a bug (usual MS explanation but for this case it might be right :)). Some interpolation algorithms reqiure more than one pixel line (applies to both axes) to work correctly. If there is no second line, they may interpolate to an empty line which causes that problem above. You may change you image width/height to 2 pixels minimum or use proper interpolation methods for single line images.

Emir Akaydın
  • 5,708
  • 1
  • 29
  • 57
  • Hi. I dont need interpolation like bicubic or bilinear. Even same issue if you will set the source to 2 lines. – Nasenbaer Oct 08 '11 at 15:55
2

Please try to add:

gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality

to your last clause. GDI magic I guess :)

Hope this helps!

Fredrik Johansson
  • 3,477
  • 23
  • 37
  • I still hoped it ist that simple. You solved a lot of answers. Very complicated answers here. Your answer is the best one for me!! works great. Thanks Fredrik. I will ask admin to send you my expired 50Bounties. – Nasenbaer Oct 17 '11 at 12:59
1

As @EmirAkaydin said in his answer, your problem lies with the interpolation. I suspect his answer about it only being one pixel high, conflicting with Microsoft's resize algorithm, is correct.

I have a two step solution for you. Unless you want to write your own resize code (I didn't want to) that resizes exactly as you want, you could still use the Graphics.DrawImage function to at least resize the width of your image, but only the width. Then you can manipulate the pixel data directly and copy each that first valid line, for the entire height of the image.

You can replace your DoDemo code with the following (I don't use VB, so I'm not sure about the coding style; it does work, however):

    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 enough, the code @FredrikJohansson posted will work as well:

gr.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality

right before you draw the image. I'm going to leave this code and answer here, in case anyone ever wants to see it, but it looks like he answered your question in an easier way :)

Christopher Currens
  • 29,917
  • 5
  • 57
  • 77
0

Have you tried NearestNeighbor interpolation?

Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76
  • Hi Bradley. Like you can read in the sample and download project on line 11 it was already in use, yes. PixelOffset solved the problem.thx – Nasenbaer Oct 17 '11 at 15:32