Scaling an image in Xojo 2018 R3 gives very blurry results

Hello!

I’m having a big problem here in 2018R3, my code for scaling images produces very blurry image compared to the same exact code in 2016R2.1
I’ve setup a simple project to show the problem here, there’s already a picture in the folder to try :slight_smile:

Did i miss some changes?

Thanks a lot!

Sorry, i’ve uploaded code in italian… here’s the same code translated to english

Graphics has a new AntiAliasMode property that might help, i.e. set it to Graphics.AntiAliasModes.HighQuality for better scaling quality

Hello William, just tried but didn’t gives me better results, still at some point of the slider the image is still very blurry (or out of focus)

Modified the code in the “ModifyImage” method like this:

If scale = 0 Then
  Return image
End If

Dim scalefactor As Double = scale/100
Dim scaledHeight As Double = image.height*scalefactor
Dim scaledWidth As Double = image.width*scalefactor

Dim scaledImage As New Picture(scaledWidth,scaledHeight,32)

scaledImage.Graphics.AntiAlias = True
scaledImage.Graphics.AntiAliasMode = Global.Graphics.AntiAliasModes.HighQuality

scaledImage.graphics.drawpicture image, 0, 0, scaledWidth, scaledHeight, 0, 0, image.width, image.height

Dim theModifiedPicture As New Picture(l,h,32)

theModifiedPicture.Graphics.AntiAlias = True
theModifiedPicture.Graphics.AntiAliasMode = Global.Graphics.AntiAliasModes.HighQuality

theModifiedPicture.Graphics.ForeColor = RGB(255,255,255)
theModifiedPicture.Graphics.FillRect(0,0,l,h)

Dim centerX As Double = (l-scaledImage.Width)/2
Dim centerY As Double = (h-scaledImage.Height)/2

theModifiedPicture.Graphics.DrawPicture scaledImage, centerX, centerY, scaledWidth, scaledHeight, 0, 0, scaledImage.Width, scaledImage.Height

Return theModifiedPicture

Got slightly better result, but still worst then 2016R2.1

I remember reading something about the ‘depth’:

Can you test without the depth and see if you get better result?

Note: I don’t have experience with pictures, this information may be wrong

[quote=411350:@Alberto De Poo]I remember reading something about the ‘depth’:

Can you test without the depth and see if you get better result?

Note: I don’t have experience with pictures, this information may be wrong[/quote]

Thanks Alberto, yes i’ve already tried but didn’t change for better.

why create two more pictures?
why not create you “theModifiedPicture” and draw the scaled image directly into it?
and if you are scaling your picture DOWN (ie. making it smaller) you will lose some detail, but it should get “blurry” unless you are scaling down ALOT. If you are scaling UP…(making it bigger)… it will get “blurry” much faster, since you have to “stretch” the data to fit.

I have an IconResizer that takes a 1024x1024 image and creates dozens of smaller icons (from 16x16 back up to 1024x1024) and they all turn out nearly perfect. I am not using the AntiAliasMode mentioned above, as it is in Xojo2016, but am using a set of declares that I assume do the same thing

Matteo said that it works with Xojo2016, Dave can you test your code with Xojo2018r3?

Not until I can get a license for it…

and his code can’t have worked with 2016,

this doesn’t exist in 2016

theModifiedPicture.Graphics.AntiAliasMode = Global.Graphics.AntiAliasModes.HighQuality

I didn’t know you need a license to test, is that because of the declares or something else? Or your code needs to be built in order to work? Sorry for the newbie questions.

The code posted here is an update from the 2016 code. You can download the sample from first post (edit: second post in English), it has 2016 and 2018 code.

Edit: I downloaded the sample, ran both apps and I can’t see any difference. Either my eyes are very bad or the hardware where the program run is making a difference.

[quote=411358:@Alberto De Poo]
I downloaded the sample, ran both apps and I can’t see any difference. Either my eyes are very bad or the hardware where the program run is making a difference.[/quote]

Really? With both compiled apps the result is the same? Are you already on Mojave maybe?

No, macOS 10.12.6. Let me try with a non-retina display.

Teste on another mac with same results.

I did a test, running the apps side by side, then screen shot both, zoom in several times (the app used doesn’t show %) and I can see that the 2018 version is not as sharp as 2016. So yes, the 2018 version is not as clear as 2016, but with my eyes I can’t say is very blurry. Hope this helps.

[quote=411354:@Dave S]why create two more pictures?
why not create you “theModifiedPicture” and draw the scaled image directly into it?
and if you are scaling your picture DOWN (ie. making it smaller) you will lose some detail, but it should get “blurry” unless you are scaling down ALOT. If you are scaling UP…(making it bigger)… it will get “blurry” much faster, since you have to “stretch” the data to fit.

