Scale quality of Canvas control

The best way would be to resample the image by code. I am trying to find a VB example that would be transposable to Xojo…

Same here, for similar reasons. Moving to fully vectorial images is something that should be possible. With the loss of PICT we lost the only vectorial image format we had access to, but whatever comes must be just as native. I’m dying to use paintcode with Xojo and for that pretty much only SVG would work :slight_smile:

Something that should be an option would be to use the platform’s native renderers for resizing. Currently resizing seems to be done by a basic algorithm without any antialising done to it.

This is my “plan B” if there isn’t an easy work-around… looking into declares.

I’m familiar with the Windows API, but not so much with OS X and Linux… hence why I’d like to explore all other possibilities before venturing down the declare route where code becomes platform specific.

Ok, I’ve created a feedback ticket to improve the quality of the images produced when scaling them with the Graphics.DrawPicture method.

<https://xojo.com/issue/32371>

@Michel: I take the liberty to post the scale function from the ImagePlay lib here:

[code]

function scale picture (p as Picture, newWidth as integer, newHeight as Integer) as picture

// based on code from Dr. Gerard Hammond

// with performance/functional improvements by Tomis Erwin

#if DebugBuild=False then
#pragma BackgroundTasks false
#pragma BoundsChecking false
#pragma NilObjectChecking false
#pragma StackOverflowChecking false
#endif

dim pIn,pOut as Picture
Dim s As RGBSurface
Dim o As RGBSurface
Dim x,y,xMax, yMax As Integer
dim xx() as Double
Dim c1, c2, c3, c4, c5 As Color
dim xMult,yMult, a,b, xSub,ySub, xAdd,yAdd as Double

if p=nil then
Return p

end

s=p.RGBSurface
if s=nil then
Return nil
end

pOut=NewPicture( newWidth, newHeight, 32 )
if pOut=nil then
Return nil
end

o=pOut.RGBSurface
if o=nil Then
Return nil
end

xMax = pOut.Width - 1
yMax = pOut.Height - 1

yMult=p.Height/newHeight
xMult=p.Width/newWidth

a=newWidth/p.Width
if a>.5 then
xSub=.45
xAdd=.5
Elseif a<.5 then
xSub=.75
xAdd=2
else
xSub=0
xAdd=1
end

a=newHeight/p.Height
if a>.5 then
ySub=.45
yAdd=.5
Elseif a<.5 then
ySub=.75
yAdd=2
else
ySub=0
yAdd=1
end

redim xx(xMax)
for x=0 to xMax
xx(x)=(x * xMult)- xSub
next

For y = 0 To yMax
b = (y * yMult)- ySub
For x = 0 To xMax
a = xx(x)
c1 = s.Pixel(a , b )
c2 = s.Pixel(a + xAdd , b )
c3 = s.Pixel(a , b + yAdd)
c4 = s.Pixel(a + xAdd , b + yAdd)

  o.Pixel(x, y) = RGB( _
  (c1.Red + c2.Red + c3.Red + c4.Red) \\ 4, _
  (c1.Green + c2.Green + c3.Green + c4.Green) \\ 4, _
  (c1.Blue + c2.Blue + c3.Blue + c4.Blue) \\ 4 _
  )
  
Next

Next

Return pOut[/code]

Thanks for posting the algorithm Ulrich. Here is a screenshot of how the algorithms compare to each other. Looks like the ImagePlay is an improvement.

WebKit still seems to be getting the best quality when down-scaling images though.

Wow! Thanks for your fast action, Alwyn!
A great comparison that is. Yes, there seems to be room for improvement, considering IP’s version looks a bit fat and still jaggy.
And I’d bet that HTML viewer uses a system call to scale and anti-alias the picture, so this would be the routine I’d go for. If only I knew how …

I’m also leaning towards going the system route. For now the ImagePlay routine does however provide an immediate improvement.

Great move. Thanks Ulrich !

Did You try the open source command line rsvg-convert svg renderer?
single exe binary available here: Windows rsv-convert

Thanks, Carlos, but I live on the Mac side of life mainly. And I’d rather go for a library I can read in clear text instead of installing a compiled exe. But for the Windows pros this could be worth a try.

For the rest of us: Did you try out MacOSLib’s NSImage class? Currently I find no time for this, but I wouldn’t be surprised if scaling a picture through it would give the desired result:

Apple Developer Library: NSImage Class Reference

Apple did quite a lot of work on WebKit, so it wouldn’t surprise me if it was better. Core Graphics can do a beautiful job at scaling. I would imagine by now that Windows would have a nice anti-aliased scaling routine in their graphics toolbox, I just don’t know much 'bout Windows.

I took some times yesterday to test the code shared here (to find the graphics I had bad results while resized down with Xojo) and here’s my results:


Left image: standard resize with Xojo,
Middle image: resize with the above shared code,
Bottom image: resized with Preview (OS X 10.8.5 / loaded in the application).

I was suspecting: “bad results depends on the kind of the original image” AND the kind of used resize method (but I do not have any knowledge about “kind of image resize”). These results let me think that I may be right.

I am not able to add a sentence in my prior message, so here I am:

to really see the differences, load the image and watch it at full size (112KB):
View
Download

In short, the best image resize comes from Preview, then Xojo native, then the code shared in this conversation.

No, I do not talked about bad or wrong or… shared code. I only say that it is not appropriate in this kind of images.

About the image: the image comes from a Xojo application that save some data in pdf file (a Record from a Data Base); I took a Beatles song listing etc… data base to generate the image. Its contents is just contents and can be my name, address, photo, phone and social #, etc. It was only a “what can this be looking at ?”. The image could be set as a front image (data information) for a single person courier box to set the search easier.
Used colours does not matters.

Still not able to modify the previous message. BUT, the edit icon appears, I clicked it but got an error message telling me that I do not have the rights to perform that action.

FWIW

After a reboot, I saw my abive shared image and noticed a difference in the size.

This recalled me a bug affecting the resized … size ! If you pass a double instead an integer ([, nDestWidth as Integer ] [, DestHeight as Integer), you will get the size you asked for.

Passing an integer, gives you sometimes a value you do not asked for (the difference is 1 pixel).

Hi Emile,
Scaling is done differently on the Mac as it is to Windows. On the Mac, Core Graphics does an excellent job and there are several options for adjusting the scaling, there is even a Core Image filter which is designed specifically for scaling down (whilst retaining details).

I’m not surprised that WebKit does a good job of scaling, don’t forget that Apple poured a ton of resources into WebKit, so they could use it for Safari.

Which leaves us with Windows native scaling. We’re planning to do a couple of apps on Windows this year, so I’m keen to see if there is anything that can be done about this, as frankly the scaling in Windows looks terrible!

I will be looking into Windows native scaling options. If I become anything the wiser on this topic I’ll make sure to post the results here.

Thanks Alwyn.

Have you looked at studio stable graphics?