elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado:


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  ¿Cómo promediar 2 colores?
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: ¿Cómo promediar 2 colores?  (Leído 1,783 veces)
Tachikomaia


Desconectado Desconectado

Mensajes: 1.249


Superhacker (es broma xD )


Ver Perfil
¿Cómo promediar 2 colores?
« en: 8 Mayo 2024, 02:52 am »

Si digo CC0000, es decir 204, 0, 0
y
CCCCCC, es decir 204, 204, 204
el resultado debe ser
204, 102, 102

Entiendo que debo convertir el hexadecimal a decimal y luego hacer promedios.

GPT me dijo que con Action Script 1.0 se puede hacer esto para la conversión:
Color1 = "CC0000";
Color2 = "CCCCCC";
Color1Convertido = Number("0x"+Color1);
Color2Convertido = Number("0x"+Color2);

Para el promedio pensé en tomar los 2 1eros caracteres de cada uno, hacer el promedio, luego tomar otros 2, y así, pero para ahorrar tiempo le dije que lo haga él. Hizo:
Código
  1. // Crea un cuadro de diálogo de entrada de texto para ingresar el primer color
  2. var color1:String = prompt("Ingrese el primer color en formato hexadecimal:", "CC0000");
  3.  
  4. // Crea un cuadro de diálogo de entrada de texto para ingresar el segundo color
  5. var color2:String = prompt("Ingrese el segundo color en formato hexadecimal:", "CCCCCC");
  6.  
  7. // Convierte los colores a decimal
  8. var decimal1:Number = Number("0x" + color1);
  9. var decimal2:Number = Number("0x" + color2);
  10.  
  11. // Calcula el promedio de cada componente RGB
  12. var r1:Number = (decimal1 >> 16) & 0xFF;
  13. var g1:Number = (decimal1 >> 8) & 0xFF;
  14. var b1:Number = decimal1 & 0xFF;
  15.  
  16. var r2:Number = (decimal2 >> 16) & 0xFF;
  17. var g2:Number = (decimal2 >> 8) & 0xFF;
  18. var b2:Number = decimal2 & 0xFF;
  19.  
  20. var rPromedio:Number = Math.round((r1 + r2) / 2);
  21. var gPromedio:Number = Math.round((g1 + g2) / 2);
  22. var bPromedio:Number = Math.round((b1 + b2) / 2);
  23.  
  24. // Convierte el color promedio a hexadecimal
  25. var colorPromedio:String = decimalToHex((rPromedio << 16) | (gPromedio << 8) | bPromedio);
  26.  
  27. // Muestra el color promedio
  28. trace("El color promedio es: #" + colorPromedio);
  29.  
  30. // Función para convertir un número decimal a hexadecimal
  31. function decimalToHex(decimal:Number):String {
  32.    var hex:String = decimal.toString(16);
  33.    while (hex.length < 6) {
  34.        hex = "0" + hex;
  35.    }
  36.    return hex.toUpperCase();
  37. }
Al intentar ejecutarlo dice:
Citar
Escena=Escena 1, Capa=Capa 1, Fotograma=1: Line 31: Se espera '{'
     function decimalToHex(decimal:Number):String {

Escena=Escena 1, Capa=Capa 1, Fotograma=1: Line 37: Se ha detectado un '}' inesperado
     }
Siempre me costó entender esas pistas, y este código claro que tampoco lo entiendo.

¿Por qué "0x"+ convierte a hexadecimal tan fácil? ¿es como una función (Number, toString, etc)?

¿Qué es esto
(decimal1 >> 16) & 0xFF;
(decimal1 >> 8) & 0xFF;
decimal1 & 0xFF;
?

¿Qué hace esto?
Código
  1. function decimalToHex(decimal:Number):String {
  2.    var hex:String = decimal.toString(16);
  3.    while (hex.length < 6) {
  4.        hex = "0" + hex;
  5.    }
  6.    return hex.toUpperCase();
  7. }
¿Convierte decimal en string? Según recuerdo lo que se convierte es lo que va entre paréntesis. ¿Qué significaría 16? ¿convierte un número a hexadecimal así nomás?
Luego entiendo que agrega 0s si la longitud del hex generado es <6.

