Formato de salida del cuadro de diálogo Selector de color estándar de Mac OS (elegir color)

Es posible crear un AppleScript que solicite el cuadro de diálogo Selector de color estándar de Mac OS ( choose color) y obtenga el valor de salida después de que el usuario elija un color:

set the rez to choose color
set the rezStr to rez2string(rez)
set the clipboard to rezStr

on rez2string({r, g, b})
    return "(" & r & ", " & g & ", " & b & ")" as string
end rez2string

Por lo tanto, el valor de color seleccionado se copiará en el portapapeles.

Mi pregunta es: ¿puedo controlar la salida de este cuadro de diálogo Selector de color en AppleScript? De forma predeterminada, devuelve el valor del color en este formato: (59432, 59441, 59428), que es un color alto de 16 bits , creo.

¿Puedo especificar de alguna manera que quiero obtener un RGB "estándar" (con 255 como valor máximo) en su lugar? ¿O cualquier otro? ¿O el color de alta densidad de 16 bits es el único formato de salida admitido para choose color? Eso sería una lástima, porque hasta donde yo sé, no hay forma de obtener los valores RGB/Hex correctos de un color de 16 bits de alto, ya que implicaría redondeo y aproximación.

Quiero decir, el mismo cuadro de diálogo Selector de color estándar al que llama choose colortiene valores RGB (junto con el hexadecimal) en su segunda pestaña (Controles deslizantes de color), por lo que es capaz de devolver valores en esos formatos. Pero, ¿están disponibles para entrar en AppleScript?

ingrese la descripción de la imagen aquí

Actualización 1.

Escribí una publicación de blog con más detalles sobre el problema.

Actualización 2.

Como Jon señaló en su respuesta, el problema se origina en el cuentagotas, por lo que las secuencias de comandos en realidad pueden convertir de color de 16 bits de alto a 255-RGB "normal" y luego HEX, pero debido al hecho de que el cuentagotas genera un valor incorrecto (aparentemente de un espacio de color diferente), todos los cálculos posteriores están condenados.

Respuestas (3)

Primero, este es el script que uso:

set format to (button returned of (display dialog "Select the format of the chosen color for the clipboard." buttons {"Cancel", "HEX", "RGB"} default button 3 with icon 1 with title "Color Picker"))
set {r, g, b} to choose color
set {r, g, b} to {_16_to_8(r), _16_to_8(g), _16_to_8(b)}
if (format = "RGB") then
    set the clipboard to ("rgb(" & r & ", " & g & ", " & b & ")")
else
    set the clipboard to ("#" & {dec_to_hex(r), dec_to_hex(g), dec_to_hex(b)})
end if

on _16_to_8(n)
    return ((n / 65535) * 255) as integer
end _16_to_8

property hex_chars : "0123456789ABCDEF"'s characters
on dec_to_hex(n)
    if (n = 0) then return "00"
    return (hex_chars's item (((n div 16) mod 16) + 1)) & (hex_chars's item ((n mod 16) + 1))
end dec_to_hex

El problema que está viendo es específico del color que eligió ({236, 236, 236} / ECECEC) usando la herramienta Cuentagotas. El selector lo mostró como {236, 236, 236} pero cuando lo devolvió a través de AppleScript, fue {59438, 59436, 59437} o algo similar donde los valores RGB no son los mismos (es decir, no es un gris verdadero). Si abre el selector de color e ingresa manualmente 236 para cada uno de los valores RGB (no use la herramienta de cuentagotas) y luego devuelve el color, devolverá el resultado RGB como 3 valores iguales ({60652, 60652, 60652} ) que luego será forzado correctamente por el script anterior.

Creo que hay un problema de redondeo con el selector de color y la herramienta cuentagotas, ya que muestra, de forma predeterminada, números enteros de 8 bits (0-255) en lugar de punto flotante (0,0-1,0). Cuando selecciona el color de su imagen de ejemplo con la herramienta Cuentagotas y cambia al control deslizante de escala de grises, se mostrará como 91%. Esto es incorrecto. El valor debe ser 92,5%, pero el selector no muestra flotantes, solo números enteros en el control deslizante de escala de grises (puede cambiar a flotantes en la sección del control deslizante RGB desde el botón de acción a la derecha del botón emergente de tipo de control deslizante). Si está en la sección del control deslizante de escala de grises, ingrese manualmente 92.5 y luego presione la tecla de tabulación para que el selector acepte el valor, luego presione el botón Aceptar y nuevamente, debería ver los resultados correctos en AppleScript.

