PDA

Ver la versión completa : Sobre el funcionamiento del Zoom



ariznaf
19/05/2008, 15:34
Hay una cosa que no me gusta en cómo funciona el zoom actualmente.

Cuando le damos a la rueda del botón para aumentar el zoom, el punto que se conserva en la imagen presentada es el de la esquina superior izquiera de la ventana. Lo que despista un poco, pues da la sensación de que toda la imagen se desplaza hacia abajo y la derecha.
Además cuando se reduce el zoom la cosa no funciona igual, pues cuando la imagen pasa a ocupar menos que la ventana de repente "salta" y se centra en la ventana.

Creo que sería más intuitivo si la imagen mantuviera siempre el punto central de la ventana en el centro durante los zooms.

Mejor aún sería que el punto que se mantuviera en su lugar dentro de la ventana fuera el correspondiente al punto sobre el que se encuentre el ratón en el momento de hacer el zoom (al darle a la rueda), pues será el punto sobre el que el usuario mantiene en ese momento la atención y se mantendría en su sitio sin saltar a ninguna otra posición.
Creo que sería mucho más intuitivo.

Guillermo Luijk
19/05/2008, 15:49
Mejor aún sería que el punto que se mantuviera en su lugar dentro de la ventana fuera el correspondiente al punto sobre el que se encuentre el ratón en el momento de hacer el zoom (al darle a la rueda), pues será el punto sobre el que el usuario mantiene en ese momento la atención y se mantendría en su sitio sin saltar a ninguna otra posición.
Creo que sería mucho más intuitivo.

Esto es lo que planteó Manuel al principio, y sería lo ideal. El visor de imágenes de Vista funciona así.

ManuelLlorens
19/05/2008, 17:09
Esto es lo que planteó Manuel al principio, y sería lo ideal. El visor de imágenes de Vista funciona así.

Efectivamente, así es como funcionará al final... aún no he tenido tiempo de implementarlo, pedís más rápido de lo que yo puedo programar :D:D:D:D.

Si puedo esta tarde/noche hago lo siguiente:
Meto el ajuste de exposición y un slider en el revelador para probarlo. Además de una gamma sRGB rápida y subo el resultado para que jugueteéis.
Subo la prueba del GUI con el parpadeo definido "a lo _GUI_" y el cálculo de 16 bits (con desplazamiento de bits) y zoom en el punto del cursor e imagen partida en vertical.
Cierro el fallo que aún afecta a la reentrada en dcraw.dll. Cuando esté TODO eso subiré a SVN. Esto de la dll depende de la inspiración más que del tiempo.Si no me da tiempo subiré al menos la prueba del GUI a 16 bits para que pobréis la velocidad y seguiré trabajando en el resto de cosas. El zoom en el punto del cursor a lo mejor puede ariznaf cambiarlo y eso que me ahorro yo.

Un saludo:

ariznaf
19/05/2008, 18:09
Si no me da tiempo subiré al menos la prueba del GUI a 16 bits para que pobréis la velocidad y seguiré trabajando en el resto de cosas. El zoom en el punto del cursor a lo mejor puede ariznaf cambiarlo y eso que me ahorro yo.


Pues lo puedo intentar.
De hecho he estado jugueteando con lo de dibujar una elipse/rectángulo encima de la imagen para seleccionar el patch de bits con el que hacer el cálculo de balance de blancos y ya me funciona... bueno menos por una cosa: el centrado que se produce cuando la imagen ocupa menos que la ventana, que me lo desconfigura todo.

Pero el cálculo de las transformaciones algebráicas para colocar la imagen, creo que debe de hacerse fuera del fastdraw, en PerfectView, para que la transformación sea idéntica para el dibujo del bitmap y el dibujo de los patch.

He mirado el código que hay al inicio de fastdraw que hace el cálculo del zoom y del centrado y la verdad es que es endemoniado, no conseguí aclararme muy bien.

Otra cosa es el tema del zoom: por lo que veo no todos los zooms se hacen, algunos de ellos se convierten al mismo valor. Esto afectará a la tranformación a realizar fuera de fastdraw, pues ha de hacerla con el zoom final que se utiliza y o con el valor almacenado como float, pues sino las transformaciones serían distintas.

Necesitaría algo más de aclaración sobre cómo implementaste esto.

Guillermo Luijk
19/05/2008, 18:40
he estado jugueteando con lo de dibujar una elipse/rectángulo encima de la imagen para seleccionar el patch de bits con el que hacer el cálculo de balance de blancos y ya me funciona... bueno menos por una cosa: el centrado que se produce cuando la imagen ocupa menos que la ventana, que me lo desconfigura todo.

Si empiezas a picar código para lo del balance de blancos, yo sugiero estas dos formas geométricas:

