Recent

Author Topic: Q. bgrabitmap newbie: how to reduce the number of units to be used?  (Read 4117 times)

d7_2_laz

  • Hero Member
  • *****
  • Posts: 542
I’m new with bgrabitmap but already recognized it’s tremendous potential.
But I’m really astonished that when trying to apply an approx. 10-liner example, eg. as from tutorial:
https://wiki.freepascal.org/BGRABitmap_tutorial_Font_rendering
that I see that far more than 100 objects will be generated and the exe grows by 1,5MB.  Honestly??
I did remind me as when using SynEdit for one language then all existing highlighters would be integrated at once.

I saw these links:
https://github.com/bgrabitmap/bgrabitmap/issues/127
https://github.com/bgrabitmap/bgrabitmap/issues/159
but could not get a clue what the recent status is.
So I’d like to ask if it’s not possible to use it with a more modular approach, eg. by excluding a couple of sub-components from compile&link.
For example I saw that there is a couple of  {$IFNDEF xyz_DONT_USE_abc}  within the incs.

So, is there anybody familiar with this:
- what might be excluded
- where this should be defined?

Many thanks for any info in advance!
Lazarus 3.6  FPC 3.2.2 Win10 64bit

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #1 on: March 05, 2024, 05:20:34 pm »
Hello d7_2_laz,

Thank you for reaching out and expressing your interest in BGRABitmap, as well as sharing your concerns regarding the size increase of your executable and the number of objects generated. I understand your concern about efficiency and the desire for a more modular approach to using our library.

BGRABitmap is designed to be user-friendly and comprehensive, which means it includes a wide range of functionalities by default to simplify usage. This has always been the topmost priority. However, this approach does result in a larger executable size, whether you add 10 lines or much more.

Regarding the possibility of excluding certain components to reduce the size, there has been some discussion and attempts at addressing this concern, as you've found in the issues #127 and #159. However, these efforts have stalled due to lack of feedback and clear direction on how to proceed. So you did not miss anything there.

The use of {$IFNDEF xyz_DONT_USE_abc} directives within the codebase could be a way forward indeed to allow for some level of modularity. An alternative package with minimal dependencies could be designed on this principle based on one directive, for example BGRABITMAP_CORE. To use other features, it will then be necessary to add relevant units in the uses clause and instantiate necessary objets.

What do you think of this proposal?
Conscience is the debugger of the mind

d7_2_laz

  • Hero Member
  • *****
  • Posts: 542
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #2 on: March 05, 2024, 09:25:18 pm »
Hello circular,

many thanks for your attention and detailed reply!
Hm, “lack of feedback”, that really doesn’t point to a widespread interest.  And where indeed drives had become somehow cheap, space and file number economics may have become a bit out of sight (excotic idea?).
But habits differ …
The more I think if you ask ten people there might be ten different answers about which technique is preferable or wanted.
But I think this shouldn't be a reason to even start … so I appreciate the question a lot.

For me both options (core and surplus (or full) package, or offered DEFINES) would be equally good. But – stability first – both would imply a somehow overhead, I’m fully aware.
- To administer two packages and keep them in synch (plus docs what each packages does and what not)
- Or implement new DEFINES that are working stable through all IFDEF structures
Both really fine, but not easy I guess.

