Recent

Author Topic: How to Optimeze use of BGRAColorQuantizer??  (Read 15274 times)

Sanem

  • Full Member
  • ***
  • Posts: 173
How to Optimeze use of BGRAColorQuantizer??
« on: August 23, 2016, 10:07:36 am »
HI
I have tested the method below to gain pixel colors of a picture, and the result is fine, but it takes too much time for a big picture (875ms for 264000 colors in a picture with size 1920*1080) . I was wondering if there is a way that I can reduce the number of pixels that the process of gaining the pixel colors trace (for example a constant percent of the picture Dimensions), to get a better branch time for this?? Or any other way to reduce the time it takes by jumping some pixels in big pictures, Any Idea??

And I am aware that with this way the result would be less exact and in big pictures it does not matter, because for example if we jumped 10 pixels (in the trace process of gaining the pixel colors) in a big picture, it seems like a single pixel in a small picture. The Screenshots attached is a sample to show what the method does, because the Picture I mentioned was too big for attaching, but the picture I mentioned is uploaded here:
https://www.dropbox.com/s/fdo1s7j0pykc7tc/GetSourceColorsTest.zip?dl=0

Any help appreciated prior
Regards




Here is my code:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.SourceColors;
  2. var
  3.   SourceBmp, SourceColorsBmp: TBGRABitmap;
  4.   quant: TBGRAColorQuantizer;
  5.   i, j, k, SourceColorCount, X, Y: integer;
  6.   sss: QWord;
  7. begin
  8.   SourceBmp := TBGRABitmap.Create('Pics' + PathDelim + 'Picture.jpg');
  9.   sss := GetTickCount64;
  10.   quant := TBGRAColorQuantizer.Create(SourceBmp, acFullChannelInPalette);
  11.   SourceColorCount := quant.SourceColorCount;
  12.   WriteLn('Source Color Count time: ', GetTickCount64 - sss);
  13.   WriteLn('Source Color Count: ', SourceColorCount);
  14.   X := round(sqrt(SourceColorCount));
  15.   y := X;
  16.   //Save Source Colors in a bitmap
  17.   SourceColorsBmp := TBGRABitmap.Create(X, Y);
  18.   j := 0;
  19.   k := 0;
  20.   for i := 0 to SourceColorCount - 1 do
  21.   begin
  22.     j := i div X;
  23.     if ((k div X) = 1) then
  24.       k := 0
  25.     else
  26.       Inc(k);
  27.     SourceColorsBmp.SetPixel(k, j, quant.SourceColor[i]);
  28.   end;
  29.   SourceColorsBmp.SaveToFile('Pics' + PathDelim + 'SourceColors.png');
  30.   SourceColorsBmp.Free;
  31.   SourceBmp.Free;
  32.   quant.Free;
  33. end;
  34.  
« Last Edit: August 23, 2016, 11:29:43 am by simin_sh »

Sanem

  • Full Member
  • ***
  • Posts: 173
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #1 on: August 23, 2016, 04:49:02 pm »
HI
I have tested the method below to gain pixel colors of a picture, and the result is fine, but it takes too much time for a big picture (875ms for 264000 colors in a picture with size 1920*1080) . I was wondering if there is a way that I can reduce the number of pixels that the process of gaining the pixel colors trace (for example a constant percent of the picture Dimensions), to get a better branch time for this?? Or any other way to reduce the time it takes by jumping some pixels in big pictures, Any Idea??

And I am aware that with this way the result would be less exact and in big pictures it does not matter, because for example if we jumped 10 pixels (in the trace process of gaining the pixel colors) in a big picture, it seems like a single pixel in a small picture. The Screenshots attached is a sample to show what the method does, because the Picture I mentioned was too big for attaching, but the picture I mentioned is uploaded here:
https://www.dropbox.com/s/fdo1s7j0pykc7tc/GetSourceColorsTest.zip?dl=0

Any help appreciated prior
Regards




Here is my code:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.SourceColors;
  2. var
  3.   SourceBmp, SourceColorsBmp: TBGRABitmap;
  4.   quant: TBGRAColorQuantizer;
  5.   i, j, k, SourceColorCount, X, Y: integer;
  6.   sss: QWord;
  7. begin
  8.   SourceBmp := TBGRABitmap.Create('Pics' + PathDelim + 'Picture.jpg');
  9.   sss := GetTickCount64;
  10.   quant := TBGRAColorQuantizer.Create(SourceBmp, acFullChannelInPalette);
  11.   SourceColorCount := quant.SourceColorCount;
  12.   WriteLn('Source Color Count time: ', GetTickCount64 - sss);
  13.   WriteLn('Source Color Count: ', SourceColorCount);
  14.   X := round(sqrt(SourceColorCount));
  15.   y := X;
  16.   //Save Source Colors in a bitmap
  17.   SourceColorsBmp := TBGRABitmap.Create(X, Y);
  18.   j := 0;
  19.   k := 0;
  20.   for i := 0 to SourceColorCount - 1 do
  21.   begin
  22.     j := i div X;
  23.     if ((k div X) = 1) then
  24.       k := 0
  25.     else
  26.       Inc(k);
  27.     SourceColorsBmp.SetPixel(k, j, quant.SourceColor[i]);
  28.   end;
  29.   SourceColorsBmp.SaveToFile('Pics' + PathDelim + 'SourceColors.png');
  30.   SourceColorsBmp.Free;
  31.   SourceBmp.Free;
  32.   quant.Free;
  33. end;
  34.  





When I read BGRAColorQuantization unit, I found out that the method in line 1940 which is TBGRAColorBox.Create, traces all the pixels of the bitmap to find colors, and when I decreased the loop counter to some percent like 25% or 50% I saw that the total branch time for get source colors is decreasing and I think it is close to what I am looking for, any IDEA how to implement it in BGRA or modifying it or adding this functionality to BGRA or what??

Any help appreciated prior
Regards

Michl

  • Full Member
  • ***
  • Posts: 226
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #2 on: August 24, 2016, 11:14:02 am »
If you don't need the alpha channel, you can write your own Method, something like (not well composed, just tested):
Code: Pascal  [Select][+][-]
  1. procedure TForm1.SourceColors;
  2. var
  3.   SourceBmp, SourceColorsBmp: TBGRABitmap;
  4.   i, SourceColorCount, aWidth, aHeight: DWord;
  5.   sss: QWord;
  6.   PPixel: PBGRAPixel;
  7.   Pixel: TBGRAPixel;
  8.   DPixel: DWord absolute Pixel;
  9.   PixelMap: array of Boolean;
  10.   D2: DWord;
  11.   D2Pixel: TBGRAPixel absolute D2;
  12.   ColorMap: array of TBGRAPixel;
  13. begin
  14.   SourceBmp := TBGRABitmap.Create('Pics' + PathDelim + 'Picture.jpg');
  15.   if SourceBmp.Bitmap.RawImage.Description.AlphaShift = 24 then begin
  16.     sss := GetTickCount64;
  17.     SetLength(PixelMap, 1 shl 24);
  18.     PPixel := SourceBmp.Data;
  19.     for i := 0 to Pred(SourceBmp.NbPixels) do begin
  20.       Pixel := PPixel^;
  21.       PixelMap[DPixel xor $FF000000] := True;
  22.       Inc(PPixel);
  23.     end;
  24.     SetLength(ColorMap, 1 shl 24);
  25.     SourceColorCount := 0;
  26.     for i := 0 to High(PixelMap) do
  27.       if PixelMap[i] then begin
  28.         D2 := i or $FF000000;
  29.         ColorMap[SourceColorCount] := D2Pixel;
  30.         Inc(SourceColorCount);
  31.       end;
  32.     WriteLn('Source Color Count: ', SourceColorCount);
  33.     aWidth := Trunc(sqrt(SourceColorCount));
  34.     aHeight := aWidth;
  35.     //Save Source Colors in a bitmap
  36.     SourceColorsBmp := TBGRABitmap.Create(aWidth, aHeight);
  37.     PPixel := SourceColorsBmp.Data;
  38.     for i := 0 to Pred(SourceColorsBmp.NbPixels) do begin
  39.       PPixel^ := ColorMap[i];
  40.       Inc(PPixel);
  41.     end;
  42.     WriteLn('Source Color Count time: ', GetTickCount64 - sss);
  43.     SourceColorsBmp.SaveToFile('Pics' + PathDelim + 'SourceColors.png');
  44.     SourceColorsBmp.Free;
  45.   end;
  46.   SourceBmp.Free;
  47. end;
(On Linux, the result with this method is the same as with your method, on Windows not. (RGBA <> BGRA))

Or without a dummy ColorMap (a little bit faster):
Code: Pascal  [Select][+][-]
  1. procedure TForm1.SourceColors2;
  2. var
  3.   SourceBmp, SourceColorsBmp: TBGRABitmap;
  4.   i, Cnt, SourceColorCount, aWidth, aHeight: DWord;
  5.   sss: QWord;
  6.   PPixel: PBGRAPixel;
  7.   Pixel: TBGRAPixel;
  8.   DPixel: DWord absolute Pixel;
  9.   PixelMap: array of Boolean;
  10.   D2: DWord;
  11.   D2Pixel: TBGRAPixel absolute D2;
  12. begin
  13.   SourceBmp := TBGRABitmap.Create('Pics' + PathDelim + 'Picture.jpg');
  14.   if SourceBmp.Bitmap.RawImage.Description.AlphaShift = 24 then begin
  15.     sss := GetTickCount64;
  16.     SetLength(PixelMap, 1 shl 24);
  17.     PPixel := SourceBmp.Data;
  18.     SourceColorCount := 0;
  19.     for i := 0 to Pred(SourceBmp.NbPixels) do begin
  20.       Pixel := PPixel^;
  21.       if not PixelMap[DPixel xor $FF000000] then Inc(SourceColorCount);
  22.       PixelMap[DPixel xor $FF000000] := True;
  23.       Inc(PPixel);
  24.     end;
  25.     //Save Source Colors in a bitmap
  26.     aWidth := Trunc(sqrt(SourceColorCount));
  27.     aHeight := aWidth;
  28.     SourceColorsBmp := TBGRABitmap.Create(aWidth, aHeight);
  29.     PPixel := SourceColorsBmp.Data;
  30.     Cnt := 0;
  31.     for i := 0 to Pred(SourceColorsBmp.NbPixels) do
  32.     begin
  33.       while not PixelMap[Cnt] do Inc(Cnt);
  34.       D2 := Cnt or $FF000000;
  35.       PPixel^ := D2Pixel;
  36.       Inc(PPixel);
  37.       Inc(Cnt);
  38.     end;
  39.     WriteLn('Source Color Count time: ', GetTickCount64 - sss);
  40.     SourceColorsBmp.SaveToFile('Pics' + PathDelim + 'SourceColors.png');
  41.     SourceColorsBmp.Free;
  42.   end;
  43.   SourceBmp.Free;
  44. end;
Code: [Select]
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;

Sanem

  • Full Member
  • ***
  • Posts: 173
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #3 on: August 24, 2016, 01:42:55 pm »
Thank you so much for your replay Michl, I tested it and it is fast.

Sanem

  • Full Member
  • ***
  • Posts: 173
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #4 on: August 25, 2016, 10:21:43 am »
HI Michl
I understood your code, thanks again, In the first time I was facing this subject (Color quantizer) I wanted to do it by tracing the pixels, and I did not know an efficient way and now when you suggest me an efficient way, I was wondering if I can do other things that I want with this way.
I want weight of each color in the color map of your code, I mean that I need to know for each pixel color in the colormap (source colors), how many pixels in the source bitmap has this color, and I tried to do it in my way, it works correctly when the source bitmap is small, I mean the weight of each pixel color that it calculates is correct, I tested it with a bitmap with 4 colors and 16*16 pixels, you can see the result in the screenshot attached. but it is not efficient for big bitmaps at all, so I was wondering if you can suggest me a better way for this.

Any help appreciated prior
Regards


here is my test code: 
Code: Pascal  [Select][+][-]
  1. procedure TForm1.SourceColorsWithWeights;
  2. var
  3.   SourceColorsBmp: TBGRABitmap;
  4.   i, Cnt, SourceColorCount, aWidth, aHeight: DWord;
  5.   sss: QWord;
  6.   PPixel: PBGRAPixel;
  7.   Pixel: TBGRAPixel;
  8.   DPixel: DWord absolute Pixel;
  9.   PixelMap: array of boolean;
  10.   D2: DWord;
  11.   D2Pixel: TBGRAPixel absolute D2;
  12.  
  13.   WeightMap: array of integer;
  14.   SavedColors: array of TBGRAPixel;
  15.   j: integer;
  16.  
  17.   procedure SaveColor(AColor: TBGRAPixel);
  18.   begin
  19.     SavedColors[Length(SavedColors) - 1] := AColor;
  20.     SetLength(SavedColors, Length(SavedColors) + 1);
  21.   end;
  22.  
  23. begin
  24.   SourceBmp := TBGRABitmap.Create('Pics' + PathDelim + 'Picture.jpg');
  25.   if SourceBmp.Bitmap.RawImage.Description.AlphaShift = 24 then
  26.   begin
  27.     sss := GetTickCount64;
  28.     SetLength(PixelMap, 1 shl 24); // 2^24=256*256*256 for all the colors in RGB
  29.     PPixel := SourceBmp.Data;
  30.     SourceColorCount := 0;
  31.     SetLength(SavedColors, 1);
  32.     for i := 0 to Pred(SourceBmp.NbPixels) do
  33.     begin
  34.       Pixel := PPixel^;
  35.       if not PixelMap[DPixel xor $FF000000] then
  36.       begin
  37.         Inc(SourceColorCount);
  38.         SaveColor(Pixel);
  39.       end;
  40.       PixelMap[DPixel xor $FF000000] := True;
  41.       Inc(PPixel);
  42.     end;
  43.  
  44.     WriteLn('Source Color Count Time: ', GetTickCount64 - sss);
  45.  
  46.     //Gain weight of each pixel color in color map
  47.     PPixel := SourceBmp.Data;
  48.     SetLength(WeightMap, SourceColorCount);
  49.     for i := 0 to Length(WeightMap) - 1 do
  50.     begin
  51.       WeightMap[i] := 0;
  52.     end;
  53.     for i := 0 to Pred(SourceBmp.NbPixels) do
  54.     begin
  55.       Pixel := PPixel^;
  56.       for j := 0 to Length(SavedColors) - 1 do
  57.       begin
  58.         if (SavedColors[j] = Pixel) then
  59.         begin
  60.           Inc(WeightMap[j]);
  61.         end;
  62.       end;
  63.       Inc(PPixel);
  64.     end;
  65.     WriteLn('Total Color Weights Time: ', GetTickCount64 - sss);
  66.  
  67.     for i := 0 to Length(WeightMap) - 1 do
  68.     begin
  69.       WriteLn('WeightMap [ ', i, ' ] : ', WeightMap[i]);
  70.     end;
  71.   end;
  72.   SourceBmp.Free;
  73. end;
  74.  
« Last Edit: August 25, 2016, 10:24:13 am by simin_sh »

circular

  • Hero Member
  • *****
  • Posts: 4220
    • Personal webpage
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #5 on: August 25, 2016, 11:45:22 am »
Hi!

That's something I have been wondering about. You could try using TBGRAWeightedPalette of BGRAPalette unit and call IncColor for each pixel.

One remark about pixel format, SourceBmp.Bitmap.RawImage.Description.AlphaShift does not indicate the format of TBGRAPixel but of the TBitmap object. To know the alpha shift of TBGRAPixel you can use TBGRAPixel_AlphaShift constant.

Regards
Conscience is the debugger of the mind

Sanem

  • Full Member
  • ***
  • Posts: 173
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #6 on: August 25, 2016, 12:15:55 pm »
Hi!

That's something I have been wondering about. You could try using TBGRAWeightedPalette of BGRAPalette unit and call IncColor for each pixel.

One remark about pixel format, SourceBmp.Bitmap.RawImage.Description.AlphaShift does not indicate the format of TBGRAPixel but of the TBitmap object. To know the alpha shift of TBGRAPixel you can use TBGRAPixel_AlphaShift constant.

Regards


Thank you for your replay Circular
Yep, I was reading the IncColor method and I was about to test it, but I did not have any idea how to do that, using the direct pixel trace way (Michl suggestion) to obtaining source colors of the bitmap, yet!

Something else, Do you have any comment about the first post I have sent in this thread?? here:
http://forum.lazarus.freepascal.org/index.php/topic,33789.msg219557.html#msg219557   
or this one:
http://forum.lazarus.freepascal.org/index.php/topic,33789.msg219622.html#msg219622

Any help appreciated prior
Regards
« Last Edit: August 25, 2016, 12:19:05 pm by simin_sh »

Michl

  • Full Member
  • ***
  • Posts: 226
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #7 on: August 25, 2016, 12:33:01 pm »
I'v not tested the useful hints from circular, but just one hint for your last posted code.

This
Code: Pascal  [Select][+][-]
  1.     SetLength(SavedColors, Length(SavedColors) + 1);
is a real time eater for bigger arrays. Cause whenever there is no space in the old memory place left, a new memory is allocated and copied from the old one. Faster is, to allocate a bigger memory, count it for your self and increase it with a bigger amount by your self, if needed.

Something like (untested):
Code: Pascal  [Select][+][-]
  1. ...
  2.     SetLength(SavedColors, min(1 shl 24, SourceBmp.NbPixels));  // <--
  3.     for i := 0 to Pred(SourceBmp.NbPixels) do
  4.     begin
  5.       Pixel := PPixel^;
  6.       if not PixelMap[DPixel xor $FF000000] then
  7.       begin
  8.         SavedColors[SourceColorCount] := AColor;  // <--
  9.         Inc(SourceColorCount);
  10.       end;
  11.       PixelMap[DPixel xor $FF000000] := True;
  12.       Inc(PPixel);
  13.     end;
  14.     SetLength(SavedColors, SourceColorCount);  // <--
  15. ...

[Edit] Changed max() to min() ...
« Last Edit: August 25, 2016, 01:04:06 pm by Michl »
Code: [Select]
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;

Sanem

  • Full Member
  • ***
  • Posts: 173
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #8 on: August 25, 2016, 01:05:59 pm »
Thank you Michl, but that part is not the part that takes time, I tested it in a 1920*1080 bitmap, and its just taking equal time to case that I run the method without SaveColor method even!
But the part that is taking to much time the below code, Which I compare pixels for calculating the weights. This part is making the problem and I was wondering that if I could do it in a faster way.
Code: Pascal  [Select][+][-]
  1. //Gain weight of each pixel color in color map
  2.     PPixel := SourceBmp.Data;
  3.     SetLength(WeightMap, SourceColorCount);
  4.     for i := 0 to Length(WeightMap) - 1 do
  5.     begin
  6.       WeightMap[i] := 0;
  7.     end;
  8.     for i := 0 to Pred(SourceBmp.NbPixels) do
  9.     begin
  10.       Pixel := PPixel^;
  11.       for j := 0 to Length(SavedColors) - 1 do
  12.       begin
  13.         if (SavedColors[j] = Pixel) then
  14.         begin
  15.           Inc(WeightMap[j]);
  16.         end;
  17.       end;
  18.       Inc(PPixel);
  19.     end;
  20.  

Michl

  • Full Member
  • ***
  • Posts: 226
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #9 on: August 25, 2016, 01:37:37 pm »
I've edited my post before. It must be min(), not (max). However.

But the part that is taking to much time the below code, Which I compare pixels for calculating the weights. This part is making the problem and I was wondering that if I could do it in a faster way.

Just don't use a Boolean, but a Integer for the Pixelarray and count it there:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.SourceColorsWithWeights;var
  2.   SourceBmp: TBGRABitmap;
  3.   i, Cnt, SourceColorCount: DWord;
  4.   sss: QWord;
  5.   PPixel: PBGRAPixel;
  6.   Pixel: TBGRAPixel;
  7.   DPixel: DWord absolute Pixel;
  8.   PixelMap: array of integer;
  9.   D2: DWord;
  10.   D2Pixel: TBGRAPixel absolute D2;
  11.   WeightMap: array of integer;
  12.   SavedColors: array of TBGRAPixel;
  13.  
  14. begin
  15.   SourceBmp := TBGRABitmap.Create('Pics' + PathDelim + 'Picture.jpg');
  16.   if SourceBmp.Bitmap.RawImage.Description.AlphaShift = 24 then
  17.   begin
  18.     sss := GetTickCount64;
  19.     SetLength(PixelMap, 1 shl 24); // 2^24=256*256*256 for all the colors in RGB
  20.     PPixel := SourceBmp.Data;
  21.     SourceColorCount := 0;
  22.     SetLength(SavedColors, min(1 shl 24, SourceBmp.NbPixels));
  23.     for i := 0 to Pred(SourceBmp.NbPixels) do
  24.     begin
  25.       Pixel := PPixel^;
  26.       if PixelMap[DPixel xor $FF000000] = 0 then
  27.       begin
  28.         SavedColors[SourceColorCount] := Pixel;
  29.         Inc(SourceColorCount);
  30.       end;
  31.       Inc(PixelMap[DPixel xor $FF000000]);
  32.       Inc(PPixel);
  33.     end;
  34.     SetLength(SavedColors, SourceColorCount);
  35.  
  36.     WriteLn('Source Color Count Time: ', GetTickCount64 - sss);
  37.  
  38.     //Gain weight of each pixel color in color map
  39.     PPixel := SourceBmp.Data;
  40.     SetLength(WeightMap, SourceColorCount);
  41.     Cnt := 0;
  42.     for i := 0 to High(PixelMap) do
  43.       if PixelMap[i] > 0 then
  44.       begin
  45.         WeightMap[Cnt] := PixelMap[i];
  46.         D2 := Cnt or $FF000000;
  47.         SavedColors[Cnt] := D2Pixel;
  48.         Inc(Cnt);
  49.       end;
  50.     WriteLn('Total Color Weights Time: ', GetTickCount64 - sss);
  51.  
  52.     for i := 0 to Length(WeightMap) - 1 do
  53.     begin
  54.       WriteLn('WeightMap [ ', i, ' ] : ', WeightMap[i]);
  55.     end;
  56.   end;
  57.   SourceBmp.Free;
  58. end;  
This, and also the methods before, are only faster for big images, cause the iteration through the Pixelmap need always its time.

Did you try circulars hints? He is the master of BGRABitmap. I'm a newbie there too, so I don't know all its posibilities.
« Last Edit: August 25, 2016, 01:48:10 pm by Michl »
Code: [Select]
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;

Sanem

  • Full Member
  • ***
  • Posts: 173
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #10 on: August 25, 2016, 02:02:37 pm »
Hi!

That's something I have been wondering about. You could try using TBGRAWeightedPalette of BGRAPalette unit and call IncColor for each pixel.

One remark about pixel format, SourceBmp.Bitmap.RawImage.Description.AlphaShift does not indicate the format of TBGRAPixel but of the TBitmap object. To know the alpha shift of TBGRAPixel you can use TBGRAPixel_AlphaShift constant.

Regards

I have tested what you said, yep the IncColor method from TBGRAWeightedPalette class, does the weight calculating for each pixel of source colors, but as the first problem of mine with TBGRAColorQuantizer, it takes too much time, even without gaining the values for display or sth! (3200ms for a bitmap 1920*1080). Any idea to gain this faster??

Any help appreciated prior
Regards


here is my test code:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.SourceColorsWithWeightsUsingIncColor;
  2. var
  3.   sss: QWord;
  4.   i: integer;
  5.   WeightedColors: TBGRAWeightedPalette;
  6.   PPixel: PBGRAPixel;
  7.   Pixel: TBGRAPixel;
  8.   NewWeight: UInt32;
  9. begin
  10.   sss := GetTickCount64;
  11.   WeightedColors := TBGRAWeightedPalette.Create;
  12.   WeightedColors.AddColors(SourceBmp);
  13.   PPixel := SourceBmp.Data;
  14.   for i := 0 to Pred(SourceBmp.NbPixels) do
  15.   begin
  16.     Pixel := PPixel^;
  17.     WeightedColors.IncColor(Pixel, NewWeight);
  18.     Inc(PPixel);
  19.   end;
  20.   WriteLn('Total Color Weights Time: ', GetTickCount64 - sss);
  21. end;
  22.  

Sanem

  • Full Member
  • ***
  • Posts: 173
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #11 on: August 25, 2016, 02:12:23 pm »
Thank you Michl, the way you said uses 100ms, and it is good for now, yep I am reading the whole unit and classes related in BGRA to discover the best way for what I want, and tested what Circular said and posted the result for him in here:
http://forum.lazarus.freepascal.org/index.php/topic,33789.msg219872.html#msg219872
Still my problem is the slowly functionality of these classes in TBGRAColorQuantizer.

Regards

Michl

  • Full Member
  • ***
  • Posts: 226
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #12 on: August 25, 2016, 02:51:57 pm »
One remark about pixel format, SourceBmp.Bitmap.RawImage.Description.AlphaShift does not indicate the format of TBGRAPixel but of the TBitmap object. To know the alpha shift of TBGRAPixel you can use TBGRAPixel_AlphaShift constant
Ah, this mean, its the same, if I load a 1, 8, 16, 24, 32 or somehow, bit image, TBGRABitmaps alphashift is always TBGRAPixel_AlphaShift = 24.
In a iteration of a PBGRAPixel from 0 (first position aBGRABitmap.Data) to aBGRABitmap.NbPixels, the PBGRAPixel^ is always a 4Byte TBGRAPixel with a AlphaShift = 24.
I didn't know this, so this check can be removed.
Code: [Select]
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;

circular

  • Hero Member
  • *****
  • Posts: 4220
    • Personal webpage
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #13 on: August 25, 2016, 07:25:44 pm »
I have tested what you said, yep the IncColor method from TBGRAWeightedPalette class, does the weight calculating for each pixel of source colors, but as the first problem of mine with TBGRAColorQuantizer, it takes too much time, even without gaining the values for display or sth! (3200ms for a bitmap 1920*1080).
Yes you can access the colors using the Count, Color[...] and Weight[...] properties.

I agree it is slow though.
Conscience is the debugger of the mind

Michl

  • Full Member
  • ***
  • Posts: 226
Re: How to Optimeze use of BGRAColorQuantizer??
« Reply #14 on: August 25, 2016, 09:18:13 pm »
@simin_sh: I've seen in your last example the SavedColors aren't sorted. If you needn't the colors in a sorted order, we can speed up the method a little bit. And with the comment from circular, we can use a ^DWord for the iteration (IMHO it is now better readable):
Code: Pascal  [Select][+][-]
  1. procedure TForm1.SourceColorsWithWeightsUsingIncColor;
  2. var
  3.   i, SourceColorCount: DWord;
  4.   sss: QWord;
  5.   aPDWord: PDWord;
  6.   aPixel: PBGRAPixel;
  7.   PixelMap: array of integer;
  8.   WeightMap: array of integer;
  9.   SavedColors: array of TBGRAPixel;
  10.  
  11. begin
  12.   sss := GetTickCount64;
  13.   SetLength(SavedColors, min(1 shl 24, SourceBmp.NbPixels) + 1);
  14.   SetLength(WeightMap, min(1 shl 24, SourceBmp.NbPixels) + 1);
  15.   SetLength(PixelMap, 1 shl 24); // 2^24=256*256*256 for all the colors in RGB
  16.   SourceColorCount := 1;         // start with 1, so SavedColor first filled position is SavedColor[1]
  17.   aPDWord := PDWord(SourceBmp.Data);
  18.   for i := 0 to Pred(SourceBmp.NbPixels) do
  19.   begin
  20.     if PixelMap[aPDWord^ xor $FF000000] = 0 then begin
  21.       PixelMap[aPDWord^ xor $FF000000] := SourceColorCount;  // saves the position, where the color is saved
  22.       aPixel := PBGRAPixel(aPDWord);
  23.       SavedColors[SourceColorCount] := aPixel^;
  24.       WeightMap[SourceColorCount] := 1;
  25.       Inc(SourceColorCount);
  26.     end else
  27.       Inc(WeightMap[PixelMap[aPDWord^ xor $FF000000]]);
  28.     Inc(aPDWord);
  29.   end;
  30.   Dec(SourceColorCount);
  31.   SavedColors[0] := SavedColors[SourceColorCount];  // fill the first position
  32.   WeightMap[0] := WeightMap[SourceColorCount];
  33.   SetLength(WeightMap, SourceColorCount);
  34.   SetLength(SavedColors, SourceColorCount);
  35.   WriteLn('Source Color Count Time: ', GetTickCount64 - sss);
  36. end;
Code: [Select]
type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;

 

TinyPortal © 2005-2018