Rectángulo: con el primer click se establace una de sus esquinas, se arrastra el ratón, y cuando se suelta se establece la segunda esquina que define el rectángulo (puede estar más arriba y/o a la izquierda qeu la primera, lo suyo es acto seguido asegurar que (x0,y0) es la esquina sup. izq., y (x1,y1) es la esquina inf. derecha, donde x0<=x1 y y0<=y1).
Elipse: con el primer click se define el centro de la elipse y a medida que se arrastra el ratón se van definiendo los dos radios que la definen.


Cuando se pasa de un modo al otro, el rectángulo/elipse previamente definido se convierte de manera biunívoca en la otra forma geométrica:
Las esquinas (x0,y0) y (x1,y1) del rectángulo se transforman en el centro de la elipse inscrita en dicho rectángulo: (x2,y2)=( (x0+x1)/2, (y0+y1)/2 ) y sus radios respectivos Rx=(x1-x0)/2 y Ry=(y1-y0)/2.
El paso contrario es sencillo también: x0=x2-Rx, y0=y2-Ry, x1=x2+Rx, y1=y2+Ry

Yo las coordenadas las hice todas relativas a una imagen de tamaño 1x1 (es decir, representaban coordenadas en tanto por 1), y luego convertía mediante width y height a los píxels reales. Como os sea más fácil.

Lo complicado es adecuar la representación y la entrada de datos al grado de zoom del display y posición de la imagen en un momento dado. Yo no tuve ese problema porque ZN no tiene zoom :)



http://img394.imageshack.us/img394/2065/wbff3.gif

ManuelLlorens
19/05/2008, 19:03
Pues lo puedo intentar.
En principio tienes que implementarlo en la función MakeZoom, a la que habrá que pasarle el punto X,Y en el que se ha hecho click respecto a las coordenadas del pictureBox y corregidas con el Zoom. Como tú ya habías hecho tu propia implementación de MakeZoom es mejor que no haga yo otra porque tendrás que cambiar tú otras cosas.

La idea es cambiar el cálculo que hacía yo antes en MakeZoom:


bX = (int)(pX[view]+ w[view] / (2*Zoom[view]));
bY = (int)(pY[view]+ h[view] / (2*Zoom[view]));

Zoom[view] *= ZoomQ;

pX[view] = (int)(bX - w[view] / (2 * Zoom[view]) + 1);
pY[view] = (int)(bY - h[view] / (2 * Zoom[view]) + 1);

Por otro en el que se tengan en cuenta las coordenada en las que estaba el ratón al mover la rueda y mantenga ese punto, no sus coordenadas absolutas claro, sino las relativas a la imagen final. En bX y bY (de before zoom X y before zoom Y) se calcula la esquina superior izquierda actual de la imagen, luego en pX, pY se calcula la nueva coordenada X,Y de la imagen para que sea igual a la anterior, lo que viene a partir de ahí lo dejas como está, que es para que se pare en los bordes, en los que no se podrá mantener el punto en el centro, claro.


De hecho he estado jugueteando con lo de dibujar una elipse/rectángulo encima de la imagen para seleccionar el patch de bits con el que hacer el cálculo de balance de blancos y ya me funciona... bueno menos por una cosa: el centrado que se produce cuando la imagen ocupa menos que la ventana, que me lo desconfigura todo.
Tienes que rehacer tú ese cálculo, que es fácil:


cx=(int)((float)width/2-(int)((float)width2*z/2.0)); cy=(int)((float)height/2-(int)((float)height2*z/2.0));

if(cx<0) cx=0;
if(cy<0) cy=0;
if((int)(cx+width2*z)>=width) cx=0;
if((int)(cy+height2*z)>=height) cy=0;

Es muy parecido al cálculo de antes, calcula desde el centro del buffer de salida, en qué coordenada hay que empezar a pintar (de ese buffer de salida) para que con el Zoom actual, quepa la mitad de la imagen en la mitad izquierda del buffer de salida.

Luego se asegura de que la coordenada no quede fuera del buffer de salida.


Pero el cálculo de las transformaciones algebráicas para colocar la imagen, creo que debe de hacerse fuera del fastdraw, en PerfectView, para que la transformación sea idéntica para el dibujo del bitmap y el dibujo de los patch.
Sí estoy de acuerdo. La clase tiene toda la información necesaria para hacer el cálculo. Otra cosa es dejar que sea el propio fastdraw el que calcule _y_ dibuje el rectángulo o el círculo, que es otra posibilidad. Pero yo creo que para eso GDI+ sí es suficientemente rápido. Habrá que decidir si se puede crear un rectángulo más allá de los bordes de la vista actual y si se podrá cambiar el zoom sin dejar de pintar. En principio se debería poder.