Maybe some kind of combination of both:
- one package, but a bgrabitmap.pas and a bgrabitmap_core.pas in it (if there are two packages, that would also already mean in the same way that there are two different flavours of bgrabitmap.pas)
- or one controlling IFDEF inside one bgrabitmap.pas which decides which units are used and belonging functions exposed.
Would this even be possible, or would it end up going through too many files? (I don't have any knowledge about this yet)
- If possible, the main controlling Define - or Defines -  could be placed where? In a kind of “custom.inc” that might be initially empty or having default values.
At the end a how-easy-to-implement plays an important role for to decide.

Let’s see how others do think about - and if there’s even an interest.
Lazarus 3.6  FPC 3.2.2 Win10 64bit

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #3 on: March 06, 2024, 11:37:51 am »
Hi d7_2_laz,

You're welcome. Every contributor brings its own unique perspective and so I am glad you popped by.

It is indeed the case that nowadays space is less of a concern. Some software size is counted in hundreds of gigabytes. Comparatively, 1.5 MB is quite small. So for many use cases, this is not a problem.

Nevertheless, I have though about the subject as well and I would be happy to have a more modular version of BGRABitmap. Let's delve into it.

Using a $DEFINE allows to have the same codebase. It would be easy to enable it on any existing package by going into its configuration or by tweaking bgrabitmap.inc file. So I think it is an efficient way to go forward.

We may:
  • add a new package with this $DEFINE. The problem though is that there are many packages and many of them could have a core version. So that would result in a lot of packages and probably confusion
  • not add a new package, and leave it to the programmer to add the directive to the package (or maybe it can defined at the project level).
  • just add one package with core option, that would work with the LCL. It could bring a starting point for people looking for that.

I can see two different approaches about the change occurring when defining BGRABITMAP_CORE:
  • features would still be visible, but would be raising an exception when the adequate unit would not be provided in the uses clause
  • most features will be hidden/removed from TBGRABitmap, one would need to instantiate objects. for example to instantiate TCanvasBGRA instead of using CanvasBGRA property (BGRACanvas unit would need to be in the uses clause)

Leaving the property visible would make the tutorials be more or less the same. One problem though is that a program may compile but crash because the $DEFINE has changed. This may not be obvious if this is the result of tweaking the package. We could only make sure that doesn't happen if the package name is different.

So I would conclude that:
• either we provide packages with BGRABITMAP_CORE directive, and then we can leave all properties as they are
Code: Pascal  [Select][+][-]
  1. uses BGRABitmap, BGRABitmapTypes, BGRACanvas{required at runtime}, SysUtils;
  2.  
  3. var bmp: TBGRABitmap;
  4. begin
  5.   bmp := TBGRABitmap.Create(400, 400, CSSSilver);
  6.   with bmp.CanvasBGRA do
  7.   begin
  8.     canvas.Brush.BGRAColor := CSSGreen;
  9.     canvas.FillRect(100, 100, 300, 300);
  10.   end;
  11.   bmp.SaveToFile(ExtractFilePath(paramStr(0))+'square.png');
  12.   bmp.Free;
  13. end.
• either we don't provide the packages and let people tweak the package, but then properties would be hidden and code would be a bit different
Code: Pascal  [Select][+][-]
  1. uses BGRABitmap, BGRABitmapTypes, BGRACanvas, SysUtils;
  2.  
  3. var bmp: TBGRABitmap;
  4.   canvas: TBGRACanvas;
  5.  
  6. begin
  7.   bmp := TBGRABitmap.Create(400, 400, CSSSilver);
  8.   canvas := TBGRACanvas.Create(bmp); {explicit use of BGRACanvas unit}
  9.   canvas.Brush.BGRAColor := CSSGreen;
  10.   canvas.FillRect(100, 100, 300, 300);
  11.   canvas.Free;
  12.   bmp.SaveToFile(ExtractFilePath(paramStr(0))+'square.png');
  13.   bmp.Free;
  14. end.
Conscience is the debugger of the mind

d7_2_laz

  • Hero Member
  • *****
  • Posts: 542
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #4 on: March 06, 2024, 07:56:12 pm »
Hi circular,
thanks again!
Of course, my handicap here is that I raised the question although the technical details are new for me. But, as you say, maybe it’s a chance too to have a view from “outside”.
About the Define way, yes, I’t think it would be the best approach. Some thoughts:

- the common code base, untouched, is a Must, untouched in so far of course as it would only have some additional IfnDefs, hopefully as few as possible (if I think of the hierarchie, uh ..).  The Define controls which “use” and which procedures/functions will get active / visible.

- The main controlling Define could be in a special user-edited place and under the explicit responsibility of the user. Eg, only as example, in a custom.inc included in bgrabitmap.inc (customUseCoreOnly.inc or such), which is initially empty resp. does contain the setting in comments. Here are some disclaimer comments too to explain for which context this all is valid and for which scopes not.

- The restriction(s) (could be expanded/changed later if needed) are (e.g.): LCL only; at least initially only valid for a dedicated subdir, not an installed package (as the lpk itself might reference to other files too); not for other packages yet (ie. not for bgracontrols) etc. – The custom setting/file contains some rough checks (eg. nullify/Undef the setting for case IFNDEF LCL, etc.).

- Test source files of the POC (hopefully as few as possible) and a mini test project could be temporarely delivered beyond or besides “bgrabitmap” in a dedicated subdir(poc_coreonly), for people who search for such, as you say.
For testers: use temporarely those files instead of the originals, after having the originals backuped.

- Main question of course: what is “core” and what is full? 100 persons, 100 opinions, but an assumption/decision needs to be taken, otherwise it won’t never start. My entry in this area had been on the font rendering tutorial (paint outlined/shadowed text transparent) using  BGRABitmap, BGRABitmapTypes, BGRATextFX), so I could imagine this could be part, as well as gradient fills and, self-evident, basic bmp (and jpg?) operations (elaborated operations are part of “full”, as well as ico, png, gif and others).


