• Welcome to Vampyre Imaging Library Forum. Please login or sign up.
 

Having problems with FindColor()

Started by binfch, 22 October 2011, 20:28:59

Previous topic - Next topic

binfch

22 October 2011, 20:28:59 Last Edit: 1 November 2011, 00:12:54 by Galfar
Hi there

I have a small test procedure to count how many times a color does occure within an image -> However it does not work, I think the issue is around FindColor() that I don't use correctly. Any idea where the mistake is?

Code (pascal) Select
procedure TForm1.Button1Click(Sender: TObject);
var
  NumberOfColors: Integer;
  ImageData: TImageData;
  ImagingBitmap: TImagingBitmap;
  Counter: Integer;
  Palette: PPalette32;
  ColorRecord: TColor32Rec;
  ColorArray: Array of Integer;
  Row, Col: Integer;
begin
  NumberOfColors := 16;
  SetLength(ColorArray, NumberOfColors);

  ImagingBitmap := TImagingBitmap.Create;
  InitImage(ImageData);

  for Counter := 0 to NumberOfColors -1 do
    ColorArray[Counter] := 0;

  try
    LoadImageFromFile('car1.png', ImageData);
    ReduceColors(ImageData, NumberOfColors);
    Palette := @ImageData.Palette;

    //List all the colors
    for Counter := 0 to NumberOfColors -1 do
      Memo1.Lines.Add( IntToStr(Counter) + ':(' + IntToStr(Palette[Counter].R) + ',' +
                                                  IntToStr(Palette[Counter].G) + ',' +
                                                  IntToStr(Palette[Counter].B) + ')' );

    //Count how many times a color is used
    for Row := 0 to ImageData.Height -1 do begin
      for Col := 0 to ImageData.Width -1 do begin
        ColorRecord := GetPixel32(ImageData, Col, Row);
        Counter := FindColor(Palette, NumberOfColors, ColorRecord.Color);
        Inc(ColorArray[Counter]);
      end;
    end;

    //List the counting result
    for Counter := 0 to NumberOfColors -1 do
      Memo2.Lines.Add( IntToStr(Counter) + ':' + IntToStr(ColorArray[Counter]) );

    //Draw the image on the canvas
    ImagingBitmap.AssignFromImageData(ImageData);
    Form1.Canvas.Draw(0, 0, ImagingBitmap);
  finally
    FreeImage(ImageData);
    ImagingBitmap.Free;
  end;
end;


Thanks in advance,
P.

Galfar

Hi, sorry for late answer.

There are two problems with your code:

1) Your setting Palette variable to point to the address of ImageData.Palette field, not to the actual
palette info. Correct way is this:
Code (pascal) Select
//Palette := @ImageData.Palette;  wrong
Palette := ImageData.Palette; // ok
Palette := @ImageData.Palette[0]; // also ok, if ImageData.Palette <> nil


2) When you fix the palette pointer problem you'll notice you get 'Access violation' exception now. That's because
ImageData.Palette = nil. ReduceColors keeps the image in its original data format and doesn't convert it to indexed (that's because ReduceColors supports color counts up to 4096 for which there is no indexed format).
In short, you need to convert to indexed format explicitly by adding ConvertImage call after ReduceColors:
Code (pascal) Select
ReduceColors(ImageData, NumberOfColors);
ConvertImage(ImageData, ifIndex8); // added
Palette := ImageData.Palette;


Now the colors are counted correctly.

binfch


Quick Reply

With Quick-Reply you can write a post when viewing a topic without loading a new page. You can still use bulletin board code and smileys as you would in a normal post.

Name:
Email:

Shortcuts: ALT+S save/post or ALT+P preview

SMF spam blocked by CleanTalk