rageworx / fltk-custom

A clone of FLTK 1.4.0 for enhance as customized GUI, more functional. This project is belong to https://fltk.org.
https://rageworx.info
Other
8 stars 1 forks source link

Fl_SVG_Image occurs wrong scaled when it used with Fl_Image scaling. #59

Closed rageworx closed 1 year ago

rageworx commented 1 year ago

Found this issue while testing Make Image 'O HDR, with Ctrl+'+'/'-' to scaling up/down.

Normal Fl_SVG_Image: image

Wrong scaling down Fl_SVG_Image: image image

rageworx commented 1 year ago

This bug is belonged to fl_imgtk::rescale(). fl_imgtk::rescale() cannot scaling image from SVG, how to consider source image is Fl_RGB or Fl_SVG ?

rageworx commented 1 year ago

Fl_SVG_Image render SVG source to Fl_RGBImage by rasterize(W,H) in step of resize().

void Fl_SVG_Image::rasterize_(int W, int H) {
  static NSVGrasterizer *rasterizer = nsvgCreateRasterizer();
  double fx, fy;
  if (proportional) {
    fx = svg_scaling_(W, H);
    fy = fx;
  } else {
    fx = (double)W / counted_svg_image_->svg_image->width;
    fy = (double)H / counted_svg_image_->svg_image->height;
  }
  array = new uchar[W*H*4];
  nsvgRasterizeXY(rasterizer, counted_svg_image_->svg_image, 0, 0, float(fx), float(fy), (uchar* )array, W, H, W*4);
  alloc_array = 1;
  data((const char * const *)&array, 1);
  d(4);
  if (to_desaturate_) Fl_RGB_Image::desaturate();
  if (average_weight_ < 1) Fl_RGB_Image::color_average(average_color_, average_weight_);
  rasterized_ = true;
  raster_w_ = W;
  raster_h_ = H;
}

But question is, why SVG image breaks ?

rageworx commented 1 year ago

Maybe the wrong w() and h() at time of resizing by this step ?

rageworx commented 1 year ago

Safe resizing in multiple mutex,

void usr_scale(Fl_RGB_Image* s, int x, int y, int w, int h, Fl_RGB_Image** o)
{
    Fl::lock();
    if ( s != NULL )
    {
        if ( s->array != NULL )
        {
            Fl_RGB_Image* tmpi = (Fl_RGB_Image*)s->copy( s->data_w(), s->data_h() );
            if ( tmpi != NULL )
            {
                *o = fl_imgtk::rescale( tmpi, w, h, fl_imgtk::BICUBIC );
            }
            delete tmpi;
        }
    }
    else
    if ( *o != NULL ) /// delete by user.
    {
        delete (Fl_RGB_Image*)*o;
        *o = NULL;
    }
    Fl::unlock();
}
rageworx commented 1 year ago

Code updated

Need to duplicated Fl_RGB_Image, and checks data_w() and data_h() to real size.

void usr_scale(Fl_RGB_Image* s, int x, int y, int w, int h, Fl_RGB_Image** o)
{
    Fl::lock();
    // Using fl_imgtk fast rescaling method here.
    if ( ( s != NULL ) & ( w > 0 ) & ( h > 0 ) )
    {
        if ( s->array != NULL )
        {
            // To rescale in safe way, some Fl_RGB_Image like from SVG, need to
            // check with data_w() and data_h().
            Fl_RGB_Image* tmpi = (Fl_RGB_Image*)s->copy( s->data_w(), s->data_h() );
            if ( tmpi != NULL )
            {
                *o = fl_imgtk::rescale( tmpi, w, h, fl_imgtk::BICUBIC );
            }
            delete tmpi;
        }
    }
    else
    // It must be implemented for removing image.
    if ( ( *o != NULL ) & ( x == 0 ) & ( y == 0 ) & ( w == 0 ) & ( h == 0 ) )
    {
        delete (Fl_RGB_Image*)*o;
        *o = NULL;
    }
    Fl::unlock();
}
rageworx commented 1 year ago

It is a fixed in latest change of fltk-1.4.0-dev, and fl_imgtk. It was cause of Fl_SVG_Image rasterizing and fl_imgtk need to refer to actual data width and height when rescaling factor.

rageworx commented 1 year ago

Issue tested and closing now.