¿Y esto qué es?
var colorPromedio:String = decimalToHex((rPromedio << 16) | (gPromedio << 8) | bPromedio);
Se define a una variable llamando a una función... ¿pero qué es << 16, << 8 y los | ?

Por ahí dice:
Citar
Después, descomponemos cada valor decimal en sus componentes RGB (rojo, verde y azul) utilizando operaciones de desplazamiento y máscaras bit a bit. Calculamos el promedio de cada componente y lo redondeamos utilizando la función Math.round().

Finalmente, convertimos el color promedio de decimal a hexadecimal utilizando la función decimalToHex(), que toma el valor decimal y lo convierte a una cadena hexadecimal de 6 dígitos, agregando ceros a la izquierda si es necesario.

El resultado se muestra en la consola utilizando la función trace().
Creo que lo intentaré a mi manera pero agradezco explicación.


En línea

profinet

Desconectado Desconectado

Mensajes: 31



Ver Perfil
Re: ¿Cómo promediar 2 colores?
« Respuesta #1 en: 8 Mayo 2024, 09:39 am »

Debes elevar al cuadrado cada valor RGB, después hacer la media, y luego calcular la raíz cuadrada de cada uno para revertir la primera operación.

Código:
NewColor = sqrt((R1^2+R2^2)/2), sqrt((G1^2+G2^2)/2), sqrt((B1^2+B2^2)/2)

Usando este enfoque, al elevar al cuadrado los componentes RGB antes de promediar, estamos aplicando un tipo de "ponderación" que favorece los valores más altos y minimiza el efecto de los valores más bajos. Esto es útil porque los valores RGB cuadrados preservan mejor las diferencias perceptuales entre los colores originales.


En línea

Don't shy away from the terminal; embrace it! In the GNU world, everything is a file.
Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.365


Ver Perfil
Re: ¿Cómo promediar 2 colores?
« Respuesta #2 en: 8 Mayo 2024, 23:48 pm »

¿Por qué "0x"+ convierte a hexadecimal tan fácil? ¿es como una función (Number, toString, etc)?
0x es el prefijo para indicar que el número debe interpretarse como un valor hexadecimal.

Citar
¿Qué es esto
(decimal1 >> 16) & 0xFF;
(decimal1 >> 8) & 0xFF;
decimal1 & 0xFF;
los signos: << y >> son operadores de desplazamiento de bits.
>> Equivale a dividir entre 2 por cada valor indicado.
<< Equivale a multiplicar por 2 por cada valor indicado.

Por ejemplo, supongamos que tengo la variable 'valor' que vale 1234
entonces: 'valor << 3' significa que se añaden 3 bits con valor 0 en la posición de menor peso, lo que equivaldría a haberlo multiplicado por 8, es decir equivale a esto:
valor = (valor * 2^³)
con lo que el valor finalmente sería:
En decimal:
antes: 1234, luego: 9872
En binario:
10011010010, luego 10011010010000

Ahora deberías entender que la operación: valor >> 3, lo que hace es eliminar los 3 bits más bajos que es equivalente a dividir entre 8.
Al ser operaciones de bit, son operaciones mucho más rápidas que multiplicar o dividir, pues requieren un solo ciclo de reloj (técnicamente).

El símbolo: '&' es el operador booleano AND y '0xFF' es el valor 255 expresado en hexadecimal, básicamene cuando haces un valor and 255, todos los bits por encima del 8º se ponen a cero.
toma la calculadora escribe (en decimal) 123456 (luego pulsa el botón de opción 'bin' para ver el valor en binario, luego devuélvelo a decimal pulsando el botón de opción 'dec') pulsa la tecla AND y luego escribe 255, el resultado será: 64, es decir 0100.0000 dicho de otro modo, hace que el valor esté en el rango 0-255. En definitiva tratándose del valor del canal de un píxel se asegura que el resultado no esté fuera de rango.


Citar
¿Qué hace esto?
Código
  1. function decimalToHex(decimal:Number):String {
  2.    var hex:String = decimal.toString(16);
  3.    while (hex.length < 6) {
  4.        hex = "0" + hex;
  5.    }
  6.    return hex.toUpperCase();
  7. }
¿Convierte decimal en string?
Sí. Es una función que convierte un número decimal en una string formateado en hexadecimal y lo devuelve en mayúsculas .

