I've noticed a problem when trying to zoom in on an image using the DrawImage method. The above image shows the problem. Basically, if you scale the image, the first row and column doesn't get scaled correctly. I've posted the problem twice on Expert-Exchange but have not found an explanation or fix yet.
I created a test app that takes a 40x40 bitmap with a checkerboard pattern and zooms it by a zoomfactor. The render code is as follows:
Protected Overrides Sub OnPaint(ByVal e As
System.Windows.Forms.PaintEventArgs) Try
If (bmp Is Nothing) Then
Else
Dim g As Graphics = e.Graphics()
g.SmoothingMode = Drawing2D.SmoothingMode.None
g.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
g.SmoothingMode = Drawing2D.SmoothingMode.None
Dim rect As New Rectangle
rect.X = 0
rect.Y = 0
rect.Width = (bmp.Width * m_ZoomLevel)
rect.Height = (bmp.Height * m_ZoomLevel) 'attribute shows that destination rect is
the right size but not needed for test.
Dim attr As System.Drawing.Imaging.ImageAttributes
attr = New System.Drawing.Imaging.ImageAttributes()
attr.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY)
g.DrawImage(bmp, rect,0, 0, 40, 40, GraphicsUnit.Pixel, attr)
attr.Dispose()End If
Catch ex As Exception
MessageBox.Show("ouch")
End Try
End Sub
This bug has been posted to Microsoft and confirmed by other programmers. A fix is to do the following:
Use (-0.5 + 0.5*srcw/dstw, -0.5 + 0.5*srch/dsth) as the source origin.
Happy Coding!
Jas
I did some testing with all of the interpolation methods and it looks to me like every pixel is scaled propertly but since the first row and column are on an edge, the information for the pixel that would have been scaled away from the center of the bitmap is discarded.
ReplyDeleteOne fix may be to use a larger graphics context, scale it to the center of the image, and extract the result at the new upper left coordinate.
I validated your bug on Connect and left a note about what I think is going on. Try using (-0.5 + 0.5*srcw/dstw, -0.5 + 0.5*srch/dsth) as the source origin.
ReplyDeleteThe above fix using works great. Thanks for the input. I will modify the blog to list this solution.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteFYI: I got word from Microsoft regarding this bug. They wanted me to create a project and send it to them. They didn't want to invest any time into reproducing the bug.
ReplyDeleteI told them I would bill them for the work...
Their response was that they only focus on the largest bugs with the greatest impact to their user base. It made since to me... We'll see if its fixed in the next release.
What does "source origin" mean?
ReplyDeletesource origin or X,Y position for the source rectangle to be passed to DrawRect, which has the bug.
ReplyDeleteHope this helps.
Thank you! Thank you! At last... phew... I has been working on the problem whole night and was such frustrated, without any hopes searched Google and found your blogpost - thank you, shame Microsoft!
ReplyDeletehey it didnt work for me :( i m using 2005 and but result is still same, and the calculation u suggested returns amount in decimal and i guess the parameter type for x,y is integer so it will not accept decimal amount
ReplyDeletemy apologies :) it worked fine with rectangleF :)
ReplyDeletethanx alot dude
it is no bug
ReplyDeleteu just need to set this:
g.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half