I still have no idea how far this (the degree of modifications) could lead – hopefully not too far, but the complexity is unmistakable. Only persons with depth insight can judge. Don’t know too what’s about the TBGRACanvas.Create (seems to open a new crucial field).

If at the end it turns out to get too complicated / too many files flooded with ifndefs (readability will suffer), possibly it won’t make sense. Same if there is no apparent interest expressed by others.
« Last Edit: March 06, 2024, 08:04:09 pm by d7_2_laz »
Lazarus 3.6  FPC 3.2.2 Win10 64bit

VTwin

  • Hero Member
  • *****
  • Posts: 1224
  • Former Turbo Pascal 3 user
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #5 on: March 06, 2024, 10:33:45 pm »
I use bgrabitmap in most of my projects (thanks circular!). Each is on the order of 30 mb, so I don't consider an extra 1 or 2 mb a deal breaker.

Simplicity is important to me. A smaller core code base might be welcome, but I would not enjoy having to figure out additional complexities that might arise.

I would also suggest that bgrabitmap be considered as part of Lazarus.

Best Regards

“Talk is cheap. Show me the code.” -Linus Torvalds

Free Pascal Compiler 3.2.2
macOS 14.5: Lazarus 3.4 (64 bit Cocoa M1)
Ubuntu 18.04.3: Lazarus 3.4 (64 bit on VBox)
Windows 7 Pro SP1: Lazarus 3.4 (64 bit on VBox)

lainz

  • Hero Member
  • *****
  • Posts: 4615
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #6 on: March 06, 2024, 10:44:25 pm »
Remember as well how this will modify bgracontrols. Because we use the entire library on it.

d7_2_laz

  • Hero Member
  • *****
  • Posts: 542
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #7 on: March 06, 2024, 11:42:09 pm »
lainz, full agreement, therefore “not for bgracontrols” above
Lazarus 3.6  FPC 3.2.2 Win10 64bit

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #8 on: March 07, 2024, 09:02:36 am »
I think we all agree that the current package will not change for regular users. We are considering here at most only local changes to packages or no change at all.

It brings one question if one wants to use BGRAControls and the BGRABitmapCore at the same time. The local change in BGRABitmap package would prevent compilation of packages that depend on it. It makes more sense to use the full package in this case because:
  • The full package is necessary to compile BGRAControls anyway
  • Code written for core version will work as well with full version
So if in a project, at some point, one need the full package, the existing code designed for the core version will still work fine.

@d7_2_laz if I understand correctly, you propose that the library would be directly included as source to the project. In this scenario, it would make it easy to enable the core version via the project options (Compiler options -> Custom options) by adding "-dBGRABITMAP_CORE". There would be no need for the user to fiddle with the code.

Other options could be added as well to reflect the behavior of specific BGRABitmap package. For example, for fpGUI, the options would be:
Code: [Select]
-dBGRABITMAP_USE_FPGUI -dBGRABITMAP_CORE
Does this methodology appeal to you?

I use bgrabitmap in most of my projects (thanks circular!). Each is on the order of 30 mb, so I don't consider an extra 1 or 2 mb a deal breaker.

Simplicity is important to me. A smaller core code base might be welcome, but I would not enjoy having to figure out additional complexities that might arise.
Hi VTwin,