Citar
Según recuerdo lo que se convierte es lo que va entre paréntesis.
Estás más verde de lo que pensaba en el lenguaje del que estás 'enamorado'...  :silbar: :silbar:
Convierte en hexadecimal el valor que contiene el parámetro de tipo numérico llamado 'decimal'.

Citar
¿Qué significaría 16? ¿convierte un número a hexadecimal así nomás?
Luego entiendo que agrega 0s si la longitud del hex generado es <6.
El 16, indica a la clase string, que lo cambie en la base numérica hexadecimal, si pones '8' lo convierte a octal, si pones '2' lo convierte a binario... creo que admite hasta la base 32 o así... (también 3, 5, 21,22... etc...)

Citar
¿Y esto qué es?
var colorPromedio:String = decimalToHex((rPromedio << 16) | (gPromedio << 8) | bPromedio);
Se define a una variable llamando a una función... ¿pero qué es << 16, << 8 y los | ?
Se define un variable sí, que recibe como valor el retorno de la función.
La función recibe un valor numérico, en este caso es una expresión numérica (una operación).
Sería equivalente a definir una variable numerica y asignarle el resultado de esa expresión... y que luego fuere esa variable la que pasaras a la función, pero así como está escrito, te ahorras código (igualmente el compilador debe crear una variable temporal para calcular el resultado de la expresión).

(rPromedio << 16) significa: multiplica 'rPromedio * 65536' (es una operación entera, como ya te indiqué más arriba no multiplica, solo añade bits, de la parte baja exactamente 16 bits '0', en realidad desplaza todos los bits (a la vez), 16 posiciones arriba, rellenando con 0 las posiciones más bajas que antes estaban ocupadas).
Después de calcular esos 2 valores 'r' y 'g' los unifica en un solo valor mediante el operador OR (el símbolo '|')
Un ejemplo de desplzamiento a la izquierda, sea el valor 5, en bnario 101, lo desplazaremos primero 1, luego 2, luego 3 y luego 8.
5 en binario: 101
5 << 1, que da: 1010, en decimal 10
5 << 2, que da: 10100, en decimal: 20
5 << 3, que da: 101000, en decimal: 40
5 << 8, que da: 10100000000, en decimal 1280


Esta expresión: (rPromedio << 16) | (gPromedio << 8) | bPromedio
lo que en realidad está haciendo es colocar cada valor (byte) que representa el canal de color del pixel, en la posición que deben ocupar... sería equivalente a:

Código:
color = (rojo * 65536) + (verde * 256) + azul
colorPromedio = decimalToHex(color)
Nota que usar la suma  en bytes perfectamente acotados en sus rangos, es
equivalente a usar el operador OR, que es más rápido que la suma.
RR000    \RR posición del byte rojo, tras multiplicarlo por 65536
00VV00  \ GG posición del byte verde, tras multplicarlo por 256
0000AA  \ posición del byte azul...
--------------
RRVVAA



Para calcular el promedio de 2 valores en efecto...
1 debes descomponer el color en sus canales:
Código:
azul1 = (color1 and 255)
verde1 = ((color1 \ 256) and 255)
rojo1 = (color1 \ 65536)
Lo mismo para color2... (rojo2, verde2 y azul2)
2 luego sumar los canales individuales y promediarlos:
Código:
tmpRojo = ((rojo1 + rojo2) \2)
tmpVerde = ((verde1 + verde2) \2)
tmpAzul = ((azul1 + azul2) \2)
3 Finalmente montar el resultado de los canales al color deseado...
Código:
color =  (tmpRojo * 65536) + (tmpVerde * 256) + tmpAzul

La forma seguida en el código es más óptima en cuanto al rendimiento, pues utiliza operaciones binarias... las multiplicaciones y divisiones son muy costosas comparativamente.

Todo esto en realidad son cosas elementales de programación, te suena a chino, no solo por ser autodidacta (que no es en sí el problema), es debido quizás a ser demasiado cabezón en no haber querido aprender las cosas elementales que además son comunes e indistintas a cualquier lenguaje. El escaso tiempo que ahorraste en no aprender (3-6 mses) lo pierdes ahora (con creces) en detalles insignificantes porque para tí son galimatías incomprensibles.
« Última modificación: 8 Mayo 2024, 23:50 pm por Serapis » En línea

Tachikomaia


Desconectado Desconectado