I have an IconResizer that takes a 1024x1024 image and creates dozens of smaller icons (from 16x16 back up to 1024x1024) and they all turn out nearly perfect. I am not using the AntiAliasMode mentioned above, as it is in Xojo2016, but am using a set of declares that I assume do the same thing[/quote]

Hello @Dave S ,

thanks a lot for you suggestion, honestly my code was pretty old… wasn’t very skilled at the time (not that i am now…) but doing everything in just one picture gives surely a better result! Still in some point of the scale result is blurry of with ugly colors compared to Xojo 2016 but it’s a very nice step forward. Thanks!

Try a better interpolation:

[code]Private Function BilinearInterpolation(OriginalPicture as Picture, newWidth as Integer, newHeight as Integer, constrainProportion as Boolean) as Picture
dim w as Integer = OriginalPicture.Width
dim h as Integer = OriginalPicture.Height
dim x_ratio as Double = (w - 1)/newWidth
dim y_ratio as Double = (h - 1)/newHeight
if constrainProportion then
if x_ratio >= y_ratio then
newHeight = h/x_ratio
else
newWidth = w/y_ratio
end if
x_ratio = max(x_ratio, y_ratio)
y_ratio = max(x_ratio, y_ratio)
end if

dim oldSurf as RGBSurface = OriginalPicture.RGBSurface
dim oldMask as Picture = OriginalPicture.CopyMask
dim oldMaskSurf as RGBSurface
if oldMask <> nil then oldMaskSurf = OriginalPicture.CopyMask.RGBSurface
dim InterpolatedPicture as new Picture(newWidth, newHeight, 32)
dim InterpolatedSurf as RGBSurface = InterpolatedPicture.RGBSurface
dim InterpolatedMaskSurf as RGBSurface = InterpolatedPicture.mask.RGBSurface

dim x, y, alphaValue as Integer
dim x_diff, y_diff, blue, red, green, gray as Double
dim a, b, c, d as Color

for i as Integer = 0 to (newHeight - 1)
for j as Integer = 0 to (newWidth - 1)
x = x_ratio * j
y = y_ratio * i
x_diff = (x_ratio * j) -x
y_diff = (y_ratio * i) - y

  'calculations for red, green and blue
  a = oldSurf.Pixel(x, y)
  b = oldSurf.Pixel(x + 1, y)
  c = oldSurf.Pixel(x, y + 1)
  d = oldSurf.Pixel(x + 1, y + 1)
  
  blue = (a.Blue * (1 - x_diff) * (1 - y_diff)) + (b.Blue * x_diff * (1 - y_diff)) + (c.Blue * y_diff * (1 - x_diff)) + (d.Blue * x_diff * y_diff)
  green = (a.green * (1 - x_diff) * (1 - y_diff)) + (b.green * x_diff * (1 - y_diff)) + (c.green * y_diff * (1 - x_diff)) + (d.green * x_diff * y_diff)
  red = (a.red * (1 - x_diff) * (1 - y_diff)) + (b.red * x_diff * (1 - y_diff)) + (c.red * y_diff * (1 - x_diff)) + (d.red * x_diff * y_diff)
  
  InterpolatedSurf.Pixel(j, i) = RGB(red, green, blue)
  
  if oldMaskSurf <> Nil then
    'now the mask
    a = oldMaskSurf.Pixel(x, y)
    b = oldMaskSurf.Pixel(x + 1, y)
    c = oldMaskSurf.Pixel(x, y + 1)
    d = oldMaskSurf.Pixel(x + 1, y + 1)
    
    gray = (a.Blue * (1 - x_diff) * (1 - y_diff)) + (b.Blue * x_diff * (1 - y_diff)) + (c.Blue * y_diff * (1 - x_diff)) + (d.Blue * x_diff * y_diff)
    
    InterpolatedMaskSurf.Pixel(j, i) = RGB(gray, gray, gray)
  end if
next

next

Return InterpolatedPicture

End Function[/code]

Wow @Beatrix Willius that gives some really impressive colors! Thanks a lot!!!
Unfortunately i get some rough edges on the guitar (see screenshot) but i’ll try to work on it.

Many thanks again!

It hurts me really to see this nice Guitar hanging outside a door.
Please give it a secure place ;-))

For all we know that could be a temperature and humidity controlled guitar storeroom :slight_smile:

4Beatrix: alphaValue is unused. Probably intentional. Just checking :slight_smile:
This really does not matter, but I replaced all ‘Integer’ with ‘int32’ to avoid confusion between 32 and 64 bit applications.

[quote=411456:@Hans-Jürgen Müller]It hurts me really to see this nice Guitar hanging outside a door.
Please give it a secure place ;-))[/quote]

Believe me, i would love to take her home with me, problem is that she’s just a little (but just a little) out of my budget :smiley: