FLTK logo

STR #3297

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 Home  |  Articles & FAQs  |  Bugs & Features  |  Documentation  |  Download  |  Screenshots  ]
 

Return to Bugs & Features | Post Text | Post File | SVN ⇄ GIT | Prev | Next ]

STR #3297

Application:FLTK Library
Status:5 - New
Priority:1 - Request for Enhancement, e.g. asking for a feature
Scope:3 - Applies to all machines and operating systems
Subsystem:Image Support
Summary:New implementation of Fl_Shared_Image...
Version:1.4-feature
Created By:rokan2
Assigned To:Unassigned
Fix Version:Unassigned
Update Notification:

Receive EMails Don't Receive EMails

Trouble Report Files:

Post File ]
Name/Time/Date Filename/Size  
 
#1 rokan2
13:53 Mar 24, 2016
Fl_Shareable_Image.cxx
41k
 
 
#2 rokan2
13:54 Mar 24, 2016
Fl_Shareable_Image.H
11k
 
 
#3 rokan2
06:41 Mar 15, 2017
Fl_Shareable_Image.zip
18k
 
     

Trouble Report Comments:

Post Text ]
Name/Time/Date Text  
 
#1 rokan2
13:53 Mar 24, 2016
This is independent implementation (not a patch) which is source compatible with original Fl_Shared_Image. It can be used alongside of the original one in current release but is aimed to replace it in fltk-1.4 Following are fixes and enhancement relative to current Fl_Shared image implementation.
What it does:

1) It fixes false-negative bug: the find() function might not find the image if it happens that supplied W and H corresponds to the full-sized original (this is due to wrongly applied logistic to the search). Although not critical, it unnecessary causes second load of the image (and in certain situation it might also cause a memory leak).

2) Various speed & efficiency enhancement:
- Currently during a search there is the whole new Fl_Shared_Image object instantiated on the heap with name copy and other fields initialized each time the search is performed. This is unnecessary, currently only name POINTER (no copy), W and H and "color effect" (see below) is passed (no heap) - and that's it.
- Expensive qsort is avoided: a replacement of bsearch is used, which in a case of failure gives information where new image should be inserted (by testing this new search function is as fast as libc implementation - at least for gcc)

3) It has full implementation of the constructor and destructor, which is equivalent to get() and release(), so that those are equivalent:

  Fl_Shareable_Image::get(name, w, h);
  new Fl_Shareable_Image(name, w, h);

  im->release();
  delete im;

You can intermix those functions for instance safely delete image what was obtained bu get() function or release image obtained by new operator. Function get() and  method release() are here only for backward compatibility, they can be declared as deprecated.

4) Function copy() is now "first class citizen". Previously if you created a copy it created an instance of Fl_Shared_Image but you could not use release() method upon it, you had to use operator delete (although destructor was not theoretically public - you had to issue delete on base class).

5) Function copy() now shares the data and cache with others: For instance for

  Fl_Shareable_Image * im = new Fl_Shareable_Image("/some/name.jpg");
  Fl_Shareable_Image * im1 = im->copy(50, 50);
  Fl_Shareable_Image * im2 = im->copy(50, 50);
  Fl_Shareable_Image * im3 = new Fl_Shareable_Image("/some/name.jpg", 50, 50);

all images im1, im2, im3 share the same data and cache

6) If you apply functinsdesaturate(), color_average(), inactive()

7) Functions desaturate(), color_average(), inactive() can be applied directly on the obtained image without worry that it would mess-up images in other places, for instance you can do:

  Fl_Shared_Image * im1 = Fl_Shared_Image::get("/some/name.jpg");
  Fl_Shared_Image * im2 = Fl_Shared_Image::get("/some/name.jpg");
  im2->desaturate();
  Fl_Shared_Image * im3 = Fl_Shared_Image::get("/some/name.jpg");
  im3->desaturate();

In this example im2 and im3 will be the same AND share the same data and cache (an internal image will be the same) but im1 will be unchanged (previously you could not do that - you had to make first copy and then desaturate() or color_average() this copy and those data were not shared) This sharing of affected images is possible because there is a new field for comparison/search - so called color effect. This color effect is a pseudo-matrix (which upon chaining is internally "multiplied" witch each new operation) and it is encoded to single 4-byte "int" value so that search and comparison are fast. For full proof/description see documentation within Fl_Shareable_Image.cxx



