clNone etc. lazarus / 39-Graphics ---------------------------------------------------------------------- user5 · 2021-06-08 07:05 The code I'm working on at some point asks the user to choose a 'work' color that does not exist anywhere in the image.     This color is used for various operations and is eventually removed. After a color is chosen it's of course easy for the program to find out if it's in the image or not but does anyone know of a way for the program to quickly pick a work color that does not exist in the image without prompting the user or is there a way to create a color that does not exist on the palatte?     I'm already using clNone for a particular purpose so I can't use it as the work color. ---------------------------------------------------------------------- circular · 2021-06-10 11:55 The color needs to be an actual color I suppose? If that's the case, what you could do is create a list of all colors in the image, sort them, and then find the first gap in the palette. Though maybe there would be another way than having such work color. What are you actually doing with it? ---------------------------------------------------------------------- user5 · 2021-06-11 06:59 It's hard to explain but I'll try since you took the time to respond.     The attached raster scan picture img1.gif shows a picture (a clRed ball) before before edge softening is applied to it. The background under the image is clWhite and the image will be edged to clWhite. The user picks clYellow as the work color and img2.gif shows the image after some preliminary edging other than gradients has been applied to it. You would have to look closely to notice that some of the pixels are slightly lighter than clRed. The use of clYellow or any other color as a work color is not new and has been used before in theory and practice. The picture img3.gif shows the image after the edging is done and img4.gif shows the image after it is made to be transparent.     You mentioned making a list and I guess that you might have referred to TList or something like that. Such a list could become quite large if the image has many colors and I still haven't figured out how to find a color that is not in the image. After a list is made of all the colors in the image (in this case just clRed and clAqua) then how would the program find a color that is not in the image like clBlue, clYellow etc? ---------------------------------------------------------------------- user5 · 2021-06-11 07:02 I noticed that the pictures I attached don't look right until you left click and enlarge them a bit. ---------------------------------------------------------------------- user5 · 2021-06-11 07:13 I want to mention that the program I'm working on does have a tool that searches for a chosen color and informs the user if that particular color exists or not in the image and this is some help but it would be so much better if the program could automatically choose a work color instead of requiring the user to choose it. ---------------------------------------------------------------------- Thaddy · 2021-06-11 09:17 I think the sort is an idea, BUT: A color that initially is not used can logically be introduced by any sharpen or soften algorithm and then you have a problem, Houston.... (Ofcourse TRUE sharpen does not have that issue, but the terms are used rather liberaly) ---------------------------------------------------------------------- user5 · 2021-06-11 11:52 Until I read what Thaddy said I was going to use the pseudocode shown below. He makes a very good point and it is something that I haven't considered. If I understand him correctly then what he's saying is: When the gradients and the other edging colors are made then the program is in effect adding some new edging colors to the image being edged. If any of these new colors = the work color then the results will not be exactly correct.     Maybe the program needs to focus on what colors are UNDER the image instead of the colors in the image (or both) since the matchup between the two are what determine the edging colors. I will have to think about this for a while. Thank you very much Thaddy and circular for your comments. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  //Make a list of all the colors in the image. //Sort list so that no color is shown more than once in the list  colordecnum := 0; //start with clBlack go := true; cancel := false; header := '$'; while (go) and (cancel = false) and (colordecnum <= 16777216) do //16777216 colors in palatte  begin   found := false;   tempstr := IntToHex(colordecnum,6);   tempstr := header+tempstr;   newcolor := StringToColor(tempstr);    //search the list for newcolor   //if newcolor is in the list then    found := true;    if found = false then //if after search found remains false then work color is found  begin     go := false;     workcolor := newcolor;    end;    colordecnum := colordecnum + 1; //test the next color in the palatte if found = true  end;  if go = true then  edit5.text := 'Cannot find a work color.'; ---------------------------------------------------------------------- Thaddy · 2021-06-11 12:02 You understood me correctly. ---------------------------------------------------------------------- Thaddy · 2021-06-11 12:32 Oh, I just came up with this: Look for the greatest span of unused colors after the sort and choose something in the middle. That makes a clash highly - but not always - unlikely. Indeed if there is a picture under yours, it is better to look for one in that.. In both cases you will loose just one pixel precision which is likely not visible to the human eye. ---------------------------------------------------------------------- user5 · 2021-06-11 12:37 The program generally does a pretty good job the way it is since the odds of conflict between a work color and a newly created edging color that equals the work color are low but it can happen.     What Thaddy said illustrates why clNone makes such a good work color since it should never exist in any of the images involved. Unfortunately, the program already uses clNone as a work color but it also needs a second work color and in some cases a third work color. If only there were clNone1, clNone2 and clNone3 then I would be in business, hah, hah.     I tried to create some non-existent work colors but the compiler wouldn't accept them I guess because they weren't actual colors on the palatte.     I'm sure glad Thaddy that you said what you said before and what you just said. Wow.     Maybe I can work something out. ---------------------------------------------------------------------- wp · 2021-06-11 13:59 Quote from: user5 on June 11, 2021, 02:37:38 pm If only there were clNone1, clNone2 and clNone3 then I would be in business, hah, hah. Why not? I suppose you work in 24-bit Pixelformat - this means that the 4th byte is unused. Looking in the graphics unit you'll see this for clNone: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i const clNone    = TColor($1FFFFFFF); This is a color with $1F in the unused 4th byte. There are some other predefined colors with something in the 4th byte: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i const  clScrollBar               = TColor(SYS_COLOR_BASE or COLOR_SCROLLBAR);   clBackground              = TColor(SYS_COLOR_BASE or COLOR_BACKGROUND);  clActiveCaption           = TColor(SYS_COLOR_BASE or COLOR_ACTIVECAPTION);  clInactiveCaption         = TColor(SYS_COLOR_BASE or COLOR_INACTIVECAPTION);  clMenu                  = TColor(SYS_COLOR_BASE or COLOR_MENU);  clWindow                = TColor(SYS_COLOR_BASE or COLOR_WINDOW);  clWindowFrame             = TColor(SYS_COLOR_BASE or COLOR_WINDOWFRAME); ... where SYS_COLOR and COLOR_* are defined in LCLTYPE to be Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i const  SYS_COLOR_BASE = TColorRef($80000000);  COLOR_SCROLLBAR = 0;  COLOR_BACKGROUND = 1;  COLOR_ACTIVECAPTION = 2;  COLOR_INACTIVECAPTION = 3;  COLOR_MENU = 4;  COLOR_WINDOW = 5;  COLOR_WINDOWFRAME = 6;...This means: They all have the normal r,g,b bytes but since there is a non-zero 4th byte they do not appear in the normal color space. So, this is my idea: Take clNone and subtract 1 to get a clNone1, subtract 2 to get a clNone2 etc. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i const  clNone1 = clNone - 1;  // $1FFFFFFE  clNone2 = clNone - 2;  // $1FFFFFFD  clNone3 = clNone - 3;  // $1FFFFFFC  clNone4 = clNone - 4;  // $1FFFFFFB  ...There 16777215=$FFFFFF ways to construct a clNone variant according to this pattern. Or even more if you relax the requirement that the 4th byte must be $1F. It only cannot be $00 (this is reserved for a normal RGB color) or $80 (this is reserved for a system color - see above). Nothing prevents you to define a Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i const  cMyOwnNoColor = $99012345; ---------------------------------------------------------------------- circular · 2021-06-11 19:22 Indeed as wp says, if you have your own storage on 4 bytes, then you can put any special value as a color. Otherwise, maybe the simplest would be to create mask: a 2d array of booleans that says if a pixel is on the edge. Thus you would have the information instead of painting an arbitrary color. ---------------------------------------------------------------------- user5 · 2021-06-11 19:45 I tested your suggestions wp and got some interesting results.     When I set the TColor variable nocolor1 to your suggestion of $1FFFFFFE then the program searched through all 16777215 (ie 0 to 16777214) palatte colors without finding a match, which is good because it means that nocolor1 does not exist on the palatte and I can use it as a workcolor. However, when I applied that color to image13 and then took a color sampling of image13 the program showed the result as $00FFFFFE, not $1FFFFFFE.     When I set nocolor1 to $00FFFFFE and applied it to image13 then a color sampling showed $00FFFFFE but a search of the palatte colors was only successful if the search was limited to 16777214 colors, not 16777215 colors.     The code I used is shown below.     I must be missing something here or this situation is simply due to a formatting issue or something like that.     The results are encouraging. Should I use $1FFFFFFE or $00FFFFFE?     Thank you so much. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  nocolor1 := StringToColor('$1FFFFFFE'); go := true; cancel := false; header := '$'; found := false; counter := 0;  while (go = true) and (cancel = false) do  begin    if counter <= 16777214 then    begin     tempstr := IntToHex(counter,6);     tempstr := header+tempstr;     newcolor := StringToColor(tempstr);    end   else    go := false;    if go then   if (newcolor = nocolor1) then    begin     go := false;     found := true;    end;    if (go = true) and (counter >= 100000) and ((counter mod 100000) = 0) then    begin     str(counter,tempstr);     edit4.text := tempstr;     application.processmessages;    end;    if counter = 16777214 then    go := false   else    counter := counter + 1;   end;  str(counter,tempstr); edit4.text := tempstr; application.processmessages;  if found = true then  edit5.text := 'nocolor1 exists on palatte.' else  edit5.text :='nocolor1 does not exist on palatte'; ---------------------------------------------------------------------- wp · 2021-06-11 19:55 I think you are right. When you use the clNone1 to paint something on the canvas with it, the 4th byte will be stripped off because the pixelformat is 24bit. And then $1FFFFFFE will be the same as the "real" color $00FFFFFE. Forget this idea... ---------------------------------------------------------------------- user5 · 2021-06-11 20:36 The way things stand now, I do have a fallback compromise solution. It the picture or video doesn't have many colors then the user should have no problem in choosing a work color. If the image has many colors and the user is in doubt then he or she can have the program come up with the work color by searching the image.     However, I will then still have the problem that Thaddy mentioned to deal with.     In any event, thanks for helping me. I'll check back here later in case someone has additional suggestions. ---------------------------------------------------------------------- user5 · 2021-06-11 23:43 Just for the record, I think that I have a simple solution for the problem that Thaddy mentioned in which the program might lay in a pixel edging color that is undesirably the same as the work color.     Solution: Just before any pixel color is laid in, that color will be sent to a procedure that will check to see if that color equals a work color. If if does then that procedure will change the rgb values by one or two digits.     That way, the color will no longer equal the work color and the new color will be so close to the original color that the difference will be imperceptible. Thanks again. ---------------------------------------------------------------------- user5 · 2021-06-12 15:33 I would like to give special thanks to Thaddy, who took the time to mention the possible problem of laying in a pixel color that = the work color. That was very sharp and it never occurred to me even though it should have. I probably never would have thought of it if he hadn't mentioned it.     I also thank the other coders who took the initiative to try and help me. This forum has been so helpful and you folks deserve appreciation.     I have coded with Standard, Turbo and Free Pascal. I'm not the best coder but I'm pretty good and I tell you what, I wish there had been a Lazarus school when I first started using Free Pascal. Maybe there was such a school and I just didn't know it. I learned some things later that I should have learned earlier and in some cases resulted in lesser program performance.     All praise to Lazarus and the Forum. ---------------------------------------------------------------------- circular · 2021-06-12 15:49 You're welcome @user5 ---------------------------------------------------------------------- Thaddy · 2021-06-12 16:44 Actually, Marcov is the expert in image programming.