Entonces, si el resultado de AppleScript no es lo que está viendo en el selector, simplemente copie el valor HEX del campo HEX del selector y cancele el selector presionando esc o el botón Cancelar. Si desea los colores RGB, ejecute el script nuevamente, pero en lugar de usar la herramienta Cuentagotas, pegue el valor HEX en el campo Hex y presione la pestaña para confirmar la entrada, luego presione regresar o Aceptar y los valores RGB correctos deberían estar en el portapapeles. Un dolor, sin duda, pero si la precisión es importante para ti, quizás sea el camino a seguir.

Fuera de tema, pero utilizando el código anterior, también puede convertir ASCII a HEX:

string_to_hex("Convert to hexadecimal!")

property hex_chars : "0123456789ABCDEF"'s characters
on dec_to_hex(n)
    if (n = 0) then return "00"
    return (hex_chars's item (((n div 16) mod 16) + 1)) & (hex_chars's item ((n mod 16) + 1))
end dec_to_hex

on string_to_hex(s)
    set r to {}
    repeat with c in s's characters
        set end of r to dec_to_hex(ASCII number c)
    end repeat
    return r as string
end string_to_hex

ACTUALIZAR

Aquí hay una secuencia de comandos revisada que buscará si el usuario canceló el selector de color con el código HEX copiado en el portapapeles. Si ambas condiciones son verdaderas, la secuencia de comandos utilizará el código HEX copiado para agregar el código RGB o HEX al portapapeles. Unos pocos pasos extra incómodos (seleccione y copie la cadena HEX, luego cancele el selector de color) pero quizás sea factible para sus necesidades.

try
    set format to (button returned of (display dialog "Select the format of the chosen color for the clipboard." buttons {"Cancel", "HEX", "RGB"} default button 3 with icon 1 with title "Color Picker"))
    set {r, g, b} to choose color
    set {r, g, b} to {_16_to_8(r), _16_to_8(g), _16_to_8(b)}
on error e number n
    if (n = -128) then --user canceled
        set clipboard_string to (get the clipboard)
        if ((clipboard_string count) = 6) then
            set {r, g, b} to hex_string_to_dec(clipboard_string)
        else
            return
        end if
    else
        log {n:n, e:e}
        return
    end if
end try
if (format = "RGB") then
    set the clipboard to ("rgb(" & r & ", " & g & ", " & b & ")")
else
    set the clipboard to ("#" & {dec_to_hex(r), dec_to_hex(g), dec_to_hex(b)})
end if

on _16_to_8(n)
    return ((n / 65535) * 255) as integer
end _16_to_8

property hex_chars : "0123456789ABCDEF"'s characters
on dec_to_hex(n)
    if (n = 0) then return "00"
    return (hex_chars's item (((n div 16) mod 16) + 1)) & (hex_chars's item ((n mod 16) + 1))
end dec_to_hex

property hex_to_dec_chars : "0.1.2.3.4.5.6.7.8.9AaBbCcDdEeFf"
on hex_to_dec(s)
    set s to s's items's reverse
    set {d, p} to {0, 0}
    repeat with c in s
        set d to d + (((offset of c in hex_to_dec_chars) div 2) * (16 ^ p))
        set p to p + 1
    end repeat
    return d as integer
end hex_to_dec

