drawImage() won't be drawn Untransformed on Windows when system scale is between 100% and 200%


#1

Kind of desperate and looking for some help. We are using juce 4.3.0.
We notice that on Windows when system scale is bigger than 1.0 and smaller than 2.0, juce won’t go into the “renderImageUntransformed” in its renderImage() method, In juce_RenderingHelpers.h.

The result is that my drawImage() call to draw an Image say (150, 150), for logic size (100, 100) under system scale 150% will result in an unclear image.
The drawImage() is used in my main component’s paint() method, so as to draw an Image as background.

Does anyone notice this issue? or should I use another way of drawing image when scale is between (1, 2)?
It seems fine when the system scale is 2. The renderImage() will go to the renderImageUntransformed().

Thanks.

 void renderImage (const Image& sourceImage, const AffineTransform& trans,
                      const BaseRegionType* const tiledFillClipRegion)
    {
        const AffineTransform t (transform.getTransformWith (trans));

        const int alpha = fillType.colour.getAlpha();

        if (isOnlyTranslationAllowingError (t))
        {
            // If our translation doesn't involve any distortion, just use a simple blit..
            int tx = (int) (t.getTranslationX() * 256.0f);
            int ty = (int) (t.getTranslationY() * 256.0f);

            if (interpolationQuality == Graphics::lowResamplingQuality || ((tx | ty) & 224) == 0)
            {
                tx = ((tx + 128) >> 8);
                ty = ((ty + 128) >> 8);

                if (tiledFillClipRegion != nullptr)
                {
                    tiledFillClipRegion->renderImageUntransformed (getThis(), sourceImage, alpha, tx, ty, true);
                }
                else
                {
                    Rectangle<int> area (tx, ty, sourceImage.getWidth(), sourceImage.getHeight());
                    area = area.getIntersection (getThis().getMaximumBounds());

                    if (! area.isEmpty())
                        if (typename BaseRegionType::Ptr c = clip->applyClipTo (new EdgeTableRegionType (area)))
                            c->renderImageUntransformed (getThis(), sourceImage, alpha, tx, ty, false);
                }

                return;
            }
        }

        if (! t.isSingularity())
        {
            if (tiledFillClipRegion != nullptr)
            {
                tiledFillClipRegion->renderImageTransformed (getThis(), sourceImage, alpha, t, interpolationQuality, true);
            }
            else
            {
                Path p;
                p.addRectangle (sourceImage.getBounds());

                typename BaseRegionType::Ptr c (clip->clone());
                c = c->clipToPath (p, t);

                if (c != nullptr)
                    c->renderImageTransformed (getThis(), sourceImage, alpha, t, interpolationQuality, false);
            }
        }
    }

#2

We ran into the same issue. The use case then was to display a bitmap image. Yes, it will be smaller at high DPI, but there is the option to zoom in. The blurring introduced by scaling with a 1.25 scale factor is often more objectionable than the difference in rendered size.

We worked around by drawing the image with a 1.0 / juce::Desktop::getInstance().getGlobalScaleFactor() scale factor, and using “low quality resampling” to avoid blurring because of misalignment with the pixel grid.


#3

Do you get the correct scaling factor through Desktop::getGlobalScaleFactor ()?

I always get 1.0 (Windows 10 64bit).


#4

That’s a different issue, that means Windows doesn’t recognise your app as high DPI, or your monitors are all set to 96 DPI. I think JUCE makes explicit calls to enable DPI scaling on initialization, but I would also mark the application as DPI-aware in the application manifest.