8) There is also properly implemented copy constructor (which with new operator is the same as copy()) and operator assignment

9) There is additional constructor

  Fl_Shareable_Image(Fl_Image * image, const char * name = 0, int take_over = 0);

which can be used for instance for creation of image from in-memory data like:

  new Fl_Shareable_Image(new Fl_RGB_Image(...), "name", 1)

Note that if name is null pointer (default) it assigns a unique internal string which can be inspected later by function name() - this is so-called "anonymous" shared image. The third parameter (default 0) tells the shared image to destroy the Fl_GRB_Image when not needed any more.

10) The copy constructor can be also issued upon Fl_Shareable_Image. In this case if name is 0 or equivalent to original name it is equivalent to function copy(), if it is different it registers the same image (with the same data/cache) under a second name.

11) All operations like copy(w, h), resize(w, h) (see below), get (w, h), find(w,h) desaturate(), color_average(), inactive(), copy constructor or other constructors (if there is already image with this name registered) are CHEAP which means that no new data is allocated even if W, H or color-effect differ. All this operations are postponed until first draw. That means for instance that if you do:

  Fl_Shareable_Image * ima = new Fl_Shared_Image("/my/icon.gif");
  Fl_Shareable_Image * deim = image->copy();
  deimage->inactive();
  button->image(im);
  button->deimage(deim);
  
and your button was never switched to inactive state, the data for the deim are never created (and of course neither the cache), taking no memory (apart from small shell of sizeof(Fl_Shared_Image))and no resources for color averaging operation.

12) There is new function resize(int W, int H) which just does that: in-place resizes the image. Again this operation is cheap, for instance after

  im->resize(20,20);
  im->resize(100000000, 1000000000);
  im->resize();
  
do not take any resources ()apart from storing new "to-be" dimensions). Note that call to resize without arguments restores the size to its original full-scale dimensions

10) Multiple copy() or resize() do nor have any quality impact because the new data are always resampled from the original, so for

  Fl_Shareable_Image * im2 = im1->copy(1,1);
  Fl_Shareable_Image * im3 = im2->copy(1000, 10000);
  im3->resize();
  
im3 will have the same quality as the original im1.

11) There is new implementation of data() and count() accessing functions. This is required because data might not yet exist upon the call, invoking those functions assure their creation.
Note that for now you have to use those functions upon fully class-specified object because those functions merely shadow the original ones. For full compatibility those functions should be declared as virtual in the base class Fl_Image.

12) There is a new function

   void fl_draw(Fl_Shareable_Image * im, int X, int Y, int W = 0, int H = 0);
   
which obeys current transformation matrix during drawing. If some parts have different zooming, you shoud create copy for that. And because copy is cheap, it soes not harm to make one even if the transformation matrix is the same, for instance when

  Fl_Shareable_Image * im1 = new Fl_Shareable_Image("/some/file.jpg");
  Fl_Shareable_Image * im2 = im1->copy();

  fl_push_matrix();
  fl_scale(s1);
  fl_draw(im1, x, y);
  fl_pop_matrix();
  ...
  fl_push_matrix();
  fl_scale(s2);
  fl_draw(im2, x, y);
  fl_pop_matrix();

and if it happens that s1 and s2 are the same im1 and im2 will share the same data/cache.

--------------

Overall the user should rather always use Fl_Shareable_Image instead of other classes as those others can be understood as mere cache for this new overlord.
It would be trivial to add other constructors which would take directly the in-memory data, for now user can just call for instance

  Fl_Shared_Image(new Fl_RGB_Image(...), 0, 1);

instead. Fluid should also generate shareable images upon compile-time data so that user can efficiently copy/share those images...

Roman
 
 
#2 rokan2
06:46 Mar 15, 2017
This new zipped source has some bugfixes and the class is named Fl_Shareable_Image so for now it could be used alongside with original Fl_Shared_Image.


Feature complete, used for over a year in production code, I am not aware of any bugs.
 
     

Return to Bugs & Features | Post Text | Post File ]

 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.