Cropping SVG image fails

103 views
Skip to first unread message

szuk...@arcor.de

unread,
Dec 31, 2020, 12:21:32 AM12/31/20
to fltk.general
I use the fltk-1.4 internal code to show an SVG image, e.g. tiger.svg .
But when I crop a small image from the greater visible image, I get
a bad crop image. E.g. to create a PNG image, I need a buffer for the
data, the canvas->cbuf:

    crop_img = new
     Fl_RGB_Image(dst, crop_width, crop_height, idepth);

static void crop_save_as_png_cb(Fl_Widget *wid, void *v)
{
(...)
    canvas->cbuf = crop_img->data()[0];
    canvas->new_iwidth = crop_img->w();
    canvas->new_iheight = crop_img->h();
    canvas->new_idepth = crop_img->d();

    save_as_png_cb(wid, v); //contains: PNG_write_file(canvas, write_idf);
(...)
}

int PNG_write_file(Canvas *canvas, const char *write_idf)
{
    FILE *writer;
    int width, height, nr_comp, ok;

    width = canvas->new_iwidth;
    height = canvas->new_iheight;
    nr_comp = canvas->new_idepth;

    writer = fopen(write_idf, "wb");

    write_buf_to_png((unsigned char*)canvas->cbuf,
        width, height, nr_comp, writer);
(...)
    fclose(writer);
(...)

}

svg-tiger-cropped_eye_2.png

Manolo

unread,
Dec 31, 2020, 2:04:54 AM12/31/20
to fltk.general
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_RGB_Image.H>
#include <FL/Fl_SVG_Image.H>
#include <FL/Fl_Image_Surface.H>
#include <FL/fl_draw.H>

int main(int argc, char *argv[])
{
  const char *name = "xxxxxxxxxx/tiger.svg";
  if ( argc> 1 )
    name = argv[1];
  fl_register_images();
 
  Fl_SVG_Image *svg = new Fl_SVG_Image(name);
  int width=100, height=100;
  Fl_Image_Surface *surf = new Fl_Image_Surface(width, height);
  Fl_Surface_Device::push_current(surf);
  fl_color(FL_WHITE);
  fl_rectf(0, 0, width, height);
  svg->draw(-80, -90);
  Fl_Surface_Device::pop_current();
  Fl_RGB_Image *rgb = surf->image();
  delete surf;
  Fl_Double_Window win(width+20, height+20);
  Fl_Box b(FL_DOWN_FRAME, 10, 10, width, height, NULL );
  b.image( rgb );
  win.end();
  win.show();
  return Fl::run();
}

szuk...@arcor.de

unread,
Dec 31, 2020, 10:21:27 AM12/31/20
to fltk.general

@manolo,
I did not ask 'Howto show an SVG image'. I did ask 'What is wrong with a copped SVG image'.
I use an Fl_Overlay_Window which allows me to crop parts of an image. When I use PNG, TIFF,
etc. images, cropping is OK. But cropping of an SVG image returns out to be bad. An I do not
know, why.
winfried

lifeatt...@gmail.com

unread,
Dec 31, 2020, 11:57:24 AM12/31/20
to fltk.general
But manolo showed you one way to crop an SVG image. After the line 

Fl_RGB_Image *rgb = surf->image();

what is in rgb is a cropped, RGB image which you can save to a PNG file.

You don't show us your code where you actually draw the SVG image to the screen, or make some call to rasterize(). That is probably where your problem lies.

imm

unread,
Dec 31, 2020, 12:02:34 PM12/31/20
to general fltk
On Thu, 31 Dec 2020, 15:21 szuk... wrote:

@manolo,
I did not ask 'Howto show an SVG image'. I did ask 'What is wrong with a copped SVG image'.
I use an Fl_Overlay_Window which allows me to crop parts of an image. When I use PNG, TIFF,
etc. images, cropping is OK. But cropping of an SVG image returns out to be bad. An I do not
know, why.

You probably need to check the image depth; that's what the corruption looks like to me at least.

I'd guess the images that work are depth 3 and I guess the failing images might be depth 4.

What platform is this on? If it's Windows it's also entirely possible that the surface being sampled is something weird, like BGRA or such, though that's not at all what the corruption looks like.
-- 
Ian
From my Fairphone FP3

Albrecht Schlosser

unread,
Dec 31, 2020, 12:03:45 PM12/31/20
to fltkg...@googlegroups.com
Hi Winfried,

