Is there a quick way to calculate the dominant color (the most common color) in a bitmap in Firemonkey?
Or is there an option in FMX to reduce the number of colors when using a color palette, e.g. as in Vcl.Imaging.GIFImg?
I have implemented my own solution yet, which is not optimized for calculating fast results.
function GetDominanteColor(Bmp: TBitmap): TAlphaColor;
var
BMPData: TBitmapData;
x, y: integer;
Col: TAlphaColor;
Count: cardinal;
Histogram: TDictionary<TAlphaColor, cardinal>;
begin
result := TAlphaColors.Null;
if Bmp.Width * Bmp.Height > 0 then
if Bmp.Map(TMapAccess.Read, BMPData) then
begin
Histogram := TDictionary<TAlphaColor, cardinal>.Create;
try
// build histogram
for x := 0 to Bmp.Width - 1 do
for y := 0 to Bmp.Height - 1 do
begin
Col := BMPData.GetPixel(x, y);
if Histogram.TryGetValue(Col, Count) then
Histogram.Items[Col] := Count + 1
else
Histogram.Add(Col, 1);
end;
// search color with highest score
Count := 0;
for Col in Histogram.Keys do
begin
if Histogram.Items[Col] > Count then
begin
Count := Histogram.Items[Col];
result := Col;
end;
end;
{$IFDEF DEBUG}
FMX.Types.Log.d('Dominante color %s from %d colors',
[IntToHex(result, 8), x]);
{$ENDIF}
finally
Histogram.Free;
end;
BMP.Unmap(BMPData);
end;
end;
On an old CPU (i5-3360@2.8GHz) this function needs up to 200ms for a full HD image. Acceleration could be to limit the color space or to take not each pixel but to use a representative set of pixels.