It is heartwarming to hear your positive experience with BGRABitmap in your projects. Your insight into the relative size of BGRABitmap and the value of simplicity is appreciated.

I'm currently gathering testimonials to feature on BGRABitmap website. Given your feedback, I'd be honored to include a quote from you.  It could be based on what you've shared here. To get an idea of how it will look, I invite you to look at the version release topic: https://forum.lazarus.freepascal.org/index.php/topic,24239.msg509981.html#msg509981

- Main question of course: what is “core” and what is full? 100 persons, 100 opinions, but an assumption/decision needs to be taken, otherwise it won’t never start. My entry in this area had been on the font rendering tutorial (paint outlined/shadowed text transparent) using  BGRABitmap, BGRABitmapTypes, BGRATextFX), so I could imagine this could be part, as well as gradient fills and, self-evident, basic bmp (and jpg?) operations (elaborated operations are part of “full”, as well as ico, png, gif and others).
That's an essential question. In fact, text rendering can take up some space, so it may be that text would be optional. For example, if you want to do something that only adjust colors in an image. It remains to determine whether the syntax would change.

TBGRACanvas.Create is to create the utility functions that look like the standard TCanvas but with transparency and antialiasing. They are provided for now as a CanvasBGRA property of the bitmap, but if we decide that the core version doesn't offer this property, then one need to instantiate it to have access to the functions. I invite you to look at the samples I gave and play with it to get a grasp of it.

If the syntax changes, it avoids unexpected crashes at runtime because one unit wasn't specified in the uses clause. It helps to make it clear at compile time whether the correct options have been specified.
Conscience is the debugger of the mind

d7_2_laz

  • Hero Member
  • *****
  • Posts: 542
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #9 on: March 07, 2024, 05:09:29 pm »
circular, i'd have the following usage image in mind:
- A: Regular usage (for many apps / several different operations/ complex components (ie. bgracontrols)) / big apps / ...) -> installed full version without any contact to the “core” version
- B: Sporadic/punctual usage (single basic operation in a specific app, ie. if  it's foreseen to be kept small) -> dedicated core version used fully separate/apart.
Regarding one specific project: A or B, not both in parallel somehow mixed "at the same time".

If there's an app having 30Mb and it grows by 1,5MB, i wouldn't care at all either; it doesn't matter.
If there's an app 4,2MB intentionally kept lean, and it grows to 5,7MB for to achieve an outlined text on a toolbutton, i'd say 'huh, why'.

If the (intentionally taken) decision could by controlled by a project compile option. rather than by a manually set variable - that could be pretty pretty cool of course  :)
To do it by manual setting would be imo fine too though. Anyhow, with both ways it gave flexibility to use it appropriately.

Btw. about: library included as source in a special subdirectory: i thought it actually conservative as a first step temporarely for interested testers for to consolidate. In a long term range it could be decided later, for to avoid doubled maintenance of source files - depending on: how stable is it, does it really not interfere with the full version, no side effects, has it proven itself?

About the duo CanvasBGRA (property) vs TBGRACanvas (object): basically I think transparency is an essential thing. So eg. for the font rendering tutorial’s example: not being able to do a “bmp.FillTransparent” here would be a very fundamental restriction. Hope I didn’t misunderstand fully. Unfortunately, I can't give any expert input on this point yet. I’ll study the examples mentioned later and be pretty sure that development takes the right decisions here.
Lazarus 3.6  FPC 3.2.2 Win10 64bit

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #10 on: March 07, 2024, 05:26:02 pm »
Hi d7_2_laz

I agree with your development, all this sounds reasonable. If you like the idea of a project option, then I am happy with that as it is for me the best option as well.

I would not have two distinct sources, only compiler directives. I think it can be manageable.

About the duo CanvasBGRA (property) vs TBGRACanvas (object), there is a misunderstanding. There is transparency in all cases, but this is kind of a bridge to make it easy, if you're coming from TCanvas, to have similar functions.
Conscience is the debugger of the mind

d7_2_laz

  • Hero Member
  • *****
  • Posts: 542
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #11 on: March 07, 2024, 05:41:18 pm »
 :) :) :) !
Lazarus 3.6  FPC 3.2.2 Win10 64bit

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #12 on: March 08, 2024, 04:10:43 pm »
Hi d7_2_laz,