on hex_string_to_dec(s)
    if character 1 of s = "#" then set s to s's text 2 thru -1
    set r to {}
    repeat with x from 1 to length of s by 2
        set end of r to hex_to_dec(s's text x thru (x + 1))
    end repeat
    return r
end hex_string_to_dec
Bueno, sí, eso es lo que está pasando, ya describí el problema en la publicación original y varias veces en los comentarios. Mi pregunta era si es posible controlar el formato de salida, pero parece que no es posible, por lo que este problema no tiene solución. De hecho, copio/pego el valor HEX del selector, por lo que al menos tiene algún uso.
Pero la clave es que es posible obtener la información que desea del selector y AS, solo que no siempre con la herramienta cuentagotas (aunque a veces funciona bien). Hay casos extremos en los que el cuentagotas establece un valor interno que tiene un error de redondeo que se corrige en la pantalla pero no en el retorno de AS. También es posible verificar el contenido del portapapeles después de ejecutar el selector de color a través de AS y obtener una respuesta de cancelación para ver si el contenido es una cadena HEX (si la copió) y luego convertir esa cadena HEX a RGB (puedo publicar código para eso también, si está interesado).
El objetivo era exactamente trabajar con el valor de retorno, el que se devuelve a AppleScript después de que el usuario haga clic en Aceptar en el cuadro de diálogo del selector de color. Y ese valor está en un formato de color alto de 16 bits, que es imposible convertir a HEX sin error.
Eso no es precisamente cierto. Si abre el selector y, en lugar de usar el cuentagotas, ingresa manualmente 236 para cada uno de los valores RGB, obtendrá el resultado correcto de 16 bits en AS que obligará al valor ECECEC HEX correcto usando el código que publiqué . Si copia el HEX y lo cancela, la secuencia de comandos puede capturarlo y convertirlo a RGB si lo desea (no se muestra en el código anterior), independientemente de cómo obtuvo el selector el valor (manual o con cuentagotas).
Profundizando más (como se menciona en el comentario de su publicación de blog), el problema es que cuando ingresa valores manualmente, el selector de color usa el espacio de color RGB calibrado (NSCalibratedRGBColorSpace), o lo que sea que esté seleccionado en el menú de acción del espacio de color, pero cuando se usa el cuentagotas, utiliza el espacio de color sRGB IEC61966-2.1 y la conversión entre los espacios de color provoca la discrepancia que está viendo. Esto no está relacionado con AppleScript y, que yo sepa, no hay forma de configurar el NSColorPanel a través de AS, Objective-C o de otra manera para elegir el espacio de color que usa el cuentagotas.
... Entonces, volviendo al problema original: cuando llamo al cuadro de diálogo del selector de color desde AppleScript, elijo un color con el cuentagotas y hago clic en Aceptar, la salida que se devuelve a AppleScript es imposible de convertir a un valor HEX correcto, y no hay forma de cambiar el formato de salida del cuadro de diálogo del selector de color. Sí, lo sabía antes. Y lo explicó varias veces también.
Eso no es correcto. Está devolviendo los valores RGB correctos que son forzados a los valores HEX correctos para el espacio de color utilizado por el cuentagotas: r sRGB. Esto es consistente y reproducible. Su problema es que no desea el color en el espacio de color sRGB sino en un espacio de color RGB de dispositivo calibrado. La distinción puede ser sutil, pero su insistencia en que es imposible obtener el valor HEX correcto del selector de color no es correcta Y no tiene nada que ver con AppleScript.
Déjame intentarlo de nuevo :) Llamo al cuadro de diálogo del selector de color desde mi AppleScript, elijo el color con el cuentagotas, hago clic en Aceptar. El diálogo devuelve el valor del color en este formato (59432, 59441, 59428)a mi AppleScript. Ahora, ¿cómo puedo obtener un valor hexadecimal correcto?
Usando cualquiera de los scripts a los que se hace referencia. El problema no es la conversión HEX, es que el cuentagotas devuelve valores RGB en el espacio de color RGB del dispositivo y los quieres del sRGB (NSCalibratedRGBColorSpace) [los volteé antes, lo siento]. Puede especificar el espacio de color cuando ingresa manualmente un valor, pero no cuando usa el cuentagotas porque toma los valores de píxeles de la pantalla en el espacio RGB del dispositivo. Si la fidelidad de color absoluta es importante, el selector de color no es la herramienta para usted o, al menos, use un CMS como Pantone (las paletas de Pantone están disponibles para el selector de color).
Entiendo tu punto, de hecho, ignoré los espacios de color. Sin embargo, todavía es imposible obtener un valor HEX (o 255-RGB) correcto porque cualquier script de este tipo tiene una división de enteros, cuyo resultado está lejos de ser siempre un entero en sí mismo, mucho más a menudo es un flotante valor que luego se redondea al número entero mediante cálculos adicionales, y eso crea un error, por lo que el resultado nunca será un valor correcto.
Entiendo su punto sobre flotantes vs enteros pero, por favor, ejecute el script que publiqué, NO use el cuentagotas, en la sección del control deslizante RGB, ingrese 236 para cada una de las configuraciones RGB (tabulando entre ellas para finalizar la entrada) y presione regresar (suponiendo que se encuentre en el espacio de color RGB genérico). Compruebe el resultado.
Tiene razón, configurar (236,236,236)manualmente y hacer clic en Aceptar proporciona el valor HEX correcto ( #ECECEC) con su secuencia de comandos. Lo mismo ocurre con otros scripts que probé antes. Entonces, el problema es, de hecho, con el cuentagotas. Sin embargo, esa es exactamente la funcionalidad que necesitaba, así que aunque ahora entiendo el origen del problema, eso no lo resuelve :) pero gracias por su paciencia, fui muy terco y no leí con atención la explicación que proporcionó en tu respuesta original.
¡Me alegro de que hayamos avanzado! De hecho, estoy escribiendo mi propia herramienta de gotas para los ojos con selector de color que (con suerte) te permitirá establecer el espacio de color del píxel seleccionado. Avanzando un poco pero obteniendo algunos resultados extraños en la conversión de los colores del espacio de color RGB del dispositivo al espacio de color RGB genérico. Manténganse al tanto...

No pude encontrar el método para cambiar la salida de ColorPicker, pero puede convertir la salida usted mismo con:

set the rez to choose color
set the rezStr to rez2string(rez)
set the clipboard to rezStr

on rez2string({r, g, b})
    return "(" & to8bit(r) & ", " & to8bit(g) & ", " & to8bit(b) & ")" as string
end rez2string

on to8bit(x)
    return (round (x / 256) rounding down) as integer
end to8bit

Utiliza el redondeo, por lo que los valores pequeños pueden estar un poco fuera de lugar.

Pero ese es el problema: si compara los valores después de la conversión a valores RGB desde la pestaña Controles deslizantes de color, verá que son diferentes. Sí, es una aproximación/redondeo bastante cercano, pero ese no es el mismo color. Encontré muchas fórmulas de conversión, pero son defectuosas "por diseño". Entonces, la única forma de obtener los valores adecuados es controlar choose colorel formato de salida (lo que aparentemente no es posible).

Como no fue posible lograr la respuesta de AppleScript, tengo una alternativa.

Si desea una versión independiente del selector de color nativo que cuente con fácil acceso para copiar códigos de color, le recomendaría instalar Hues 1.0: zachwaugh/hues: Selector de color Hues para Mac

Lo he estado usando durante años y, a pesar de haber comprado todos los demás en el mercado, sigo volviendo a Hues (y Sip) . Se basa en el selector nativo, por lo que hay soporte para todos sus complementos [por eso lo ♡].


Otra opción sería usar complementos junto con choose colorAppleScript o ColorPicker :


Selector de color del desarrollador

Todavía no es una solución de elegir color y copiar automáticamente al portapapeles, pero está bastante cerca si desea seguir con el selector de color predeterminado y no quiere usar aplicaciones de terceros como Sip .


Color Skala

Por ejemplo, o incluso el antiguo Hex Color Picker del software waffle (si aún funciona).

Es una aplicación bastante buena, pero desafortunadamente también produce una salida incorrecta (porque lo más probable es que use la misma aproximación que otras). Aquí hay una captura de pantalla que compara los valores de color para la misma muestra: como puede ver, el selector de color de MacOS muestra #ECECEC (correcto) y Hues muestra #E7E7E7 (incorrecto): i.imgur.com/BXSMpyp.png
@retif Gracias por el puntero. Lo verifiqué dos veces y me alegro de haber publicado esto aquí, de lo contrario habría dado por sentada la precisión de Hues. (Hm, me puse a trabajar en esa solución de AppleScript en un punto).