your description and particularly the code you posted was too terse and
incomplete, so it's hard to see what you exactly want to achieve. A
simple (but complete) program that shows the issue would have been much
easier to understand. BTW, that's the reason why I didn't add any
comments after I saw Manolo's reply. No offense intended, just something
I noticed and that should hopefully help for the future.

On 12/31/20 4:21 PM szuk...@arcor.de wrote:

> I did not ask 'Howto show an SVG image'. I did ask 'What is wrong with a
> copped SVG image'.

As I wrote above, it's not exactly clear for me how you tried to crop
the SVG image. OTOH Manolo pointed out *one* way to crop an SVG image
that obviously works (didn't try it though).

> I use an Fl_Overlay_Window which allows me to crop parts of an image.
> When I use PNG, TIFF,
> etc. images, cropping is OK. But cropping of an SVG image returns out to
> be bad. An I do not know, why.

Perhaps because the data() array of an Fl_SVG_Image is only defined
after it was rendered (drawn) at least once, but I'm not sure about it.
Again, if you could show us a simple, complete, and compilable program
in one file that shows the issue we could better test it and hopefully
help you.

That said, you could either use Manolo's approach (see this line in his
code which actually crops the image)

Fl_RGB_Image *rgb = surf->image();

or try to use the data() array after the image has been rendered to the
screen or another (maybe Fl_Image_Surface) device.

HTH
Albrecht
> --
> You received this message because you are subscribed to the Google
> Groups "fltk.general" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to fltkgeneral...@googlegroups.com
> <mailto:fltkgeneral...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/fltkgeneral/1421f2d4-34a5-4bf0-b3a8-90f40f70d26dn%40googlegroups.com
> <https://groups.google.com/d/msgid/fltkgeneral/1421f2d4-34a5-4bf0-b3a8-90f40f70d26dn%40googlegroups.com?utm_medium=email&utm_source=footer>.

szuk...@arcor.de

unread,
Jan 1, 2021, 1:14:21 AM1/1/21
to fltk.general
The attached file is a change of the original file. It (hopefully) contains all to show what I mean.
winfried
pixmap_browser.cxx.gz

Albrecht Schlosser

unread,
Jan 1, 2021, 11:50:58 AM1/1/21
to fltkg...@googlegroups.com
On 1/1/21 7:14 AM szuk...@arcor.de wrote:
> The attached file is a change of the original file. It (hopefully)
> contains all to show what I mean.

It's a pretty large test case, but anyway...

> > I use an Fl_Overlay_Window which allows me to crop parts of an
> image.
> > When I use PNG, TIFF,
> > etc. images, cropping is OK. But cropping of an SVG image returns
> out to
> > be bad. An I do not know, why.

The only serious error I found in your code was the way you accessed the
image data. See the fix in the attached diff with a pointer to article
#466 that explains it.
https://www.fltk.org/articles.php?L466

The wrong access to the image data would also have failed with PNG and
other images although you wrote that "cropping is OK" with other image
types (how did you load TIFF images?). If it "worked" then only by
accident and (AFAICT) you did not crop the exact image pixels (memory
layout may have made you think it worked and it did likely not crash as
it did in my tests with SVG images).

The other smaller errors are due to coordinate translation errors which
I *worked around* by always scaling the image to fit the original image
window *and* by correcting the x and/or y offset(s). This is not an
*exact* fix but it's close. I'm leaving the exact fix up to you.

That all said, the access to the data() array is not entirely correct:

First of all the way you access the data (even after my fix) is AFAICT
only valid for Fl_RGB_Image types (not for pixmaps etc.) - although
Matthias didn't mention this difference in his article. In my tests it
failed with xpm images, for instance.

Another potential fault is that you don't use the correct ld() value for
stepping forward in the original image array. Explanation: ld() = "line
delta" is the number of bytes you need to skip forward. In most images
it's either w*d or 0 (which implies w*d). You are always using w*d which
doesn't *need* to be correct for all images but ld() != w*d is probably
a rare exception.

> That said, you could either use Manolo's approach (see this line in his
> code which actually crops the image)
>
> Fl_RGB_Image *rgb = surf->image();

Hint: the way Manolo pointed out to crop an image by "drawing" it on a
Fl_Image_Surface should really work with all image types (including
pixmaps and other exotic formats) and you wouldn't have to access the
data() array of the original image format directly.
crop-image.diff
Message has been deleted

lifeatt...@gmail.com

unread,
Jan 1, 2021, 12:23:38 PM1/1/21
to fltk.general
My thanks Albrecht, Manolo - even when I'm not the OP I almost always learn something!

Albrecht Schlosser

unread,
Jan 1, 2021, 1:05:00 PM1/1/21
to fltkg...@googlegroups.com
On 1/1/21 6:23 PM lifeatt...@gmail.com (Kevin?) wrote:
> My thanks Albrecht, Manolo - even when I'm not the OP I almost always
> learn something!

You're welcome, and thank you for your own contributions.

Your recent message regarding the wrong crop offsets was what I found
out too but I decided to mitigate the effect by scaling the image for my
test purposes. Your info should make it easier for the OP to solve his
issues. Thanks.

janezz55

unread,
Jan 2, 2021, 1:12:40 PM1/2/21
to fltk.general
You could have prevented all problems by just using cairo. IMO the SVG approach taken by FLTK is wrong. NanoSVG was/is meant to be a toy implementation, hence incorporating it into FLTK was wrong. Cairo has easy .png export, easy cropping and a lot of other features and you can easily render svg with cairo.

imm

unread,
Jan 2, 2021, 1:24:00 PM1/2/21
to general fltk
On Sat, 2 Jan 2021 at 18:12, janezz55 wrote:
>
> You could have prevented all problems by just using cairo. IMO the SVG approach taken by FLTK is wrong.

That's probably overstating things somewhat - there are clear and
well-understood reasons for the the SVG approach taken by fltk.

> NanoSVG was/is meant to be a toy implementation, hence incorporating it into FLTK was wrong.