I've created a branch called dev-core and already implemented most of the conditional compilation. For more details, I invite you to have a look at the issue #127.

Thank you for input, it has helped clarify what the core version would be.

Although there remain to remove the extended colorspaces, I would be happy to hear about your feedbacks at this point.

 :)
Conscience is the debugger of the mind

d7_2_laz

  • Hero Member
  • *****
  • Posts: 542
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #13 on: March 08, 2024, 07:49:07 pm »
Hi circular, wow, that fast .....

I’m not sure if my test steps are legible yet and really meaningful for you.
I used the app having a self-written toolbar where I had tried the outlining font rendering for the tool buttons.

1. Picked up, from branch dev-core,  the folder “bgrabitmap” and used it as a local subdir
2. Generated without having changed any options => compile/link and behavior are well (it think, good to know no regression so far)
3. Compiled after having added the -dBGRABITMAP_CORE to the project's compiler option
(there are also options in it coming from the MDelphi resp. original Delphi conversion)
 -> compile error, but only on bgragrayscalemask.pas concerning Filter*Blur (image)
4. Removed (commented) all bgra-related actions, so that only the “uses” did remain. Those are: BGRABitmap, BGRABitmapTypes, BGRATextFX 
-> Same error
5. Removed “BGRATextFX” from the uses: compiled without errors.
6. Like mentioned in the github issue #127, (“Filter* functions can be found in BGRAFilter and BGRAFilterBlur units”),  I used instead for try belonging units bgrafilters, bgrafiltertype, bgrafilterblur, bgrafilterscanner  -> compiled fine
7.  Reactivated the bgra actions step by step.  Worked partially, that means, all but not the text renderer (TBGRATextEffectFontRenderer).  // Text snippet below
9. Removed the Filter* units again from uses and regenerated.
==> Unfortunately, the size advantage is neglaticable so far (after strip,  5.510 instead of  5.561 MB / full version).

Code: Pascal  [Select][+][-]
  1. // Inside an outer procedure:
  2.   procedure DoDrawTextBgra;
  3.   var  bmp: TBGRABitmap;   { renderer: TBGRATextEffectFontRenderer; }  aLeftOffs: Integer;
  4.   begin
  5.     bmp := TBGRABitmap.Create(AParent.Width, AParent.Height, $00616161);
  6. {
  7.     renderer := TBGRATextEffectFontRenderer.Create;
  8.     bmp.FontRenderer := renderer;
  9.     renderer.ShadowVisible := True;
  10.     renderer.OutlineVisible := True;
  11.     renderer.OutlineColor := BGRABlack;
  12.     renderer.OuterOutlineOnly := True;
  13. }
  14.     bmp.FontFullHeight := (AFont.Size * 2) - 1;   // 15
  15.     aLeftOffs :=  (Rect.Width -  ACanvas.TextWidth(AText)) Div 2;  // Need to assure text centering now
  16.     bmp.FillTransparent;   // Needed this for transparency
  17.     bmp.TextOut(Rect.Left + aLeftOffs, Rect.Top + 2, AText, AFont.Color);
  18.     bmp.Draw(ACanvas, 0, 0, False);   // False Not opaque
  19.     bmp.Free;
  20.   end;
Lazarus 3.6  FPC 3.2.2 Win10 64bit

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: Q. bgrabitmap newbie: how to reduce the number of units to be used?
« Reply #14 on: March 09, 2024, 01:59:21 am »
Hi d7_2_laz,

Thank you so much of giving me this detail feedback. I understand what's the problem. There was some remaining code that needed to be adapter. You basically couldn't use the core version for text.

I've done the necessary changes. Your test program will probably compile without tweaks now. I think the only things that would not compile are 3d scenes, but I prefer to leave that for now.

It is possible that when using text rendering the changes are not significant, because drawing text use quite a lot of things. There still some significant gain possible I guess if we can make extended colorspaces optional.

About the call to FillTransparent, it was needed because the call to TBGRABitmap.Create has the color $616161 as parameter. Instead you can omit the parameter and the bitmap will be filled with transparent pixels by default.
Conscience is the debugger of the mind

 

TinyPortal © 2005-2018