Graphics scaling in 2016r2

Hi all,

I’m using GDI+ to scale my UI graphics, specifically GdipSetInterpolationMode.

[code] Function ScalePicture(p as picture, width as integer, height as Integer) As picture
Dim res as new picture(width,height)
#if TargetWin32 then
// tell GDI+ to do quality scaling
Soft Declare Function GdipSetInterpolationMode Lib “Gdiplus” (graphics as int32, Mode as int32) As int32
Call GdipSetInterpolationMode(res.graphics.Handle(Graphics.HandleTypeGDIPlusGraphics), 8)
#endif
res.Graphics.DrawPicture(p, 0, 0, width, height, 0, 0, p.width, p.height)
return res
End Function

[/code]

Made ZERO code changes, just a compile in 2016r2 to see the new retina changes on Windows.

Here’s how the scaling looks in 2016r1.1: http://i.imgur.com/lpPkZqt.png

And here’s how it looks in 2016r2: http://i.imgur.com/gsu16TW.png

Here’s an album view to compare the two: http://imgur.com/a/1z9rH

Scaling now looks ridiculously UGLY (and it was already much uglier on Windows than on Mac). What changed? How can I get the smoother scaling back?

A low DPI scaled at higher DPI will look jagged. You may want to update your picture with a new one, entered as an image at three resolutions. 75 DPI, 150 DPI and 300 DPI at the same image size. Or a picture at 150 DPI (in my own tests, either way works well)

The image is loaded at 150, 300 and 600 dpi (I have it larger because the user can scale the window up to full screen and the image needs to scale with it).

Everything worked acceptably in 2016 r1.1. Something changed between then and now.

What has changed is that now full HiDPI support means the pictures dragged into the project are immutable and that can explain the issue if you pass the picture as is.

You may want to first draw p into an intermediary picture before passing it to your declare.

Actually, reading again your code, what happens if you simply comment the two lines pertaining to the declare ?

Will this new version affect how fonts render in various DPIs on Windows?

Michel is probably right (as is often the case!). Xojo tries to handle the interpolation itself. It is possible that the call to GdipSetInterpolationMode is superfluous and actully play a role in the issue. That escaped me on the first read.

Yep. They will look crisper when display is scaled. Actually all the app display will be crisper.

I removed the GdipSetInterpolationMode calls and it’s drawn identically (still poorly). It’s almost as if GDI Plus is skipped by the new framework. I have verified that the switch IS still on in the Windows build settings.

The whole reason I was using GDI Plus to scale the image was that the scaling algorithm is much smoother than the internal Xojo one, which downscales unacceptably ugly IMHO. If there is an alternative, I’m all ears.

[quote=276931:@Christian Wheel]I removed the GdipSetInterpolationMode calls and it’s drawn identically (still poorly). It’s almost as if GDI Plus is skipped by the new framework. I have verified that the switch IS still on in the Windows build settings.

The whole reason I was using GDI Plus to scale the image was that the scaling algorithm is much smoother than the internal Xojo one, which downscales unacceptably ugly IMHO. If there is an alternative, I’m all ears.[/quote]

There is a long thread about different downscaling algorithms : https://forum.xojo.com/9403-scale-quality-of-canvas-control/0

That thread is where the ScalePicture method in my OP came from. Unfortunately it seems to be broken in 2016r2. The alternative solutions in that thread either compromise quality or speed.

Am I the only one experiencing this issue?

Indeed the declare does not work anymore in 2016R2. That is one of the major drawbacks of declares : they may or may not survive changes in versions.

I verified regular scaling works just the same.

Maybe Jim McKay will have a new version if he got time, and if it is at all possible. Seems for the moment you better use pictures already scaled,

Or use the slower Xojo code at the thread I linked to, which is still very nice.

I suspect I won’t be the last to complain about this and hope that another solution is discovered (or ideally at some point Xojo includes high-quality scaling in the framework). Pre-Scaled pictures are not an option for my app as the pictures scale dynamically as the user resizes the window.

In the meantime, I’m using the MBS scaling function, which seems to be better-looking than Xojo scaling, but it also can antialias which helps quite a bit. It’s still not great (these same images look fantastic using the internal downscaling in .NET apps), but it’s acceptable.

Here’s the revised function in case it helps anyone else.

Function ScalePicture(p as picture, width as integer, height as Integer) As picture Dim res as new picture(width,height) res=p.ScaleImageAndMaskMBS(width, height, true, 0) return res End Function

I think the issue has to do with the new HiDPI Support that somehow broke the declare. It should not be out of this world to come up with a new way to use GdipSetInterpolationMode. Since this seems to bother you quite a bit, maybe if you ask very nicely @jim mckay in PM, he will be able to adapt his code.

That said, this shows the limit of free and voluntary declare code, which can be quite fragile. Whereas well supported plugins like MBS are reliable, and come with a great service.

If I had to take a random, unresearched guess, it would be that GdipSetInterpolationMode can’t understand the new Picture format (hi-dpi with multiple resolutions) and there would have to be some translation to a standard bitmap before passing the handle off to the api.

@jim mckay , if you ever decide to update your code, I would be in your debt if you would be willing to share it.

Once I finish some of the more vital aspects of my app’s logic I too will revisit this issue and try to find a better solution.

That is not it. I tried the declare in non HiDPI mode, and the result is the same. I would suspect there was a change in the way Xojo calls the system to resize the picture, since in the end the code calls a standard Xojo code resize.

It should be possible to carry out the entire resize process inside the declare.