SVGIconImageList
SVGIconImageList copied to clipboard
Blueish tint on Android and MacOS-X
I see blueish tint on Android when using the latest TSVGIconImageList from GetIt Package Manager
Windows:

Android:

The app is at https://github.com/zoomicon/READCOM_App
Apart from using TSVGIconImage for the SVG images in the stories, I use TSVGIconImageList for the app icons. All those are tinted. However, stories that contain bitmap images show fine, so it's something with the SVG rendering
I think it uses Image32 for rendering now (judging from a little debugging). Is there any known issue with that? How can I tell your library to use Skia SVG renderer instead? (or is there other engine alternative on Android too?) Do I need to install Skia4Delphi too and right click my project and enabled Skia (to added needed lib to deployment)?
UPDATE:
the same tint appears on MacOS-X (those are supposed to be English/Greek/Italian/Portuguese/Spanish flags in the image)

Is it something related to RGB versus BGR? Is Image32 also being used by default on OS-X?
Note that bitmap images (rendered via FMX) look fine

Please try to restore previous version of Img32.SVG.Reader that contains:
if (fillColor = clCurrent) then
{$IF Defined(MACOS) or Defined(MACOSX)}
drawDat.fillColor := SwapRedBlue(thisElement.fReader.currentColor)
{$ELSE}
drawDat.fillColor := thisElement.fReader.currentColor
{$IFEND}
else if (fillColor <> clInvalid) then
{$IF Defined(MACOS) or Defined(MACOSX)}
drawDat.fillColor := SwapRedBlue(fillColor);
{$ELSE}
drawDat.fillColor := fillColor;
{$IFEND}
if fillOpacity <> InvalidD then
drawDat.fillOpacity := fillOpacity;
if (fillEl <> '') then
drawDat.fillEl := fillEl;
if (strokeColor = clCurrent) then
{$IF Defined(MACOS) or Defined(MACOSX)}
drawDat.strokeColor := SwapRedBlue(thisElement.fReader.currentColor)
{$ELSE}
drawDat.strokeColor := thisElement.fReader.currentColor
{$IFEND}
else if strokeColor <> clInvalid then
{$IF Defined(MACOS) or Defined(MACOSX)}
drawDat.strokeColor := SwapRedBlue(strokeColor);
{$ELSE}
drawDat.strokeColor := strokeColor;
{$IFEND}
because it was lost during update to Image32 4.11 version. Then give me a feed-back if it works, so i can restore this fix and notify Angus Johnson, the author of Image32. Thanks.
problem is I'm using the GetIt version (not sure if GetIt allows one to rollback to previous versions). Can I patch it by including my copy of that unit (I can get it from their version control) in the uses clause of the app? I haven't tried building your library, was afraid I'd lose time trying to pull in all dependencies
another problem I see is that this code (which looks promising btw) check if it's targetting MACOS-X, but I don't see Android or iOS mentioned (at Android it's the same issue and I suspect it's on iOS too).
Unfortunately, I don't have mobile devices on which to test. I advise you to install the library by cloning the repo from Git: the installation is simple, just open the package group do the build / install of the packages, as explained here: Now you can develop by compiling the sources directly and trying to make changes to fix the color problem on the different devices.
There is another place to adjust color that affect also ANDROID platform, into FMX.Image32SVG:
function AlphaToColor32(AlphaColor: TAlphaColor): TColor32;
var
res: TARGB;
begin
res.A := TAlphaColorRec(AlphaColor).A;
res.R := TAlphaColorRec(AlphaColor).R;
res.G := TAlphaColorRec(AlphaColor).G;
res.B := TAlphaColorRec(AlphaColor).B;
Result := res.Color;
{$IF Defined(ANDROID) or Defined(MACOS) or Defined(MACOSX)}
Result := SwapRedBlue(Result);
{$IFEND}
end;
thanks, will take a look
btw, an easy way to test is to upload an APK at https://www.browserstack.com/android-testing (note one needs to create a certificate from inside Delphi to sign the resulting .apk, else BrowserStack won't install it)
Looking at that code snippets you shared, it seems they were loading the RGB as BGR (but only on OS-X) and then they were swapping again back to RGB or something (this time both on Android and OS-X).
So their original code (without the code that was removed from the SVG loader) would work on OS-X (had double inversion that was self-canceling), but on Android I guess. Now that they removed that they have it broken both on OS-X and Android (then probably on iOS it may work, will check on the iOS emulator)
Started looking at it, one quick comment I have is that I feel the .groupproj should contain the demo projects too for convenience (so that one can easily test a change they did), or could add extra groupproj with everything (packages and demos), since the existing is called "SVGIconImageListGroupPackages". Not sure if GetIt needs that groupproj to only contain the packages or something, plus hope if extra is added with everything that GetIt isn't confused (e.g. losing time to build all demos or something)
I can confirm that the issue occurs on Android with the SVGIconImageListDemoFMX project too (here I project via Miracast [wifi] from Android to Windows 11):

