0

I'm trying to resize / enlarge a image achieving same good results as IrfanView program. I just took this veteran and professional program as a point of reference for comparing the resulting quality that I can achieve using my "own" image resizing algorithm within .NET.

However, my resized image is blurry in comparison, and the image size differs within the canvas size, like 1px smaller, I don't know why, I mean I don't know if this difference is a fault of mine, or a fault of IrfanView.

Original image:

enter image description here

Image Resized using IrfanView:

enter image description here

Image resized using the .NET code below:

enter image description here


Maybe the differences will not be noticeable at all unless you save both images to disk, and open them with any image viewer (like IrfanVieew) to pass fast between both images, so you will notice something like this:

enter image description here


This is the code I'm using:

Public Function Resize(source As Image, size As Size,
                       preserveAspectRatio As Boolean) As Drawing.Image

    If (size.Width <= 0) Then
        Throw New ArgumentException("Width bigger than zero is reqired.", NameOf(size))

    ElseIf (size.Height <= 0) Then
        Throw New ArgumentException("Height bigger than zero is reqired.", NameOf(size))

    Else
        Dim bmp As Drawing.Bitmap

        If (preserveAspectRatio) Then
            ' https://codereview.stackexchange.com/a/70916/25995
            Dim scaleHeight As Single = CSng(size.Height) / CSng(source.Height)
            Dim scaleWidth As Single = CSng(size.Width) / CSng(source.Width)
            Dim smallerScale As Single = Math.Min(scaleHeight, scaleWidth)

            bmp = New Bitmap(CInt(Math.Truncate(source.Width * smallerScale)), 
                             CInt(Math.Truncate(source.Height * smallerScale)), 
                             source.PixelFormat)

        Else
            bmp = New Bitmap(size.Width, size.Height, source.PixelFormat)

        End If

        Using g As Graphics = Graphics.FromImage(bmp), 
              attributes As New ImageAttributes()

            ' g.CompositingQuality = CompositingQuality.AssumeLinear
            g.InterpolationMode = InterpolationMode.Bicubic
            g.PixelOffsetMode = PixelOffsetMode.Half
            g.SmoothingMode = SmoothingMode.None
            g.CompositingMode = CompositingMode.SourceCopy

            ' Avoid 1px semi-transparent black borders: 
            ' https://stackoverflow.com/a/41718683/1248295
            attributes.SetWrapMode(WrapMode.TileFlipX)
            g.DrawImage(source, New Rectangle(Point.Empty, bmp.Size), 0, 0, 
                        source.Width, source.Height, GraphicsUnit.Pixel, attributes)

        End Using

        Return bmp

    End If

End Function

Why I'm getting worse results than IrfanView?. Why my image is blurry and have different size drawn within the canvas size?. What I'm doing wrong and how do I fix it?.

Please note that in the code above I tested almost all possible quality combinations. And bicubic interpolation gives me a better / sharp image than highqualitybicubic, I'm not sure if this will apply always when enlarging a image.

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • 1
    You may find [Image Resizing - outperform GDI+](https://www.codeproject.com/articles/11143/image-resizing-outperform-gdi) an interesting read. – TnTinMn May 27 '21 at 14:50
  • I totally forgot about Lanczos!! (the filter I was using in Irfanview). Thanks. but what about the 1px drawn difference inside the canvas, that could be related to using Lanczos too?. – ElektroStudios May 27 '21 at 15:08
  • You should: load the Image preserving ICM information, if any (it's a bool argument to specify in `Image.FromStream()`), copy the original to a `32bit bgra` image (!important), use `InterpolationMode = InterpolationMode.HighQualityBicubic`, pixel offset now becomes not relevant, `CompositingMode.SourceCopy` depends on the surface. -- After that, apply a mild Sharpen filter (it's a 3x3 Matrix): something like: `{ 0f, -1.88f, 0f, }, { -2f, 11f, -2f, }, { 0f, -1.88f, 0f, }` would do. – Jimi May 27 '21 at 16:27
  • I forgot: the Shapen filter needs a Factor of `~.34f` and no Bias (set to `0.0f`) – Jimi May 27 '21 at 16:38

0 Answers0