Recent

Author Topic: Color range  (Read 2161 times)

user5

  • Full Member
  • ***
  • Posts: 232
Color range
« on: January 31, 2019, 03:19:50 pm »
    Greetings. It's been a while. I have a question about color. Let's say that I have a sample of some various colors and after conversion from TColor hex numbers that sample ranges from color numbers 592895 to 1575423. I also have a single color sample of a green color that I want to exclude from the previous range and it's number is 917259. In this case I would simply raise 592895 to 917260 so that the green color is excluded from the new range of 917260 - 1575423. I want to exclude the green color from the original sample range but I have no way of knowing beforehand the number of the green color. This is hard to put into words but is there some way of knowing the point in the original range in which any green color first appears? If I knew that then I could just set the low range number to just above that point to exclude all green colors.

wp

  • Hero Member
  • *****
  • Posts: 6365
Re: Color range
« Reply #1 on: January 31, 2019, 03:55:21 pm »
How large is your sample of colors? Only if every integer between 592895 and 1575423 is contained in your sample, i.e. your sample size is 982529, then your method works.

In all other cases you must store each color of the sample in an array, iterate through the array and check whether the number 917259 is among the array elements. If you found it move the subsequent elements down by one element and shorten the array length by 1 (or use a TIntegerList, in which you simply can call "Delete" to remove the found item).

But maybe I don't understand your question.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

lucamar

  • Hero Member
  • *****
  • Posts: 2085
Re: Color range
« Reply #2 on: January 31, 2019, 04:56:45 pm »
This is hard to put into words but is there some way of knowing the point in the original range in which any green color first appears? If I knew that then I could just set the low range number to just above that point to exclude all green colors.

To know whether a color is "green" you'll have to reconvert each integer to TColor and test whether the green component dominates the other two by some margin (for example 1%). Testing the integers by themselves doesn't give you that: you would be discarding p.e. $0000FF, which is pure blue.

I think you're not explaining clearly what you want to do.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Color range
« Reply #3 on: January 31, 2019, 05:40:00 pm »
Check the hue element of the color using ColorToHSL from GraphUtil unit.  Every color has a range of hue values.

Edit:
Corrected unit name.
« Last Edit: January 31, 2019, 05:44:10 pm by engkin »

user5

  • Full Member
  • ***
  • Posts: 232
Re: Color range
« Reply #4 on: January 31, 2019, 07:43:43 pm »
    I have a picture with blue and green colors with each color being composed of different tones. I want the program to turn all of the blue tones into the solid color yellow while leaving the green tones alone. The reason that a solid color is desired is so that it can be made transparent. The user moves a paintbox over the blue color for example, then the program puts all the colors under the paintbox into an array.
    The program gets the color for every pixel (var1) in the picture and then decides whether or not to change it to yellow of some other color. I've been trying two methods.

    The first method shown below is similar to what you suggested. It checks to see if each pixel is in the array. If it is then it is changed to yellow. Otherwise it's left alone. It's accurate because it leaves the green pixels alone but it's very slow because it must go through the entire array for every pixel even if the array is sorted to remove redundant numbers and I also found out that I had to take many samples with each sample being a repeat of the whole process. The problem is compounded by the fact that the program also works with videos and in such cases will have to alter all of the frames of each video.
   
    The second method is very much faster and it works for some pictures but not the picture that I'm talking about. This method gets the lowest and highest numbers in the array (lowvar and highvar respectively) and if the pixel number var1 is between them it gets changed to yellow. The variable lowvar = 592895 and highvar = 1575423.  Unfortunately the number for the green color (var1) is 917259 so it gets erroneously changed to yellow because that number is between lowvar and highvar. This can only mean that the color numbers for blue aren't necessarily in sequence as I hoped they would be!

    The green color 917259 is definitely not in the array and that's why method 1 works.
    In the color chart for predefined color constants the decimal number for clBlue is 16711680 but I don't know the numbers for all of its tones or where they begin and end. The same goes for lime green.

Code: Text  [Select]
  1. tempstr := ColorToHex(image5.canvas.Pixels[pointx,pointy]);
  2. var1 := Hex2Dec(tempstr);
  3. for newcount := 1 to colorcounter do
  4.   begin
  5.     tempstr := coloritem[newcount];
  6.     var2 := Hex2Dec(tempstr);
  7.     if var1 = var2 then
  8.     image5.canvas.Pixels[pointx,pointy] := colordialog1.Color;
  9.   end;
  10.  
  11. //2nd method - lowvar is the lowest number in the array and highvar is the highest number in the array
  12. tempstr := ColorToHex(image5.canvas.Pixels[pointx,pointy]);
  13. var1 := Hex2Dec(tempstr);
  14. if (var1 >= lowvar) and (var1 <= highvar) then
  15.   image5.canvas.Pixels[pointx,pointy] := colordialog1.Color;
  16. ]

    Thanks again for your help. I would be glad to hear any ideas about how to proceed.




lucamar

  • Hero Member
  • *****
  • Posts: 2085
Re: Color range
« Reply #5 on: January 31, 2019, 08:59:18 pm »
I think engkin's idea is the best for you: convert each pixel color to HSL, check whether it's a shade of green and change it if not.

The operation should take no more time than building the array of integers and then checking it wastes.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Color range
« Reply #6 on: January 31, 2019, 09:25:13 pm »
Your code is unnecessarily using strings to represent colors in hex. The conversion between to/from string is expensive for your application.

Edit:
In the first method, you should sort the list of colors and use binary search to check if the color of a pixel is one of them. That should increase the speed as well.
« Last Edit: January 31, 2019, 09:53:00 pm by engkin »

user5

  • Full Member
  • ***
  • Posts: 232
Re: Color range
« Reply #7 on: February 01, 2019, 06:31:58 am »
    I've never used some of this stuff before so please be patient with me. From the scarce documentation on this subject I got the code below. The result I got for Hue was the number 85 but I don't know what to do with it. Can you tell me how to find out if the arbitrary color choice newcolor has green in it?

    If I'm doing this wrong then could you give me a simple example of what to do without using colordialog? The program itself has to be able to tell whether or not newcolor has green in it.

    Does anyone know where I can find the full range of numbers/values for the various colors?

Code: Text  [Select]
  1.  



user5

  • Full Member
  • ***
  • Posts: 232
Re: Color range
« Reply #8 on: February 01, 2019, 06:37:42 am »
    The code example didn't show in my previous message so here it is;

procedure TForm1.Button1Click(Sender: TObject);
var H, S, L: Word;
       tempstr:string;
       newcolor:TColor;
begin
  newcolor := clLime;
  ColorRGBToHLS(newcolor, H, L, S);
  tempstr:= IntToStr(H);
  edit1.text := tempstr;
end;

user5

  • Full Member
  • ***
  • Posts: 232
Re: Color range
« Reply #9 on: February 01, 2019, 06:59:05 am »
    I think that I solved the program on my own. The simple code below gives the answer "R0 G0 B255" which I believe tells me that newcolor contains no green. This is what I was looking for.

newcolor := clBlue;
tempstr := Format('R%d G%d B%d', [Red(newcolor), Green(newcolor), Blue(newcolor)]);
edit1.text := tempstr;

Thanks.

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Color range
« Reply #10 on: February 02, 2019, 04:54:39 am »
The chosen color in the attached image has 206 for the green element. It is not green according to its hue value.

You know what you need better than us. We can only clarify what we think.