(I also notice some layout glitch at the FixedColor checkbox and the color dropdown [and its dropdown arrow] under it)
To build/run on Android, I had to right click the Libraries not and select "Revert System Files to Default":

the issue isn't probably with loading the SVGs, but with rendering them, since if I play with the Fixed Color option at that demo, I see other color result (though I'm not sure how the Fixed Color functionality is implemented [if it "reloads" the SVG from a modified source or if it changes it in memory without invoking an SVG reader/parser again]):

making AlphaToColor32 not call SwapRedBlue didn't work, but making SwapRedBlue not do anything (comment out the swapping commands) did work:
function SwapRedBlue(color: TColor32): TColor32;
var
c: array[0..3] of byte absolute color;
r: array[0..3] of byte absolute Result;
begin
result := color;
//r[0] := c[2];
//r[2] := c[0];
end;
probably though that method is needed to be there (don't want to make it do nothing), so will look into it a bit more to see who calls it
searching for the symbol with find in files gives:
opening one by one seems actual callers are these methods:
- RgbToHsl at Img32.pas(1229)
- HslToRgb at Img32.pas(1292)
- AlphaToColor32 at FMX.Img32SVG.pas(83) - commenting it out there didn't do the trick as I mentioned above and the most suspicious one:
- UTF8StringToColor32 at Img32.SVG.Core.pas(1191)
fixing the last one also does the trick (instead of making SwapRedBlue do nothing), but it has a conditional check for Android only, so have to check why MacOS-X also has the issue and if this fixes it for it too, or it needs fix also at other place
I forwarded the issue to Angus Johnson, author of Image32...
thanks, will post here any more findings since I'll try on OS-X too later on today
note that just adding to SVGIconImageListDemoFMX project the patched Img32.SVG.Core.pas (with commented out SwapRedBlue call at line 1191) does the trick on Android, even with the GetIt version of SVGIconImageList
{$IFDEF ANDROID}
//color := SwapRedBlue(color); //TODO: this fixes Blueish SVG color tint (RGB-BGR substitution) on Android, but should try to fix OS-X too (https://github.com/EtheaDev/SVGIconImageList/issues/229) - haven't tried iOS yet
{$ENDIF}
forwarded the issue to Angus Johnson, author of Image32...
Thanks Carlo. I'm not doubting there's a problem, but I can't duplicate it, at least when just using Image32. I've attached a very simple demo FMX app that just uses Image32. And here are the Windows and Android screenshots:


Edit: tidied up demo.
I'm now wondering if this problem is due to a conflict between Image32 and Carlo's FMX.Image32SVG unit.
As you've observed above, Image32 swaps the red and blue channels (when the precompiler directive ANDROID is defined). However, I note Carlo's AlphaToColor32 function (line 72) calls TAlphaColorRec which also switches these color channels depending on endianness. IOWs, I suspect the blue and red channels are being swapped twice.
Edit: Unrelated to the above problem, I can see it's much better to manage red-blue color swaps based on endianness rather than platform, so I'll need to change this in Image32.
Edit2: Scrap all that. The red-blue issue is unrelated to endianness.
Hi, if you don't see the issue in Image32 demos (didn't notice any in the version included in SVGIconImageList repo), but only happening in SVGIconImageList FMX demos (and in my app that uses that library), then it's definitely something added there or some difference in the files they have.
So, since there was another suspisious thing in that code, I think I found it.
My original fix showed ok:

but not the FixedColor functionality of that demo, it was broken:

