How to share image data between differently-sized drawing areas

23 views
Skip to first unread message

Manolo

unread,
Oct 5, 2017, 1:05:25 PM10/5/17
to fltk.general
I'd like to pinpoint this FLTK technique that allows to have the pixeldata of a single image
re-used to draw this image any number of times in any width and height.

1) start from an Fl_RGB_Image object, let's call it rgb

2) create any number of Fl_Shared_Image objects constructed from rgb in 1):
   Fl_Shared_Image *sh1 = Fl_Shared_Image::get(rgb, 0); // notice the second argument
   Fl_Shared_Image *sh2 = Fl_Shared_Image::get(rgb, 0);
   Fl_Shared_Image *sh3 = Fl_Shared_Image::get(rgb, 0);
All these share the same pixel data (present once in memory).

3) give to these Fl_Shared_Image objects the desired drawing size of each:
   sh1->scale(W1, H1); // this will preserve the aspect ratio of rgb
   sh2->scale(W2, H2, 0); // this will authorize change in the aspect ratio
   sh3->scale(W3, H3);

4) use these Fl_Shared_Image objects in the GUI

5) destroy all of that, when images are no longer used, with:
   sh1->release();
   sh2->release();
   sh3->release();
   delete rgb; // must be last

With this technique, the image data exist only once in memory, and its cached form
also exists once. The scaled drawing capacity of the hardware is used to draw
the unique cached image to diversely sized window areas. This capacity is native
on MacOS and MSWindows. It requires Xrender under X11.

Member function Fl_Shared_Image::scale() is in FLTK 1.3.4 but requires building with
FL_ABI_VERSION >= 10304. It is also in FLTK 1.4 of course.


//==================== example toy program ===========
#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl_PNG_Image.H>
#include <FL/Fl_Window.H>

int main()
{
  Fl_Window *win = new Fl_Window(400,400);
  Fl_Button *b = new Fl_Button(10,10,260,130,0);
  Fl_Button *b2 = new Fl_Button(10,150,50,100,0);
  win->end();
  win->show();
  const char *fname = "/path/to/an/image.png";
  Fl_RGB_Image *original = new Fl_PNG_Image(fname);
  Fl_Shared_Image *scaleable =  Fl_Shared_Image::get(original, 0);
  b->image(scaleable);
  b->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_CLIP);
  scaleable->scale(b->w(), b->h()); // keep image's aspect ratio
 
  Fl_Shared_Image *scaleable2 =  Fl_Shared_Image::get(original, 0);
  b2->image(scaleable2);
  b2->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_CLIP);
  scaleable2->scale(b2->w(), b2->h(), 0); // alter image's aspect ratio

  Fl::run();
  scaleable->release();
  scaleable2->release();
  delete original;
  return 0;
}
//=============================

Reply all
Reply to author
Forward
0 new messages