Sobre el Histograma

Estás viendo el contenido archivado del viejo foro de Ojodigital. No podrás iniciar sesión ni crear nuevo contenido o comentarios.

El foro de ojodigital ha migrado a: https://foro.ojodigital.com, con un aspecto mucho más moderno, amigable y adaptado a dispositivos móviles.

¡¡PINCHA AQUÍ PARA ACCEDER AL NUEVO FORO!!

Resultados 1 al 47 de 47
  1. #1
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like

    Sobre el Histograma

    Bueno esta parte aunque sea la base en pseudo código me tocaba a mí. Hay que discutir varias cosas:


    SOBRE QUÉ BUFFER SE CALCULA EL HISTOGRAMA

    Quedamos que se hace sobre el bffer de salida final, pero hay dos casuísticas:
    • Histograma en gamma compensada (tipo Photoshop): se calcula sobre el buffer de salida final, incluida la aplicación de la gamma compensada. Este histograma será 100% congruente con el chivato de altas luces quemadas así que tiene que mamar del mismo sitio.
    • Histograma logarítmico: para plotear el histograma logarítmico (por pasos de diafragma) lo idóneo es partir del buffer justo antes de la gamma; la podría deshacer yo pero es tontería si se puede acceder a la imagen antes de gamma. Hay 2 posibilidades: o permitirmos que este histograma solo esté disponible cuando se tiene ajustada una salida lineal (gamma=1.0), o tiene que chupar de un buffer pre-gamma. Cómo de complicado es esto último?

    Hay otra duda que me surge, ahora estais trabajando con imágenes de muestra, pero en el caso real cuando hablemos de sacar por pantalla la imagen, y la gamma no se ha ajustado (es decir, sea lineal), cómo lo vamos a hacer? se aplica una gamma sRGB con una LUT para el display? sale la imagen oscura? (no lo veo como opción).
    Lo que tengo claro es que si se elige gamma=1.0 el histograma en gamma compensada ha de reflejar dicha linealidad, es decir será un histograma pegadito a la izquierda.

    Y otra cosa: queremos un histograma que pueda representar solo el área sobre la que se está haciendo zoom? yo tengo claro que tiene que ser posible tenerlo sobre la imagen completa independientemente del grado de zoom, pero no veo mucho problema en un modo adicional que solo muestre el histograma de lo que aparezca en pantalla (como cuando en PS seleccionas un área y el histograma corresponde solo a ella).



    DÓNDE SE DIBUJA Y CON QUÉ FORMATO

    Se dibuja:
    • En una ventana aparte que haga popup al activarlo
    • En una parte del GUI dedicada
    • Sobre la misma imagen (en modo transparente o pantalla partida por ejemplo)

    Y las opciones de cada una:
    • La tercera opción es super galáctica (casi tanto como que aparezca la foto de la cámara como propuso Manuel en una de sus maquetas ), plantea el problema de que dependemos del tamaño del display que es variable.
    • La segunda inutlizaría una parte importante del display cuando no se use.
    • La primera no le gusta a Manuel, pero es la que solucionaría los problema de formato.


    En cuanto al formato, os digo que es MUY MUY recomendable, tener la garantía del que el eje X del histograma tiene una potencia de 2 de píxels (256, 512, incluso 768). Es la forma de que no aparezcan picos que puedan malinterpretarse debido al redondeo del ajuste al display.



    FUNCIONALIDADES

    Que tenga histograma gamma y logarítmico por pasos de diafragma lo tengo claro (va a ser el único revelador que lo tenga! y esto aparte de ser un concepto 100% fotográfico va a permitir medir el rango dinámico de las escenas). A este efecto, qué os parece un modo de display de la imagen en gamas de gris por pasos de diafragma (zonas de Ansel Adams)?



    Por supuesto funcionalidad de representar las 7 combinaciones de canales: R, G, B, RG, RB, GB, RGB mediante 3 checkboxes R,G,B. Marcar niveles vacíos. Dibujar o no ejes y etiquetas,... esas chorradillas.

    Lo que no tengo claro si vale la pena es la parte de poder hacer zoom y movernos a cualquier parte del histograma. Esto os digo que es con diferencia lo que da más lata, y no se si teniendo un histograma de 512 píxels (ningún revelador lo tiene tan potente) vale la pena. Para analizar a fondo histogramas ya está Histogrammar.




    IMPLEMENTACIÓN

    Necesito que me digáis el nombre de la variable (buffer) que contendrá los niveles de la imagen a mostrar en el histograma y la forma de acceder a ellos (image[c][x+width*y], algo así), así como el buffer donde hay que pintar el histograma. Si lo hacemos fijo será un bufffer de 512x256px por ejemplo.

    Y los nombres de los parámetros requeridos para el histograma y que deberán provenir del GUI (del GUI general o del Gui del propio histograma si va en una ventana aparte):
    • Modo (gamma/log)
    • Canales a representar R,G,B
    • ...
    Última edición por Guillermo Luijk; 24/05/2008 a las 13:43
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  2. #2
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    ¿Llovía demasiado para irte a Alicante?

    Cita Iniciado por _GUI_ Ver mensaje
    • Histograma en gamma compensada (tipo Photoshop): se calcula sobre el buffer de salida final, incluida la aplicación de la gamma compensada. Este histograma será 100% congruente con el chivato de altas luces quemadas así que tiene que mamar del mismo sitio.
    Mi idea era calcular cuatro histogramas: gamma compensada y sin compensar para la vista y para la imagen completa, todos de 16 bits. Los completos sólo se calcularían al abrir el "visor de histogramas" en ventana aparte. Los de la vista se recalculan junto con la vista y sólo se mostrarían superpuestos a esta. Pero era sólo una idea.

    Cita Iniciado por _GUI_ Ver mensaje
    • Histograma logarítmico: para plotear el histograma logarítmico (por pasos de diafragma) lo idóneo es partir del buffer justo antes de la gamma; la podría deshacer yo pero es tontería si se puede acceder a la imagen antes de gamma. Hay 2 posibilidades: o permitirmos que este histograma solo esté disponible cuando se tiene ajustada una salida lineal (gamma=1.0), o tiene que chupar de un buffer pre-gamma. Cómo de complicado es esto último?
    Nada. La idea es que la gamma se aplique sobre la vista (es decir sobre la porción de la imagen que se visualiza) y no sobre la imagen completa. Así que tienes disponibles los dos buffers permanentemente. Ahora (al no estar mezcladas las dos maquetas), se calcula en toda la imagen una vez obtenida la salida de dcraw. Estos cálculos se hacen con una LUT muy rápida a 16 bits, justo antes de la conversión a 8 bits (en realidad en el mismo paso), viene a ser así: out=(PX8)(LUTsRGB[in]>>8);

    Cita Iniciado por _GUI_ Ver mensaje
    Hay otra duda que me surge, ahora estais trabajando con imágenes de muestra, pero en el caso real cuando hablemos de sacar por pantalla la imagen, y la gamma no se ha ajustado (es decir, sea lineal), cómo lo vamos a hacer? se aplica una gamma sRGB con una LUT para el display? sale la imagen oscura? (no lo veo como opción).
    Lo que tengo claro es que si se elige gamma=1.0 el histograma en gamma compensada ha de reflejar dicha linealidad, es decir será un histograma pegadito a la izquierda.
    Como te pongo arriba. En principio, la idea era que el usuario no pudiera elegir la gamma de salida hasta el momento de dar a grabar y que mientras tanto sólo se visualizara en sRGB (en esta primera versión, hasta que podamos meter gestión de color)... podemos cambiarlo, pero será un lío que el histograma sí corresponda a la gamma de salida y sin embargo en la pantalla se muestre con sRGB, ¿no crees? Mi idea era que en esta primera versión en la vista de histograma se pudiera elegir entre mostrarlo con la gamma sRGB (tal cual se ve en la vista) y gamma 1.0. Eso lo tenemos chupao porque ambos buffers están disponibles y es rápido de calcular.

    Cita Iniciado por _GUI_ Ver mensaje
    Y otra cosa: queremos un histograma que pueda representar solo el área sobre la que se está haciendo zoom? yo tengo claro que tiene que ser posible tenerlo sobre la imagen completa independientemente del grado de zoom, pero no veo mucho problema en un modo adicional que solo muestre en el histograma lo que aparezca en pantalla (como cuando en PS seleccionas un área y el histograma corresponde solo a ella).
    Mi idea era, como ya pongo arriba, que ese fuera el modo de ver el histograma cuando se solapa con la imagen. El único tema a resolver es la escala, pero podría tener 512 píxels, 256, 128, etc. No pretende ser un histograma exacto, solo informativo. Si quieres más precisión abres el histograma de ventana aparte y tienes la funcionalidad de histogrammar completa.

    Cita Iniciado por _GUI_ Ver mensaje
    DÓNDE SE DIBUJA Y CON QUÉ FORMATO
    Y las opciones de cada una:
    • La tercera opción es super galáctica (casi tanto como que aparezca la foto de la cámara como propuso Manuel en una de sus maquetas ), plantea el problema de que dependemos del tamaño del display que es variable.
    Bueno, es de esos detalles que entra por los ojos, y no me parece difícil de implementar. Lo de la foto está chupao. Solo hay que bajarse una imagen de cada cámara que soporte dcraw y reescalarla... más o menos. Pensaba tirar a lo bruto de dpreview. Es una pijada, pero ¿a que mola?

    Cita Iniciado por _GUI_ Ver mensaje
    • La segunda inutlizaría una parte importante del display cuando no se use.
    Yo descartaría esta directamente. No le veo ninguna ventaja.

    Cita Iniciado por _GUI_ Ver mensaje
    • La tercera no le gusta a Manuel, pero es la que solucionaría los problema de formato.
    No es que no me guste, es que iba en la filosofía de la aplicación usar una sola pantalla... pero hace tiempo que acepté que el histograma iría de ese modo, me parece bien abrir el histograma en plan histogrammar en ventana aparte, siempre que también se pueda ver solapado un histograma menos exacto. Así tienes lo mejor de las dos opciones.

    Cita Iniciado por _GUI_ Ver mensaje
    En cuanto al formato, os digo que es MUY MUY recomendable, tener la garantía del que el eje X del histograma tiene una potencia de 2 de píxels (2256, 512, incluso 768). Es la forma de que no aparezcan picos que puedan malinterpretarse debido al redondeo del ajuste al display.
    En la ventana aparte totalmente de acuerdo, en el histograma solapado habrá que usar 512, 256, 128... hmm... es que 512*2=1024 y aún hay monitores que trabajan a esa resolución, quitando márgenes... no cabrá si forzamos 512. ¿Crees que sería aceptable poner un histograma solapado a 256 teniendo en cuenta que es aproximado y que hay otra opción de verlo más grande? Si es así ponemos de tamaño mínimo de ventana 800 (está así ahora) y lo dejamos siempre a 256.

    Cita Iniciado por _GUI_ Ver mensaje
    FUNCIONALIDADES
    Que tenga histograma gamma y logarítmico por pasos de diafragma lo tengo claro (va a ser el único revelador que lo tenga! y esto aparte de ser un concepto 100% fotográfico va a permitir medir el rango dinámico de las escenas). A este efecto, qué os parece un modo de display de la imagen en gamas de gris por pasos de diafragma (zonas de Ansel Adams)?
    Perfecto. Habría que meterla en la DLL, es muy fácil. Me parece que encaja en la línea de perfectRAW como un guante, de hecho una vez funcione perfectRAW habrá que fusionar todos tus artículos y manuales para que perfectRAW sea un revelador perfecto y didáctico al mismo tiempo.

    Cita Iniciado por _GUI_ Ver mensaje
    Lo que no tengo claro si vale la pena es la parte de poder hacer zoom y movernos a cualquier parte del histograma. Esto os digo que es con diferencia lo que da más lata, y no se si teniendo un histograma de 512 píxels (ningún revelador lo tiene tan potente) vale la pena. Para analizar a fondo histogramas ya está Histogrammar.
    En la ventana aparte yo sí lo pondría, a mí me gustaría tener toda la funcionalidad de histogrammar dentro de perfectRAW... o eso o pones el Command$ en histogrammar que te pedí hace... ¿tres semanas? y lo llamamos desde perfectRAW (así salimos del paso en la versión 1.0). Pero mi opción para más adelante es rehacer histogrammar en C# dentro de una clase y así poder compilarlo dentro de perfectRAW y como un producto a parte: perfectHistogram/perfectH/perfectHist/perfectHistogrammar... tú decides.

    Cita Iniciado por _GUI_ Ver mensaje
    IMPLEMENTACIÓN
    Creo que no me costaría nada implementarlo en mi DLL. Sólo hay que decidir si lo implemento yo o lo hace ariznaf para que no nos pisemos, como hacemos habitualmente. Yo creo que lo lógico sería que yo implementara el cálculo y él el dibujo solapado.

    RESUMO MI POSTURA PARA QUE QUEDE MÁS CLARO:
    • Para la versión 1.0: sólo histograma solapado de baja precisión pudiendo elegir gamma sRGB/lineal, con 256/512 bytes de ancho y volcado a disco TIFF 16 bits y llamada a histogrammar para verlo ampliado. Yo implementaría el cálculo y ariznaf la visualización solapada.
    • En paralelo: rehacer histogrammar en C#/C con dos formularios y código totalmente independiente: uno para abrirlo dentro de perfectRAW desde donde recibiría el buffer (y desde perfectBLEND, etc. en el futuro) y otro formulario para funcionar como aplicación (y producto) independiente. De ese modo se saca mucho más rendimiento del esfuerzo.
    Un saludo:
    Última edición por ManuelLlorens; 25/05/2008 a las 02:17
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  3. #3
    Ingreso
    02 may, 06
    Ubicación
    Levante
    Mensajes
    244
    Post Thanks / Like
    Cita Iniciado por _GUI_ Ver mensaje
    DÓNDE SE DIBUJA Y CON QUÉ FORMATO
    Se dibuja:
    En una ventana aparte que haga popup al activarlo
    En una parte del GUI dedicada
    Sobre la misma imagen (en modo transparente o pantalla partida por ejemplo)
    En mi humilde opinión, veo interesante la ventana pop up teniendo en cuenta que muchos fotógrafos usamos dos pantallas y sería genial poder poner el histograma en la ventana secundaria.

    Estoy maravillado con los avances que lleváis hechos.

    Álex.

  4. #4
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Según la maqueta que se había propuesto, el usuario puede mantener entre 1 y cuatro zonas para la representación de la imagen.

    Mi idea era que en ellas se dibujara la imagen y se fuera superponiendo otro tipo de información (pixels quemados, histograma, patch de la zona seleccionada para el ajuste de blancos, información sobre el grado de zoom y cosas por el estilo, etc.
    Esto se superpondría con un cierto grado de transparencia y se debería de poder activar sobre cualquiera de las cuatro zonas (vistas) visualizadas en un momento dado.

    Se debería de poder también dejar que se quite la imagen ya así quedaría únicamente el histograma, por ejemplo.

    Tampoco habría mayor problema en permitir que se puediera dibujar el histograma (además de en la forma anterior) en una ventana popup.

    El cálculo del histograma sobre la imagen completa, creo que debería de hacerse en 16 bits (con 65536 clases, de 0 a 65535) y dos histogramas: el histograma sobre la imagen lineal (sin gamma aplicada) y el de la imagen corregida en gamma PARA LA GAMMA Y ESPSCIO DE COLOR SELECCIONADOS no para la gamma de pantalla, ya que el que se aprecie o no en la pantalla de nuestro monitor no creo que sea importante, lo importante es si el espacio de salida los representa como un mismo color o no.

    En la representación la cosa puede ser más delicada.

    Estamos acostumbrados a histogramas de 8 bits, con colores agrupados en 256 clases. Un histograma de 65536 clases tendrá un aspecto diferente mucho más "ruidoso" con picos que suben y bajan. Al agrupar en menos clases el histograma se suaviza.

    El problema también está en que si intentamos utilizar los 16 bits completos (65536 clases) no tendremos pixels suficientes para representar cada uno de los valores en pantalla (en el eje horizontal) y por tanto necesariamente va a haber que agruparlos.
    Pero entonces el aspecto del histograma cambiará según la pantalla de visualización sea más o menos ancha (pues aumentaremos el número de clases a medida que la ventana se hace más grande).

    ¿Vamos a utilizar 256 clases o agrupaciones, o un mayor número de ellas?

    En cualquier caso, creo que el histograma almacenado debe de hacerse siempre sobre el total de valores posibles (65536) pues agrupar luego en un número menor de clases es sencillo (basta con sumar todos los valores asociados a las clases a agrupar).
    Mantendremos así en todo momento el máximo de información disponible.

    Para dibujar en GDI+ no hay ningún problema en que la ventana sea de tamaño variable, es sólo cuestión de preparar el dispositivo de manera adecuada y la matriz de transformación de coordenadas, de manera que nosotros dibujamos en el eje x siempre entre 0 y 255 por ejemplo, y GDI se ocupa de escalarlo a la ventana de salida.

    Lo que sí que puede ocurrir es (como dice GUI) que aparezcan picos extraños cuandos se usa un número de pixels que no sea múltiplo del número de clases representadas. Pero para ello es suficiente con usar una porción de la ventana disponible que sí que sea múltiplo (la parte izquierda, la derecha o centrado en la ventana de salida, a vuestra opción).

  5. #5
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Pero entonces el aspecto del histograma cambiará según la pantalla de visualización sea más o menos ancha (pues aumentaremos el número de clases a medida que la ventana se hace más grande).
    No te preocupes de estas cosas que lo tengo ya trillado; por eso insistía todo el rato en que el histograma ha de tener un eje X en potencias de 2, ésa es la clave para no tener problemas. Siendo potencias de 2, todo histograma que se dibuje, en el grado de zoom que sea, siempre tendrá en cada nivel del eje X el mismo número de niveles reales de la imagen de 16 bits representados, y por eso nunca se van a producir picos (esto es importante en grados de zoom grandes, o sea, cuando nos zambullimos en el histograma para verlo de más cerca, algo que nunca hacen los reveladores comerciales ni PS).

    Lo que es IMPRESCINDIBLE (y esto choca con lo que comentó Manuel) es que el histograma, así como el chivato de zonas quemadas, se base en la imagen convertida al perfil de color de salida elegido, y aplicada la gamma final (no la de pantalla). Esto mismo es lo que hace ACR y es una de sus ventajas sobre LR.

    Por lo menos lo de la conversión al espacio de color es la única manera de hacer una gestión de color correcta: una de las mayores críticas a LightRoom, es que en cuanto a gestión de color es tan sumamente cutre, que el histograma que te muestra es el del espacio de color intermedio, que es una versión de ProPhoto (muy amplio), con lo que puedes ver el histograma perfecto y cuando lo exportas a PS te llevas la sorpresa de que en sRGB has recortado niveles.
    La gestión de color empieza en el propio revelado: elegir un perfil de color que sea capaz de representar toda la gama de la imagen, así como un grado de exposición que no recorte niveles son críticos para acondicionar la imagen correctamente. Luego acaberemos eligiendo Adobe RGB para casi todo y arreando, pero qué menos que las simplificaciones sean decisión del usuario, no del revelador.

    Para el histograma logarítmico se ha de acudir al paso anterior a la aplicación de la gamma, y no sé (dependiendo de la facilidad de acceder al buffer correspondiente) si sería mejor incluso acudir al buffer anterior a la conversión al espacio de color final; aunque este tema del histograma log ya es secundario.

    Esta noche leo más en detalle todo lo que hemos comentado sobre los modos de visualización del histograma.
    Última edición por Guillermo Luijk; 26/05/2008 a las 15:08
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  6. #6
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por _GUI_ Ver mensaje
    Lo que es IMPRESCINDIBLE (y esto choca con lo que comentó Manuel) es que el histograma, así como el chivato de zonas quemadas, se base en la imagen convertida al perfil de color de salida elegido, y aplicada la gamma final (no la de pantalla). Esto mismo es lo que hace ACR y es una de sus ventajas sobre LR.
    Técnicamente no tenemos ningún problema para calcular un histograma u otro, aunque sobrecargará un poco la aplicación si tenemos que mantener dos buffers completos distintos para cada imagen, por lo que propongo abajo mi solución técnica.

    Lo que yo decía era que va a quedar raro que lo que se ve por pantalla no coincida con el histograma. Por ejemplo, el chivato de luces altas indicará algo diferente al histograma y eso no es muy coherente, porque, de momento en la primera versión, la salida por pantalla siempre va a ser sRGB. Otra opción es calcular las altas luces sobre el mismo espacio de color que la salida. Opciones que tenemos: asumir que el histograma depende de la elección del usuario y que lo que se ve en pantalla es distinto (me parece raro) y dos, meter la gestión de color completa en la primera versión. Entre estas opciones yo me quedaba con la intermedia que me parecía que era poner un histograma logarítmico y otro con gamma sRGB.

    Técnicamente tendremos que obtener la imagen sin espacio de color ni gamma y convertirla dos veces, una con el espacio de color de salida y otra con el espacio de color sRGB. Eso o nos planteamos meter gestión de colr desde la primera versión ¿Tan difícil puede ser meter la gestión de color en esta primera versión? Mirando el código de Coffin parece fácil convertir de un espacio a otro y tenemos la librería LCMS.

    Cita Iniciado por _GUI_ Ver mensaje
    Por lo menos lo de la conversión al espacio de color es la única manera de hacer una gestión de color correcta: una de las mayores críticas a LightRoom, es que en cuanto a gestión de color es tan sumamente cutre, que el histograma que te muestra es el del espacio de color intermedio, que es una versión de ProPhoto (muy amplio), con lo que puedes ver el histograma perfecto y cuando lo exportas a PS te llevas la sorpresa de que en sRGB has recortado niveles.
    Vamos a ver si me aclaro lo que necesitamos para ir implementándolo:
    1. Salida pura 16 bits: sin espacio de color ni gamma, para el histograma logarítmico.
    2. Salida pura 16 bits+espacio de color de salida+gamma de salida, para el histograma completo.
    3. Salida pura 16 bits+espacio de color sRGB+gamma sRGB+conversión a 8 bits, para la presentación en pantalla. Habrá que decidir si el histograma superpuesto sale de aquí o del anterior y lo mismo del chivato.
    Eso en la versión 1.0. En la versión en la que metamos gestión de color quitaríamos la salida 3 y sacaríamos por pantalla directamente la 2. Para ahorrar memoria deberíamos tener solo la salida 1 y calcular la 2 a la vez que el histograma, sin almacenarlo y la 3 para el trozo que se ve en la vista sin calcularlo para toda la imagen. Eso sería un poco lento pero ahorra memoria. En la siguiente versión podemos pensar si sacrificamos memoria y tenemos la salida 2 calculada en un buffer.

    Tenemos que coger el buffer de salida puro de dcraw (en eso no hay problema) y crear una función nuestra en C (copiando código de Coffin supongo que será muy fáci) que convierta al espacio de color y aplique la gamma con LUT para un solo píxel de 16 bits. Luego se le llama desde la función que calcula el histograma o desde la que pinta en pantalla, manteniendo dos LUTs en memoria a la vez. Supongo que será posible meter en una misma LUT la conversión al espacio de color y la gamma. Si es así irá muy rápido. Esta tarde miro el código de Coffin.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  7. #7
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    ...por eso insistía todo el rato en que el histograma ha de tener un eje X en potencias de 2...
    O sea, que el número de clases en que se divida deberían de ser 256,512,1024,2048....
    Evidentemente, nunca podrá ser mayor que el número de pixels en la ventana de representación (pues si lo hacemos de 512 y lo representamos en 256 habría información solapada).

    Pero si la ventana es de 800 pixels por ejemplo, no hay mucho problema en utilizar 512 clases pero dibujarlas en los 800 pixels completos (rectangulitos verticales por cada clase). Lo único es que habrá clases que se dibujen con barras de dos pixels de ancho y otras con uno (no serán todas de exactamente el mismo ancho, unas tendrían un pixel más que otras).
    Esto no da lugar a la aparición de picos, y tendría mejor aspecto al dibujarlo de extremo a extremo del área disponible, en vez de ocupar una zona solo de la ventana. Del escalado "en horizontal" se ocupa el GDI.

    El algoritmo para dibujarlo podría ser algo así:
    • Obtener ancho de la ventana (en pixels).
    • Calcular la potencia de dos que es inmediatamente inferior al número de pixels.
    • Reagrupar las clases del histograma guardado (de 0 a 65535) en el número de clases seleccionado (esto es rápido, pues se trabaja sobre el histograma, no sobre la imagen. Sólo hay que sumar los valores del histograma de 16 bits que están en la misma clase que el de salida).
    • Preparar la transformación de escala de la ventana de salida para que el eje x vaya de 0 al número de clases.
    • Dibujar una franja vertical por cada clase utilizando GDI para escalar la franja.
    El algoritmo así planteado es sencillo de modificar para poder hacer zooms en el histograma entre dos valores dados v0 y v1 del histograma de 16 bits.
    Sólo hay que agrupar en este caso las clases entre dichos valores v0 y v1.
    Del escalado a la hora de dibujar se ocupa GDI.

    Lo que es IMPRESCINDIBLE (y esto choca con lo que comentó Manuel) es que el histograma, así como el chivato de zonas quemadas, se base en la imagen convertida al perfil de color de salida elegido, y aplicada la gamma final (no la de pantalla). Esto mismo es lo que hace ACR y es una de sus ventajas sobre LR.
    Completamente de acuerdo. De nada sirve el histograma o los pixels quemados de la salida a pantalla, sino de lo que el usuario va a querer guardar en su fichero de salida: es decir gamma y espacio de color de salida, no del sRGB de pantalla.

    Creía que en un principio se había dicho que sobre el de salida por pantalla (con gamma 2.2) y no me parecía correcto.

    Otra cosa es que Manuel estará preocupado por las dificultades de implementación de esto y el aumento de tiempo de revelado.

    Evidentemente hay que hacer la compensación gamma final (y ajuste de espacio de color) para poder calcular los histogramas correctos.
    Eso no hay quién lo evite. Lo único que se puede poner un flag de que lo calcule o no en las funciones de la DLL. Sólo activaríamos el cálculo de histograma cuando hay algún histograma viéndose en pantalla.
    Si luego el usuario lo activa, habrá que llamar a la función de cálculo a partir del buffer correspondiente.

    Ese punto es un punto de bifurcación del algoritmo... por un lado se parte de la salida lineal para hacer la preparación para mostrar en pantalla y por otro las correcciones para el archivo final.
    Habíamos quedado en que las correcciones finales no se harían hasta el revelado final.
    El histograma impone tener que hacer esos cálculos (al menos parte de ellos) en todo momento.
    En cualquier caso, yo el resultado no lo almacenaría en un buffer intermedio.
    El histograma se puede calcular haciendo las correcciones gamma y de espacio de color pixel a pixel pero sin almacenar el resultado en un buffer de salida, únicamente aumentando el contador de la clase correspondiente al resultado de la conversión para dicho pixel.

    Con ello nos ahorramos un buffer más de memoria y nos aseguramos de que el revelado final se pueda hacer partiendo desde cero y con la máxima precisión, sin concesiones que se hayan podido hacer para acelerar los cálculos intermedios para presentación en pantalla.

  8. #8
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Lo que yo decía era que va a quedar raro que lo que se ve por pantalla no coincida con el histograma. Por ejemplo, el chivato de luces altas indicará algo diferente al histograma y eso no es muy coherente, porque, de momento en la primera versión, la salida por pantalla siempre va a ser sRGB. Otra opción es calcular las altas luces sobre el mismo espacio de color que la salida. Opciones que tenemos: asumir que el histograma depende de la elección del usuario y que lo que se ve en pantalla es distinto (me parece raro) y dos, meter la gestión de color completa en la primera versión. Entre estas opciones yo me quedaba con la intermedia que me parecía que era poner un histograma logarítmico y otro con gamma sRGB.
    Hombre a mi me parece lo suyo. Precisamente si el histograma sirve para algo es para mostrar información que no se aprecia fácilmente en pantalla o que por las limitaciones del dispositivo en que se muestra, queda oculta.

    Que el ojo no pueda apreciar una diferencia entre dos tonos dados (por sus propias limitaciones o más habitualmente por las limitaciones del dispositivo de salida) no implica que esos dos tonos sean iguales en el fichero que manejamos. Si son iguales no hay forma de separarlos. Si son distintos, podremos procesarlo para acentuar esa diferencia (aumentando contraste, briloo, lo que sea) y que el ojo lo aprecie.
    Un histograma bien calculado nos ayudará a distinguir entre esas dos situaciones y no nos engañará haciéndonos pensar que no hay información donde en realidad sí que la hay.

    En cuanto a lo de las altas luces: habíamos quedado en que la gamma no afecta a los pixels quemados. Al poner un umbral esto no es exactamente así, pues el valor que se conserva con la gamma es únicamente el correspondiente al más elevado.
    Esto lo podemos obviar recalculando el umbral corrigiéndolo en la diferencia entre los valores con la gamma de salida y la de pantalla (con salida 2.2).
    Quizás el umbral debería de estar definido sobre la imagen lineal y no sobre el valor compensado en gamma. De hecho el umbral a escoger debería de ser cercano al punto de saturación de la cámara.
    Para obtener el valor del chivato o umbral a utilizar en FastDraw una vez convertida la imagen a gamma de pantalla, es suficiente con calcular la compensación gamma para el umbral lineal: umbral= gammaPantalla(umbralLineal).

    Si el umbral se quiere establecer sobre los valores en el fichero de salida, calcularíamos el umbralLineal deshaciendo la compensación gamma de salida.

    Así evitamos tener que hacer las compensaciones de salida cuando no hay ningún histograma en pantalla.
    Eso en la versión 1.0. En la versión en la que metamos gestión de color quitaríamos la salida 3 y sacaríamos por pantalla directamente la 2. Para ahorrar memoria deberíamos tener solo la salida 1 y calcular la 2 a la vez que el histograma, sin almacenarlo y la 3 para el trozo que se ve en la vista sin calcularlo para toda la imagen. Eso sería un poco lento pero ahorra memoria. En la siguiente versión podemos pensar si sacrificamos memoria y tenemos la salida 2 calculada en un buffer.

    Tenemos que coger el buffer de salida puro de dcraw (en eso no hay problema) y crear una función nuestra en C (copiando código de Coffin supongo que será muy fáci) que convierta al espacio de color y aplique la gamma con LUT para un solo píxel de 16 bits. Luego se le llama desde la función que calcula el histograma o desde la que pinta en pantalla, manteniendo dos LUTs en memoria a la vez. Supongo que será posible meter en una misma LUT la conversión al espacio de color y la gamma. Si es así irá muy rápido. Esta tarde miro el código de Coffin.
    Vaya, aquí hemos coincidido en la respuesta (aunque lo tuyo está mucho mejor explicado que lo mío ).

    Claro que eso es fácil de decir por mi parte, por que como lo tiene que hacer tú .
    De ello lo que puede ser más complicado es convertir el pixel individual al espacio de color de salida, pues hay que sacarlo del código de Coffin. Lo otro lo tienes controlado
    Última edición por ariznaf; 26/05/2008 a las 15:56

  9. #9
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Me voy a 2º ESO a dar una clase precisamente sobre Estadística que, cómo no, habla de histogramas. Luego os contesto.
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  10. #10
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Pues háblales de la fotografía y así verán que lo de los histogramas sive para algo.

  11. #11
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Pues háblales de la fotografía y así verán que lo de los histogramas sive para algo.
    Una vez a la semana les suelo hablar de "temas transversales", es decir, de aplicaciones de las matemáticas... y no sólo les he hablado de fotografía, saben lo que es una matriz de Bayer, el modo raw, un revelador...

    Un saludo:
    Última edición por ManuelLlorens; 26/05/2008 a las 17:36
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  12. #12
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like

    Recapitulación

    A ver si tenemos algo definitivo y podemos ponernos con ello. Más que nada porque yo tengo aún bastante trabajo por delante, pero ariznaf cuando termine lo de ahora (que entiendo que le va quedando poco) tendrá que ponerse con lo siguiente.
    1. dcraw.dll devolverá un buffer de 16 bits sin espacio de color ni gamma a perfectRAW. Cambios que hay que hacer: ninguno, simplemente cambiar en el revelador que no pida espacio de salida sRGB, sino color raw.
    2. Voy a renombar image.dll a colormng.dll, para encapsular toda la (escasa de momento) gestión de color de la aplicación. En el futuro esta DLL llamará a LCMS.dll por nosotros. Dicho ésto, colormng.dll tomará ese buffer que sale de dcraw.dll y calculará un histograma completo al que se le podrán pasar tres parámetros (espacio de color, gamma, lineal/logarítmico). Eso lo hará una sola vez cuando se le pida y el resultado se pintará directamente en un Bitmap con el que luego podréis hacer lo que queráis. Cogiendo código de Coffin para el espacio de color (que como dice ariznaf es lo único que no he mirado) + la LUT gamma lo metemos en una LUT para sacar el histograma directamente tal y como especifique _GUI_. Yo le paso ese nuevo Bitmap a ariznaf y él se encarga de pintarlo, bien superpuesto, bien en una ventana aparte (recomiendo encapsularlo en una clase Histograma para en el futuro poder usarla desde otros proyectos). Cambios que hay que hacer en colormng.dll: que calcule, además de la LUT sRGB que calcula ahora, la LUT de la gamma de salida (5 minutos). Que convierta al espacio de color un píxel y exponga ambas funciones fuera. Añadir la función que calcula los histogramas, que entiendo que está chupado.
    3. perfectImageDLL lee la imagen lineal que ha salido de dcraw.dl y tirará de colormng.dll para aplicar el espacio de color y gamma a un sólo píxel de 16 bits del trozo de la imagen que se muestra en la vista antes de convertirlo a 8 bits (aunque lo ideal de nuevo es que lo haga en un solo paso), pidiendo espacio de color sRGB y gamma sRGB para la versión 1.0 (más adelante ya veremos). Si quisiéramos calcular el histograma del trozo de imagen mostrado en la vista (por cierto, ariznaf, creo que al final quedamos que dos vistas eran suficientes, en vez de 4, que aporta poco, consume memoria y hace más complicado el código, para la versión 1.0), lo haríamos en perfectImageDLL, no en colormng.dll, en la misma función que hace los demás cálculos y yo creo que no debería ser posible calcularlo logarítmico para evitar ralentizar el pintado en pantalla.
    4. Para ir más rápido colormng.dll mantendrá internamente dos LUTs diferentes (sRGB y gamma de salida). Además, (eso creo que no está aún bien definido), el código que llama a perfectImageDLL desde C# podrá solicitar a colormng.dll que invierta en gamma y espacio de color el rango del chivato para poder definirlo sobre la imagen corregida en gamma. Esa operación no debería ser complicada.
    ¿Qué os parece?

    Un saludo:
    Última edición por ManuelLlorens; 26/05/2008 a las 17:39
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  13. #13
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    no metáis demasiada info en este hilo que si esta noche me veo mucho texto me estreso y acabo por no leeros...
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  14. #14
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    A ver en lineas generales me parece bien, Manuel, pero algunas matizaciones:
    2.- En este punto dices que para el histograma generas un bitmap y que yo lo pinte. No me parece bien un bitmap. Tal y como lo veo, el histograma consiste simplemente un 4 vectores (uno por canal más luminosidad) con 65536 números el número de pixels en la imagen que tienen el valor correspondiente al índice del vector en el canal asociado a cada vector (RGB+L). Eso sería lo que hay que calcular. A la hora de pintarlo, se puede hacer en C# sin problemas sobre una ventana (utilizando transparencias si se quiere). Si el pintado es un poco lento, se puede pintar desde GDI en un bitmap del tamaño de la ventana y superponerla cada vez que haga falta.
    La rutina de pintado se ha de ocupar de agrupar las clases en un número menor de clases (la potencia de 2 inmediatamente inferior al tamaño de la ventana). Esto es muy rápido y no es necesario volver a recorrer la imagen.
    Ventaja: sólo contamos los pixels que contienen un color una vez, no cada vez que se quiera dibujar.
    La otra opción es crear un bitmap de 256 pixels de ancho, pero es más pobre y menos flexible, y no se adapta al cambio de tamaño de la ventana.

    3.- Para manejar las vistas pensaba utilizar un contenedor de controles de tipo tabla. Con él será fácil añadir columnas y filas y meter en cada celda un PerfectView de manera dinámica. No creo que el que sean 2 o 4 dificulte mucho esa parte de la programación. Entonces por lo que entiendo, la propia rutina de escalado hará la conversión al espacio de color y la gamma de salida para comprobar si está quemado (sólo si se ha seleccionado marcar los pixels quemados). Por las mismas puede también hacer la conversión a sRGB+Gamma y nos evitamos buffers intermedios. Si es manejar una LUT no habría mucho problema ¿no?
    El algoritmo sería algo así:
    1. Para cada pixel en la imagen de salida
    2. Usar la LUT para convertir a Color de Salida y Gamma de salida (16 bits).
    3. Aumentar el contador del número de pixels del color correpondiente en el histograma parcial.
    4. Comprobar si el pixel está quemado.
    5. Usar la LUT para convertir a sRGB y gamma de monitor (16 bits)
    6. Convertir de 16 a 8 bits.
    ¿Es así? ¿Qué te parece el hacer la conversión a sRGB en directo en vez de precalcularla en un buffer? Si se hace con LUTs y dado que hay que hacer necesariamente la correspondiente al espacio y gamma de salida para los pixels quemados, no creo que se ralentize mucho.

    En cuanto a lo que dices de calcular el histograma logarítmico... no creo que hubiera problema.
    Lo primero a ver si entiendo bien qué es el histograma logarítmico. Entiendo que cuando habláis del histograma logarítmico os referís a calcular el histograma sobre la imagen en lineal, sin la corrección gamma ¿no? y el histograma normal hace referencia al histograma calculado con el conjunto de valores que salen después de la corrección.

    ¿Por qué crees que es más problemático? Se podría implementar entre los pasos 1 y 2 ¿no? Simplemente hacer lo mismo que en el paso 3.
    Lo único que ese histograma no tengo claro si habría de ser sobre la imagen Raw o ya convertida al espacio de color... Si es sobre el Raw no hay problema ¿no?

  15. #15
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    2.- En este punto dices que para el histograma generas un bitmap y que yo lo pinte. No me parece bien un bitmap.
    Era por no tener que guardar en memoria el histograma completo y ahorrar algo. Calcular el histograma es muy rápido y pintar con GDI+ muy lento. Me parece mejor opción calcular un Bitmap directamente desde el histograma en C y recalcularlo si hace falta cambiarlo de tamaño etc. y dejar que GDI+ sólo vuelque el histograma en la pantalla, que pasar a C# un histograma completo y pintarlo línea a línea ¿en dónde? ¡En un Bitmap! Otra opción es guardar el histograma completo en memoria... pero en cualquier caso hacer una función en C que pinte el histograma en un Bitmap.

    Cita Iniciado por ariznaf Ver mensaje
    3.- Para manejar las vistas pensaba utilizar un contenedor de controles de tipo tabla. Con él será fácil añadir columnas y filas y meter en cada celda un PerfectView de manera dinámica. No creo que el que sean 2 o 4 dificulte mucho esa parte de la programación. Entonces por lo que entiendo, la propia rutina de escalado hará la conversión al espacio de color y la gamma de salida para comprobar si está quemado (sólo si se ha seleccionado marcar los pixels quemados). Por las mismas puede también hacer la conversión a sRGB+Gamma y nos evitamos buffers intermedios. Si es manejar una LUT no habría mucho problema ¿no?
    Lo del control tipo tabla como tú quieras. A mí me gustaba más la solución actual que crea menos objetos y te da todo el control, pero a mí me da igual una cosa que otra.

    La rutina de escalado llama a una función inline (si sigue así) que es la que convierte de 16 a 8 bits ¿no? Pues en vez de algo así:
    out[i]=(P8X)(in[i]>>8); que hay ahora, sería algo así Convert16to8Pixel(out+=3,in+=3);

    Es decir, que la rutina de reescalado no tiene que hacer nada nuevo, sólo llamar a una función de otra DLL. Antes de eso habrá que inicializar la conversión indicando la gamma y el espacio de color... una especie de InitColorConverter(sRGB,sRGB); para que no haya que pasar esos dos parámetros en cada píxel. Eso es una opción que puede ser más o menos rápida porque, si la función no se puede llamar inline, sobrecarga cada píxel con la pila... la otra opción es pasarle todo el buffer y que ella haga todo el trabajo. Esa opción tiene de malo que se recorre le buffer dos veces. La que sea más rápida será la elegida, de implementar son más o menos igual, aunque la segunda requiere reservar memoria.

    Esa nueva función estará en colormng.dll, que se encargada de todo lo que sean conversiones de imágenes y manejo del color. Es necesario pasarle punteros a los píxeles porque para la conversión del espacio de color (para la gamma no) hay que tener los tres canales (si no me equivoco) y no uno a uno.

    Cita Iniciado por ariznaf Ver mensaje
    El algoritmo sería algo así:
    1. Para cada pixel en la imagen de salida
    2. Usar la LUT para convertir a Color de Salida y Gamma de salida (16 bits).
    3. Aumentar el contador del número de pixels del color correpondiente en el histograma parcial.
    4. Comprobar si el pixel está quemado.
    5. Usar la LUT para convertir a sRGB y gamma de monitor (16 bits)
    6. Convertir de 16 a 8 bits.
    [/quote]
    Bueno, el paso 2 no va ahí. Ese se hace para toda la imagen una vez obtenida de dcraw y antes de dibujarla en pantalla. Ten en cuenta que esa conversión es sólo para tener el histograma completo no para mostrarla en pantalla.

    Cita Iniciado por ariznaf Ver mensaje
    ¿Es así? ¿Qué te parece el hacer la conversión a sRGB en directo en vez de precalcularla en un buffer? Si se hace con LUTs y dado que hay que hacer necesariamente la correspondiente al espacio y gamma de salida para los pixels quemados, no creo que se ralentize mucho.
    Me estoy temiendo viendo el código de Coffin que la conversión al espacio de color se hace con una matriz RGB y que eso no se puede linealizar en una LUT. Es ese caso sería demasiado lento hacerlo en cada píxel y habría que guardar un buffer completo con la imagen en sRGB. Al final no es mucha más memoria y a cambio simplificamos infinitamente el código. Si confirmo que la conversión a otro espacio de color no se puede meter en una LUT (y estoy casi seguro de que no) yo apuesto decididamente por sacrificar memoria y tener un buffer más en sRGB.

    Cita Iniciado por ariznaf Ver mensaje
    Lo primero a ver si entiendo bien qué es el histograma logarítmico. Entiendo que cuando habláis del histograma logarítmico os referís a calcular el histograma sobre la imagen en lineal
    Entiendo que _GUI_ se refiere dibujarlo en escala logarítmica, como hace Histogrammar (por cierto, deberías bajártelo y trastear con él), de modo que los diafragmas queden lineales... para ello supongo que hay que calcular el logaritmo de la "variable x" y eso sin una LUT será lento. Habrá que crear otra LUT más... y van por lo menos 4 .

    Un saludo:
    Última edición por ManuelLlorens; 26/05/2008 a las 19:21
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  16. #16
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por _GUI_ Ver mensaje
    no metáis demasiada info en este hilo que si esta noche me veo mucho texto me estreso y acabo por no leeros...
    Con que te leas el primero y el último...
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  17. #17
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Bueno, el paso 2 no va ahí. Ese se hace para toda la imagen una vez obtenida de dcraw y antes de dibujarla en pantalla. Ten en cuenta que esa conversión es sólo para tener el histograma completo no para mostrarla en pantalla.
    Te olvidas de la comprobación de pixels quemados. Si esa comprobación se ha de hacer (como parece que viene proponiendo GUI últimamente) sobre la salida definitiva a fichero, no será suficiente con ponerla en un paso previo, a no ser que se guarde el buffer completo y se pase también a la subrutina de escalado.

    Por lo comentado por GUI más arriba sobre los pixels quemados y el histograma parcial (que ha de ser sobre la imagen con perfil y gamma de salida) y tus respuestas creía que era obligado el hacer esto aquí.

    Y si hay que hacer el histograma parcial de la parte visible de la imagen, éste será el único sitio donde tengamos esa información.

    Por lo que dices la conversión de LUT (si la LUT ya viene preparada de un paso previo) consiste únicamente en sustituir los valores del pixel por los obtenidos del índice correspondiente de la tabla. No hay ningún cálculo que hacer, por lo que será muy rápida.

    Si se hace esto aquí nos podremos evitar muchos buffers intermedios y quebraderos de cabeza, pues lo que pondremos en pantalla será exactamente lo que se está procesando en ese momento.

    Si la rapidez del proceso descrito anteriormente fuera razonable, creo que sería la mejor manera de hacerlo, pues evita muchos problemas y almacenamiento intermedio.

    Luego siempre se podrá buscar la forma de mejorar lo que vaya más lento y si es necesario sacarlo fuera. O buscar una manera de hacer todos los cálculos que se puedan fuera del algoritmo principal (similar a lo que haces con la LUT).

    Lo del histograma logarítmico, creo que se resuelve efectivamente con una tabla de logaritmos precalculada. En vez de dibujarlo en la posición x lo dibujas en la posición donde la tabla con log(x) te diga. En realidad es hacer en el eje x lo mismo que en el y ¿no?

  18. #18
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Te olvidas de la comprobación de pixels quemados. Si esa comprobación se ha de hacer (como parece que viene proponiendo GUI últimamente) sobre la salida definitiva a fichero, no será suficiente con ponerla en un paso previo, a no ser que se guarde el buffer completo y se pase también a la subrutina de escalado.
    ¿Eso dice _GUI_? No lo había leído. Sí es así no quedará más remedio, como dices, o bien se recalcula cada vez, o bien tenemos un buffer precalculado de cada gamma.

    Aplicar la gamma es fácil y rápido mediante una LUT, pero la conversión de espacio de color es una multiplicación matricial 1x3 · 3x3. A menos que usemos MMX a capón en ensamblador (se diseñó entre otras cosas para acelerar ese tipo de operaciones), es una operación bastante lenta (por píxel, 9 multiplicaciones y 6 sumas de las que no nos libra nadie) no veo viable meterlo en cada píxel.

    Así que tendremos tres opciones:
    1. Meterlo en cada píxel y si va lento, pues va lento y si va decente pues mejor. Creo que esta vez sí que ralentizaría una barbaridad. Lo malo es que en cualquier caso tarde o temprano meteremos LCMS y esa librería no tiene sentido usarla píxel a píxel, así que habría que volver a cambiarlo.
    2. Meter LCMS desde ya y pasar del sRGB desde el principio, usando en pantalla el espacio de color y la gamma de salida. La verdad es que la librería LCMS parece muy fácil de usar, pero mis conocimientos teóricos sobre gestión del color me limitan un poco para entender lo que supondría, aunque creo que es tan fácil como lo que pone más abajo. _GUI_, que está puesto en el tema tal vez pueda iluminarnos un poco. Creo que sólo habría que convertir toda la imagen nada más obtenerla desde dcraw y guardar un sólo buffer. Sorprendentemente, es la opción que menos cambios requiere en el código tal y como funciona ahora. Además, es la que más se acerca al revelador ideal y la que menos memoria utiliza. Abajo os pongo un ejemplo de lo fácil que parece usar la librería LCMS.
    3. Tener dos buffers uno en sRGB y otro en espacio de color/gamma de salida. Eso desperdicia memoria y obliga a cambiar las funciones de reescalado para recibir más buffers de los que reciben ahora. Y nos estamos refiriendo ¡a dos buffers por vista! Eso es mucho, sinceramente. Pero es lo más fácil de implementar hoy por hoy.
    Yo, si _GUI_ nos explica un poco el tema, me tiraría a por la 2, en caso de verlo complicado a por la 3, limitando las vistas a 2 (esta vez no queda más remedio, ariznaf, no podemos permitirnos mantener 8 buffers), metiendo la optimización de memoria a dcraw.dll para ahorrar RAM por algún sitio y haciéndonos a la idea de que la aplicación va a necesitar fácilmente 2 Gb de RAM para funcionar con soltura.

    Todo ello suponiendo que no necesitamos un buffer sin espacio de color ni gamma. Si me decís que también necesitamos tener ese (_GUI_ dice que sí para el histograma logarítmico, pero el histrograma se puede calcular y luego pasar del buffer) os diré desde ya que no va a darnos la RAM para tanto con tres buffers completos por vista: sin espacio de color ni gamma, con espacio de color y gamma de salida y con espacio de color y gamma sRGB. Si tenemos dos vistas activas eso son 4 buffers más de los necesarios ahora. En total 6 + 5 de dcraw.dll, una barbaridad. Con cuatro vistas, como ya he puesto, completamente inviable. Si podemos prescindir de la gamma sRGB debemos hacerlo.

    El esquema de cómo quedaría la cosa con LCMS será el siguiente:
    1. Obtenemos de dcraw el buffer sin espacio de color ni gamma.
    2. Lo pasamos a colormng.dll que calcula el histograma logarítmico y luego convierte a espacio de color y gamma de salida y calcula el histograma normal. Finalmente transforma la imagen según el perfil del monitor y pasa el resultado a perfectImage.dll para pintar en la pantalla (si esto se hace en un único buffer o se desdobla en dos es la única duda que tengo: cálculo de chivatos y salida por pantalla).
    3. perfectImage.dll calcula el histograma parcial y el chivato sobre la imagen que ha recibido, que ya lleva todo lo necesario para calcular y mostrar en pantalla.
    La única duda que me queda es si la transformación al perfil del monitor debe hacerse antes del chivato y el histograma parcial, aunque me temo que sí. De ser así, mantendríamos dos buffers, uno con esa conversión para mostrar y otro sin ella para calcular. En total dos buffers por vista en el peor de los casos, en vez de los cuatro que supondría la solución actual.



    CÓMO METER LCMS EN NUESTRO CÓDIGO
    El ejemplo básico de LCMS es trivial, llamarla desde nuestra colormng.dll debería ser muy fácil y viene ya compilada para todas las plataformas que queremos soportar. Lo único que sí habría que poner es un formulario en la configuración del programa para elegir los perfiles de los dispositivos y el tipo de conversión que queremos, aunque de momento puede ir a capón en un xml. Voy a intentar integrarla en colormng.dll a ver qué tal va la cosa, ¿os parece?

    Avance: he conseguido compilar LCMS como una DLL con DEV-C++, también integrada en colormng.dll y creo que podré integrarla sin dificultad en dcraw.dll. Otra cosa es que lo haga funcionar, de momento peta.

    (Otro tema diferente es compilarla junto con dcraw.dll para usar el perfil de la cámara, eso sí que sería para más adelante porque para eso hay que preparar un proyecto que compile LCMS con MinGW o lograr que dcraw.dll compile y funcione en VC++ y, aunque no parece difícil, podría retrasar bastante la salida de perfectRAW).
    Código:
    /*
            A simpler example of how to use lcms
    */
    #include "lcms.h"
    
    int main(void)
    {
         cmsHPROFILE hInProfile, hOutProfile;
         cmsHTRANSFORM hTransform;
         int i;
    
         hInProfile  = cmsOpenProfileFromFile("HPSJTW.ICM", "r");
         hOutProfile = cmsOpenProfileFromFile("sRGBColorSpace.ICM", "r");
    
         hTransform = cmsCreateTransform(hInProfile,
                                               TYPE_BGR_8,
                                               hOutProfile,
                                               TYPE_BGR_8,
                                               INTENT_PERCEPTUAL, 0);
    
         /*
            here a loop for translating your image.
         */
         /*
         for (i=0; i < AllScanlinesTilesOrWatseverBlocksYouUse; i++)
         {
               cmsDoTransform(hTransform, YourInputBuffer,
                                          YourOutputBuffer,
                                          YourBuffersSizeInPixels);
         }
         */
    
         cmsDeleteTransform(hTransform);
         cmsCloseProfile(hInProfile);
         cmsCloseProfile(hOutProfile);
    
         return 0;
    }
    ariznaf, _GUI_, demás gente... necesitamos vuestras opiniones para poder decidir y seguir avanzando.

    Un saludo:
    Última edición por ManuelLlorens; 28/05/2008 a las 00:22
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  19. #19
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    Hola, ahora que he logrado leerlo todo, voy a decir lo que pienso, me pongo a escribir...

    Hay 2 cosas a decidir, de diferente importancia:


    BUFFERS REQUERIDOS PARA HISTOGRAMA Y AVISO DE ALTAS LUCES

    Me gusta esta opción de Manuel como objetivo final: "Meter LCMS desde ya y pasar del sRGB desde el principio, usando en pantalla el espacio de color y la gamma de salida. La verdad es que la librería LCMS parece muy fácil de usar, pero mis conocimientos teóricos sobre gestión del color me limitan un poco para entender lo que supondría, aunque creo que es tan fácil como lo que pone más abajo. _GUI_, que está puesto en el tema tal vez pueda iluminarnos un poco. Creo que sólo habría que convertir toda la imagen nada más obtenerla desde dcraw y guardar un sólo buffer. Sorprendentemente, es la opción que menos cambios requiere en el código tal y como funciona ahora. Además, es la que más se acerca al revelador ideal y la que menos memoria utiliza. Abajo os pongo un ejemplo de lo fácil que parece usar la librería LCMS."

    Pero sin LCMS aún. Propongo olvidarnos de una gamma sRGB para pantalla y otra para la salida: si la salida se elige en ProPhoto por ejemplo, poco importa que su gamma 1.8 se vea oscura en pantalla, lo que más cantará es que los colores van a ser horribles.

    Como la idea final es hacer verdadera gestión de color (e incluso aunque no lo fuera, por dificultad o por lo que sea), para esta 1ª versión propongo volver al concepto de que el usuario manda, el usuario tiene que ser un usuario avanzado, y el usuario tiene que saber interpretar qué está saliendo en la pantalla y porqué. Así que:
    • Único buffer (en lo tocante a la salida) convertido siempre al espacio de color elegido por el usuario y con la gamma elegida por el usuario.
    • Esta gamma se ajusta automáticamente a la del espacio de color cuando éste se elije, pero el usuario la puede cambiar (poner 1.0, sRGB, u otro valor). Las gammas son rápidas pues se aplican con LUTs rápidas.
    • El histograma y el chivato de altas luces se calculan sobre la imagen FINAL, con perfil de color y gamma elegidas por el usuario.
    • El histograma logarítmico (Fernando, es éste, representa la imagen en 16 pasos de diafragma; se calcula fácil a partir de la imagen lineal, deshaciendo la gamma si no es lineal)


    Si lo miráis bien solo se requiere 1 buffer, el final. Incluso el histograma log que no requiere gran precisión, se puede calcular de ella deshaciendo la gamma (LUTs inversas); pero si considerais más oportuno un buffer pre-gamma me parece bien (solo existiría cuando estuviera activado el modo histograma log).

    Ventajas que veo en hacerlo así:
    • Encaja con el concepto DCRAW: el usuario manda y tiene que aportar y saber interpretar las fases del revelado. A cambio tiene el control, no le controlan
    • La más fácil implementación de las barajadas: se puede llegar a un solo buffer, un solo revelado y gamma, coherente 100% con las opciones elegidas por el USR en el formulario. Lo que se ve en pantalla, es lo que se lee en los parámetros del formulario.
    • Fácilmente evolucionable: pone la base natural para añadirle LCMS, lo que propiciará un aspecto siempre correcto en pantalla (ojo que para mí lo más importante de la gestión de color no es el aspecto en pantalla, sino detectar con precisión las áreas quemadas por convertir a uno u otro espacio, y esto ya lo hemos logrado sin el LCMS).


    Desventajas:
    • Solo cuando convertimos a perfil de salida sRGB y elegimos como gamma sRGB, lo que se vea por pantalla parecerá una foto (se puede poner como opción inicial por defecto y se solucionará con LCMS). Pero eso el usuario lo sabe (hace mucho que no me asusto por ver una imagen verde y oscura, por ejemplo, porque sé qué estoy haciendo).


    Zero Noise funciona así, y no me causa ningún problema ya que en todo momento sé lo que hago y sé porqué la imagen se ve así o asá.


    VISUALIZACIÓN

    Ahora voy a opinar de la visualización...

    Aunque me parece super galáctico superponer el histograma a la imagen, no le veo ventajas (más que eso, lo galáctico) y sí desventajas:
    • Más código a programar (porque no se muestra como el otro)
    • Más calculos a realizar si nos ponemos a trabajar con 2 histogramas a la vez
    • Fontanería coñazo (para vosotros) para encajarlo en una pantalla que se reescala y que puede adquirir tamaños no potencia de 2


    Por eso propongo lo siguiente:
    • Único histograma en ventana popoup adicional que se abre solo al activarlo,
    • Anchos discretos de 256/512/1024 a elegir. No sé si se pueden forzar tamaños fijos, imagino que sí no?
    • Este histograma tiene 2 modos: imagen completa o porción de la vista actual (nunca echaremos en falta usar los dos a la vez así que la reutilización es positiva)
    • AlexG puede poner el histograma en su segundo monitor (cabronaso...)


    Las ventajas son:
    • Máxima precisión del histograma en cualquier modo porque es el más grande posible
    • Se simplifica el código: solo una implementación de histograma
    • Si queremos luego añadir uno superpuesto a la vista de la imagen siempre hay tiempo y hasta se podrá reutilizar fácilmente el código del modo 'histograma de vista'


    Desventajas ninguna.

    Cómo lo veis?

    Por cierto, que el código de calcular los histogramas me gustaría hacerlo a mí. No necesito tener entorno, con que me digáis el nombre de las variables que contienen la imagen final y quizá cómo se dibujan píxels en pantalla me basta (no sé si con GDI la forma de trabajo es dibujar píxels o generar la imagen en 3 canales en un array de memoria y volcarla a pantalla, pero eso es lo de menos).
    Última edición por Guillermo Luijk; 28/05/2008 a las 02:04
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  20. #20
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Manuel, si yo entiendo bien, los buffers no tienen nada que ver con las vistas en pantalla.

    Buffers sólo necesitamos dos juegos: uno para los parámetro de revelado antiguos y otros para el revelado actual.
    Que se muestre luego esa información en 1,2 o 4 vistas es lo de menos.
    Las clases de perfectView sólo manejan (todas ellas) dos buffers: uno para el revelado anterior y otro para el revelado con los parámetros actuales (salvo los buffers de 8 bits de salida recortados al tamaño de la ventana que son uno por vista).

    Si miras el código del Test, los buffers de entrada los comparten. Nada lo impide.
    En una vista podemos estar viendo el revelado actual a zoomx1, en otra imagen partida vertical (revelado anterior y actual) y en otro el revelado anterior con histograma.
    Todas ellas comparten los mismos dos buffers de entrada (Bitmap y OldBitmap).

    Funciona perfectamente. No veo la necesidad de 4 conjuntos de buffers, salvo que se quieran comparar los resultados de más de dos conjuntos de parámetros de revalado. Yo creo que debería de quedar en dos: uno guardado y el actual. En cualquier momento, podremos guardar un revelado para sustituir al antiguo y poder comparar con otros parámetros.

    El buffer con espacio de color y salida de monitor sólo es útil para mostrar en pantalla. No haría falta almacenarlo ¿no? Incluso se podría hacer al vuelo en convert16to8, antes de convertir, pasar a espacio de color de monitor y gamma de monitor, comprobar quemados (calcular histograma parcial?) y convertir a 8.
    Si Lcms permite convertir un pixel individual, ya estaría.
    No puede ser muy lento si se usa una gamma con LUT y la conversión de LCMS es lineal (producto de vector por matrix). Ten encuenta que sólo se calcula para los pixels mostrados en pantalla 800x600 o similar.
    El cálculo de chivatos se está haciendo al vuelo. No enlentece para nada. Es también una LUT. Por tanto sólo hay un buffer de 8 bits del tamaño de la ventana, sin ningún buffer intermedio.
    Creo que lo del lcms y gamma se podría hacer así también.

    De todas formas, tal y como está a mi no me salen tantos buffers. De tu mismo esquema salen los siguientes:
    1.-Los que almacene dcraw internamente (el último de ellos será el de salida lineal sin perfil ni gamma. Dices que son 5).
    2.-Uno de 16 bits convertido a espacio de color y gamma de salida.
    3.-Otro de 16 bits convertido a perfil de colro y gamma de monitor.

    4.- Uno de ocho bits (y tamaño de la ventana) por cada ventana, con la imagen que se muestra.

    si dices que dcraw maneja 5 internos son 5+2.
    Como manejamos dos conjuntos de parámetros (actual y anterior) y 4 vistas de salida
    serán 2x(5+2) + 4 de 8 bits y tamaño de las ventanas de representación.

    Si la conversión a perfil de color y gamma de monitor la podemos hacer al vuelo, ahorraremos un buffer más de 16 bits.
    ¿El buffer sin espacio de color ni gamma (el lineal) no es el que sale de dcraw en la última etapa? ¿No está ya contado en los 5?

    A mi me salen pues únicamente 5+2 y luego los 4 de 8 bits que son una minucia (pues si la pantalla la dividimos en vistas, cada vista es más pequeña, por lo que el consumo es casi constante).
    Si jugamos con dos conjuntos de revelado (actual y previo) son 2x(5+2) y los 4 de 8 bits.

    Por lo demás el esquema me parece perfecto, y si se puede hacer lo de la gestión de color pues estupendo. Si no, pues hacemos la cutre pero manteniendo el esquema de buffers como si ya se hiciera la gestión con lcms para poder enchufarlo luego con facilidad.
    Última edición por ariznaf; 28/05/2008 a las 02:51

  21. #21
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    El histograma logarítmico (Fernando, es éste, representa la imagen en 16 pasos de diafragma; se calcula fácil a partir de la imagen lineal, deshaciendo la gamma si no es lineal)
    Pero lo que no entiendo en el planteamiento que se venía haciendo son las dificulatades expuestas por Manuel...
    Me refiero a que si partimos de la imagen de la cámara en raw, siempre tenemos un buffer con la imagen en lineal. Por tanto no hay nada que deshacer. El algoritmo es exactamente el mismo que con el de la gamma aplicada: contar pixels que muestran cada posible valor (de 0 a 65535) en cada canal.
    Y se representa también en escala linea, puesto que no se ha aplicado la gamma ¿no?

    En realidad no entiendo muy bien el nombre de logarítmico, pues es LINEAL es el que mide directamente la intensidad de luz presente en cada canal.
    El que no será lineal (y será exponencial) será el que se calcula después de la gamma.

    Bueno, es que aún me hago un poco de lío con esto.

    Si lo miráis bien solo se requiere 1 buffer, el final. Incluso el histograma log que no requiere gran precisión, se puede calcular de ella deshaciendo la gamma (LUTs inversas); pero si considerais más oportuno un buffer pre-gamma me parece bien (solo existiría cuando estuviera activado el modo histograma log).
    Aún en el caso de tener activado los histogramas, no es necesario almacenar el buffer. El almacenar el buffer es para no tener que ir más atrás si el usuario cambia gamma o espacio de color de salida o de monitor, y poder empezar a trabajar desde el buffer lineal.
    El proceso es un pipeline: desde el buffer lineal, calculamos el histograma log, lo convertimos a espacio de salida y el histograma completo (si no es muy lento y no vamos a almacenar este buffer yo calcularía siempre el histograma, y así si luego se activa no tenemos que volver más atrás a recalcular).
    Luego convertimos al espacio y gamma de monitor y borramos buffer lineal.

    En realidad creo que será mejor almacenar el lineal y convertir a sRGB y Gamma monitor al vuelo, pero sino es posible, podermos convertirlo aquí deshaciéndonos del histograma gamma.

    Una última cosa:

    He pensado que si preocupa la memoria, todos los buffers intermedio de dcraw y demás de la imagen correspondiente al revelado anterior se pueden borrar.
    En realidad sólo necesitamos los finales, para mostrar la imagen, ya que los parámetros de revelado de la imagen previa no se van a alterar y no hay nada que acelerar.
    Si el usuario rechaza el revelado actual y vuelve al anterior, lo único que notará es que la primera vez que cambie algo irá un poco más lento porque no tiene buffer intermedios almacenados.
    Última edición por ariznaf; 28/05/2008 a las 03:07

  22. #22
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Pero lo que no entiendo en el planteamiento que se venía haciendo son las dificulatades expuestas por Manuel...
    Me refiero a que si partimos de la imagen de la cámara en raw, siempre tenemos un buffer con la imagen en lineal. Por tanto no hay nada que deshacer. El algoritmo es exactamente el mismo que con el de la gamma aplicada: contar pixels que muestran cada posible valor (de 0 a 65535) en cada canal.
    Y se representa también en escala linea, puesto que no se ha aplicado la gamma ¿no?

    En realidad no entiendo muy bien el nombre de logarítmico, pues es LINEAL es el que mide directamente la intensidad de luz presente en cada canal.
    El que no será lineal (y será exponencial) será el que se calcula después de la gamma.

    Bueno, es que aún me hago un poco de lío con esto.
    Pero el histograma log debe ser de la imagen TRAS la conversión al espacio de color. Si lo quieres antes, como usuario no tienes más que poner la conversión a perfil de color de salida a nulo, pero que sea siempre el usuario el que elija.

    El histograma es lineal, pero la representación es logarítmica. Por ejemplo:
    Un pixel que adquiere un valor 32768 en el rango de 16 bits tras el revelado lineal, es un píxel que está a 1 diafragma de la saturación, correcto?
    • Si se muestra el histograma normal de la imagen lineal caerá en el punto central del mismo, en la posición del eje X de la gráfica: 65536/2
    • Si se muestra el histograma logarítmico caerá al principio del último diafragma, en la posición del eje X de la gráfica: 65536*15/16
    • Si la imagen ahora se compensa en gamma, y se muestra el histograma normal de dicha imagen gamma caerá en la posición del eje X de la gráfica: 65536*0,5^(1/2,2)


    Arriba histograma lineal (de un RAW MUUUUY derecheado), abajo su equivalencia en log:


    ______________________

    Otra comparación, de un RAW más normal (menos derecheado) e incluyendo gamma:

    LINEAL


    LOGARÍTMICO


    GAMMA



    Los dos primeros son histogramas de los mismos datos lineales de la imagen, solo cambia el eje X. El tercero, gamma, se obtiene cuando representamos con el eje X del primer histograma la imagen pero con los datos compensados en gamma; es decir, en el tercero sí hemos cambiado los datos de la imagen antes de dibujar el histograma.

    Capici?

    Instálate Histogrammar y juega leyendo en él TIFFs salidos de DCRAW, lo entenderás muy bien. El histograma log solo tiene sentido si el TIFF suministrado es lineal (gamma=1.0).
    Última edición por Guillermo Luijk; 28/05/2008 a las 03:17
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  23. #23
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Manuel, si yo entiendo bien, los buffers no tienen nada que ver con las vistas en pantalla.
    Cada vista corresponde a un revelado distinto, con su conjunto de parámetros y su resultado diferente. Es decir, cada una guarda un buffer de la imagen completa. Si quieres comparar el mismo revelado con dos niveles de zoom diferentes o pones los mismos parámetros en las dos vistas o haces zoom con la rueda, que para eso hemos hecho un zoom tan cómodo y rápido.

    Cita Iniciado por ariznaf Ver mensaje
    Que se muestre luego esa información en 1,2 o 4 vistas es lo de menos. Las clases de perfectView sólo manejan (todas ellas) dos buffers: uno para el revelado anterior y otro para el revelado con los parámetros actuales (salvo los buffers de 8 bits de salida recortados al tamaño de la ventana que son uno por vista).
    Por eso sólo tiene que haber dos vistas en vez de cuatro. Dos revelados, dos vistas. Otra cosa sería un lío.

    Cita Iniciado por ariznaf Ver mensaje
    Todas ellas comparten los mismos dos buffers de entrada (Bitmap y OldBitmap).
    Eso no tiene mucho sentido. Cada vista tiene que tener sus propios buffers (1 normalmente y 2 si la vista es en pantalla partida). Si el día de mañana queremos meter cuatro vistas tienen que poder visualizar cada una un revelado distinto. Además, el modo de pantalla partida es incompatible con el resto. Los modos de visualización de la versión 1.0 los definimos en su día como:
    • Una sola vista
    • Dos vistas independientes H
    • Dos vistas enlazadas H
    • Dos vistas partidas H
    • Dos vistas independientes V
    • Dos vistas enlazadas V
    • Dos vistas partidas V
    Y no hay nada más. Lo que pasa es que las vistas partidas internamente son como una vista sola por el modo de dibujado que hemos diseñado (que es el óptimo, tal y como discutimos en su día), pero eso el usuario no tiene que notarlo, para él son dos revelados independientes que se muestran de ese modo. Solo en el modo de vista única hay un solo revelado, en el resto hay dos revelados y dos vistas a todos los efectos. Olvídate de más de dos vistas de momento. También definimos que los zooms eran siempre en potencias de 2, aunque tu algoritmo de reescalado lo permita, no permitas zooms que no lo sean desde C#.

    Cita Iniciado por ariznaf Ver mensaje
    El buffer con espacio de color y salida de monitor sólo es útil para mostrar en pantalla. No haría falta almacenarlo ¿no? Incluso se podría hacer al vuelo en convert16to8, antes de convertir, pasar a espacio de color de monitor y gamma de monitor, comprobar quemados (calcular histograma parcial?) y convertir a 8.
    Como ya he dicho, la conversión al espacio de color es una operación matricial, no se puede meter en una LUT, la gamma sí, y NO puede hacerse más rápida sin depender de hardware específico. Además, dado que todos los cálculos y la visualización van a tirar del mismo buffer, no tiene sentido sobrecargar la representación en pantalla metiendo ese cálculo en cada píxel. Se hace una sola vez de golpe al obtener la imagen y listo, ¿no crees? Cuando metamos LCMS a tope habrá que tener otro buffer por revelado con la corrección de la imagen en el monitor del usuario para que en pantalla se vea bien, pero los cálculos se hagan sobre la versión sin corregir. Pero todos los cálculos se hacen antes de mandar las imágenes a representar.

    Cita Iniciado por ariznaf Ver mensaje
    Si Lcms permite convertir un pixel individual, ya estaría.
    LCMS tiene una función que recibe un buffer y lo convierte. En el peor de los casos habría que pasarle TODO el bitmap resultante, nunca píxel a píxel. Si llegado el momento de meter LCMS consideramos que es mejor sacrificar velocidad a cambio de memoria consideraríamos la opción de pasar todo el buffer se salida de perfectImage al perfil del monitor. En este momento no hace falta meter ningún cálculo más a nivel de píxel. Ya se calculan los chivatos y la conversión a 8 bits... yo creo que es suficiente.

    Cita Iniciado por ariznaf Ver mensaje
    No puede ser muy lento si se usa una gamma con LUT y la conversión de LCMS es lineal (producto de vector por matrix).
    Como ya te he puesto más arriba, por cada píxel son 9 muls y 6 adds. Usar una LUT es muy rápido porque el procesador tiene operaciones específicas para eso. Lo único que podríamos ganar metiéndolo a nivel de píxel es: complicar y sobrecargar el código, y ahorrar un búffer de memoria extra en el futuro, ahora ni siquiera eso. Además, ¿no te parece más lógico que la gestión del color se haga sobre toda la imagen en una dll específica y que la dll que rerpesenta se dedique a eso, a representar?

    Cita Iniciado por ariznaf Ver mensaje
    Ten encuenta que sólo se calcula para los pixels mostrados en pantalla 800x600 o similar. El cálculo de chivatos se está haciendo al vuelo. No enlentece para nada. Es también una LUT. Por tanto sólo hay un buffer de 8 bits del tamaño de la ventana, sin ningún buffer intermedio.
    Creo sinceramente que no tiene mucho sentido que perfectImage se dedique a la gestión del color. Lo único que hace en ese sentido es la conversión de 16 a 8 bits porque hemos visto que es muy rápida y es el único sitio donde se necesita hacer. Lo demás lo lógico es hacerlo en una dll especializada. Además, para qué vamos a rehacer una y otra vez el mismo cálculo en cada fotograma si se puede hacer una sola vez de golpe y guardarlo en un buffer. ¿Por qué te preocupa tanto el uso de RAM y no el de CPU? Hoy en día es mucho más barato y fácil actualizar la RAM que la CPU.

    El cálculo de chivatos enlentence un poco, en mi máquina va un poco más a trompicones según esté activado o no, pero no es más que una comparación y una búsqueda en tabla por píxel, que está insertada como inline en el código, lo que tú dices implica, además del propio cálculo, llamar a una función por píxel que no se puede meter en línea, es decir: parámetros a la pila, ejecución, quita parámetros de la pila, vuelve. Y ¿qué ganas a cambio?

    En todo caso, podríamos considerar, como he puesto un poco más arriba, cuando metamos LCMS del todo convertir al perfil del monitor al final del reescalado en una sola llamada y a 8 bits, con el fin de ahorrar otro buffer. Eso lo podemos probar llegado el momento y tendría su lógica porque ese nuevo buffer sólo serviría para presentar en pantalla y, por tanto, puede ser lógico meterlo en ese punto, pero otra cosa no me cuadra. Creo que sería demasiado lento, pero como ya me equivoqué en mi estimación de que sería lenta la conversión a 16 a 8 bits (que requiere una sola operación), lo probaremos. Aunque de hacer un desplazamiento de bits a todo lo que supone lo otro hay un abismo.

    Cita Iniciado por ariznaf Ver mensaje
    De todas formas, tal y como está a mi no me salen tantos buffers. De tu mismo esquema salen los siguientes:
    1.-Los que almacene dcraw internamente (el último de ellos será el de salida lineal sin perfil ni gamma. Dices que son 5).
    2.-Uno de 16 bits convertido a espacio de color y gamma de salida.
    3.-Otro de 16 bits convertido a perfil de colro y gamma de monitor.
    El 1 y el 2 pueden ser el mismo según como lo montemos. El 3 no existiría al principio y sí cuando metiéramos LCMS o tal vez no si lo llamamos al vuelo en perfectImage. Así que son 1 ó 2 buffers por vista como máximo.

    Cita Iniciado por ariznaf Ver mensaje
    Como manejamos dos conjuntos de parámetros (actual y anterior) y 4 vistas de salida
    serán 2x(5+2) + 4 de 8 bits y tamaño de las ventanas de representación.
    dcraw.dll sólo mantendrá los buffers del revelado activo, los otros se desechan para ahorrar memoria. De momento no queda otro remedio.

    Cita Iniciado por ariznaf Ver mensaje
    ¿El buffer sin espacio de color ni gamma (el lineal) no es el que sale de dcraw en la última etapa? ¿No está ya contado en los 5?
    Bueno, ese es el 6, aunque como tengo desactivado el 0 son en total sólo 5. Pero internamente se copia sobre un Bitmap de 16 bits... eso aún no está muy definido hasta que no lo mezclemos todo. Creo que al meter LCMS se quedarán al final en 6 buffers por revelado activo + 2 por revelado inactivo. En total 8 como máximo.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  24. #24
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Pero lo que no entiendo en el planteamiento que se venía haciendo son las dificulatades expuestas por Manuel...
    Sólo digo que el histograma es muy rápido de calcular en lineal, pero en logarítmico implica usar otra LUT más para calcular el logaritmo y que no tiene sentido meterlo en el reescalado.

    Cita Iniciado por ariznaf Ver mensaje
    Aún en el caso de tener activado los histogramas, no es necesario almacenar el buffer. El almacenar el buffer es para no tener
    Efectivamente, los histrogramas se calculan y se guardan, porque ocupan mucha menos memoria que el buffer del que provienen. Si luego se desecha en buffer no pasa nada.

    Cita Iniciado por ariznaf Ver mensaje
    En realidad creo que será mejor almacenar el lineal y convertir a sRGB y Gamma monitor al vuelo, pero sino es posible, podermos convertirlo aquí deshaciéndonos del histograma gamma.
    No hay ninguna necesidad de usar una LUT inversa, los histogramas se calculan nada más obtener los buffers desde dcraw. El histograma parcial sí que se calcularía en perfectImagedll, pero siempre sobre el buffer de salida, no sobre el que tiene el perfil del monitor.

    Cita Iniciado por ariznaf Ver mensaje
    He pensado que si preocupa la memoria, todos los buffers intermedio de dcraw y demás de la imagen correspondiente al revelado anterior se pueden borrar.
    En realidad sólo necesitamos los finales, para mostrar la imagen, ya que los parámetros de revelado de la imagen previa no se van a alterar y no hay nada que acelerar.
    Sí, claro, en ese caso sí... eso ya se hace. ¡Que susto!, creía que te referías a desechar los del revelado activo .

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  25. #25
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por _GUI_ Ver mensaje
    Pero sin LCMS aún. Propongo olvidarnos de una gamma sRGB para pantalla y otra para la salida: si la salida se elige en ProPhoto por ejemplo, poco importa que su gamma 1.8 se vea oscura en pantalla, lo que más cantará es que los colores van a ser horribles.
    Voy a seguir haciendo pruebas con LCMS a ver si lo consigo hacer funcionar. Si lo consigo va en la versión 1.0 porque con que funcionara el ejemplo que puse sería suficiente, en caso contrario, no lo ponemos y lo hacemos como dices, que solo se vea bien en sRGB. Por tanto, es también mi opción.

    Cita Iniciado por _GUI_ Ver mensaje
    • El histograma logarítmico (Fernando, es éste, representa la imagen en 16 pasos de diafragma; se calcula fácil a partir de la imagen lineal, deshaciendo la gamma si no es lineal)
    El buffer lineal que sale de dcraw hay que mantenerlo sí o sí. Si no lo hacemos obligamos a revelar de nuevo al cambiar la gamma o el espacio de color de salida y no podremos poner el histograma logarítmico de la vista, porque podemos deshacer le gamma, pero no el espacio de color (por velocidad). Si lo mantenemos podemos calcular todos estos histogramas:
    1. Logarítmico de toda la imagen (obtenido del buffer lineal en colormng).
    2. Normal de toda la imagen (obtenido de la imagen de salida en colormng).
    3. Logarítmico de la vista (obtenido del buffer lineal en perfectImage).
    4. Normal de la vista (obtenido de la imagen de salida en perfectImage).
    Y tendríamos estos buffers de la imagen por cada revelado:
    1. Lineal 16 bits (no se puede desechar).
    2. El 1 con espacio de color de salida y gamma de salida.
    3. En el futuro el 2 con perfil del monitor o al vuelo sin buffer.
    Creo que este modelo es el más sensato de todos. Si nos preocupa la memoria (os recuerdo que aún no he metido la optimización de memoria en dcraw.dll) podemos ahorrar perdiendo el buffer 1 y por tanto el histograma 3 y revelando desde la etapa 4 ó 5 al cambiar la gamma/espacio de color de salida.

    Cita Iniciado por _GUI_ Ver mensaje
    Aunque me parece super galáctico superponer el histograma a la imagen, no le veo ventajas (más que eso, lo galáctico) y sí desventajas:
    Por mí vale. Tiramos a ventana aparte y nos dejamos de líos, que si no la versión 1.0 va a estar lista en navidades.

    Cita Iniciado por _GUI_ Ver mensaje
    • Único histograma en ventana popoup adicional que se abre solo al activarlo,
    • Anchos discretos de 256/512/1024 a elegir. No sé si se pueden forzar tamaños fijos, imagino que sí no?
    • Este histograma tiene 2 modos: imagen completa o porción de la vista actual (nunca echaremos en falta usar los dos a la vez así que la reutilización es positiva)
    • AlexG puede poner el histograma en su segundo monitor (cabronaso...)
    Suscribo punto por punto, incluido el cabronaso... .

    Cita Iniciado por _GUI_ Ver mensaje
    Por cierto, que el código de calcular los histogramas me gustaría hacerlo a mí. No necesito tener entorno, con que me digáis el nombre de las variables que contienen la imagen final y quizá cómo se dibujan píxels en pantalla me basta (no sé si con GDI la forma de trabajo es dibujar píxels o generar la imagen en 3 canales en un array de memoria y volcarla a pantalla, pero eso es lo de menos).
    Mi idea es meter en colormng.dll una función que calcula el histograma en un array y otra que pinta un Bitmap de GDI+ a partir del array que se le pase como parámetro (que puede ser el anterior o uno calculado sobre la vista) píxel a píxel. Como sólo hay que poner líneas verticales y horizontales (éstas últimas a base de memset) será mucho más rápido que andar tirando de funciones de GDI+ para pintar líneas y rellenar áreas. Luego en C# se añaden al Bitmap los textos que quieras (usando la fuente del GUI, claro). Yo te preparo el esqueleto de ambas funciones (la que calcula y la que pinta) y te lo paso. El Bitmap, como lo vamos a controlar nosotros y será BGR de 8 bits con ancho múltiplo de 4, tendrá un extra 0 a capón y será un código muy sencillito. Luego una vez pintado el Bitmap ariznaf puede desarrollar el formulario de la ventana que interactúa con él y trasladar el código de colormng que calcula el histograma para calcular el suyo de la vista en perfectImage. Así participamos todos, ¿qué os parece?

    Lo que no me parece demasiado lógico, _GUI_, es que lo hagas todo sin poder probarlo en casa. La parte del cálculo sí, la de pintar no creo que te salga a la primera. Yo creo que lo ideal es que yo te pase un formulario C# ya compilado (un EXE) que cargue una imagen, llame a colormng.dll para calcular su histograma, cree un Bitmap, llame a colormng.dll para pintar en histograma en ese Bitmap, y lo saque por pantalla. De ese modo tú sólo tienes que hacer funcionar el DEV-C++ (¿ya conseguiste que compilara con Vista?) y recompilar la DLL, ejecutas el EXE de C# que yo te paso y ves el resultado. ariznaf tiene el DEV-C++ corriendo en Vista, él puede ayudarte a configurarlo. En el peor de los casos te instalas una máquina virtual con un XP y listo.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  26. #26
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    Cita Iniciado por ManuelLlorens Ver mensaje
    Si lo mantenemos podemos calcular todos estos histogramas:
    1. Logarítmico de toda la imagen (obtenido del buffer lineal en colormng).
    2. Normal de toda la imagen (obtenido de la imagen de salida en colormng).
    3. Logarítmico de la vista (obtenido del buffer lineal en perfectImage).
    4. Normal de la vista (obtenido de la imagen de salida en perfectImage).


    Y tendríamos estos buffers de la imagen por cada revelado:
    1. Lineal 16 bits (no se puede desechar).
    2. El 1 con espacio de color de salida y gamma de salida.
    3. En el futuro el 2 con perfil del monitor o al vuelo sin buffer.
    No me queda claro si queda claro que el histograma log viene de la imagen final, solo a falta de la gamma. Es decir, el histograma logarítmico incluye el efecto de la conversión al perfil de color elegida por el usuario. Dicha conversión no deja de ser lineal por lo tanto la imagen resultante lo es y está lista para ser pasada a log de manera correcta.
    Así de nuevo el control lo tiene siempre el usuario; que éste quiere ver el histograma log tal como captó la información el sensor de su cámara? no tiene más que ajustar un balance de blancos nulo (multiplicadores 1 1 1 1) y no conversión a perfil de salida (-o 0).

    Por eso el buffer lineal clave quizá un buffer pre-gamma, o sea, justo antes de aplicar la gamma final, y que solo necesitaría calcularse cuando tengamos activado el histograma y además éste esté en modo log.
    Lo que pasa es que si la gamma la aplicas como en la versión mejorada de DCRAW que hiciste para trabajar con out[] en float y obtener un histograma final más rico:

    if(user_gamma==1){
    FORC3 img[c] = CLIP((int) out[c]);
    }else{
    FORC3 img[c] = CLIP((int) 65535.0*pow(MAX(out[c],0)/65535.0,gammaexp));
    }


    habría que obtener el buffer lineal pero con conversión a perfil de color previo a la gamma antes de hacer el: 65535.0*pow(MAX(out[c],0)/65535.0,gammaexp)



    Cita Iniciado por ManuelLlorens Ver mensaje
    Lo que no me parece demasiado lógico, _GUI_, es que lo hagas todo sin poder probarlo en casa. La parte del cálculo sí, la de pintar no creo que te salga a la primera. Yo creo que lo ideal es que yo te pase un formulario C# ya compilado (un EXE) que cargue una imagen, llame a colormng.dll para calcular su histograma, cree un Bitmap, llame a colormng.dll para pintar en histograma en ese Bitmap, y lo saque por pantalla. De ese modo tú sólo tienes que hacer funcionar el DEV-C++ (¿ya conseguiste que compilara con Vista?) y recompilar la DLL, ejecutas el EXE de C# que yo te paso y ves el resultado. ariznaf tiene el DEV-C++ corriendo en Vista, él puede ayudarte a configurarlo. En el peor de los casos te instalas una máquina virtual con un XP y listo.
    Totalmente de acuerdo, de hecho prefiero esta opción. Para ser pragmáticos y no intercambiar 1000 emails y volvernos locos los dos propongo visitar tu casa un día con mi portátil con el objetivo de dejarlo operativo en cuanto a poder compilar y todo el rollo, te parece? te lo agradecería muchísimo. Si Vista no es lo adecuado para montar el tinglado me llevo el XP de sobremesa bajo el brazo.
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  27. #27
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por _GUI_ Ver mensaje
    No me queda claro si queda claro que el histograma log viene de la imagen final, solo a falta de la gamma. Es decir, el histograma logarítmico incluye el efecto de la conversión al perfil de color elegida por el usuario. Dicha conversión no deja de ser lineal por lo tanto la imagen resultante lo es y está lista para ser pasada a log de manera correcta.
    Perfecto. Eso como lo definamos porque ni la conversión al espacio de color ni la gamma la va a hacer dcraw.dll, sino colormng.dll, es decir, que voy a duplicar el código. Sus funciones al respecto las dejamos sólo para la salida a disco. Mucho mejor así porque solo hay que invertir la LUT si queremos calcular el histograma logarítmico de la vista y no hay que guardar un buffer extra. En colormng.dll convertimos al espacio de color, calculamos el histograma logarítmico, aplicamos gamma y calculamos el histograma completo. En perfectImage.dll hacemos todo, al final, invertimos gamma, calculamos el histograma logarítmico de la vista, escalamos a 8 bits y listo. Todo rápido y ahorrando memoria.

    Cita Iniciado por _GUI_ Ver mensaje
    Totalmente de acuerdo, de hecho prefiero esta opción. Para ser pragmáticos y no intercambiar 1000 emails y volvernos locos los dos propongo visitar tu casa un día con mi portátil con el objetivo de dejarlo operativo en cuanto a poder compilar y todo el rollo, te parece? te lo agradecería muchísimo. Si Vista no es lo adecuado para montar el tinglado me llevo el XP de sobremesa bajo el brazo.
    ¡Tú lo quieres es darte un masaje en el sillón! De verdad que me gustaría ayudarte, el problema es que quedar en mi casa implicar quedar con los niños por el medio, sería mejor quedar en la calle, en un VIPS o similar, pero eso tiene que ser con el portátil, claro. Para ese plan no tengo mucho inconveniente, cualquier día de lunes a jueves a partir de las 21:30 es factible, hay uno cerca de mi casa. Además, a partir de la semana que viene tengo jornada intensiva y podría acercame yo a Pozuelo o a dónde puedas quedar tú (a pié o en transporte público porque no conduzco). Si puedo arreglarlo para que mi mujer se lleve a los niños un sábado por la mañana o algo así, perfecto, pero ya le estoy pidiendo mucho al enzararme en este proyecto y eso sería abusar. Por otro lado, hacer que DEV-C++ compile en Vista es algo que sabe hacer ariznaf, yo sólo uso XP, aunque siguiendo las instrucciones del hilo correspondiente debería estar chupado. ¿Porqué no le das a ariznaf acceso remoto a tu portátil y te pone en marcha el DEV-C++? De momento sólo necesitarás eso... y otro día vienes a casa y te das el masaje en el sillón.

    Como he puesto en el foro principal del módulo revelador (por cierto, he renombrado los dos temas principales de pruebas para que sean más claros), ya funciona colormng.dll con LCMS. Así que podremos meter gestión del color completa desde la versión 1.0 y sin apenas trabajo extra . Voy a completar el tema y a poner un flag para activar o desactivar la gestión de color y luego probaré su velocidad a ver si podemos meterlo en el último paso de DrawFast o hay que hacerlo antes en toda la imagen. Os mantendré informados.

    Un saludo:
    Última edición por ManuelLlorens; 28/05/2008 a las 15:58
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  28. #28
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Capici?

    Instálate Histogrammar y juega leyendo en él TIFFs salidos de DCRAW, lo entenderás muy bien. El histograma log solo tiene sentido si el TIFF suministrado es lineal (gamma=1.0).
    Perfecto!! Claro y meridiano como el agua. Jugaré con Histogrammer (ya lo tengo instalado )
    Ahora sí que lo he entendido.
    El diagrama normal calculado sobre una imagen lineal (sin compensación gamma) no resulta muy útil, nos da una imagen del histograma que se parece poco a lo que el ojo aprecia.
    Sin embargo en el que llamáis lineal, el eje x no está en realidad en representiación lineal sino en pasos de diafragma. Eso es lo que en realidad aprecia el ojo: necesita duplicar la intensidad de luz para apreciar un incremento de luminosidad significativo. Por eso los diafragmas son más significativos para la interpretación de cómo está iluminada una escena que la medida (lineal) de la intensidad de luz.

    Lo que planteaba Manuel varios mensajes más arriba era que el histograma lineal iba a ser mucho más lento de calcular por tener que calcular los diafragmas (logaritmos de base 2).
    En realidad se podrá hacer a través de una LUT también que calcule previamente cuál es el diafragma de salida de cada valor de entrada (en realidad serán desplazamientos de bits 1 bit de cada vez de los valores de entrada).
    Asi para contabilizar los pixels de un diafragma, recorremos la imagen y sumamos uno al contador pero no del valor almacenado en el canal, sino del valor correspondiente a la LUT almacenado para ese valor. Eso debería de ser bastante rápido.

  29. #29
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Por eso sólo tiene que haber dos vistas en vez de cuatro. Dos revelados, dos vistas. Otra cosa sería un lío.
    Bueno no era así como había interpretado yo la maqueta.
    Yo siempre estaba pensando en manejar únicamente dos conjuntos de parámetros de revelado uno anterior y el activo. Manejar más puede ser un lío para el usuario.
    Otra cosa es cuántas vistas quiero yo manejar de esa información (vistas en pantalla me refiero).

    Sí que tiene sentido manejar más de dos: en una puedo tener un zoom al 100% del revelado actual, en otra una imagen partida en vertical del revelado actual y anterior, en otra el histograma de la imagen actual (superpuesto el histograma a la imagen o sólo el histograma, a mi gusto) y en la última el histograma del revelado anterior.

    Mi idea era que el usuario tuviera control absoluto sobre qué quiere mostrar en una de las vistas de pantalla (4 como máximo) añadiendo o quitando histogramas, imagen partida, etc. De esa manera cada uno podría organizar la pantalla a su gusto, según las necesidades del momento, con 1, 2 o 4 vistas.

    La programación no se complica en absoluto, porque tenemos una sola clase (PerfectView) en la que se activan o desactivan las distintas opciones de visualización y luego hasta cuatro objetos de PerfectView representados en pantalla, trabajando todos ellos sobre los buffers de los dos revelados (actual y previo).
    Lo único que hay que poner es una forma de tener una vista activa resaltada, de manera que las opciones seleccionadas por el usuario en la interface que se refieran a las vistas (activar/desactivar histograma, intercambiar buffer actual y anterior, etc) se apliquen a la vista activa.

    ¿Qué véis de malo en este esquema? No ocupa más memoria y resulta flexible para el usuario. Y tampoco tiene más dificultad de programación. Yo así creía que estaba planteado en la maqueta desde el primer momento, pero por lo que veo no era eso exactamente.

  30. #30
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Estupenda noticia lo del LCMS, Manuel.

    Y si GUI necesita información sobre cómo compilar en vista con DEV-C++, no hay problema, había un hilo donde lo explicaba. Era sólo cuestión de establecer en las opciones de la aplicación los directorios donde están las librerías y otras utiliadades.

    GUI, usando messenger podré acceder a tu PC si lo necesitas ¿no?

    Manuel, he visto que has simplificado mucho el esquema de buffers y demás y todo ha quedado más claro.

    Únicamente resta ver si el buffer de color y gamma de monitor es necesario o se puede hacer al vuelo.
    En cualquier caso estamos hablando únicamente de dos o tres buffers de 16bits además de los de dcraw.
    Tendremos 5 de DCraw, 2 o tres intermedios para el revelado actual y únicamente uno o dos para el revelado anterior. Total 6 u 8 según almacenemos el de monitor o lo hagamos al vuelo.

  31. #31
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    ¿Qué véis de malo en este esquema? No ocupa más memoria y resulta flexible para el usuario. Y tampoco tiene más dificultad de programación. Yo así creía que estaba planteado en la maqueta desde el primer momento, pero por lo que veo no era eso exactamente.
    Yo no veo nada malo, no era como estaba definido pero puede que sea mejor. Además, si lo tienes hecho así y funciona es mejor dejarlo. Si a _GUI_ le parece bien... Ahora, _GUI_ tenía muy claro que el reescalado NN sólo nos es útil con factores de zoom que sean potencias de 2.

    La vista por defecto será una sola para que el que no quiera liarse no se lie.

    Lo que no entiendo bien de tu esquema, pero seguro que tú tienes algo pensado, es cómo asocia el usuario revelado y vista. Tienes dos revelados y hasta 4 vistas, ¿cómo tienes pensado indicar cuál corresponde a cada una?

    Quizás... en la parte de abajo se creen revelados con conjuntos de parámetros en plan A | B, marcando el activo en color (de momento verde). Arriba se asocia a cada vista que no sea partida si el revelado es el A o el B. ¿Algo así? Voy a preparar una maqueta en PS definitiva y así la podemos ver todos.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  32. #32
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Con el fin de documentar las dos opciones que estamos barajando en este momento y que se decidirán en función de lo rápida que sea la conversión al perfil de color del monitor de LCMS (en ensamblador, puede ser muy rápida aplicada a toda la imagen, pero habrá que verlo), he modificado el diagrama que ya puse arriba con la segunda opción. Pongo aquí lo dos juntos.

    Opción A, si LCMS es lento:


    Opción B, si LCMS es muy rápido:


    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  33. #33
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Yo no veo nada malo, no era como estaba definido pero puede que sea mejor. Además, si lo tienes hecho así y funciona es mejor dejarlo. Si a _GUI_ le parece bien... Ahora, _GUI_ tenía muy claro que el reescalado NN sólo nos es útil con factores de zoom que sean potencias de 2.
    Si existía algún motivo para impedir que se pudiera hacer un zoom x3 o x4 (porque afecte al histograma u otras opciones) y tienen que ser 2^N o 2^N no hay ningún problema en cambiarlo es únicamente añadir una linea al principio.
    Para forzar que los zooms sean enteros, el grado de zoom lo almaceno en un entero N y estoy calculando el zoom como 1/(1-N) si N<0 o 1+N si N >0.
    Bastaría cambiar eso por poner 2^N cuando se calcula el zoom al principio de los algoritmos de FastDraw.

    Lo que no entiendo bien de tu esquema, pero seguro que tú tienes algo pensado, es cómo asocia el usuario revelado y vista. Tienes dos revelados y hasta 4 vistas, ¿cómo tienes pensado indicar cuál corresponde a cada una?
    Revelado sólo hay uno en cada momento ¿no? Los parámetros del revelado afectan únicamente al revelado actual (o eso creía yo entender). Luego no hace falta definir sobre qué vista trabaja el revelado: afecta a todas las vistas.
    Lo que mostrarán las vistas partidas son el resultado del revelado en curso y el del revelado previo (o almacenado). Per el revelado previo o almacenado no se puede modificar. Para ello el usuario tendría que cancelar el revelado actual y volver al anterior.

    Otra cosa es escoger lo que se quiere mostrar en cada vista (vista partida, histograma, etc). Para no tener que poner controles diferentes para cada uno, habría una vista activa a la que se aplicaría todos los comandos de la interface que afecten a las vistas. Si quiere modificar lo que se ve en otra, seleccionaría esa otra como vista activa.

    En un futuro incluso se podría añadir una lista de historial de revelado, en la que se fueran almacenando los diferentes parámetros de revelado que se han ido probando para poder volver hacia atrás. Pero por ahora iría solo el actual y previo.
    Ya digo que así lo había entendido yo, pero si la idea era otra, no hay problema en cambiarlo, en realidad habrá poco que cambiar puesto que perfectview no se ve afectado en su funcionamiento actual y la interface todavía está en sus inicios.

    Sólo definir si es así como os parece bien que funcione o por el contrario se quiere
    Quizás... en la parte de abajo se creen revelados con conjuntos de parámetros en plan A | B, marcando el activo en color (de momento verde). Arriba se asocia a cada vista que no sea partida si el revelado es el A o el B. ¿Algo así? Voy a preparar una maqueta en PS definitiva y así la podemos ver todos.
    Algo así, yo lo que había puesto ahora era un radio buttom de intercambiar buffers. Lo que hace es hacer un swap de los dos buffers, de manera que lo que se muestra en un lado de la ventana partida pasa a mostrarse en el contrario.
    En el caso de la ventana simple, lo que hace es mostrar el buffer de revelado anterior en vez de el actual.

  34. #34
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Con el fin de documentar las dos opciones que estamos barajando en este momento y que se decidirán en función de lo rápida que sea la conversión al perfil de color del monitor de LCMS (en ensamblador, puede ser muy rápida aplicada a toda la imagen, pero habrá que verlo), he modificado el diagrama que ya puse arriba con la segunda opción. Pongo aquí lo dos juntos.
    Manuel, me parece perfecto, creo que están bastante claras las dos opciones.
    Como dices, el optar entre una y otra (almacenando un buffer previo para el espacio y gamma de monitor o haciendo esto al vuelo) dependerá de lo rápida que sea la conversión al vuelo en espacio de color y gamma. Creo que no irá mal, porque sólo hay que hacerlo sobre los pixels seleccionados para la ventana correspondiente.
    Será sólo cuestión de ver cuánto tarda en hacer conversión de color y gamma a una imagen de 1024x768 o 1600x1200 (que será el número de pixels a convertir en un momento dado para el monitor).

    Únicamente un par de matizaciones:
    • En ambas opciones, el histograma lineal lo pones en una sola cajita de colormng que da como salida conversión a espacio de salida y gamma.. Pero por lo discutido antes y expuesto por GUI, el histograma logarítmico se calcula después de aplicar el espacio de color de salida y antes de la gamma (por lo que contestaste lo tienes claro, pero no queda reflejado en el esquema). Habría que dividir la cajita en dos poniendo como la salida de la primera el histograma logarítmico y el flujo de datos convertido a espacio de color y la segunda cajita sólo hace el paso adicional de convertir a gamma de salida.
    • Tal y como está en la propuesta 1, parece que la cajita de colormng que da como salida el histograma completo y la conversión a monitor parte del flujo (buffer) ya convertido a espacio de salida. ¿Esto es así? la conversión a perfil de monitor ¿ha de hacerse desde el espacio de color de salida o desde el buffer lineal sin conversión? Hombre, seguramente lcms tenga que partir de un espacio estandar y conocido, y la información lineal de la cámara no le sirva sin convertir a un espacio conocido, pero lo pregunto por si acaso.
    • Añadiría únicamente especificar en qué puntos los flujos del buffer se almacenan (resaltándo el buffer en rojo o algo así a la salida y dándoles un número, para poder referirnos a ellos por número). En este aspecto, según lo que ha comentado GUI, el buffer a guardar sería el de espacio de salida sin conversión a gamma todavía, puesto que la gamma es rápida y el espacio de salida más lento. Por eso se hace también más necesario dividir esas dos fases en el esquema.
    En cuanto a la segunda opción poco más que decir. Lo mismo referente a las cajitas del histograma y si la conversión a perfil de monitor se hace desde el espacio de salida y no desde el lineal, entonces está bien.

    Lo único lo referente a la gamma de monitor:
    Si como entrada recibimos únicamente el buffer con la gamma de salida aplicada (como está en el esquema) entonces habrá que hacer sólo una conversión de gamma incremental únicamente y después de comprobar los pixels quemados y hacer el cálculo de histograma parcial.

    No hay problema en convertir la gamma de la gamma de salida a la gamma de monitor en vez de partir de la gamma lineal (1.0) ¿no?
    Sino habría que tomar los datos de ambos buffers: el de espacio y gamma de salida y el de espacio de salida con gamma lineal (antes de convertir a gamma de salida).

    Por último falta añadir la fase de escalado. Convendría que quedara reflejado en qué punto del flujo está:
    Tal y como está se hace a la vez que el chivato de altas luces, y únicamente sobre los pixels seleccionados, por lo que a nivel lógico es como si el chivato de altas luces se calculara después de hacer el escalado. La conversión a espacio de color de monitor y gamma de monitor con lcms también se haría después (y así sólo se aplica a la imagen ya escalada).
    Pero el histograma parcial ¿se ha de aplicar a la imagen ya escalada o a la parte de imagen que se ve en pantalla pero sin escalar?

    Yo creo que debe de ser previo al escalado, porque lo que interesa es saber qué información hay en esa zona de la imagen aunque en pantalla no se esté mostrando con el zoom ¿no?
    En ese caso el histograma parcial se haría en una subrutina a parte de la de escalado, pues no tiene utilidad el incorporarlo a la de escalado, ya que no ganamos mucho con ello.
    La del chivato tiene que ir en el escalado, pues necesitamos trabajar sobre los pixels de salida únicamente pero antes de convertirse a 8 bits.
    ¿Y la de conversión espacio y gamma de monitor?
    ¿Es suficiente conque se haga sobre imagen ya convertida a ocho bits?
    Si se ha de hacer sobre los valores de pixels en 16 bits y únicamente sobre los pixels ya escalados, las llamadas a las funciones de conversión han de hacerse necesariamente desde la subrutina de escalado.

    El esquema de la función en la parte que hace la conversión a 8 bits sería este, creo yo:

    Código:
     
    Para cada pixel seleccionado como pixel en la imagen de salida {
        Comprobar altas luces y marcar pixel si quemado.
        si está quemado {
           asignar color en 8 bits y espacio de monitor según canal quemado
        }
        si no está quemado {
             convetir a perfil de monitor
             aplicar diferencia de gamma entre monitor y salida utilizando LUT
             convertir a 8 bits
        }
    }
    Última edición por ariznaf; 28/05/2008 a las 19:48

  35. #35
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    No escribáis mucho que luego por la noche me agobio de ver tanto texto y en lugar de leeros me voy a otros foros a decir chorradas o me pongo a ver CSI Miami (Horatio, el puto amo)...
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  36. #36
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Aclaro el tema de las vistas.

    Hay dos revelados (A y B), uno activo y otro inactivo (no necesariamente el último revelado). Vamos a olvidarnos de momento de las vistas. Con un botón se podrá activar el revelado A o el B. Al hacerlo, se cambian todos los parámetros para reflejar los del revelado activo y si se cambian se vuelve a revelar ese mismo revelado, además se libera la memoria del revelado inactivo (menos el buffer 1, que es común a ambos y evita tener que volver a leer el archivo del disco). Si se cambia de archivo se borran los dos revelados y se vuelva a empezar con un solo revelado y una sola vista.

    Las vistas. Vamos a simplificar de momento y vamos a implementar solo dos vistas. Cuando todo funcione, lo tengamos claro y manejemos el GUI, veremos si hacen falta más. Es muy bueno que lo hayas implementado de un modo muy flexible porque así si queremos más o menos vistas apenas habrá que modificar nada.

    Estoy con la maqueta, en cuanto la acabe la subo y la explico.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  37. #37
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Al hacerlo, se cambian todos los parámetros para reflejar los del revelado activo y si se cambian se vuelve a revelar ese mismo revelado, además se libera la memoria del revelado inactivo (menos el buffer 1, que es común a ambos y evita tener que volver a leer el archivo del disco). Si se cambia de archivo se borran los dos revelados y se vuelva a empezar con un solo revelado
    Menos el buffer 1 y el final o los dos finales (espacio y gamma de salida y perfil y gamma de monitor, si es que al final se hace almacenándolo) ya que se necesitan para redibujar las vistas.

    Parece un funcionamiento bastante flexible, aunque veremos cómo funciona de cara al usuario y si no resulta confuso. Me gusta.

    En un futuro se podrán implementar snapshots (conjuntos de parámetros guardados) para cargar en el revelado activo y quedará una cosa muy muy flexible y práctica. Incluso se podrá habilitar un historial. Que sea para la versión 1.x

  38. #38
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Revelado sólo hay uno en cada momento ¿no? Los parámetros del revelado afectan únicamente al revelado actual (o eso creía yo entender). Luego no hace falta definir sobre qué vista trabaja el revelado: afecta a todas las vistas.
    No necesariamente. Lee la descripción que hago aquí y luego lo discutimos si no te parece bien.

    Cita Iniciado por ariznaf Ver mensaje
    En un futuro incluso se podría añadir una lista de historial de revelado, en la que se fueran almacenando los diferentes parámetros de revelado que se han ido probando para poder volver hacia atrás. Pero por ahora iría solo el actual y previo.
    Algo así tenía pensado... pero creo que eso habrá que hacerlo al final del todo.

    Cita Iniciado por ariznaf Ver mensaje
    Ya digo que así lo había entendido yo, pero si la idea era otra, no hay problema en cambiarlo, en realidad habrá poco que cambiar puesto que perfectview no se ve afectado en su funcionamiento actual y la interface todavía está en sus inicios.
    Sí, y el mérito es de tu implementación. Tenemos una clase muy versátil para adaptarla a lo que definamos ahora.

    Yo creo que como lo describo en la maqueta es útil y sensato. Pero ya me dirás cuando lo leas.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  39. #39
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    rápida que sea la conversión al vuelo en espacio de color y gamma.
    Al vuelo sólo es necesario convertir al perfil del monitor, porque el buffer que a ti te llega ya tiene el espacio de color y la gamma, ya que según _GUI_ debe tenerlo para calcular el histograma y los chivatos.

    Cita Iniciado por ariznaf Ver mensaje
    Será sólo cuestión de ver cuánto tarda en hacer conversión de color y gamma a una imagen de 1024x768 o 1600x1200 (que será el número de pixels a convertir en un momento dado para el monitor).
    Eso es. LCMS sí que linealiza con LUTS multidimensionales (¡el manual habla de hipercubos LUT!) el cálculo y lo calcula en ensamblador (si se activa esa opción al compilar). Así que imagino que irá bastante rápido, pero habrá que probarlo.

    Cita Iniciado por ariznaf Ver mensaje
    Únicamente un par de matizaciones:
    • En ambas opciones, el histograma lineal lo pones en una sola cajita de colormng que da como salida conversión a espacio de salida y gamma.. Pero por lo discutido antes y expuesto por GUI, el histograma logarítmico se calcula después de aplicar el espacio de[...]
    Sí, llevas razón, internamente tendrá que usar una LUT inversa para quitar la gamma antes de calcular el histograma logarítmico parcial. Pero como eso ocurre internamente creía que era más claro dejarlo así en el esquema.

    Cita Iniciado por ariznaf Ver mensaje
    • Tal y como está en la propuesta 1, parece que la cajita de colormng que da como salida el histograma completo y la conversión a monitor parte del flujo (buffer) ya convertido a espacio de salida. ¿Esto es así? la conversión a perfil de monitor ¿ha de hacerse desde el espacio de color de salida o desde el buffer lineal sin conversión? Hombre, seguramente lcms tenga que partir de un espacio estandar y conocido, y la información lineal de la cámara no le sirva sin convertir a un espacio conocido, pero lo pregunto por si acaso.
    Son tres cosas distintas:
    • Conversión al espacio de color de salida.
    • Compensación de gamma de salida (por defecto la que corresponda al espacio de color de salida, pero configurable por el usuario).
    • Conversión al dispositivo de salida.
    Las dos primeras se hacen en ese punto, la última al final del todo y sólo si se activa la opción correspondiente de la vista (míralo en la maqueta).

    Cita Iniciado por ariznaf Ver mensaje
    • Añadiría únicamente especificar en qué puntos los flujos del buffer se almacenan (resaltándo el buffer en rojo o algo así a la salida y dándoles un número, para poder referirnos a ellos por número). En este aspecto, según lo que ha comentado GUI, el buffer a guardar sería el de espacio de salida sin conversión a gamma todavía, puesto que la gamma es rápida y el espacio de salida más lento. Por eso se hace también más necesario dividir esas dos fases en el esquema.
    El que se guarda es con espacio de color y gamma de salida, pero sin conversión al dispositivo de salida. Así es como ha definido _GUI_ que debemos hacer los cálculos, con la salvedad de los histogramas logarítmicos que van con espacio de color de salida pero sin gamma. Uno se calculará antes de aplicar la gamma y el otro (siempre sólo si se pide claro) antes de presentar aplicando la gamma inversa (pero sin quitarle la gamma al buffer, solo se mete una LUT inversa para llenar el histrograma logarítmico, obviamente).

    Cita Iniciado por ariznaf Ver mensaje
    En cuanto a la segunda opción poco más que decir. Lo mismo referente a las cajitas del histograma y si la conversión a perfil de monitor se hace desde el espacio de salida y no desde el lineal, entonces está bien.
    Sí, eso seguro.

    Cita Iniciado por ariznaf Ver mensaje
    Lo único lo referente a la gamma de monitor:
    No se corrige a la gamma del monitor, únicamente a su perfil ICC. La gamma será la que especifique el usuario. Lo único que pretende la gestión de color ICC es que los colores se vean bien aunque el espacio de color de tu pantalla no coincida con el que has especificado en la salida (es decir, cualquiera que no sea sRGB).

    Cita Iniciado por ariznaf Ver mensaje
    Pero el histograma parcial ¿se ha de aplicar a la imagen ya escalada o a la parte de imagen que se ve en pantalla pero sin escalar?
    Es exactamente lo mismo, ¿no? Lo único que cada píxel te aparecerá n^2 veces, con dividir entre ese valor ya lo tienes. Lo que sí está claro es que hay que calcularlo antes de meter los chivatos, porque si no saldrán los propios chivatos en el histograma. Ya iremos definiendo eso bien para que vaya rápido.

    Cita Iniciado por ariznaf Ver mensaje
    ¿Y la de conversión espacio y gamma de monitor?
    ¿Es suficiente conque se haga sobre imagen ya convertida a ocho bits?
    Sí, esa es una duda que tengo. Yo creo que podría ser suficiente, pero podemos hacerla en 16 bits. Creo que habrá que hacer lo siguiente:

    Dentro de perfectImage.dll, justo antes de escalar a 16 bits, se copia el cacho que se va a sacar por pantalla aún a 16 bits y se manda la copia a lcms.dll (a través de colormng.dll para encapsularlo bien) para que calcule el histograma logarítmico sin la gamma y lo convierta al perfil de la pantalla; a la vuelta escalamos y calculamos los chivatos sobre el buffer que no hemos mandado, pero los pintamos sobre el otro. Si no queremos complicarlo tanto mantenemos un segundo buffer ya calculado por imagen y es mucho más fácil de implementar.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  40. #40
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por _GUI_ Ver mensaje
    No escribáis mucho que luego por la noche me agobio de ver tanto texto y en lugar de leeros me voy a otros foros a decir chorradas o me pongo a ver CSI Miami (Horatio, el puto amo)...
    Lo he intentado. He puesto una maqueta que es más visual que leer. Mañana intentaré hacer un cómic con todo el proyecto para que no te aburras leyendo ... no te preocupes, en alguna viñeta saldrá Horatio.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  41. #41
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Bueno, muy bien, esto va quedando mucho más claro, Manuel.
    He entendido bien que la conversión lcms a perfil de monitor ha de hacerse desde el espacio de salida.

    El buffer ya almacena la conversión gamma de salida y lo que se plantea es deshacer la gamma si en un paso posterior es necesario sin gamma (como en el histograma logarítmico).

    No se corrige a la gamma del monitor, únicamente a su perfil ICC. La gamma será la que especifique el usuario. Lo único que pretende la gestión de color ICC es que los colores se vean bien aunque el espacio de color de tu pantalla no coincida con el que has especificado en la salida (es decir, cualquiera que no sea sRGB).
    Esto sí que no lo he entendido muy bien... Hasta ahora había entendido que se manejaba un espacio de color y una gamma de salida y luego (para su correcta visualización) una perfil de monitor y una gamma de monitor (como bien dices si se activa la gestión de color).
    Si no es así y el monitor tiene una respuesta de luminisodad muy distinta a la del monitor, la luminosidad no se verá como está en la imagen ¿no?
    Por ejemplo, si el usuario decide usar una gamma de salida lineal 1.0 y el monitor es un monitor standar con gamma 2.2, la imagen la va a ver muy oscura aunque seleccione la opción de gestionar el perfil de color y no la verá como finalmente se va a reproducir si la imprime con el photoshop correctamente, con una impresora perfilada y con gestión de color.

    Disculpa si estoy equivocado, pero creo que eso es lo que ocurriría y no es lo que se buscaba ¿no?.
    Habría que aplicar una gamma que fuera la diferencia entre la del monitor y la de salida.

    Es exactamente lo mismo, ¿no? Lo único que cada píxel te aparecerá n^2 veces, con dividir entre ese valor ya lo tienes. Lo que sí está claro es que hay que calcularlo antes de meter los chivatos, porque si no saldrán los propios chivatos en el histograma. Ya iremos definiendo eso bien para que vaya rápido.
    No, no es exactamente lo mismo... si lo hacemos sobre la imagen una vez escalada, efectivamente es multiplicar por n^2 puesto que cada pixel está repetido nxn veces en dirección horizontal y vertical.

    Pero yo lo que planteo es que lo suyo sería utilizar para el cálculo del histograma la porción de imagen original que está en pantalla CON TODOS SUS PIXELS, antes de eliminar pixels en un zoom de reducción.
    Como los pixels que no se ven en pantalla pueden tener unos colores diferentes que los que se están mostrando, el histograma no será igual (aunque lógicamente se podrán parecer).

    En un zoom ampliado, tampoco habría que multiplicar por nxn ya que al usuario no le interesa lo que está en pantalla, sino lo que había en esa zona que está viendo EN LA IMAGEN ORIGINAL.

  42. #42
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Esto sí que no lo he entendido muy bien... Hasta ahora había entendido que se manejaba un espacio de color y una gamma de salida y luego (para su correcta visualización) una perfil de monitor y una gamma de monitor (como bien dices si se activa la gestión de color).
    Si no es así y el monitor tiene una respuesta de luminisodad muy distinta a la del monitor, la luminosidad no se verá como está en la imagen ¿no?
    Por ejemplo, si el usuario decide usar una gamma de salida lineal 1.0 y el monitor es un monitor standar con gamma 2.2, la imagen la va a ver muy oscura aunque seleccione la opción de gestionar el perfil de color y no la verá como finalmente se va a reproducir si la imprime con el photoshop correctamente, con una impresora perfilada y con gestión de color.
    Es un tema que no tengo demasiado claro, la verdad. A ver si Hugo nos lo puede aclarar. Pero supongo que llevas razón, que con la gestión de color activada las imágenes deben verse en pantalla más o menos exactamente igual independientemente del espacio de color de salida y una gamma de salida que escoja el usuario. Si es así (y de momento lo voy a implementar así), habrá que escoger:
    • Perfil de entrada de la cámara (en el futuro).
    • Espacio de color de salida.
    • Gamma de salida.
    • Perfil del monitor (sRGB o calibrado).
    • Gamma del monitor.
    Y entonces, el buffer que se muestra en pantalla no llega nunca a aplicar la gamma de salida, sino directamente la del monitor, pero sí el espacio de color de salida y luego se convierte al perfil del monitor. Ya veremos.

    Cita Iniciado por ariznaf Ver mensaje
    No, no es exactamente lo mismo... si lo hacemos sobre la imagen una vez escalada, efectivamente es multiplicar por n^2 puesto que cada pixel está repetido nxn veces en dirección horizontal y vertical.
    Sí, llevas razón de nuevo, no lo había pensado para reducciones. Pues como tú lo veas.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  43. #43
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like

    Velocidad de LCMS

    Bueno, pues ya he hecho una prueba de velocidad de LCMS y me temo que tendremos que hacerlo una sola vez sobre toda la imagen y guardar dos buffers por cada revelado.

    He convertido de un perfil a otro una imagen de 800x600 (y podemos tener vistas más grandes que eso) 1000 veces y ha tardado 122.5 segundos, es decir que tenemos poco más de 8 fotogramas por segundo. Eso no es suficiente para dar un aspecto suave al scroll/zoom de las vistas, que necesita un mínimo de 20 fps.

    Hago 1000 veces sólo la conversión, no la carga de los perfiles y lo hago en toda la imagen en un sólo paso. LCMS podría ir más rápido si compilara con la opción de usar algoritmos en ensamblador, pero eso limitaría la portabilidad y requeriría cambios más laboriosos en su código fuente (porque la sintaxis para incluir ensamblador en gcc es muy diferente a la que usa LCMS... lo malo es que LCMS no admite el uso de ensamblador en entornos que no sean Windows, así que creo que es mejor dejarlo así. De momento no se puede hacer más rápido. Pego un poco de código:

    Código:
    #ifdef NON_WINDOWS
    
    [...]
    
    #ifdef  USE_ASSEMBLER
    #  undef  USE_ASSEMBLER
    #  define USE_C               1
    #endif
    ¿Alguno os animáis a traducir de la sintaxis de ensamblador de VC++ a la de gcc? Esto sería lo que habría que reescribir:

    Código:
    ASM {
                  xor       eax, eax
                  mov       ax, word ptr ss:Value
                  mov       edx, ss:xDomain
                  mul       edx                         //  val3 = p -> Domain * Value;
                  shld      edx, eax, 16                // Convert it to fixed 15.16
                  shl       eax, 16                     // * 65536 / 65535
                  mov       ebx, 0x0000ffff
                  div       ebx
                  mov       ecx, eax
                  sar       ecx, 16                        // ecx = cell0
                  mov       edx, eax                       // rest = (val2 & 0xFFFFU)
                  and       edx, 0x0000ffff                // edx = rest
                  mov       ebx, ss:LutTable
                  lea       eax, dword ptr [ebx+2*ecx]     // Ptr to LUT
                  xor       ebx, ebx
                  mov        bx, word  ptr [eax]           // EBX = y0
                  movzx     eax, word  ptr [eax+2]         // EAX = y1
                  sub       eax, ebx                       // EAX = y1-y0
                  js        IsNegative
                  mul       edx                            // EAX = EAX * rest
                  shld      edx, eax, 16                   // Pass it to fixed
                  sal       eax, 16                        // * 65536 / 65535
                  mov       ecx, 0x0000ffff
                  div       ecx
                  add       eax, 0x8000                    // Rounding
                  sar       eax, 16
                  add       eax, ebx                       // Done!
                  }
    
                  RET((WORD) _EAX);
    
           IsNegative:
    
                  ASM {
                  neg       eax
                  mul       edx                            // EAX = EAX * rest
                  shld      edx, eax, 16                   // Pass it to fixed
                  sal       eax, 16                        // * 65536 / 65535
                  mov       ecx, 0x0000ffff
                  div       ecx
                  sub       eax, 0x8000
                  neg       eax
                  sar       eax, 16
                  add       eax, ebx                       // Done!
                  }
    
                  RET((WORD) _EAX);
    }
    Es que el formato de ensamblador de gcc es un peñazo. Un enlace por si alguien se anima. Al final acabaré perdiendo una tarde que me aburra mucho.

    Otra opción sería compilar el .c que tiene las funciones en asm con VC++ y enlazarlo. Lo he intentado pero no lo he conseguido. Finalmente no he conseguido llamar a la DLL ya compilada que se puede descargar de la página web desde C, lo que sería otro posibilidad de ir más rápido.

    Por tanto, yo apuesto por dos buffers.

    Fernando, toma nota: lo que sí que vamos a probar es a cambiar la conversión de 16 a 8 bits que usamos, out=(PX8)(in>>8), por ésta otra que usa LCMS y que debe ser más precisa (que no más rápida):

    Código:
    #define RGB_16_TO_8(rgb) (PX8) ((((rgb) * 65281 + 8388608) >> 24) & 0xFF)
    Un saludo:
    Última edición por ManuelLlorens; 31/05/2008 a las 02:15
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  44. #44
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like

    Nuevo flujo de información

    Después de consultarlo con la almohada, he pensado que no hace falta tener dos buffers de 16 bits por vista, sino que basta con uno de 16 con el espacio de color y la gamma de salida sobre el que calcular el histograma y los chivatos y otro de 8 bits convertido al perfil del monitor y con la gamma del monitor, como decía ariznaf.

    De ese modo el cálculo será rápido, no desperdiciaremos memoria, porque un buffer de 8 bits ocupa muy poca memoria, y los cambios en el código son mínimos.

    El esquema de trabajo quedaría así (lo explico más abajo):

    • Obtenemos, como siempre, un buffer de 16 bits con color crudo desde dcraw.dll (en el futuro lo podremos obtener corregido por el perfil de la cámara si está incrustado en el RAW, de momento tiene que ser así, y ya veremos si lo otro no nos complica demasiado la vida).
    • En colormng.dll aplicamos el espacio de color de salida.
    • Obtenemos desde ese buffer (con espacio de salida, pero sin gamma) el histograma logarítmico de la imagen completa.
    • Aquí tenemos una bifurcación según esté activada la gestión de color (ICC) o no lo esté (NO ICC):
      • Con ICC: se duplica el buffer obtenido desde dcraw y se convierte, por una parte al perfil de monitor, se aplica gamma de monitor y se convierte el resultado a 8 bits. Por la otra parte se aplica gamma de salida (corregido _GUI_) al otro buffer, que se deja en 16 bits.
      • Sin ICC se hace una copia en 8 bits del buffer tras aplicarle gamma de salida.
    • En ambos casos se calcula el histograma lineal completo de la imagen desde un buffer de 16 bits con espacio de color y gamma de salida.
    • Ahora volvemos a perfectRAW con dos buffers, uno de 16 bits para hacer los cálculos y otro de 8 bits para mostrar en pantalla.
    • En perfectImage.dll se calcula el trozo de la imagen total que se va a representar y (si se está pidiendo histograma parcial logarítmico) se manda ese trozo del buffer a colormng.dll para que invierta la gamma de salida mediante una LUT inversa y calcule el histograma logarítmico de la vista.
    • Se calcula el histograma lineal de la vista a partir del trozo recortado, pero no reescalado a 16 bits de la imagen.
    • Se reescalan ambos buffers (esta operación se hace en un sólo bucle), calculando a la vez los chivatos sobre el buffer de 16 bits, pero pintándolos sobre el buffer de 8 bits.
    • Terminamos con una vista de 8 bits con los histogramas y chivatos todos calculados a 16 bits desde los buffers que determinó _GUI_, desperdiciando muy poca memoria (unos 20 megas por revelado) y con el volcado a pantalla muy rápida y con gestión del color.
    Obviamente, algunos pasos no se ejecutan según el valor de los parámetros (espacio de color de salida crudo, gamma 1, etc.).

    Ahí queda eso, ahora a opinar.

    Un saludo:
    Última edición por Guillermo Luijk; 01/06/2008 a las 16:01
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  45. #45
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    Yo lo veo perfecto (he corregido un perfil de monitor por salida arriba). Para una primera pasada se pueden obviar los histogramas logarítmicos que son solo flecos finales que no afectan al flujo, y añadirlos luego.

    Solo me pregunto una cosa: la gamma del monitor se aplica por separado de la gamma de salida elegida por el usuario. La gamma del monitor cuál es? va implícita en el perfil del monitor o será un dato más a introducir por el usuario? lo digo porque tal como está establecido ahora, si revelamos en lineal y con gamma de salida lineal (1.0), el TIFF de salida será efectivamente lineal (es decir, histograma pegado a la izquierda), pero al activar la gestión ICC en pantalla saldrá bien. En la gamma de pantalla se podrá poner 1.0 también?
    Si no activamos la gestión ICC por pantalla saldrá la imagen oscura, es decir con gamma 1.0, pero con colores erróneos porque no se ha convertido de Adobe RGB por ejemplo al perfil del monitor (similar a sRGB). Mi duda es: con el esquema actual podemos llegar a ver la imagen oscura (gamma 1.0) en pantalla, pero con los tonos correctos?

    Le mando un email a Hugo Rodríguez sobre si le parece correcto el flujo de gestión de color. Te pongo en copia Manuel.
    Última edición por Guillermo Luijk; 01/06/2008 a las 16:36
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  46. #46
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por _GUI_ Ver mensaje
    Yo lo veo perfecto (he corregido un perfil de monitor por salida arriba). Para una primera pasada se pueden obviar los histogramas logarítmicos que son solo flecos finales que no afectan al flujo, y añadirlos luego.
    No creo que calcular los histogramas ralentice mucho, lo más lento es la conversión al perfil del monitor.

    Cita Iniciado por _GUI_ Ver mensaje
    Solo me pregunto una cosa: la gamma del monitor se aplica por separado de la gamma de salida elegida por el usuario. La gamma del monitor cuál es? va implícita en el perfil del monitor o será un dato más a introducir por el usuario? lo digo porque tal como está establecido ahora, si revelamos en lineal y con gamma de salida lineal (1.0), el TIFF de salida será efectivamente lineal (es decir, histograma pegado a la izquierda), pero al activar la gestión ICC en pantalla saldrá bien. En la gamma de pantalla se podrá poner 1.0 también?
    Si no activamos la gestión ICC por pantalla saldrá la imagen oscura, es decir con gamma 1.0, pero con colores erróneos porque no se ha convertido de Adobe RGB por ejemplo al perfil del monitor (similar a sRGB). Mi duda es: con el esquema actual podemos llegar a ver la imagen oscura (gamma 1.0) en pantalla, pero con los tonos correctos?
    Esa era un poco la duda que teníamos Fernando y yo. En principio la gamma del monitor debes ponerla en la configuración del programa y debe ser aquella para que has calibrado el monitor, ayer si recuerdas calibramos tu monitor para gamma 2.2... pues esa tendrás que poner. Con el esquema actual será tan fácil como dar a config y poner 1.0 en la gamma de tu monitor y dejar activada la gestión de color de la vista para ver los colores correctos pero con gamma 1.0. Vamos, que tenemos TODAS las posibilidades contempladas. Otra cosa será que si vemos que ese cambio (activar/desactivar la gamma del monitor) es importante y se va a querer hacer a menudo, el botón ICC de la vista se descomponga en dos, uno para activar el perfil del monitor y otro para la gamma del monitor de modo que no haya que entrar en la configuración de la aplicación para hacer el cambio. Eso es fácil de implementar.

    Cita Iniciado por _GUI_ Ver mensaje
    Le mando un email a Hugo Rodríguez sobre si le parece correcto el flujo de gestión de color. Te pongo en copia Manuel.
    Esa será nuestra mejor garantía.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  47. #47
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Bueno, pues está claro: si lo del lcms es lento, habrá que tener dos buffers.
    Con el esquema que planteas, manteniendo sólo uno de 16 bits y otro de ocho, no se consume mucha memoria y parece que tendremos lo mejor de los dos esquemas, únicamente a costa de tener que deshacer la aplicación de la gamma de salida para algunas operaciones.

    He tomado nota de lo que dijiste de la conversión a 8 bits y ya he modificado la función PixelFrom16To8 con el nuevo código.

    Lo de la gamma de monitor, efectivamente creo que se tiene lo mejor también: poder aplicar o no gestión de color y la gamma si se quiere se puede cambiar.
    Si es de interés, sería fácil poner un checkbox o algo para aplicar o no la gamma de monitor.


 

Marcadores

Marcadores

Permisos de publicación

  • No puedes crear nuevos temas
  • No puedes responder temas
  • No puedes subir archivos adjuntos
  • No puedes editar tus mensajes
  •