Pixel Color Reading Script with shell script fails on Monterey

Yes. It’s the way the AppleScript compiler works. The first appearances of the labels x and x are the upper-case ones in the lines set X to item i of xrow and set Y to item ic of yrow, so all subsequent occurrences of those labels are compiled in the same case. The obvious cures here are to change the first appearances to lower case or to use different labels. “Different labels” could include using bars with the upper-case versions:

set |X| to item i of xrow
set |Y| to item ic of yrow

set theColor to (thisRep's colorAtX:0 y:0)

Thanks Nigel for the explanation. :cool:

This topic is resolved but I thought I would add a final comment on accuracy.

I opened the Digital Color Meter and set it to the smallest aperture size–which the documentation appears to indicate is 1 pixel–and I set the color space to “Display in Generic RGB”. I then modified my script to return cursor position and generic RGB colors at the cursor position. Finally, I ran tests comparing the two.

With solid colors the returned results were essentially identical. However, on images with variegated colors, there were differences but they were generally quite small. For example, on an image of a grass lawn, Digital Color Meter returned 151 175 39 and my script returned 152 176 42.

Just as an aside, the script as writen returns the RGB data for one pixel; this can be changed by modifying theWidth and theHeight values. Also, if sRGB output is desired, replace genericRGBColorSpace in the script with sRGBColorSpace.

use framework "AppKit"
use framework "Foundation"
use framework "QuartzCore"
use scripting additions

on main()
	set {xCoordinate, yCoordinate} to getCursorPosition()
	set {redColor, greenColor, blueColor} to getRGBData(xCoordinate, yCoordinate)
	set dialogText to "X Coordinate: " & xCoordinate & linefeed & "Y Coordinate: " & yCoordinate & linefeed & linefeed & "Red Color: " & redColor & linefeed & "Green Color: " & greenColor & linefeed & "Blue Color: " & blueColor
	display dialog dialogText buttons {"OK"} default button 1 with title "Coordinates and Color at Cursor"
end main

on getCursorPosition()
	set cursorPosition to current application's NSEvent's mouseLocation()
	set {{x1, y1}, {x2, y2}} to (current application's NSScreen's mainScreen())'s frame()
	set cursorPosition to {(cursorPosition's x as integer), (y2 as integer) - (cursorPosition's y as integer)}
end getCursorPosition

on getRGBData(theX, theY) -- a minor rewrite of a handler by Shane Stanley
	set {theWidth, theHeight} to {1, 1}
	set theX to theX - (theWidth div 2) -- center width and height on cursor
	set theY to theY - (theHeight div 2) -- center width and height on cursor
	do shell script "screencapture -R " & theX & "," & theY & "," & theWidth & "," & theHeight & " -c"
	set imageData to (current application's NSPasteboard's generalPasteboard()'s dataForType:(current application's NSPasteboardTypeTIFF))
	set theImage to (current application's CIImage's imageWithData:imageData)
	set theFilter to current application's CIFilter's filterWithName:"CIAreaAverage"
	theFilter's setValue:theImage forKey:(current application's kCIInputImageKey)
	set theResult to theFilter's valueForKey:(current application's kCIOutputImageKey)
	set imageRep to (current application's NSBitmapImageRep's alloc()'s initWithCIImage:theResult)
	set theColors to (imageRep's colorAtX:0 y:0)
	set theColors to theColors's colorUsingColorSpace:(current application's NSColorSpace's genericRGBColorSpace())
	set redColor to ((theColors's redComponent()) * 255) as integer
	set greenColor to ((theColors's greenComponent()) * 255) as integer
	set blueColor to ((theColors's blueComponent()) * 255) as integer
	return {redColor, greenColor, blueColor}
end getRGBData

main()