ArthurHub / HTML-Renderer

Cross framework (WinForms/WPF/PDF/Metro/Mono/etc.), Multipurpose (UI Controls / Image generation / PDF generation / etc.), 100% managed (C#), High performance HTML Rendering library.
https://htmlrenderer.codeplex.com/
BSD 3-Clause "New" or "Revised" License
1.24k stars 522 forks source link

Help sought with image smoothing and text rendering #157

Open fullphat opened 5 years ago

fullphat commented 5 years ago

We're hoping to use this library in a future iteration of Snarl, but we're having some challenges rendering scaled PNG images - in summary, images don't appear to be anti-aliased or smoothed at all when they're drawn smaller than their actual size.

We're also having problems creating rounded corners so we tried to create a pre-staged C# Image using GDI+ and then render the HTML content into it, but this gives us problems with text rendering as HtmlRender.RenderGdiPlus() doesn't support text aliasing.

Ultimately, we're looking to achieve the following (created using native GDI+ under VB6) but via HTML, CSS and this library in C#:

snarl_1

Any help would really be appreciated!

PeterWone commented 5 years ago

CssBoxFrame.cs scales the image in DrawImage at line 494.

        private void DrawImage(RGraphics g, RPoint offset, RRect rect)
        {
            if (_imageWord.Image != null)
            {
                if (rect.Width > 0 && rect.Height > 0)
                {
                    if (_imageWord.ImageRectangle == RRect.Empty)
                        g.DrawImage(_imageWord.Image, rect);
                    else
                        g.DrawImage(_imageWord.Image, rect, _imageWord.ImageRectangle);

The problem I'm experiencing is that it doesn't scale images at all. _imageWord.ImageRectangle is set in CssBoxImage.cs: to the rectangle parameter but this has the value RRect.Empty, causing the condition to resolve to true executing 492 instead.

I have tried to supply container dimensions both directly as attributes and indirectly as CSS and am currently investigating the provenance of the rectangle.

If you can tell me how you got it to scale in the first place, I will look into smooth scaling while I'm figuring out how to make it respect min-width and max-width

fullphat commented 5 years ago

I just used this:

<img src=\"c:\\test\\snarl.png\" width='48px' height='48px' />

Which worked fine, although the image looks awful (it's only 128px native). Assuming RGraphics is something derived from a GDI+ Graphics object, I guess the following is all that's needed?

g.SmoothingMode = SmoothingMode.AntiAlias

Right now, I've made progress by rendering the HTML at 4x scale and then taking the resulting image and shrinking it by a factor of 4. This generates pretty much the desired effect, but isn't sustainable, or sane... 😄

image

For completeness, this is what pure HTML looks like (with resizing the icon to 48px via HTML):

image2

PeterWone commented 5 years ago

RGraphics is a wrapper. On WinForms it has a Graphics object.

The library has a plugin architecture. To allow him to swap WinForms, WPF or PDF rendering primitives he uses proxies and factories. They closely resemble WinForms.

As an aside, I think this library is a perfect demonstration of why this approach is a waste of time when done at the level of platform primitives: it never produces a satisfactory outcome because either you mimic one of the platforms and other platforms have incomplete implementations, or you don't and everything is lowest-common-denominator. It could work if the level of abstraction were raised to the outer API. I'm seriously considering getting the last version prior to this multi-platform complexity. I suspect the code is a lot more compact.