He mirado el código que hay al inicio de fastdraw que hace el cálculo del zoom y del centrado y la verdad es que es endemoniado, no conseguí aclararme muy bien.
Sí, estaba un tanto poseído cuando lo hice :mad:, :D:D:D:D... tienes que replicar _exactamente_ lo mismo que hace la DLL en C#, no puede ser complicado, la sintaxis de C y C# es similar.


Otra cosa es el tema del zoom: por lo que veo no todos los zooms se hacen, algunos de ellos se convierten al mismo valor. Esto afectará a la tranformación a realizar fuera de fastdraw, pues ha de hacerla con el zoom final que se utiliza y o con el valor almacenado como float, pues sino las transformaciones serían distintas.
No hombre, sí se hacen todos los zooms. Lo que pasa es que cuando no pones un break; en un case: de un switch sigue al case siguiente. Es decir, que los zooms x1/32, x1/16, x1/8, x1/4 y x1/2 se hacen con el mismo algorirmo, pero teniendo en cuenta el valor del zoom. Por otro lado se hace el x1 (bueno en la versión de 16 bits ya no), y lo mismo para x2, x4 y x8, que se hacen con el mismo algoritmo. Lo he dejado así por si me animo a optimizar el algoritmo NN en cada caso, aunque ahora que vamos a meter la gamma y el parpadeo en el propio fastdraw no queda mucho espacio para optimizar.

Por cierto, como vamos a usar sRGB a capón voy a crear una LUT para exactamente 65536 valores con esa gamma y se hace en tiempo de visualización con solo una búsqueda de tabla, que en los procesadores actuales es rapidísimo... ya puestos...


Necesitaría algo más de aclaración sobre cómo implementaste esto.
Sobre esto que te cuento, pregunta lo que necesites. En realidad programo casi siempre por intuición, así que tampoco puedo darte muchas más explicaciones. Tendría que ponerme a analizar más a fondo lo que yo mismo he hecho :P:P:P:P:P.

Un saludo:

ariznaf
19/05/2008, 19:21
Sí estoy de acuerdo. La clase tiene toda la información necesaria para hacer el cálculo. Otra cosa es dejar que sea el propio fastdraw el que calcule _y_ dibuje el rectángulo o el círculo, que es otra posibilidad. Pero yo creo que para eso GDI+ sí es suficientemente rápido. Habrá que decidir si se puede crear un rectángulo más allá de los bordes de la vista actual y si se podrá cambiar el zoom sin dejar de pintar. En principio se debería poder.
Esto creo que es mejor hacerlo en GDI+. Ya lo he hecho y va perfecto (salvo por el tema de los zooms menores que 1), dibujando sobre el objeto Image del PictureBox una vez que lo hemos establecido con el bitmap de salida de FastDraw.
Además se puede dibujar fuera de la ventana. De hecho yo hago una transformación para que las coordenadas coincidan con las de la imagen total al dibujar con esa transformación, si el círculo queda fuera de la ventana, no se dibuja nada, pero cuando se haga el pan de la ventana a la zona donde cae el círculo, este aparece y el GDI hace el clipping.


No hombre, sí se hacen todos los zooms. Lo que pasa es que cuando no pones un break; en un case: de un switch sigue al case siguiente. Es decir, que los zooms x1/32, x1/16, x1/8, x1/4 y x1/2 se hacen con el mismo algoritmo, pero teniendo en cuenta el valor del zoom. Por otro lado se hace el x1 (bueno en la versión de 16 bits ya no), y lo mismo para x2, x4 y x8, que se hacen con el mismo algoritmo. Lo he dejado así por si me animo a optimizar el algoritmo NN en cada caso, aunque ahora que vamos a meter la gamma y el parpadeo en el propio fastdraw no queda mucho espacio para optimizar.
Ah! bueno, es que como lo ponías en el mismo case creía que sólo hacías el mayor de los zooms por ahorrar cases. Si el código lo contempla, no hay problema.
Ya me extrañaba porque lo de dibujar parecía funcionar bien.

Lo del parpadeo sí, pero lo de la gamma, ya comenté antes que creo que sería mejor hacerlo una sola vez sobre la imagen de 16 bits revelada (aunque la "estropee"). Cuando se vaya a guardar en disco o clipboard habría que hacer un revelado completo nuevamente.

Así evitaremos un cálculo de gamma cada vez que se cambie el zoom o se haga desplazamiento de la ventana.
Según GUI la gamma no afecta a los pixels quemados (no cambia el valor del 0 y el 65535) por tanto se puede hacer antes que esto.
Hacerlo después de los pixels quemados afectaría al color mostrado para los pixels quemados que no sería un valor medio (aunque no creo que eso sea importante).
En cualquier caso si se quiere hacer después por el motivo que sea, lo suyo sería hacerlo después del FastDraw sobre los 356 bits (aunque no sea tan exacto) ¿no?

ManuelLlorens
19/05/2008, 21:58
Según GUI la gamma no afecta a los pixels quemados (no cambia el valor del 0 y el 65535) por tanto se puede hacer antes que esto. Hacerlo después de los pixels quemados afectaría al color mostrado para los pixels quemados que no sería un valor medio (aunque no creo que eso sea importante). En cualquier caso si se quiere hacer después por el motivo que sea, lo suyo sería hacerlo después del FastDraw sobre los 356 bits (aunque no sea tan exacto) ¿no?
Depende de si se pone un umbral de píxeles quemados o no. Si se pone entonces sí afecta la gamma. A los valores extremos de 0 y 65535 no afecta, pero al resto sí. El problema es que si se pone la gamma antes de marcar los píxeles quemados y se usa un umbral se mostrarán los píxeles quemados con esa gamma, si la gamma de salida va a ser diferente los píxeles quemados pueden cambiar. Y por otro lado, si se marcan los píxeles quemados en gamma lineal luego pueden aparece más al corregir en gamma. Así que una de dos: o marcamos píxeles quemados sin umbral, o los marcamos usando la gamma real que se quiera usar... que _GUI_ decida.

De todos modos creo que con una LUT como la que comento no habrá ningún problema de velocidad (y se sería exactamente igual de rápida en 16 que en 8 bits), visto lo visto con el desplazamiento. Además, sería muy fácil cambiar la tabla cuando se meta la gestión de color en la aplicación. Las búsquedas en tablas están también muy optimizadas en el procesador. Lo que pretendo es mapear en una tabla los 0-65535 valores, antes de corregir como índices a la tabla, y una vez corregidos con la gamma como valores de la tabla. De ese modo no hay que hacer ningún cálculo, sólo cambiar un valor por el valor que la tabla da para ese valor como índice:

valor16=LUT(valor16); // Antes de pasar a 8 bits.
Eso por cada canal, obviamente. Probaré a ver qué tal va de velocidad, que es la solución para todo en este proyecto :D:D:D.

Un saludo:

ariznaf
19/05/2008, 23:43
Depende de si se pone un umbral de píxeles quemados o no. Si se pone entonces sí afecta la gamma. A los valores extremos de 0 y 65535 no afecta, pero al resto sí. El problema es que si se pone la gamma antes de marcar los píxeles quemados y se usa un umbral se mostrarán los píxeles quemados con esa gamma, si la gamma de salida va a ser diferente los píxeles quemados pueden cambiar. Y por otro lado, si se marcan los píxeles quemados en gamma lineal luego pueden aparece más al corregir en gamma. Así que una de dos: o marcamos píxeles quemados sin umbral, o los marcamos usando la gamma real que se quiera usar... que _GUI_ decida.

Tienes razón, cuando se usa umbral afectará un poquito. Pero los valores muy altos y muy bajos serán los menos afectados (la curva llega a 0 y 65535) por tanto les afectará poco. Además si el umbral es ajustable, no será un problema grave, porque se podrá modificar un poco el umbral en función de la gamma al gusto del usuario.

Yo lo de la gamma (la corrección para el monitor) lo haría antes de llamar a FastDraw para ahorrar tiempo de cálculo y dejar un código más limpio. Añadirá algún pixel quemado más, pero eso se puede modificar cambiando el umbral.
Incluso se puede pensar en meter el umbral correspondiente a una gamma lineal y modificar el valor del umbral en función de la gamma (convirtiendo el valor correspondiente a 65535-umbral con la curva de gamma. El valor que salga será el nuevo umbral).

Si aún así creéis imprescindible hacerlo después de los pixels quemados, será mejor hacerlo a posteriori del reescalado. El código será más entendible y además facilitará cambios posteriores en el flujo del procesamiento de la imagen revelada.

Lo de la LUT me parece una gran idea. ¿La generas al cargar la dll?
El sitio adecuado para ponerla sería en el DLLMain de la dll, al cargarla, podrías calcular todos los valores de la curva gamma entre 0 y 65535. Así te evitas ponerla a pedal en el código.
Hombre puesto en el código como una tabla const será un pelín más rápida probablemente, por las optimizaciones que pueda hacer el procesador al ver que multiplica por valores constantes en vez de por el valor de una variable.
Pero no sé si merece la pena.

ManuelLlorens
20/05/2008, 10:47
Lo de la LUT me parece una gran idea. ¿La generas al cargar la dll? El sitio adecuado para ponerla sería en el DLLMain de la dll, al cargarla, podrías calcular todos los valores de la curva gamma entre 0 y 65535. Así te evitas ponerla a pedal en el código.
Eso había pensado hacer. La LUT se genera rapidísimo, no se nota. Creo que al obtener la imagen dcraw hay que hacer lo siguiente:

Imagen de dcraw (16 bits) -> Obtención del histograma completo (image.dl) -> Aplicación de gamma sRGB rápida (pero precisa) (image.dll) -> Visualización de esa copia en una vista a 8 bits (image.dll) -> Histograma parcial de la vista (image.dll).

Como ahora tú mantienes image.dll te pasaré código en C para las tres cosas nuevas que pongo arriba y tú lo integras.

_GUI_, lee y comenta estos dos párrafos que siguen:
Luego, la visualización o no del histograma parcial puede ir en GDI+. Me queda la duda de si la aplicación de la gamma afecta al balance de blancos, que entiendo que no, y por tanto, no hace falta guardar una copia del buffer que devuelve dcraw sin aplicar la gamma, ya que hemos definido que los píxeles quemados se calculan después de aplicar la gamma.

Otra cosa que quiero definir: dice _GUI_ que pongamos un slider para el control del punto de saturación (creo que mejor será un control numericUpDown que es más preciso que un slider, pero ese es otro tema). Digo yo que lo lógico sería poder poner el umbral del marcado de píxeles quemados igual al punto de saturación de la cámara, ¿no? Para eso, ambos controles deben estar juntos en el GUI y con una opción de enlazarlos de modo que al mover uno lo haga el otro, ¿qué os parece?

Un saludo:

ariznaf
20/05/2008, 11:29
Imagen de dcraw (16 bits) -> Obtención del histograma completo (image.dl) -> Aplicación de gamma sRGB rápida (pero precisa) (image.dll) -> Visualización de esa copia en una vista a 8 bits (image.dll) -> Histograma parcial de la vista (image.dll).
Dos cositas nada más... "la imagen que dices imagen de dcraw" me imagino que ya está procesada: interpolación (demosaicing) --> corrección de exposición --> conversión al espacio de color de salida --> corrección de altas luces -->[/quote]
La corrección de gamma de dcraw no la vamos a usar nada más que para la salida a TIFF, la reharemos en la DLL. Lo demás sí es así.


Creo que ese es el orden y no me dejo nada. No estoy seguro si lo del espacio de color va ahí, pero creo que sí, que eso había dicho GUI pues puede afectar a las luces quemadas.
Va ahí, la gamma de dcraw se aplica justo después de la conversión al espacio de salida (dentro de la misma función, de hecho), la de perfectRAW va a aplicarse al final del todo, una vez dentro de la aplicación. Es posible que acabemos cambiando la de dcraw igual, que lo defina _GUI_.


-No hacer la conversión de la gamma de salida de la imagen en la etapa de revelado y aplicar la gamma de visualización en la etapa de visualización. La LUT sería siempre la misma (mientras no se modifique la gamma de visualización). La gamma de salida sólo se aplicaría en el momento de guardar la imagen en el "revelado definitivo".
Eso es lo entiendo que haremos.


Lo que llamas image.dll en el proyecto final ya lo he cambiado: será PerfecImageDLL para seguir con el espíritu de nombres del resto del proyecto.
Sí, así será.

Un saludo:

Guillermo Luijk
21/05/2008, 00:30
Uy no había visto este hilo sorry:


_GUI_, lee y comenta estos dos párrafos que siguen:

Luego, la visualización o no del histograma parcial puede ir en GDI+. Me queda la duda de si la aplicación de la gamma afecta al balance de blancos, que entiendo que no, y por tanto, no hace falta guardar una copia del buffer que devuelve dcraw sin aplicar la gamma, ya que hemos definido que los píxeles quemados se calculan después de aplicar la gamma.

El balance de blancos es muy anterior a la gamma, es incluso anterior al demosaicing. La secuencia sería:


Ajuste negro y sat. de cámara y conversión a float
Balance de blancos
Interpolación Bayer (algoritmos)
(Recuperación de altas luces)
(Corrección de exposición; modos)
Conversión a perfil de color
Gamma
(Cálculo chivato zonas quemadas e histograma) - solo para display, no afectan a la imagen final
Salida Clipboard/TIFF





Otra cosa que quiero definir: dice _GUI_ que pongamos un slider para el control del punto de saturación (creo que mejor será un control numericUpDown que es más preciso que un slider, pero ese es otro tema). Digo yo que lo lógico sería poder poner el umbral del marcado de píxeles quemados igual al punto de saturación de la cámara, ¿no? Para eso, ambos controles deben estar juntos en el GUI y con una opción de enlazarlos de modo que al mover uno lo haga el otro, ¿qué os parece?


A ver son cosas distintas:

El punto de saturación del RAW: es un asunto hardware por llamarlo de algún modo. El revelador debería mostrar el valor que lleva DCRAW de cada cámara, y además permitir que se pueda corregir con un control preciso como tú indicas -> es un paso necesario del revelado, es decir, afecta fuertemente al revelado RAW
El umbral del chivato de luces quemadas, es puro display, y es posterior a todo el proceso de revelado. Es una saturación software por decirlo de algún modo.



El primero será del orden de 2^n con n los bits del RAW. Por ejemplo en el fuente de DCRAW puede verse:

{ "Canon EOS 40D", 0, 0x3f60,
{ 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } },

0x3f60 = 16224, punto de saturación incorrecto de la 40D. Ya nos dedicaremos a corregir esos fallos en el fuente de DCRAW, pero lo ideal es que nuestro revelador permita establecerlo por si fuera erróneo (es el comando -S de DCRAW)

El segundo será 65535 menos el umbral que queramos poner. Precisamente, poner un punto de saturación incorrecto en 1 dará lugar a que zonas quemadas del RAW no sean detectadas como tales porque no alcanzarán el valor 65535 tras el revelado, lo que nos ayudará a corregir con 2 el punto de saturación del sensor y hacer un revelado milimétrico.


Estos aspectos son muy importantes para qeu este revelador sea realmente "algo diferente" a todo lo existente. Os queda claro el pipeline del revelado?

ManuelLlorens
21/05/2008, 11:30
El balance de blancos es muy anterior a la gamma, es incluso anterior al demosaicing.
No me refiero a dónde se aplique la corrección de WB, sino a sobre qué buffer se hará el cálculo de los multiplicadores seleccionando una zona en la vista de perfectRAW. ¿Quieres decir que tendremos que calcular el balance de blancos sobre un buffer de dcraw antes de la interpolación?



A ver son cosas distintas:
El punto de saturación del RAW: es un asunto hardware [...]
El umbral del chivato de luces quemadas, es puro display, [...]
Sí, eso lo tengo claro, la cámara mide en 10/12/14 bits, y nosotros tenemos 16 bits. Entiendo que al cambiar el punto de saturación y volver a revelar seguiremos teniendo valores entre 0-65535 y eso no afecta al chivato de luces quemadas. Es cierto.


[...] "algo diferente" a todo lo existente. Os queda claro el pipeline del revelado?
A mí sí, salvo por la duda que pongo arriba, ¿el cálculo de WB de perfectRAW debe hacerse sobre un buffer pre-interpolado? Si es así habrá que guardar siempre ese buffer y no vamos a poder optimizar mucho más el uso de memoria de la DLL, quizás pueda quitar algún otro buffer pero lo veo cada vez más difícil (no de programar que ya lo tengo pensado sino que al final necesitamos casi todos los buffers para una cosa u otra). Le daré otra vuelta.

Un saludo:

Guillermo Luijk
21/05/2008, 12:11
No me refiero a dónde se aplique la corrección de WB, sino a sobre qué buffer se hará el cálculo de los multiplicadores seleccionando una zona en la vista de perfectRAW. ¿Quieres decir que tendremos que calcular el balance de blancos sobre un buffer de dcraw antes de la interpolación?

(...)

A mí sí, salvo por la duda que pongo arriba, ¿el cálculo de WB de perfectRAW debe hacerse sobre un buffer pre-interpolado? Si es así habrá que guardar siempre ese buffer y no vamos a poder optimizar mucho más el uso de memoria de la DLL, quizás pueda quitar algún otro buffer pero lo veo cada vez más difícil (no de programar que ya lo tengo pensado sino que al final necesitamos casi todos los buffers para una cosa u otra). Le daré otra vuelta.



Te contesto aquí: Sobre el Balance de Blancos con parches (http://www.ojodigital.com/foro/showthread.php?t=204519).

ariznaf
21/05/2008, 12:28
Contestación movida al hilo anterior empezado por GUI

ManuelLlorens
21/05/2008, 12:35
El flujo de revelado creo que lo has dejado bastante claro...

No estaría mal que Manuel pusiera ahora (sobre el flujo de revelado que tú has puesto) dónde están los buffers intermedios que se almacenan y si son de 32 o de 16.
He contestado en Etapas del revelado con perfectRAW (http://www.ojodigital.com/foro/showthread.php?t=204517).


Creo que lo que dice Manuel es importante: el proceso de interpolación creo que es de los más lentos. Si se pone antes el balance de blancos que la interpolación, la cosa va a ir bastante más lenta, pues cada vez que se toque el balance de blancos (que puede ser algo más o menos habitual) hay que reinterpolar y rehacer todos los buffers.
Habrá que escoger interpolación lineal al principio, es muy rápida. Yo creo que habrá que mantenerla casi todo el rato y cambiar de interpolación al final.


Poner un buffer tras la aplicación del balance de blancos no mejoraría nada creo yo Manuel, pues el cálculo del balance de blancos creo yo que se muchísimo más rápido que el interpolado ¿no?
Eso depende de dónde se calculen los multiplicadores, si en C# o en dcraw.dll. Si es en lo primero hay que tener la información en C# y eso requiere pasar un buffer (no hay problema con eso porque el buffer ya se crea en ese punto). Pero creo que lo haremos en dcraw.dll para que sea más rápido.

Un saludo:

Guillermo Luijk
21/05/2008, 13:14
Habrá que escoger interpolación lineal al principio, es muy rápida. Yo creo que habrá que mantenerla casi todo el rato y cambiar de interpolación al final.

Perfecto a que sea la interp. aplicada por defecto, pero siempre que el usuario pueda cambiarla en un momento dado, y cuando lo haga se vea en pantalla, tarde lo que tarde.

ManuelLlorens
21/05/2008, 13:29
Perfecto a que sea la interp. aplicada por defecto, pero siempre que el usuario pueda cambiarla en un momento dado, y cuando lo haga se vea en pantalla, tarde lo que tarde.
Evidentemente, pero en el manual de la aplicación habrá que explicar el tema de los buffers para que sepan que la interpolación lenta es mejor elegirla en una etapa avanzada del revelado.

Un saludo:

Guillermo Luijk
30/05/2008, 01:46
Fernando, he calculado valores de zoom intermedios a los que ya teníamos (potencias de 2) para tener un proceso de zoom más suave pero garantizando:
Que la percepción del aumento/disminución de zoom siga siendo lineal
Que en ningún caso se deforme la imagen con nearest neighbour

Me salen estos valores:


Zoom reducir: 1/32x 1/23x 1/16x 1/11x 1/8x 1/6x 1/4x 1/3x 1/2x
No Zoom: 1x
Zoom aumentar: 2x 3x 4x 6x 8x



http://img515.imageshack.us/img515/1335/zoomqw1.gif

Recuerdo que pusísteis el código del zoom pero no lo encuentro, quería mirar si usabais el hecho de que la secuencia era una potencia de 2 para simplificarlo; si es así siento pedir esta mejora.


En el zoom para reducir se hace un diezmado, es decir, es toma 1 de cada 32 filas de píxels, 1 de cada 23, 1 de cada 16,... y en los dos ejes claro.
En el zoom para aumentar es obvio, cada píxel original aparece replicado en superpíxels de 2x2, 3x3, 4x4,... píxels.


Cómo lo véis? por cierto dónde estaba el código a que me refería? lo suyo sería traerlo a este hilo.

Salu2

ManuelLlorens
30/05/2008, 09:29
Zoom reducir: 1/32x 1/23x 1/16x 1/11x 1/8x 1/6x 1/4x 1/3x 1/2x
No Zoom: 1x
Zoom aumentar: 2x 3x 4x 6x 8x
Pues que los implemente ariznaf, y vemos qué tal va. Según lo que comenta él de cómo lo ha implementado parece que tendrá que hacer pocos cambios.


http://img515.imageshack.us/img515/1335/zoomqw1.gif


Recuerdo que pusísteis el código del zoom pero no lo encuentro, quería mirar si usabais el hecho de que la secuencia era una potencia de 2 para simplificarlo; si es así siento pedir esta mejora.
Desde que metimos el escalado a 16 bits se acabó la posibilidad de optimizarlo, así que ya da igual. A Fernando no le funcionaba el x10, que veo que no hace falta, si le funcionan el resto ya estaría listo. En caso contrario seguro que es algún detalle y Fernando lo arregla en breve.

Un saludo:

ariznaf
30/05/2008, 15:01
Bueno, el código está ahora en una fase intermedia de cambio...
Como os había dicho se la pegaba alguna vez con algunos factores (por encima de 10).

No creo que tenga nada que ver con el factor de zoom en realidad, sino con algún bug que no conseguí locallizar.

El algoritmo del nearest neighbour puede implementar cualquier escalado que sea un factor entero es decir xN o 1/N, ya que lo único que hace es saltarse N pixels (en zoom 1/N) de la imagen original o copiar un pixel N veces de la imagen orginal (en zoom xN).

El código ahora admite un número entero zoomFactor y calcula el zoom como 1/(1-zoomFactor) para zoomFactor <0 o 1+zoomFactor para zoomFactor >=0.
Por tanto cualquier zoomFactor es posible.

Lo que no tenía ni idea es que lo del zoom como potencia de 2 fuera por un tema de percepción del ojo...
Implementar lo que tú dices no será ningún problema: cuando el usuario aumente el zoom con la rueda, en vez de sumar 1 a zoomFactor (o reducir 1) lo único que habrá que hacer es pasar al siguiente valor de la lista permitida, para evitar zooms intermedios.

Estos días no he podido programar casi nada... a ver si me pongo un día a fondo con ello y lo acabo.
Tengo un buen tinglao con lo del zoom centrado y alguna modificación en el funcionamiento de perfectView.
El cálculo del zoom y de la zona de la imagen original que se ve exactamente en la ventana, lo he pasado al código C#, por el motivo de que al calcular el centrado, tenía que duplicar el código en los dos sitios, para poder calcular "dónde se iba a parar la imagen". No tenía mucho sentido duplicarlo, pues cualquier modificación en el funcionamiento, daría lugar a bugs.
Eso no afectará al rendimiento, pues son cálculos previos al proceso de escalado, y se hace para toda la imagen, no pixel a pixel.

Guillermo Luijk
30/05/2008, 15:21
Lo que no tenía ni idea es que lo del zoom como potencia de 2 fuera por un tema de percepción del ojo...

claro, potencias de 2 o potencias de lo que sea. Para que al girar la rueda tengamos una percepción lineal de aumento del grado de zoom, cada paso debe aumentar/disminuir la imagen en la misma proporción (factor) que el anterior. Por ejemplo si implementaras todos los posibles grados de aumento conviertiendo 1 píxel en 2, luego triplicándolo, luego cuadriplicándolo,... obtendrías una secuencia de tamaños: 1,2,3,4,...,400,401,... en los primeros saltos la imagen aumentaría mucho (de 1 a 2 es duplicar el tamaño), mientras en los últimos apenas habría cambio (de 400 a 401). Las percepción al usar un zoom así es que el control se ha atascado y que llegado un punto aquello ya no aumenta más de tamaño.

Pero con potencias de 2 (que es el factor entero más pequeño) aún teníamos pocos pasos intermedios de modo que el zoom, siendo progresivo, era brusco (en dos clicks tu imagen pasaba de ser enana a no caber en la pantalla). Lo que he hecho es introducir entre cada 2 valores antiguos de zoom uno extra, eligiendo el factor entero que mejor siga la progresión lineal de percepción de aumento (log). El único punto donde se rompe es justo a ambos lados del zoom 1x, pero es que es imposible reescalar por nearest neighbour a tamaños intermedios entre 1x y 2x, y entre 1x y 1/2x, sin distorsionar la imagen.

Son refinamientos, pero si se puede hacer bien por qué hacerlo mal, no?

ManuelLlorens
30/05/2008, 15:24
Fernando, a mí me parece perfecto como lo tienes ahora. Y este proyecto es una carrera de fondo, no hay prisa.

Un saludo:

Guillermo Luijk
04/06/2008, 09:22
Fernando, rutina real para ajuste en nearest neighbour de la imagen al área disponible en el formulario (modo de zoom adicional):



Const MAXX As Integer = 557 ' Dimensiones en pixels del área gráfica disponible en la vista,
Const MAXY As Integer = 317 ' es decir en el formulario (en tu caso serán variables)

Dim i As Integer, j As Integer, iMaxX As Integer, iMaxY As Integer
Dim rRatio As Double

lWidth = MyObj1.Width ' MyObj1 es la imagen
lHeight = MyObj1.Height
rRatio = lWidth / lHeight

Set MyObj2 = New GflAx.GflAx ' MyObj2 es la vista
If rRatio > MAXX / MAXY Then
iMaxX = MAXX
iMaxY = Int(MAXX / rRatio)
Else
iMaxX = Int(MAXY * rRatio)
iMaxY = MAXY
End If
MyObj2.NewBitmap iMaxX, iMaxY ' iMaxX x iMaxY será el área disponible para la vista
' que se llenará con píxels

For i = 0 To iMaxX - 1
For j = 0 To iMaxY - 1
lColour = MyObj1.GetColorAt((lWidth - 1) * i / (iMaxX - 1), (lHeight - 1) * j / (iMaxY - 1))
MyObj2.LineColor = lColour
MyObj2.DrawPoint i, j
Next j
Next i

Guillermo Luijk
08/06/2008, 15:19
Sé que soy un pesado pero jugando con Perfect RAW creo que estaría bien poder llegar a un grado de zoom mayor, sobre todo en pantallas con mucha resolución, 16x. Para seguir con el escalonado progresivo se añadiría el valor intermedio no potencia de dos 11x:


Zoom reducir: 1/32x 1/23x 1/16x 1/11x 1/8x 1/6x 1/4x 1/3x 1/2x
No Zoom: 1x
Zoom aumentar: 2x 3x 4x 6x 8x 11x 16x



http://img217.imageshack.us/img217/8906/dibuzs3.jpg

Tal como está hecho el código es muy sencillo añadirlos no?

ManuelLlorens
15/01/2009, 12:55
Dado que este tema ya está claro e implementado y que la versión con OpenGL también, cierro este hilo.