Recent

Author Topic: BGRABitmap function not found / needed  (Read 1637 times)

af0815

  • Hero Member
  • *****
  • Posts: 1288
BGRABitmap function not found / needed
« on: April 19, 2021, 08:36:33 am »
I have searched for useful function, but not found inside of BGRABitmap, maybe my issue :-)

i use this chunks of code
Code: Pascal  [Select][+][-]
  1.   size:= img.Height*img.Width;
  2.   p:= img.Data;
  3.   for x:= 0 to size-1 do begin
  4.     sumB := sumB + p^.blue;
  5.     sumG := sumG + p^.green;
  6.     sumR := sumR + p^.red;
  7.     inc(p);
  8.   end;
  9.   avgR:= trunc(sumR / size);
  10.   avgG:= trunc(sumG / size);
  11.   avgB:= trunc(sumB / size);
  12.   k := 0.299 * avgR + 0.587 * avgG + 0.114 * avgB;
  13.  
Is there a sum per color (with BGRA) or mean function/filter/whatelse in BGRABitmap ? 

Second: I want to shift color by color save by a factor (for 8-Bit BGRA)
Code: Pascal  [Select][+][-]
  1.   p:= img.Data;
  2.   for x:= 0 to size-1 do begin
  3.     newB:= p^.blue * kb;
  4.     newG:= p^.green * kg;
  5.     newR:= p^.red * kr;
  6.     if trunc(newB) > 255 then
  7.       p^.blue:= 255
  8.     else
  9.       p^.blue:= trunc(newB);
  10.     if trunc(newG) > 255 then
  11.       p^.green:= 255
  12.     else
  13.       p^.green:= trunc(newG);
  14.     if trunc(newR) > 255 then
  15.       p^.red:= 255
  16.     else
  17.       p^.red:= trunc(newR);
  18.     inc(p);
  19.   end;
  20.  

Can i shorten this with builtin functions of BGRABitmap ?

Extra question: is a builtin whitebalance filter in BGRABitmap ? The two snipets are from such a function :-)

Andreas
regards
Andreas

circular

  • Hero Member
  • *****
  • Posts: 4195
    • Personal webpage
Re: BGRABitmap function not found / needed
« Reply #1 on: April 19, 2021, 08:57:47 am »
There is an TBGRABitmap.AveragePixel property that computes the average color taking into account transparency.

Then there is TBGRAPixel.Lightness that returns the a weighted sum of R/G/B taking as a linear value.

There isn't a straightforward multiply function though you could use BlendRect function for some adjustments with blend operations like boMultiply, boSvgSoftLight, boSoftLight, boHardLight.

About light balance, you could convert first your image into XYZ colorspace and then back to RGB but with a different reference white. To do so, you can for example create a TXYZABitmap of the same size as original image, call SetReferenceWhite with the target illuminant, do TXYZA.PutImage of the BGRA image, then call SetReferenceWhite with the original illuminant, then do TBGRABitmap.PutImage of the XYZA image.

That's not the most memory efficient way, but you get the idea. To use less memory, you can do that for each scanline into an array of colors, using the conversion function of the colorspaces. Thinking about it, that could be a new function to add to BGRABitmap.
« Last Edit: April 19, 2021, 09:06:06 am by circular »
Conscience is the debugger of the mind

af0815

  • Hero Member
  • *****
  • Posts: 1288
Re: BGRABitmap function not found / needed
« Reply #2 on: April 19, 2021, 10:06:33 am »
That's not the most memory efficient way, but you get the idea. To use less memory, you can do that for each scanline into an array of colors, using the conversion function of the colorspaces. Thinking about it, that could be a new function to add to BGRABitmap.
Is not the easiest way to make a (shift-)filter , where you can give a RGBA factor and all pixels are multiplied with the given RGBA values ?!
regards
Andreas

circular

  • Hero Member
  • *****
  • Posts: 4195
    • Personal webpage
Re: BGRABitmap function not found / needed
« Reply #3 on: April 19, 2021, 01:21:09 pm »
Well to do a change of white balance, that would be a way to do the chromatic adaptation.

What about the other functions I have mentioned?
Conscience is the debugger of the mind

af0815

  • Hero Member
  • *****
  • Posts: 1288
Re: BGRABitmap function not found / needed
« Reply #4 on: April 19, 2021, 02:40:38 pm »
AveragePixel have done most of the needed work.

The actual code is
Code: Pascal  [Select][+][-]
  1. procedure GrayWorld(var img: TBGRABitmap);
  2. var
  3.   p: PBGRAPixel;
  4.   pavg: TBGRAPixel;
  5.   size:integer;
  6.   k:double;
  7.   newB, newG, newR: double;
  8.   x: integer;
  9.   kb,kg,kr: double;
  10. begin
  11.   pavg:= img.AveragePixel;
  12.   k := 0.299 * pavg.red + 0.587 * pavg.green + 0.114 * pavg.blue;
  13.   // This part can differ if you want another weighting
  14.   //see https://www.programmersought.com/article/98291796437/
  15.   kr:= k / pavg.red  ;
  16.   kg:= k / pavg.green;
  17.   kb:= k / pavg.blue ;
  18.   size:= img.Height*img.Width;
  19.   //
  20.   p:= img.Data;
  21.   for x:= 0 to size-1 do begin
  22.     newB:= p^.blue * kb;
  23.     newG:= p^.green * kg;
  24.     newR:= p^.red * kr;
  25.     if trunc(newB) > 255 then
  26.       p^.blue:= 255
  27.     else
  28.       p^.blue:= trunc(newB);
  29.     if trunc(newG) > 255 then
  30.       p^.green:= 255
  31.     else
  32.       p^.green:= trunc(newG);
  33.     if trunc(newR) > 255 then
  34.       p^.red:= 255
  35.     else
  36.       p^.red:= trunc(newR);
  37.     inc(p);
  38.   end;
  39. end;
  40.  
I have to dive a little more in BGRABitmap and the mentinoed function to answer you. I want to understand the functions before i use it.
 
regards
Andreas

af0815

  • Hero Member
  • *****
  • Posts: 1288
Re: BGRABitmap function not found / needed
« Reply #5 on: April 20, 2021, 07:29:50 am »
If i use
Code: Pascal  [Select][+][-]
  1.   pavg:= img.AveragePixel;
  2.   k1:= pavg.Lightness;
  3.   k := 0.299 * pavg.red + 0.587 * pavg.green + 0.114 * pavg.blue;
  4.  
k1 and k are not the same (or nearly the same). Because ligthness is not calculation in the same schema (8-Bit value) it is using a 16Bit schema
Quote
Returns the lightness of a pixel. The lightness is the perceived brightness, 0 being black and 65535 being white

If i dive deeper, it looks like the same calculation, but with a 'shr 10'. So it looks the domain of the calculation is shifted to word instead of real used by the calculation of k.




regards
Andreas

circular

  • Hero Member
  • *****
  • Posts: 4195
    • Personal webpage
Re: BGRABitmap function not found / needed
« Reply #6 on: April 20, 2021, 07:54:53 pm »
The difference comes probably from gamma correction.

GammaExpansion and GammaExpansionTab return 16-bit linear values whereas the TBGRAPixel contains 8 bit sRGB values (non linear).

Later when you do the computation, you can take gamma correction into account like that:
Code: [Select]
newB:= round(GammaExpansionTab[p^.blue] * kb);
if newB > 65535 then p^.blue := 255
else p^.blue := GammaCompressionTab[round(newB)];
Conscience is the debugger of the mind

 

TinyPortal © 2005-2018