find nearest colour in list (nearest RGB/BGR value)

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

find nearest colour in list (nearest RGB/BGR value)

17 Jul 2017, 15:31

I've created a script to find, for a given RGB (or BGR) value, the closest colour (color) in a list.
- I'd be interested as to whether there are any other common algorithms for this, that use different approaches, or perhaps any Gdip methods that 'simplify' colours/images by replacing colours with nearby colours.
- Also, I'd be interested if anybody uses something like this regularly, or might find this script or a similar script useful. Thanks.

Code: Select all

q:: ;find nearest colour (sum of R/G/B differences, or, sum of squares of R/G/B differences)
;colour list from:
;Progress/SplashImage
;https://autohotkey.com/docs/commands/Progress.htm

vListRGB := "Black=000000,Silver=C0C0C0,Gray=808080,White=FFFFFF,Maroon=800000,Red=FF0000,Purple=800080,Fuchsia=FF00FF,Green=008000,Lime=00FF00,Olive=808000,Yellow=FFFF00,Navy=000080,Blue=0000FF,Teal=008080,Aqua=00FFFF"
oArray := Object(StrSplit(vListRGB, ["=",","])*)
vPfx := !!SubStr(1,0) ? "O)" : "" ;two-way compatibility
for vKey, vValue in oArray
{
	RegExMatch(vValue, vPfx "(..)(..)(..)", oMatch1)
	vList := ""
	for vKey2, vValue2 in oArray
	{
		if (vValue = vValue2)
			continue
		RegExMatch(vValue2, vPfx "(..)(..)(..)", oMatch2)
		vDiff := 0
		Loop, 3
			vDiff += Abs(Format("{:i}", "0x" oMatch1[A_Index])-Format("{:i}", "0x" oMatch2[A_Index])) ;raw difference
			;vDiff += (Format("{:i}", "0x" oMatch1[A_Index])-Format("{:i}", "0x" oMatch2[A_Index]))**2 ;difference squared
		;vDiff := Round(Sqrt(vDiff)) ;difference squared
		if (vList = "") || (vDiff < vMin)
			vMin := vDiff, vList := vDiff "|" vKey2 " " vValue2
		else if (vDiff = vMin)
			vList .= "," vKey2 " " vValue2
	}
	vOutput .= vKey " " vValue "|" vList "`r`n"
}
Clipboard := vOutput
MsgBox, % "done"
return

;==================================================

;RESULTS:

;find nearest colour (sum of R/G/B differences)
Aqua 00FFFF|254|Teal 008080
Black 000000|128|Green 008000,Maroon 800000,Navy 000080
Blue 0000FF|127|Navy 000080
Fuchsia FF00FF|254|Purple 800080
Gray 808080|128|Olive 808000,Purple 800080,Teal 008080
Green 008000|127|Lime 00FF00
Lime 00FF00|127|Green 008000
Maroon 800000|127|Red FF0000
Navy 000080|127|Blue 0000FF
Olive 808000|128|Gray 808080,Green 008000,Maroon 800000
Purple 800080|128|Gray 808080,Maroon 800000,Navy 000080
Red FF0000|127|Maroon 800000
Silver C0C0C0|189|White FFFFFF
Teal 008080|128|Gray 808080,Green 008000,Navy 000080
White FFFFFF|189|Silver C0C0C0
Yellow FFFF00|254|Olive 808000

==================================================

;find nearest colour (sum of squares of R/G/B differences)
Aqua 00FFFF|32258|Teal 008080
Black 000000|16384|Green 008000,Maroon 800000,Navy 000080
Blue 0000FF|16129|Navy 000080
Fuchsia FF00FF|32258|Purple 800080
Gray 808080|12288|Silver C0C0C0
Green 008000|16129|Lime 00FF00
Lime 00FF00|16129|Green 008000
Maroon 800000|16129|Red FF0000
Navy 000080|16129|Blue 0000FF
Olive 808000|16384|Gray 808080,Green 008000,Maroon 800000
Purple 800080|16384|Gray 808080,Maroon 800000,Navy 000080
Red FF0000|16129|Maroon 800000
Silver C0C0C0|11907|White FFFFFF
Teal 008080|16384|Gray 808080,Green 008000,Navy 000080
White FFFFFF|11907|Silver C0C0C0
Yellow FFFF00|32258|Olive 808000

;==================================================

;find nearest colour (square root of: sum of squares of R/G/B differences)
Aqua 00FFFF|180|Teal 008080
Black 000000|128|Green 008000,Maroon 800000,Navy 000080
Blue 0000FF|127|Navy 000080
Fuchsia FF00FF|180|Purple 800080
Gray 808080|111|Silver C0C0C0
Green 008000|127|Lime 00FF00
Lime 00FF00|127|Green 008000
Maroon 800000|127|Red FF0000
Navy 000080|127|Blue 0000FF
Olive 808000|128|Gray 808080,Green 008000,Maroon 800000
Purple 800080|128|Gray 808080,Maroon 800000,Navy 000080
Red FF0000|127|Maroon 800000
Silver C0C0C0|109|White FFFFFF
Teal 008080|128|Gray 808080,Green 008000,Navy 000080
White FFFFFF|109|Silver C0C0C0
Yellow FFFF00|180|Olive 808000

;==================================================
[EDIT:] Some ideas for 'simplifying' or 'rounding' colours in pixels other than the repeated use of Gdip_GetPixel and Gdip_SetPixel:
Gdip: image binary data to hex string for OCR - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=35339
GDI_GrayscaleBitmap() - Converts GDI bitmap to Greyscale - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/8279 ... greyscale/
Last edited by jeeswg on 10 Aug 2017, 19:42, edited 2 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
scriptor2016
Posts: 860
Joined: 21 Dec 2015, 02:34

Re: find nearest colour in list (nearest RGB/BGR value)

17 Jul 2017, 23:46

I'm always super-interested in any sort of script which has anything to do with color identification, color matching, etc. I tried running your script but nothing was happening - it just showed a message box saying "Done" - am I doing something wrong?

I've been trying to come up with a script that will:

search a defined area on the screen, then identify the color within that area, and then search a different area on the screen and try to find the nearest color match in that area. So for example:

Step 1: x200 y200 (for example) will be a certain color on the screen - the color will always be changing, but at any given time it will be a solid color. The script will get that color upon pressing a hotkey.

Step 2: Next, it will search a different area on the screen, which will have many colors. (This particular area will be a "swatches" panel in Photoshop). So, it will now search the swatches panel and will click on the nearest color match to the first color that was found in step 1. The color will never be the exact same, but it should find the nearest match in terms of R, G and B.

I have some rough work that I tried out in the past, and will have to dig it up.

Is this something that your script is close to doing?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: find nearest colour in list (nearest RGB/BGR value)

18 Jul 2017, 00:16

Btw the script puts information onto the clipboard.

A possible solution (although possibly slow), is to use the Gdip_All library. Use the Gdip_BitmapFromScreen function to store the image in memory, and use Gdip_GetPixel to get the ARGB values for each pixel, you may need to use vNum & 0xFFFFFF, to discard the 'A' transparency byte, and the Format function, to get the RGB value in the right form (hex with no 0x prefix) for use with my code above. You would then modify my code a bit.

There may be other methods, especially faster methods, maybe Gdip_ImageSearch could do this, or some other existent function, maybe a function could be written in C++, and then converted for use as a machine code function.

MCode Tutorial (Compiled Code in AHK) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=32

[EDIT:] An interesting link, with details on how the PixelSearch command relaxes the RGB threshold (the 'Variation' parameter).
Script to determine how close colors are together - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=20521
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Descolada and 319 guests