Again, overstating things somewhat.
Incorporating NanoSVG into fltk was a deliberate choice - yes, it is a
limited implementation of SVG, but it is adequate for the purpose for
which it was included (such as rendering gradients on buttons and so
forth.)
Of course, NanoSVG in fltk will never be a full SVG implementation (it
doesn't even handle text, for example, but then it does not have too)
but it fits well with the fltk "fast and light" ethos and does not
bulk the ftk core too much.

Cairo can provide a more complete implementation of SVG, but is itself
neither fast nor light, so it is not appropriate as a "built in" for
fltk.
On the other hand, it is fairly trivial to use Cairo from a fltk
context, if that added capability s desired.
There is room in the world for both.
There is no conflict there.

janezz55

unread,
Jan 2, 2021, 2:06:34 PM1/2/21
to fltk.general
> There is room in the world for both.
> There is no conflict there.

You did not touch on the quality of rendering issue. Obviously, the quality of rendering cairo is able to achieve is much greater than that of NanoSVG. After all, cairo is used by Inkscape, a well-known SVG editor. So not only is there a completeness issue, but also a quality issue.

Greg Ercolano

unread,
Jan 2, 2021, 2:34:37 PM1/2/21
to fltkg...@googlegroups.com
On 1/2/21 10:56 AM, janezz55 wrote:
> There is room in the world for both.
> There is no conflict there.

You did not touch on the quality of rendering issue. Obviously, the quality of rendering cairo is able to achieve is much greater than that of NanoSVG.

    The vector rendering in FLTK's examples/howto-simple-svg seems pretty good to me.
    The edges are beautifully antialiased, the font curves are smooth, and the entire rendering
    can be translated/rotated/scaled nicely.

    I dunno, nanosvg seems perfect for what FLTK needs to render higher end widgets;
    antialiased lines across platforms, gradients, and curved vectors across all platforms,
    in addition to other features.

    When FLTK starts providing higher end widgets that make use of nanosvg for rendering
    on the back end, it would improve the look of interfaces greatly. Some nicer looking
    switches/buttons/dials/meters/numeric displays would all be possible, and a great improvement.

    Anyone wanting the full features of an SVG image library can certainly link in cairo to
    access such functionality. But not everyone using FLTK needs such high end rendering.

NanoSVG was/is meant to be a toy implementation, hence incorporating it into FLTK was wrong.

    Disagree most strongly.

    The minimal implementation of nanosvg is a perfect fit for what FLTK needs
    without all the extra overhead of a full SVG/cairo implementation.

    If there's an SVG library that better supports SVG without requiring external libs,
    we might switch to it while keeping our API the same.

    NanoSVG isn't wrong, it's a very good start.

szuk...@arcor.de

unread,
Jan 2, 2021, 4:18:02 PM1/2/21
to fltk.general
I have now removed the old code. A new function works fine with SVG:

void FLImage_use_manolo(const char *cname)
{
// with help of Manolo, https://groups.google.com/forum/#!forum/fltkgeneral
// Subject: Cropping SVG image fails
// :-)

winfried

janezz55

unread,
Jan 2, 2021, 4:19:29 PM1/2/21
to fltkg...@googlegroups.com
> The minimal implementation of nanosvg is a perfect fit for what FLTK needs
> without all the extra overhead of a full SVG/cairo implementation.

To each his own. Browsing through NanoSVG source code should convince
you that the author was just toying/experimenting. Also, NanoSVG is a
toy SVG parser AND a toy 2d vector renderer, so you're packing 2 2d
renderers into a single library (fltk), one the gui part of fltk is
using and the other one used solely for SVG rendering (that's not the
case with Qt, which uses its QPainter system for both SVG and GUI
rendering). This arrangement is not for the purists among us.

V V sob., 2. jan. 2021 ob 20:34 je oseba Greg Ercolano
<er...@seriss.com> napisala:
> --
> You received this message because you are subscribed to a topic in the Google Groups "fltk.general" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/fltkgeneral/SaVtXOqtMtY/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to fltkgeneral...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/56f986f7-fd46-124c-3440-f7198eee1193%40seriss.com.

Greg Ercolano

unread,
Jan 2, 2021, 5:14:47 PM1/2/21
to fltkg...@googlegroups.com

On 1/2/21 12:19 PM, janezz55 wrote:

To each his own. Browsing through NanoSVG source code should convince
you that the author was just toying/experimenting.


    OK, let's say nanosvg in FLTK is a problem that needs to be solved.

    What SVG library specifically would be the right solution for FLTK?

    The developers are open to suggestions, and certainly nanosvg's
    addition to FLTK started out as a suggestion and was voted in because
    it met all of FLTK's core criteria: small code footprint, no external
    library dependencies, seemed well embraced by those who've used
    it in practice, and worked efficiently for what it does support, and
    provides noticeable improment to the FLTK library in the form of
    providing antialiased vector rendering across all platforms.

    We could always support a different SVG library when the time comes
    via FLTK's configure options, e.g. --enable-svg-xyz


janezz55

unread,
Jan 3, 2021, 4:09:18 AM1/3/21
to fltk.general
>    What SVG library specifically would be the right solution for FLTK?
Not a single SVG library, you need 3 components: a SVG parser, a 2d vector renderer and a SVG renderer, that takes the output of a SVG parser as input and uses a 2d vector renderer for output. NanoSVG implements all three components. cairo is an example of a 2d vector renderer - but is apparently too bulky. Ideally, 2d vector rendering would be provided by a fltk display driver. The SVG renderer could be written by the fltk team (trivial, if you have a working and sane SVG parser). So, it's down to finding/writing a suitable SVG parser. You could call such a solution a genuine part of fltk. If you really find NanoSVG sufficient in all regards, you could take its 2d vector rendering part and use it as a display driver, to render both GUI and SVG. Implement a kind of fltk_vg component, in other words. So, I would modernise the fltk display driver API taking, say, OpenVG, cairo or even QPainter as inspiration. Writing a SVG renderer would then be trivial, using practically any available SVG parser. If you take a look at Qt's QPainter, you'll see that it has good support for vector graphics. It is trivial to use QPainter and a SVG parser to write a SVG renderer.

lifeatt...@gmail.com

unread,
Jan 3, 2021, 8:27:52 AM1/3/21
to fltk.general
 
So, I would modernise the fltk display driver API taking, say, OpenVG, cairo or even QPainter as inspiration. Writing a SVG renderer would then be trivial, using practically any available SVG parser.

Then I, for one, look forward to seeing your pull request implementing this trivial component for FLTK.

janezz55

unread,
Jan 3, 2021, 8:58:30 AM1/3/21
to fltkg...@googlegroups.com
>Then I, for one, look forward to seeing your pull request implementing this trivial component for FLTK.
The display driver API would need to be modernised first and I won't
contribute anything, as I already wrote a SVG renderer for cairo,
sufficient for my needs, bypassing the severely-deficient fltk drawing
API.

V V ned., 3. jan. 2021 ob 14:27 je oseba lifeatt...@gmail.com
<lifeatt...@gmail.com> napisala:
>
>
>>
>> So, I would modernise the fltk display driver API taking, say, OpenVG, cairo or even QPainter as inspiration. Writing a SVG renderer would then be trivial, using practically any available SVG parser.
>
>
> Then I, for one, look forward to seeing your pull request implementing this trivial component for FLTK.
>
> --
> You received this message because you are subscribed to a topic in the Google Groups "fltk.general" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/fltkgeneral/SaVtXOqtMtY/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to fltkgeneral...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/342bb448-0750-49d8-b3de-358e8bdd98e6n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages