AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Color Pot - Color Grabber and Mixer

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
ManaUser



Joined: 24 May 2007
Posts: 900

PostPosted: Thu Jun 28, 2007 9:23 pm    Post subject: Color Pot - Color Grabber and Mixer Reply with quote

I made this to to perform two related functions I've often wished my art program had. One is to sample the color of an area, rather than just one pixel and take the average. The other is to arbitrarily blend two or more colors together.

I'm fairly pleased with how it came out, though getting the result back into the art program is a little bit of a pain. You can either copy the hexadecimal color code, or a little square of the color itself, and you're on your own form there.

Here's a short description, as seen when clicking the help button:
Quote:
Color Pot can grab and mix colors found on the screen. Hold down the Windows Key to grab the color the mouse is pointing at. The color and its hex code will appear in the boxes labeled "Current". Clicking while holding down the Windows Key will add the color you're pointing at to the "Pot", the second two boxes. If there was already a color in the Pot, the colors will be combined. If you add multiple colors, they will be mixed in equal proportions. The number in ()s tells how many colors are in the Pot.

Left-clicking one of the hex labels or color boxes will copy the hex code or a small swatch of that color to the clipboard respectively.

Using the Sample Size dropdown you can have Color Pot draw color from a larger area instead of just one pixel. This might be useful when the sample is not a completely solid color.

You can also hold down these keys in addition to the Windows Key, with the following effects:
Shift - Replace the color in the Pot instead of adding to it.
Alt - Blend with the color in the Pot 1:1 even if it contains several samples.
Ctrl - Sample only one pixel, even if Sample Size is set larger.

Clicking the small square buttons will open the Windows color picker.

The Opt. button will open the options menu. Two options are available:

BGR Color Codes - Shows all colors in BGR format, instead of RGB.

Show Color Difference - Displays the difference between the Pot and the "Current" color. This includes both the difference in each primary color in signed hex and the greatest "variation" as used by the AHK Search commands, in decimal. For example if the Pot was 3310DB and Current was 2230AB it would display -1120-33 (48). Additionally the different between the Pot and the pixel under the cursor is displayed in a Tooltip when the Windows Key is held down. If the sample size is greater than Point this will display difference between the most different pixel, the most similar pixel and the average of all the pixels.

Code:
#NoEnv
#Persistent
#SingleInstance Force
#NoTrayIcon

SendMode Input
CoordMode Pixel, Screen
CoordMode Mouse, Screen
CoordMode ToolTip, Screen

SetTimer GetColor, 10

MixR := 0
MixG := 0
MixB := 0
MixNum := 0
Size := 1
CurColor = 0x000000
MixColor = 0x000000

OptShowDiff := 0
OptBGR := 0

Gui +ToolWindow +E0x40000 -Theme +AlwaysOnTop

Gui Add, Text, X4 Y0 H16 W64, Current
Gui Add, Text, X4 Y16 H24 W48 +0x200 +0x1000 Center vCurHexBox gCopyCurHex, 000000
Gui Add, ListView, X60 Y16 H24 W48 ReadOnly +0x4000 +Background000000 vCurColBox lv0x800000 0x4 -TabStop gCopyCurColor AltSubmit
Gui Add, Button, X112 Y20 H12 W12 -TabStop gCurColEdit,

Gui Add, Text, X44 Y40 H16 W80 BackgroundTrans Right vDiffLabel,

Gui Add, Text, X4 Y40 H16 W48 BackgroundTrans vMixedLabel, Pot (0)
Gui Add, Text, X4 Y56 H24 W48 +0x200 +0x1000 Center vMixHexBox gCopyMixHex, 000000
Gui Add, ListView, X60 Y56 H24 W48 ReadOnly +0x4000 +Background000000 vMixColBox lv0x800000 0x4 -TabStop gCopyMixColor AltSubmit
Gui Add, Button, X112 Y60 H12 W12 -TabStop gMixColEdit,

Gui Add, Text, X4 Y84 H16 W64, Sample Size:
Gui Add, DropDownList, X4 Y100 W56 vSize gSetSize Choose1, Point|3x3|5x5|7x7|9x9|11x11|13x13|15x15
Gui Add, Text, X64 Y100 H1 W1 0x4 vSampleSize

Gui Add, Button, X90 Y88 H16 W34 -TabStop gOptions, &Opt.
Gui Add, Button, X90 Y108 H16 W34 -TabStop gHelp, &Help

Gui Font, S9, Courier New
GuiControl Font, CurHexBox
GuiControl Font, MixHexBox
Gui Show, W128 H128, Color Pot

Menu Options, Add, Show Color Difference, MenuShowDiff
Menu Options, Add, BGR Color Codes, MenuBGR

;----------HotKeys---------
*#LButton::
If GetKeyState("Shift")
{
   MixR := 0
   MixG := 0
   MixB := 0
   MixNum := 0
}
Else If GetKeyState("Alt")
{
   MixR /= MixNum
   MixG /= MixNum
   MixB /= MixNum
   MixNum := 1
}
SetTimer GetColor, Off
GoSub GetColorNow
CurR := SubStr(CurColor, 1, 4)
CurG := "0x" . SubStr(CurColor, 5, 2)
CurB := "0x" . SubStr(CurColor, 7, 2)
MixR += CurR, MixG += CurG, MixB += CurB
MixNum += 1
SetFormat Integer, H
   MixColor := Round(MixR/MixNum) * 65536 + Round(MixG/MixNum) * 256 + Round(MixB/MixNum)
SetFormat Integer, D
TidyHex(MixColor)
GuiControl +Background%MixColor%, MixColBox
GuiControl, , MixHexBox, % FormatHex(MixColor)
GuiControl, , MixedLabel, Pot (%MixNum%)
SetTimer GetColor, On
Return

~LWin:: ;This prevents the Windows Key from opening the
~RWin:: ;start menu if you hold it down for at least a second.
Return

;-----------Gui Subs-----------

SetSize:
Gui Submit, NoHide
If (Size = "Point")
   Size := 1
Else
   StringTrimLeft Size, Size, InStr(Size, "x")
GuiControl Move, SampleSize, H%Size% W%Size%
Return

CopyCurHex:
ClipBoard := FormatHex(CurColor)
Return

CopyCurColor:
If (A_GuiEvent == "F")
{
   GuiControl Focus, Size
   CopySwatch(CurColor)
}
Return

CopyMixHex:
ClipBoard := FormatHex(MixColor)
Return

CopyMixColor:
If (A_GuiEvent == "F")
{
   GuiControl Focus, Size
   CopySwatch(MixColor)
}
Return

Help:
Gui -AlwaysOnTop
MsgBox, 0, Help,
(
Color Pot can grab and mix colors found on the screen. Hold down the Windows Key to grab the color the mouse is pointing at. The color and its hex code will appear in the boxes labeled "Current". Clicking while holding down the Windows Key will add the color you're pointing at to the "Pot", the second two boxes. If there was already a color in the Pot, the colors will be combined. If you add multiple colors, they will be mixed in equal proportions. The number in ()s tells how many colors are in the Pot.

Left-clicking one of the hex labels or color boxes will copy the hex code or a small swatch of that color to the clipboard respectively.

Using the Sample Size dropdown you can have Color Pot draw color from a larger area instead of just one pixel. This might be useful when the sample is not a completely solid color.

You can also hold down these keys in addition to the Windows Key, with the following effects:
Shift - Replace the color in the Pot instead of adding to it.
Alt - Blend with the color in the Pot  1:1 even if it contains several samples.
Ctrl - Sample only one pixel, even if Sample Size is set larger.

Clicking the small square buttons will open the Windows color picker.

The Opt. button will open the options menu. Two options are available:

BGR Color Codes - Shows all colors in BGR format, instead of RGB.

Show Color Difference - Displays the difference between the Pot  and the "Current" color. This includes both the difference in each primary color in signed hex and the greatest "variation" as used by the AHK Search commands, in decimal. For example if the Pot was 3310DB and Current was 2230AB it would display -1120-33 (48). Additionally the different between the Pot and the pixel under the cursor is displayed in a Tooltip when the Windows Key is held down. If the sample size is greater than Point this will display difference between the most different pixel, the most similar pixel and the average of all the pixels.
)
Gui +AlwaysOnTop
GuiControl Focus, Size
Return

CurColEdit:
NewColor := ChooseColor(CurColor, WinActive("A"))
If (NewColor != -1)
{
   CurColor := "0x" . NewColor
   GuiControl +Background%CurColor%, CurColBox
   GuiControl, , CurHexBox, % FormatHex(CurColor)
}
GuiControl Focus, Size
Return

MixColEdit:
NewColor := ChooseColor(MixColor, WinActive("A"))
If (NewColor != -1)
{
   MixColor := "0x" . NewColor
   GuiControl +Background%MixColor%, MixColBox
   GuiControl, , MixHexBox, % FormatHex(MixColor)
   MixNum := 1
   MixR := SubStr(MixColor, 1, 4)
   MixG := "0x" . SubStr(MixColor, 5, 2)
   MixB := "0x" . SubStr(MixColor, 7, 2)
   GuiControl, , MixedLabel, Pot (%MixNum%)
}
GuiControl Focus, Size
Return

Options:
Menu Options, Show
GuiControl Focus, Size
Return

;--menu--
MenuShowDiff:
OptShowDiff := !OptShowDiff
Menu Options, ToggleCheck, Show Color Difference
If OptShowDiff
   GuiControl, , DiffLabel, % GetDiff(FormatHex(MixColor), FormatHex(CurColor), 1)
else
   GuiControl, , DiffLabel,   
Return

MenuBGR:
OptBGR := !OptBGR
Menu Options, ToggleCheck, BGR Color Codes
Return
;--end menu--

GuiClose:
ExitApp

;-----------Other Subs and Functions-----------

GetColor:
If NOT (GetKeyState("LWin") OR GetKeyState("RWin"))
   Return
GetColorNow:
MouseGetPos X, Y
If (Size = 1 OR GetKeyState("Ctrl"))
{
   PixelGetColor CurColor, %X%, %Y%, RGB
   If OptShowDiff
      ShowToolTip(GetDiff(FormatHex(MixColor), FormatHex(CurColor)))
}
else
{
   X -= Floor(Size/2)
   Y -= Floor(Size/2)
   CurR := 0, CurG := 0, CurB := 0
   PixCount := 0
   If OptShowDiff
   {
      MinDiff := 256
      MaxDiff := -1
   }
   Loop % Size
   {
      Loop % Size
      {
         PixelGetColor PixColor, %X%, %Y%, RGB
         PixR := SubStr(PixColor, 1, 4)
         PixG := "0x" . SubStr(PixColor, 5, 2)
         PixB := "0x" . SubStr(PixColor, 7, 2)
         CurR += PixR, CurG += PixG, CurB += PixB
         PixCount += 1
         Y += 1
         If OptShowDiff
            GetMinMax(PixColor, MinDiff, MaxDiff)
      }
      X += 1
      Y -= Size
   }
   If OptShowDiff
      ShowToolTip("Min: " . MinLin . "`nMax: " . MaxLin . "`nAvg: " . GetDiff(FormatHex(MixColor), FormatHex(CurColor)))
   SetFormat Integer, H
   CurColor := Round(CurR/PixCount) * 65536 + Round(CurG/PixCount) * 256 + Round(CurB/PixCount)
   SetFormat Integer, D
}

TidyHex(CurColor)
GuiControl +Background%CurColor%, CurColBox
GuiControl, , CurHexBox, % FormatHex(CurColor)
If OptShowDiff
   GuiControl, , DiffLabel, % GetDiff(FormatHex(MixColor), FormatHex(CurColor), 1)
Return

TidyHex(ByRef MyHex)
{
   ;Makes uppercase and pads eith 0s
   StringTrimLeft MyHex, MyHex, 2
   MyHex := "00000" . MyHex
   StringRight MyHex, MyHex, 6
   StringUpper MyHex, MyHex
   MyHex := "0x" . MyHex
   Return
}

FormatHex(MyHex)
{
   Global OptBGR
   MyHex := SubStr(MyHex, 3)
   If OptBGR
      MyHex := RegExReplace(MyHex, "(..)(..)(..)", "$3$2$1")
   Return MyHex
}

CopySwatch(MyColor)
{
   Gui 2:-Caption +AlwaysOnTop
   Gui 2:Color, %MyColor%
   Gui 2:Show, H32 W32, Swatch
   WinWaitActive Swatch
   ClipBoard =
   Send !{PrintScreen}
   ClipWait, , 1
   Gui 2:Destroy
}

GetDiff(BaseColor, CompColor, GuiMode = 0, ByRef AbsDiff = 0)
{
   SetFormat Integer, H
   OutString =
   Loop 3
   {
      Foo := ("0x" . SubStr(CompColor, 1, 2))
      Bar := ("0x" . SubStr(BaseColor, 1, 2))
      ThisDiff := Foo - Bar
      OutString .= ThisDiff
      ThisDiff := Abs(ThisDiff)
      If (ThisDiff < 0x10)
         OutString := RegExReplace(OutString, "(.)$", "0$1") ;Add leading zero
      AbsDiff := ThisDiff > AbsDiff ? ThisDiff : AbsDiff
      BaseColor := SubStr(BaseColor, 3)
      CompColor := SubStr(CompColor, 3)
   }
   SetFormat Integer, D
   StringUpper OutString, OutString
   StringReplace OutString, OutString, 0x, , All
   AbsDiff += 0
   If GuiMode
      OutString .= " (" . AbsDiff . ")"
   Else
      OutString := "(" . AbsDiff . ") " . OutString
   Return OutString
}

ShowToolTip(TipText)
{
   ToolTip %TipText%
   SetTimer KillToolTip, -1000
}

KillToolTip:
ToolTip
Return

GetMinMax(OthColor, ByRef MinDif, ByRef MaxDif)
{
   Global MixColor, MinLin, MaxLin
   CurLin := GetDiff(FormatHex(MixColor), FormatHex(OthColor), 0, AD)
   If (Ad > MaxDif)
   {
      MaxDif := AD
      MaxLin := CurLin
   }
   If (Ad < MinDif)
   {
      MinDif := AD
      MinLin := CurLin
   }
}

ChooseColor( Color=0x0, hPar=0x0, ccFile="")  { ;Thanks Skan
Color := SubStr(Color,1,2)="0x" ? Color : "0x" Color      ; Check & Prefix Color with "0x"
VarSetCapacity(CHOOSECOLOR, 36, 0) , mainPtr := (&CHOOSECOLOR)     ; Create Main structure
DllCall( "RtlFillMemory", UInt,mainPtr+0, Int,1, UChar,36 ) ; Insert size of the Structure

hPar := WinExist(ahk_id %hPar%) ; Validate the passed Parent window ID
; Break Parent window ID into 4 bytes
H1 := hPar>>0 & 255,   H2 := hPar>>8 & 255,   H3 := hPar>>16 & 255,   H4 := hPar>>24 & 255
Loop 4                       ; Insert Parent window ID to CHOOSECOLOR structure @ Offset 4
  DllCall( "RtlFillMemory", UInt,mainPtr+3+A_Index, Int,1, UChar,H%A_Index% )

; Break Color into R,G and B values
RGB1 := Color>>16 & 255,    RGB2 := Color>>8  & 255,    RGB3 := Color>>0  & 255
Loop 3                      ; Insert R,G and B values to CHOOSECOLOR structure @ Offset 12
  DllCall( "RtlFillMemory", UInt,mainPtr+11+A_Index, Int,1, UChar,RGB%A_Index% )

; CustomColors ( CUS1 will be primary array and CUS2 will be a copy to detect any change )
VarSetCapacity(CUS1, 64, 0),   aPtr := (&CUS1),   VarSetCapacity(CUS2, 64, 0)
IfEqual,ccFile,, SetEnv,ccFile,%A_WinDir%\CUSTOMCOLOR.BIN ; Assign default save filename
IfExist,%ccFile%,  FileRead,CUS1, *m64 %ccFile%           ; Array CUS1 will be overwritten
Loop 64                                                   ; Copy data from CUS1 to CUS2
 oS:=A_Index-1, DllCall( "RtlFillMemory", UInt,&CUS2+oS, Int,1, UChar,*(&CUS1+oS) )
A1 := aPtr>>0 & 255,   A2 := aPtr>>8 & 255,   A3 := aPtr>>16 & 255,   A4 := aPtr>>24 & 255
Loop 4        ; Insert pointer to Custom colors array to CHOOSECOLOR structure @ Offset 16
   DllCall( "RtlFillMemory", UInt,mainPtr+15+A_Index, Int,1, UChar,A%A_Index% )

; Insert Integer 259 @ Offset 21 (259 is CC_RGBINIT + CC_FULLOPEN + CC_ANYCOLOR )
DllCall( "RtlFillMemory", UInt,mainPtr+20, Int,1,UChar,3  ) ; CC_RGBINIT=1 + CC_FULLOPEN=2
DllCall( "RtlFillMemory", UInt,mainPtr+21, Int,1,UChar,1  ) ; CC_ANYCOLOR=256

If ! DllCall("comdlg32\ChooseColorA", str, CHOOSECOLOR) OR errorLevel   ; Call ChooseColor
     Return -1            ; and return -1 in case of an error or if no color was selected.

Loop 64 ; Compare data CUS2 and CUS1, if custom color changed, then save array to BIN file
   If ( *(&CUS1+A_Index-1) != *(&CUS2+A_Index-1) )   {       ; Check byte by byte
       h := DllCall( "_lcreat", Str,ccFile, Int,0 )         ; Overwrite/create file
            DllCall( "_lwrite", UInt,h, Str,CUS1, Int,64 )  ; write the array,
            DllCall( "_lclose", UInt,h )                    ; close the file,
            Break                                           ; break the loop.
                                                    } 
Hex := "123456789ABCDEF0",   RGB := mainPtr+11
Loop 3 ; Extract nibbles directly from main structure and convert it into Hex (initd. abv)
  HexColorCode .=  SubStr(Hex, (*++RGB >> 4), 1) . SubStr(Hex, (*RGB & 15), 1)
Return HexColorCode ; finally ... phew!
}


Update: New Show Difference and BGR options. Also direct access to the Windows color picker.


Last edited by ManaUser on Tue Jul 17, 2007 4:58 am; edited 1 time in total
Back to top
View user's profile Send private message
Titan



Joined: 11 Aug 2004
Posts: 5007
Location: imaginationland

PostPosted: Thu Jun 28, 2007 11:05 pm    Post subject: Reply with quote

This is very helpful, particularly for macroing when you need to find the common colour variation from a sample for PixelSearch. I have already found use for this so thanks. A couple suggestions: could you add a button to copy the code to the clipboard and have an BGR/RGB option.
_________________

RegExReplace("irc.freenode.net/autohotkey", "^(?=(.(?=[\0-r\[]*((?<=\.).))))(?:[c-\x73]{2,8}(\S))+((2)|\b[^\2-]){2}\D++$", "$u3$1$3$4$2")
Back to top
View user's profile Send private message Visit poster's website
ManaUser



Joined: 24 May 2007
Posts: 900

PostPosted: Fri Jun 29, 2007 4:28 am    Post subject: Reply with quote

It already has a feature to copy the code to the clipboard, just click the box displaying the code. BGR should be fairly easy, but just out of curiosity, when does one use that? I've never enounterde a need for it.

The other thing you said gave me an idea too. A feature for displaying the difference between two color could be very handy. That's that's exactly the kind of thing I was using this for myself, but I didn't think to build it in. Hmm...
Back to top
View user's profile Send private message
ManaUser



Joined: 24 May 2007
Posts: 900

PostPosted: Tue Jul 17, 2007 5:04 am    Post subject: Reply with quote

Update: New Show Difference and BGR options. Also direct access to the Windows color picker.
The format for showing the difference is a little strange, but it was the best I could think of. It subracts the R G and B values of the Pot from the current color and displays them in Hexadecimal and then shows the greastest difference (as used by ImageSearch and PixelSearch) in decimal. For example if the Pot was 3310DB and Current was 2230AB it would display -1120-33 (48).
Back to top
View user's profile Send private message
canadaman123
Guest





PostPosted: Wed Aug 15, 2007 4:12 pm    Post subject: reset button Reply with quote

This is a great tool. It might be helpful to have a reset button to clear the pot and set the color back to 000000. Right now you can go find a black pixel and CTRL+SHIFT+LClick to reset it that way, but it would be nice to have a reset button. Maybe even "Reset to black" and "Reset to white" options. Just a thought. Great job though.
Back to top
Rhys



Joined: 17 Apr 2007
Posts: 618
Location: Florida

PostPosted: Fri May 09, 2008 6:57 pm    Post subject: Reply with quote

Holy cow this is really useful - Thanks! (Sorry to bump an old thread, but this is a really great little script and maybe now someone will see it who didn't before!)
_________________
Back to top
View user's profile Send private message
pockinator



Joined: 06 Dec 2007
Posts: 32

PostPosted: Sun May 11, 2008 1:27 pm    Post subject: Reply with quote

This is a great little tool, ManaUser! And thanks for the bump, Rhys. Wink
Back to top
View user's profile Send private message
Wouther



Joined: 01 May 2007
Posts: 61
Location: The Netherlands

PostPosted: Sun May 11, 2008 3:28 pm    Post subject: Reply with quote

A wonderful tool! Thanks ManaUser!
I do agree with canadaman123, though: a button to reset the pot would be nice. Other than that, a very useful tool!
(And indeed thanks for the bump, Rhys, I didn't notice this until now. Wink)
_________________
Printing css/html-formatted text
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group