so I went back to the code, first of all had checked the method you had mentioned and though it was being called a lot in the debugger (had breakpoint to confirm I had overriden it with my added changed unit in the demo project), it wasn't affecting the tint issue (whether I had my other fix added or not, it didn't affect something [apart maybe from the FixedColor I mention, didn't try that with it])
the correct (that solves both the tint and the FixedColor functionality) fix is here:
at the FMX.Image32SVG file of SVGIconImage repo
to recap, ignore my originally proposed fix, the issue is in FMX.Image32SVG @carloBarazzetta please do this fix, tried on both Windows and Android (the R-B color channel reversal goes away and the FixedColor switch works fine too in both) - UPDATE: added pull request here: https://github.com/EtheaDev/SVGIconImageList/pull/231
Since I had observed the issue on OS-X, added OS-X too. However I have some issue with that demo to add OS-X target, fails to compile due to some file rights (can't write to the bin folder etc.). On my READCOM_App project OS-X target builds fine, so will check there too that the fix works on OS-X and let you know
Will also try on iOS Simulator soon (I hope) to see if the issue was ever there for that platform too
since it's a major bug if you could release on GetIt a new version it would be great (just wait for me to check on iOS too)

Yes, that may be useful in Image32 too.
I confirmed this fix is fine for my app on Android, but on Mac OS-X it isn't doing the job (I tried both RGBA and BGRA there with no difference which is strange)
The reason might be that some other code that also does reversals and has only check for Android, not Mac OS-X (or vice-versa). In fact there's a chance there are too many reversals happening that could be avoided.
PAServer is quite slow to deploy to remote Mac, so not easy to try alternatives (takes some time)
Plus had seen some Image32 code that was getting the TPixelFormat from BitmapSurface, not sure what that was about, but maybe one could avoid conditional defines and just get the PixelFormat from the device canvas (though I'm not sure if that is accessible early in the app startup)? e.g. would Android on Intel platforms be using other pixel format that Android on ARM? (not that Delphi can target Android on Intel currently, but Windows is moving onto ARM too so we might have issues with that too in the future if MS doesn't handle such things under the hood)
Another thing is that I don't see MACOSX symbol at https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Conditional_compilation_(Delphi) is it for FreePascal or something? I only see a newer one called OSX, but I guess best is to use older MACOS one (and just that if only targetting Delphi). Just in case I tried the fix with OSX symbol (my taget is Mac 64-bit [Intel CPU, an older iMac]), does the same
Just remembered at UTF8StringToColor32 at Img32.SVG.Core.pas(1191) it was only reversing for Android, probably it needed to reverse for OS-X too so that the Copy Image32 to Bitmap other fix will then work. Fingers crossed, will try
Indeed, it worked with this extra fix (this time at Image32's Img32.SVG.Core), aka to have near the end of UTF8StringToColor32 do color reversal for both Android and MacOS-X
an issue is that Image32 was using {$IFDEF ANDROID}...{$ENDIF} instead of {$IF Defined(Android)}...{$IFEND} (note the IFEND btw)
I used this but not sure if it compiles on FreePascal/Lazarus, plus see my question on what MACOSX symbol is (that Carlo uses in his code):

[DONE] will update the pull request if still open to have the fixes for both Android and OS-X or else make new one
btw, regarding the use of IFEND, it's required by older compilers if one use $IF (newers accept $ENDIF from what I see). If compiler has issues it's mentioned that one can add {$IF CompilerVersion >= 24.0 } {$LEGACYIFEND ON} {$IFEND} https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Legacy_IFEND_(Delphi) https://stackoverflow.com/a/38052789/903783
to be consistent with existing code in SVGIconImageList I'll use {$IFEND} at the fix I had done in FMX.Image32SVG too
also note I tested on "Android on ARM" and "MacOS-X on Intel" targets
an issue is that Image32 was using {$IFDEF ANDROID}...{$ENDIF} instead of {$IF Defined(Android)}...{$IFEND} (note the IFEND btw)
I used this but not sure if it compiles on FreePascal/Lazarus, plus see my question on what MACOSX symbol is (that Carlo uses in his code):
I've just fixed this but now I'm having problems uploading to Sourceforge.
I'm still having problems with SourceForge and have decided to move the repository over to GitHub. (This was something I'd been considering for a while but with the issues I'm currently having with SF has prompted me to move to GitHub immediately. Besides, I have other repositories there.) Anyhow, Image32's updated code can be found here.
will probably need to use that LEGACYIFEND code block I mentioned above to stop emitting warning for the use of the legacy IFEND (unless one doesn't care about older compilers that needed $IFEND to match $IF), else will get:
- SVGIconImageList\Source\FMX.Image32SVG.pas(83,3): warning H2586: H2586 Legacy '$IFEND' directive found. Consider changing to '$ENDIF' or enable $LEGACYIFEND
- SVGIconImageList\Source\FMX.Image32SVG.pas(177,155): warning H2586: H2586 Legacy '$IFEND' directive found. Consider changing to '$ENDIF' or enable $LEGACYIFEND