Mensajes: 1.249


Superhacker (es broma xD )


Ver Perfil
Re: ¿Cómo promediar 2 colores?
« Respuesta #3 en: 11 Mayo 2024, 16:35 pm »

profinet:
Eso lo pensaré más adelante.

para tí son galimatías incomprensibles.
En general  :xD

Citar
0x es el prefijo para indicar que el número debe interpretarse como un valor hexadecimal.
Ya veo:
A = 0x20;
me da 32.

Así que con >> y << las operaciones funcionan más rápido... Nunca me habían dicho. Pero sólo sirven si son *2^algo o /2^algo ¿no?

Citar
El símbolo: '&' es el operador booleano AND y '0xFF' es el valor 255 expresado en hexadecimal, básicamene cuando haces un valor and 255, todos los bits por encima del 8º se ponen a cero.
toma la calculadora escribe (en decimal) 123456 (luego pulsa el botón de opción 'bin' para ver el valor en binario, luego devuélvelo a decimal pulsando el botón de opción 'dec') pulsa la tecla AND y luego escribe 255, el resultado será: 64, es decir 0100.0000 dicho de otro modo, hace que el valor esté en el rango 0-255. En definitiva tratándose del valor del canal de un píxel se asegura que el resultado no esté fuera de rango.
Esto me cuesta entenderlo ¿tiene sentido que le llaman AND? Bue, le llaman % al resto, no debería sorprender. El diccionario de Flash dice:
& (operador AND como bit)
Sintaxis

expresión1 & expresión2
Argumentos

expresión1, expresión2 Cualquier número.

Descripción

Operador (como bit); convierte expresión1 y expresión2 en números enteros de 32 bits sin signo y realiza una operación Booleana AND en cada bit de los argumentos del número entero. El resultado es un nuevo número entero de 32 bits sin signo.

Reproductor

Flash 5 o posterior. Si se ha utilizado el operador & en Flash 4 para concatenar cadenas. En Flash 5 el operador & es un AND como bit y los operadores add y + concatenan cadenas. Los archivos de Flash 4 que utilizan el operador & se actualizan automáticamente para utilizar add cuando se traen al entorno de autoría de Flash 5.
Hice la prueba que me dijiste pero igual no lo entendí.

A = 0 & 1;
da 0.

A = 2 & 34;
da 2.

A = 5 & 678;
da 4.

A = 9 & 1234;
da 0.

GPT:
En Macromedia Flash 5, la línea de código "A = 0 & 1;" realiza una operación de "AND" a nivel de bits entre los números 0 y 1, y el resultado se asigna a la variable A.

En lenguajes de programación como ActionScript, el operador "&" se utiliza para realizar operaciones de bits a nivel de los valores binarios de los números. En este caso, el número 0 se representa como "00000000" y el número 1 como "00000001". Al realizar el operador "&", se compara cada bit en la misma posición en ambos números y se devuelve 1 solo si ambos bits son 1. De lo contrario, se devuelve 0.

En este caso específico, el resultado de la operación es 0, porque no hay ninguna posición en la que ambos números tengan un bit 1. Por lo tanto, la variable A se asignará con el valor 0.


Otro:
La expresión "123 & 456" también realiza una operación de "AND" a nivel de bits, pero esta vez entre los números decimales 123 y 456.

Para entender el resultado, primero debemos convertir esos números a su representación binaria:

123 en binario: 1111011
456 en binario: 111001000

Luego, aplicamos el operador "&" a nivel de bits comparando cada posición:

1111011
& 111001000
111001000


O sea:
1111011
&
111001000
=
111001000
Significa escribir un nuevo número de modo que, en el lugar donde cada uno tenga un 1 va un 1 y sino un 0, hasta que sea tan largo como el nro más largo. Lo que no entiendo es lo de "convierte expresión1 y expresión2 en números enteros de 32 bits", imagino que si son números pequeños les pone 0s delante ¿y sin son largos sólo toma lo que está delante?

Cuando se dice que el operador "&" convierte las expresiones a números enteros de 32 bits, significa que toma las expresiones y las representa internamente como números enteros de 32 bits antes de realizar la operación "AND" a nivel de bits.

Un número entero de 32 bits es una representación binaria de un número que utiliza 32 posiciones o bits. Cada bit puede tener un valor de 0 o 1. La conversión a 32 bits asegura que las expresiones se traten como números enteros de longitud fija antes de realizar cualquier operación a nivel de bits.

Si las expresiones originales son números más pequeños que 32 bits, se completa el número con ceros a la izquierda para alcanzar los 32 bits. Por ejemplo, si una expresión es el número decimal 5, se representa en binario como "00000000000000000000000000000101" para ocupar 32 bits.

Una vez que ambas expresiones se han convertido a números enteros de 32 bits, el operador "&" realiza la operación "AND" a nivel de bits entre cada par de bits correspondientes en las expresiones. El resultado es un nuevo número entero de 32 bits sin signo.

En resumen, la conversión a 32 bits asegura que las expresiones se traten como números enteros de longitud fija antes de realizar la operación "AND" a nivel de bits. Esto proporciona consistencia en la representación y permite realizar la operación de manera adecuada.
Ah, ya veo, son muchos 0s, 32, me confundía con algo como esto:
Si hay 1 número son 2 posibles valores.
2 -> 4
3 -> 8
4 -> 16
5 -> 32
O no sé, tengo mucho lío, cuando busco cheats en juegos la opción 8 bits son 2 dígitos (o sea de 00 a FF), y de 32 son más pero no tantos, ah, puede ser porque eso es hexadecimal...

Entonces por ejemplo 123456 & xFF:
11110001001000000
&
00000000011111111
=
00000000001000000 = 64

¡Ok! Y esto sirve para... "tratándose del valor del canal de un píxel se asegura que el resultado no esté fuera de rango.", entiendo, pero no para qué aumentó los valores o cómo es eso.

Pero en el caso anterior no es así.
1111011
&
111001000
quedaría:
001111011
&
111001000
=
001001000

No entiendo entonces.

Citar
Es una función que convierte un número decimal en una string formateado en hexadecimal y lo devuelve en mayúsculas .
Estás más verde de lo que pensaba en el lenguaje del que estás 'enamorado'...  :silbar: :silbar:
Convierte en hexadecimal el valor que contiene el parámetro de tipo numérico llamado 'decimal'.
Ya, pero es que hace mucho que no convierto algo único a String, lo más parecido que he estado haciendo es concatenar números así Dato1+" "+Dato2, y como pensaba acabo de ver que esto:
J = 3;
J = J+"";
Hace que J sea "3", string, por lo que no hay necesidad de usar String(J) parece. Pero eso de J.toString(), no sé si alguna vez lo había visto, sobre cuestiones binarias y similares aún he visto muy poco.

Citar
sería equivalente a:

Código:
color = (rojo * 65536) + (verde * 256) + azul
colorPromedio = decimalToHex(color)
Ya ¿pero por qué funciona? A ver si lo puedo entender más simple:
- Supongamos que en vez de 0 a 255 fuese de 0 a 2 y que tenemos los colores 200 y 210.
- El resultado debería ser 100 o 110 dependiendo de cómo se redondeé.
¿Cómo se llega a ese resultado? ¿algo así?
R1 = Floor(200/100) = 2
Restante = 200-100*R1 = 0
G1 = Floor(Restante/10) = 0
B1 = Restante-10*G1 = 0
R2 = Floor(210/100) = 2
Restante = 210-100*R1 = 10
G1 = Floor(Restante/10) = 1
B1 = Restante-10*G2 = 0
NuevoR = Round((R1+R2)/2)
NuevoG = Round((G1+G2)/2)
NuevoB = Round((B1+B2)/2)
NuevoColor = NuevoR+""+NuevoG+NuevoB
Se supone que eso concatena bien, sino lo cambio.

Es mejor que obtener los caracteres como había planeado. Pero explicame el método de GPT o el tuyo con un ejemplo para que yo lo pueda entender, ojalá. Una de las diferencias es que los valores originales son hexadecimales y deben ser convertidos a decimales, supongo, para poder hacer el promedio. Ah, veo que lo hiciste:
Citar
azul1 = (color1 and 255)
verde1 = ((color1 \ 256) and 255)
rojo1 = (color1 \ 65536)
Lo que no entiendo es el and 255, y creo que te faltó ponerlo en rojo1 ¿no?
Ese and 255 ¿se puede convertir en una operación normal como hiciste con los >> y << o es más bien algo lógico?

Citar
son cosas elementales de programación, te suena a chino, no solo por ser autodidacta (que no es en sí el problema), es debido quizás a ser demasiado cabezón en no haber querido aprender las cosas elementales que además son comunes e indistintas a cualquier lenguaje. El escaso tiempo que ahorraste en no aprender (3-6 mses) lo pierdes ahora (con creces) en detalles insignificantes
No sé, con ese criterio tendría que haber estudiado electrónica y física atómica que es más elemental, yo aprendí lo que me fue necesario (y que me enteré qie era posible), hasta ahora nunca había precisado esto... De hecho quiero entender si se puede hacer "normal" porque yo programo en un lenguaje "normal", ya sabes, la típica discusión de si conviene aprender lenguaje máquina o no, en mi caso no creo porque me cuesta y tengo poca memoria para ciertas cosas...
¿Te parece que pierdo más tiempo por estar unas horas intentando aprender eso, en vez de pasarme horas haciendo ejercicios? Yo quise estudiar Programación hace años pero había cupos limitados y no obtuve suficiente buena calificación (hubo gente que con 1 punto más que yo entró, pero bue), pero luego vi que a un amigo le pedían hacer cálculos de convertir a binario o cosas que me parecían raras o poco útiles... así que perdí interés. Es como en Química y Física, yo quiero hacer cosas, no cálculos. Tampoco quiero hacer las cosas haciendo malabares si se pueden hacer más simple, me refiero a no usar moles y en este caso... bue, me interesó porque dices que funciona más rápido, pero sino lo del desplazamiento no lo usaría.
« Última modificación: 12 Mayo 2024, 07:12 am por Tachikomaia » En línea

EdePC
Moderador Global
***
Desconectado Desconectado

Mensajes: 2.083



Ver Perfil
Re: ¿Cómo promediar 2 colores?
« Respuesta #4 en: 12 Mayo 2024, 21:31 pm »

Citar
Si digo CC0000, es decir 204, 0, 0
y
CCCCCC, es decir 204, 204, 204
el resultado debe ser
204, 102, 102

Entiendo que debo convertir el hexadecimal a decimal y luego hacer promedios.

Citar
¿Por qué "0x"+ convierte a hexadecimal tan fácil? ¿es como una función (Number, toString, etc)?

Depende de como tomes el dato, por ejemplo CC0000 dará error porque para flash eso no es un número por lo que entenderá que es un nombre de variable que seguramente tampoco lo sea, para que Flash entienda que es un número debería ser: 0xCC0000, entonces Flash entenderá que le diste un número hexadecimal, si le das "CC0000" entenderá que es un String o Texto, en ambos no es que estás convirtiendo, solo le estás entregando los valores correctamente para que Flash lo entienda.

Citar
Siempre me costó entender esas pistas, y este código claro que tampoco lo entiendo.

Ese es código Action Script 2 o 3 por lo que se está usando declaración de variables tipadas especificando el tipo de variable (variable:String, variable:Number), se escribe la variable o función seguido de dos puntos y el tipo de dato que debe contener o devolver, quítalos para no tener problemas en Action Script 1 que es el que usas, no sé si ya hayas visto que hay programadores que usan prefijos en sus variables para indicar que tipo de variables son para ser más legibles, por ejemplo: sNombre = "pepe"; iEdad = 17; fEstatura = 1.67; (s de String, i de Integer, f de Float)

---
Todo lo demás son operaciones a nivel bit, básicamente se usan los desplazamientos binarios y la operación AND binaria para descomponer tu número hexadecimal 0xCC0000 en 0xCC, 0x00 y 0x00, puedes tomar ese camino o puedes trabajar con String que es más legible siempre y cuando ya hayas trabajado o conozcas el método SubStr y/o SubString para extraer partes de una String, supongo que parseInt y toString ya lo conoces bien, sino revisa la documentación o pregunta:

Código
  1. sColor1 = "CC0000";
  2. sColor2 = "CCCCCC";
  3.  
  4. iR1 = parseInt(sColor1.SubStr(0, 2), 16);
  5. iG1 = parseInt(sColor1.SubStr(2, 2), 16);
  6. iB1 = parseInt(sColor1.SubStr(4, 2), 16);
  7.  
  8. iR2 = parseInt(sColor2.SubStr(0, 2), 16);
  9. iG2 = parseInt(sColor2.SubStr(2, 2), 16);
  10. iB2 = parseInt(sColor2.SubStr(4, 2), 16);
  11.  
  12. iPromR = (iR1 + iR2) / 2;
  13. iPromG = (iG1 + iG2) / 2;
  14. iPromB = (iB1 + iB2) / 2;
  15.  
  16. trace(iPromR + ", " + iPromG + ", " + iPromB);
  17.  
  18. sColorPromHex = iPromR.toString(16) + iPromG.toString(16) + iPromB.toString(16);
  19. trace(sColorPromHex);

Esto devuelve:

Código
  1. 204, 102, 102
  2. cc6666
En línea

Tachikomaia


Desconectado Desconectado

Mensajes: 1.249


Superhacker (es broma xD )


Ver Perfil
Re: ¿Cómo promediar 2 colores?
« Respuesta #5 en: 13 Mayo 2024, 20:17 pm »

Depende de como tomes el dato, por ejemplo CC0000 dará error porque para flash eso no es un número por lo que entenderá que es un nombre de variable que seguramente tampoco lo sea, para que Flash entienda que es un número debería ser: 0xCC0000, entonces Flash entenderá que le diste un número hexadecimal, si le das "CC0000" entenderá que es un String o Texto, en ambos no es que estás convirtiendo, solo le estás entregando los valores correctamente para que Flash lo entienda.
Ah, eso tiene mucha lógica.

Citar
Ese es código Action Script 2 o 3 por lo que se está usando declaración de variables tipadas especificando el tipo de variable (variable:String, variable:Number), se escribe la variable o función seguido de dos puntos y el tipo de dato que debe contener o devolver, quítalos para no tener problemas en Action Script 1 que es el que usas
Supuse que podía ser eso.

Citar
no sé si ya hayas visto que hay programadores que usan prefijos en sus variables para indicar que tipo de variables son para ser más legibles, por ejemplo: sNombre = "pepe"; iEdad = 17; fEstatura = 1.67; (s de String, i de Integer, f de Float)
Sí pero si lo veía sin que me lo dijeras no me daría cuenta, se me olvida, pero yo uso mCuadradito por ejemplo si me refiero al vínculo de Cuadradito (el nombre que se usa en el attach movie para indicar cual).

Citar
puedes trabajar con String que es más legible siempre y cuando ya hayas trabajado o conozcas el método SubStr y/o SubString para extraer partes de una String, supongo que parseInt y toString ya lo conoces bien, sino revisa la documentación o pregunta
Pruebo ahora, yo pensaba usar charat pero lo que dices es mejor.
En línea

EdePC
Moderador Global
***
Desconectado Desconectado

Mensajes: 2.083



Ver Perfil
Re: ¿Cómo promediar 2 colores?
« Respuesta #6 en: 14 Mayo 2024, 00:27 am »

Si le quieres dar una aproximación más matemática puedes partir de este ejemplo en base 10 (lo normal):

iColor1 = 123456;

Si quisieras despejar 12 bastaría con dividirlo entre 10000, quedando 12.3456 y a esto le quitamos la parte decimal convirtiéndolo a entero = 12

Para despejar 34 hay que dividirlo entre 100, quedando 1234.56, luego lo convertimos a entero para obtener 1234, y por último obtenemos el módulo (residuo entero) entre 100 para conseguir 34

Para despejar 56 basta con obtener el módulo entre 100, quedando 56

Bien, pero esto que hemos hecho es con base 10, pero tú quieres trabajar con un valor hexadecimal, podrías convertirlos a decimal y trabajarlos así pero también lo puedes trabajar directo en hexadecimal sin complicaciones y sin perder legibilidad:

iColor1 = 0xAABBCC;

Si quisieras despejar 0xAA bastaría con dividirlo entre 0x10000

Para despejar 0xBB hay que dividirlo entre 0x100, quedando 0xAABB, luego obtenemos el módulo (residuo entero) entre 0x100 y obtenemos 0xBB

Para despejar 0xCC basta con obtener el módulo entre 0x100

Código
  1. iColor1 = 0xAABBCC;
  2.  
  3. iR1 = parseInt(iColor1 / 0x10000);
  4. iG1 = parseInt(iColor1 / 0x100) % 0x100;
  5. iB1 = iColor1 % 0x100;
  6.  
  7. sColorHex = iR1.toString(16) + iG1.toString(16) + iB1.toString(16);
  8.  
  9. trace(sColorHex);

Esto devuelve:

Código
  1. aabbcc

El código completo para esta solución sería:

Código
  1. iColor1 = 0xCC0000;
  2. iColor2 = 0xCCCCCC;
  3.  
  4. iR1 = parseInt(iColor1 / 0x10000);
  5. iG1 = parseInt(iColor1 / 0x100) % 0x100;
  6. iB1 = iColor1 % 0x100;
  7.  
  8. iR2 = parseInt(iColor2 / 0x10000);
  9. iG2 = parseInt(iColor2 / 0x100) % 0x100;
  10. iB2 = iColor2 % 0x100;
  11.  
  12. iPromR = (iR1 + iR2) / 2;
  13. iPromG = (iG1 + iG2) / 2;
  14. iPromB = (iB1 + iB2) / 2;
  15.  
  16. trace(iPromR + ", " + iPromG + ", " + iPromB);
  17.  
  18. sColorPromHex = iPromR.toString(16) + iPromG.toString(16) + iPromB.toString(16);
  19. trace(sColorPromHex);

Obteniendo:

Código
  1. 204, 102, 102
  2. cc6666

---
La solución por el método binario te lo propuso ChatGPT pero para que te sea legible debes saber como funcionan internamente los operadores de desplazamiento binario y And binario, o al menos su equivalencia matemática, eso lo estaba explicando Serapis, te darás cuenta que es similar al método matemático que pasé antes, salvo que yo uso parseInt para deshacerme de los decimales y módulo para quitar números de la izquierda
En línea

Tachikomaia


Desconectado Desconectado

Mensajes: 1.249


Superhacker (es broma xD )


Ver Perfil
Re: ¿Cómo promediar 2 colores?
« Respuesta #7 en: 17 Mayo 2024, 08:13 am »

Debes elevar al cuadrado cada valor RGB, después hacer la media, y luego calcular la raíz cuadrada de cada uno para revertir la primera operación.

Código:
NewColor = sqrt((R1^2+R2^2)/2), sqrt((G1^2+G2^2)/2), sqrt((B1^2+B2^2)/2)

Usando este enfoque, al elevar al cuadrado los componentes RGB antes de promediar, estamos aplicando un tipo de "ponderación" que favorece los valores más altos y minimiza el efecto de los valores más bajos. Esto es útil porque los valores RGB cuadrados preservan mejor las diferencias perceptuales entre los colores originales.
No confío mucho en esto, pero veamos.

Si un color es 100, 100, 10
y el otro 10, 100, 100
el resultado normal sería 55, 100, 55
pero me dices que haga:
Raíz((100*100+10*10)/2) para el 1er color en este caso.
Raíz((10000+100)/2)
Raíz((10100)/2)
Raíz(5050)
71,06335201775947748485464743814
¿Si son iguales cambia? A ver, el 2ndo color
Raíz((100*100+100*100)/2)
Raíz((10000+10000)/2)
Raíz(10000)
No, me da 100.
Yo no veo que 71, 100, 71 sea el promedio y no le veo la ventaja.


EdePC:
Está bien, me puede servir.

Luego intento averiguar cómo funciona lo del & y | por curiosidad y porque me puede servir, si el efecto que causa no es simplificable.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
como capturar en colores con pinnacle?
Multimedia
Cuasar 0 1,198 Último mensaje 27 Diciembre 2006, 03:55 am
por Cuasar
promediar
Programación C/C++
karmi 1 1,605 Último mensaje 22 Noviembre 2010, 03:58 am
por Beakman
como cambiar colores con Substance?
Java
_teiki 5 6,032 Último mensaje 28 Febrero 2011, 10:59 am
por NetJava
[COLORES] Como cambiar colores en c++
Programación C/C++
ianmorar03 1 3,234 Último mensaje 20 Abril 2016, 06:50 am
por engel lex
.cmd .bat Como cambiar colores y como manejar el sistema desde la Consola
Scripting
UserDistortion 4 7,221 Último mensaje 31 Marzo 2017, 15:09 pm
por Eleкtro
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines