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 14 de 14
  1. #1
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like

    Sobre la implementación de PerfectView

    Estoy desarrollando un control PerfectView que encapsula el comportamiento de las Vistas de la imagen.
    El control se encarga del reescalado de la imagen original y su recorte, así como de la superposición de otra información como pixels quemados, histograma, etc.

    El código base para el reescalado y manejo a bajo nivel de los bitmaps lo implementa ManuelLlorens en la librería PerfectImageDLL.

    El control para el encapsulado se basa en el código fuente de la maqueta del visualización partida en dos ventanas proporcionado por ManuelLlorens.

    Pondré aquí las dudas que me surjan en la interpretación de dicho código o los problemas de implementación, destinadas principalmente a ManuelLlorens, pero también a cualquier otro que las pueda responder.
    _________________________________
    Manuel tengo algunas dudas con el código:
    1. Manuel, en el Form1_Load, al hacer el LockBits, estableces un PixelFormat.Format24bppRgb...
      eso ¿es sólo en esta prueba porque la imagen es un jpeg o debe de quedar así?
      ¿No debería de ser de 16bits por color, es decir Format48bppRgb?
      ¿O es que la imagen que llega aquí ya va a estar siempre convertida a 8bits?
      Yo creía que fastdraw trabajaba directamente sobre la imagen procedente del revelado efectuado con dcraw y por tanto en 16 bits (o float 32 cuando se haga todo en 32 bits).
    2. Sobre las variables que manejas tengo algunas dudas sobre su significado. Pongo a continuación lo que yo creo que son y me corriges sino es así.
      Zoom= grado de zoom.
      w,h= ancho y alto del trozo de imagen original que se muestra en la pantalla, es decir, antes de aplicar el grado de zoom.
      Me edito: w y h son el ancho y alto del control de la pantalla. Por tanto en la versión encapsuladas los he quitado y he utilizado las propiedades Width y Height del control PictureBox base.
      pX,pY= posición en la esquina superior izquierda de la imagen original que se muestra (en coordenadas de la imagen original).
    3. ¿w21 y h21 que son? Según parece es el ancho de la imagen total, pues lo obtienes del ancho de data21 (BitmapData devuelto por LockBits) pero eso coincide con img1.Width y Height ¿no?
      Me respondo: no, w21 y h21 eran el ancho y alto de la imagen original que se muestra en pantalla al zoom establecido. En la versión de PerfectView las he llamado wDataImg y hDataImg.
    4. ¿Por qué utilizas el flag? Si lo he entendido bien, dices que la dll no es reentrante y por eso esperas a que acabe. Pero ¿por qué no es reentrante? No he visto que utilices ninguna variable global o interna que no esté declarada en el interior de la función o sea pasada como parámetros de paso, po lo que a mi entender, es perfectamente reentrante. Mientras las funciones declaradas en la DLL no trabajen con variables globales y usen sólo variables locales y las de paso, no debería de haber problemas y se podrían hacer simultáneos los reescalados de la imagen izquierda y derecha (en un biprocesador tendría ventajas claras).
      Otra cosa distinta es que se llame otra vez a la misma función sobre el mismo bitmap, sin que halla acabado la anterior. Pero eso no ocurre, porque no he visto que uses hilos en el onPaint, así que FastDraw no volverá hasta que no acabe y el onPaint no continuará.
      De momento en la versión de PerfectView he quitado este flag.
    _________________________________
    Tengo algún problema con la implementación del evento OnMouseWheel.

    Lo he sobrecargado en el control derivado de PictureBox (PerfectView), quitando el evento sobrecargado del Form, pero el control PerfectView nunca recibe el evento.
    Sin embargo, he sobrecargado otros eventos del ratón como MouseMove, MouseHover, MouseDown y MouseUp y esos sí que funcionan y los recibe.

    ¿Es MouseWheel algún evento especial que halla que inicializar de alguna manera?
    ¿Hay que hacer algo en el Form?

    Es lo único que me queda por hacer pues lo otro ya está portado y encapsulado.
    Sólo queda lo del MouseWheel y la implementación de lo de contar el tiempo que tarda implementado en el botón2, porque al pasar los bitmaps y los bitmapData al interior de los controles, el botón no tiene acceso a las variables.
    No quiero exponer esas variables como públicas porque el usuario del control no debería tener acceso al detalle de la implementación interna del PerfectView.
    Así que habrá que retocar un poco el código de buttom2 para que vuelva a construir el BitmapData para contar el tiempo.
    Última edición por ariznaf; 17/05/2008 a las 17:36 Razón: Fusión automática de mensajes para prevenir autosubir post

  2. #2
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Manuel, en el Form1_Load, al hacer el LockBits, estableces un PixelFormat.Format24bppRgb... eso ¿es sólo en esta prueba porque la imagen es un jpeg o debe de quedar así? ¿No debería de ser de 16bits por color, es decir Format48bppRgb? ¿O es que la imagen que llega aquí ya va a estar siempre convertida a 8bits?
    Yo creo que para mostrar en pantalla 24bpp son suficientes, en muchos sitios se dice que el ojo no distingue entre 24bpp y 32bpp y el cálculo es mucho más rápido. Mi idea es mantener un buffer de 16bits devuelto por dcraw y convertirlo (una sola vez) a 8bits para representar. Para cálculos de balance de blanco e histograma tiramos del buffer de 16 bits. No sé si con esto será suficiente, ¿tú crees que para visualizar son necesarios 32bpp? Voy a copiar esto al foro general para que lo discutan otros, especialmente _GUI_, que es nuestro teórico.

    Un saludo:
    Manuel Llorens

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

  3. #3
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    No, Manuel, creo que para visualizarlo es más que suficiente con 24 bits.
    Los 32 bits no creo que aporten nada (de hecho creo que los otros 8 bits se usan más bien como canal alfa, para implementar trasparencias por hardware cuando la pantalla está en modo de 32 bits).

    Pero lo que no tenía claro es si el bitmap que se le pasaría a PerfectView era la imagen ya revelada y convertida a 8 bits o la imagen revelada en 16 bits.
    Por lo que contestas, veo que es la de 8 bits una vez ajustada en gamma y demás, así que está bien como está.

  4. #4
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    1. De momento en la versión de PerfectView he quitado este flag.
    Si quitas el flag el evento OnPaint se puede volver a disparar cuando aún no ha terminado y se queda medio tostado. Yo no uso hilos, pero se le llama, creeme. No casca, porque efectivamente la DLL sí es reentrante, pero trabaja innecesariamente y deja la CPU ocupada. Tal como está va bien y es imposible mover las dos vistas simultáneamente, así que ¿qué más da? Prueba con el flag y sin él y me entenderás.

    _________________________________
    Cita Iniciado por ariznaf Ver mensaje
    ¿Es MouseWheel algún evento especial que halla que inicializar de alguna manera?
    Eso mismo.

    Cita Iniciado por ariznaf Ver mensaje
    Sólo queda lo del MouseWheel y la implementación de lo de contar el tiempo que tarda implementado en el botón2,
    No, no... no vuelvas a implementar el botón dos, eso quítalo tranquilamente. Cuando queramos probar la velocidad de los cálculos metemos la rutina a parte.

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

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

  5. #5
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Bueno, pues ya está acabado.
    Lo he subido al svn.

    Tengo que ver lo que comentas del flag y volver a ponerlo o buscar una alternativa de funcionamiento.
    Según dices se pueden recibir dos eventos OnPaint seguidos cuando aún no ha terminado. Eso me parece imposible, pues un evento no lo podemos recibir hasta que hemos procesado el anterior, ya que mientras no salgamos de un OnPaint no podremos procesar el siguiente. Seguramente no te he entendido. Analizaré lo que habías hecho con el flag.
    Efectivamente las vistas no se podrán procesar simultáneamente ... ¿o sí? ahora los dos controles son independientes entre sí, y en teoría al menos cada uno podría recibir su evento de forma independiente y procesarlo, aunque seguramente esto no sea así por la forma en que se procesa la cola de eventos de un aplicación por parte de .NET. No conozco en detalle cómo funciona la cola de procesamiento de .NET.

    He quitado lo del MouseWheel del control y en su lugar he puesto una propiedad Zoom y otra MakeZoom para establecer el zoom y multiplicar el zoom por un factor respectivamente. Estas funciones se llaman desde el OnMouseWheel del formulario.

    También he añadido una función TestVelocidad que hacía lo del botón 2 para implementar lo de medir la velocidad.
    En versiones futuras, quitaremos esa función pues no tiene ninguna utilidad, sólo sirve para testear la velocidad.

    Bueno, estoy contento de haberlo podido acabar. Me he desoxidado un poco y he comprendido un poco mejor cómo va el programa, aunque no en todos sus detalles.

  6. #6
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Bueno, pues ya está acabado.
    Lo he subido al svn.
    Enhorabuena, eres una máquina.

    Cita Iniciado por ariznaf Ver mensaje
    Tengo que ver lo que comentas del flag y volver a ponerlo o buscar una alternativa de funcionamiento.
    En cualquier caso es algo externo a las vistas, ¿no? Pruébalo tú a ver cómo te va sin el flag, a mí se me empezaba a ocupar la CPU. No casca, pero se queda tostado un rato.

    Cita Iniciado por ariznaf Ver mensaje
    Según dices se pueden recibir dos eventos OnPaint seguidos cuando aún no ha terminado. Eso me parece imposible, pues un evento no lo podemos recibir hasta que hemos procesado el anterior, ya que mientras no salgamos de un OnPaint no podremos procesar el siguiente. Seguramente no te he entendido. Analizaré lo que habías hecho con el flag.
    No, sí me has entendido bien. Esa es la visión que yo tengo del asunto. De no ser así, poner o no el flag no influiría en absoluto, ¿no crees?

    Cita Iniciado por ariznaf Ver mensaje
    Bueno, estoy contento de haberlo podido acabar. Me he desoxidado un poco y he comprendido un poco mejor cómo va el programa, aunque no en todos sus detalles.
    De momento...

    Un saludo:
    _________________________________
    Llevas tú razón.

    He probado a quitar el flag y ahora funciona bien. Efectivamente es un poco rara la forma de procesar los eventos del .NET.

    Lo puse al principio cuando hacía el procesado dentro del OnPaint del PictureBox en lugar de hacerlo dentro del OnPaint del Form. Allí iba mal y además fallaba otra cosa que no pude solucionar. Por eso lo saqué al OnPaint del Form y di por supuesto que si hacia falta en un sitio debía hacer falta en el otro.

    Pero llevas tú razón, puedes quitarlo tranquilamente, disculpa mi error. Desde luego es más limpio sin el flag puesto.

    Un saludo:
    Última edición por ManuelLlorens; 17/05/2008 a las 20:22 Razón: Fusión automática de mensajes para prevenir autosubir post
    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
    He estado haciendo pruebas con lo del flag.
    He puesto una variable stillPainting que inicializo true a true al inicio del OnPaint y la pongo en false al final.
    En la primera linea del OnPaint compruebo la variable y si está a true, lanzo una excepción.

    Esto provocaría que si se llama a un OnPaint antes de finalizar el anterior, el programa se pararía con una excepción porque stillPainting sería true.

    He hecho zooms y desplazamientos rápidos y nunca me ha aparecido la excepción.
    Por tanto concluyo que (al menos en la versión de los controles PerfectView) el OnPaint nunca se llama antes de finalizar de procesar la anterior llamada y el flag no es en consecuencia necesario.

  8. #8
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Nos hemos cruzado, mira más arriba.

    A ver si termino lo que he puesto que le falta al tema de las vistas y lo juntamos todo.
    Manuel Llorens

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

  9. #9
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Vaya nos hemos curzado los mensajes. No había visto el tuyo.
    Bueno definitivamente quitaré el flag.
    ¿Y ahora qué?
    Manuel, dale cacahuetes al mono
    ¿Qué hago ahora?
    He pensado ponerme con lo del xmp-sdk.
    Voy a ver si consigo añadir los parámetros de revelado como metadatos xmp en un fichero xmp adjunto o en el interior de los dng (según si el formato raw lo soporta o no, el añadir metadatos xmp).
    Esto será algo más fácil que lo de crear dng y me permitirá ir cogiendo soltura con los sdk de Adobe.
    Claro que también está lo de crear sliders personalizados y demás.

  10. #10
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    He pensado ponerme con lo del xmp-sdk.
    Inténtalo y si te atascas te pones con los controles y lo dejas para más adelante. No merece que te quedes atascado con eso y "te pierdas" el resto del proyecto. Cuando lo junte todo, si no te importa, le echas un vistazo y lo retocas.

    Un saludo:
    Manuel Llorens

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

  11. #11
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    OK Manuel, estoy contigo, eso puede añadirse en cualquier momento, una vez que el revelado se haga correctamente y las piezas estén en su sitio. De todas formas le iré echando un vistazo mientras no tenga otras cosas que hacer.
    Estoy limpiando un poquito más el código.
    Una duda:
    había puesto una Propiedad Bitmap para recuperar el Bitmap interno y establecerlo.
    Por otra parte, en el destructor del control he añadido una llamada a img.Dispose para liberar los recursos utilizados por el bitmap interno cuanto antes, sin tener que esperar al recolector de basura.
    Lo mismo cuando el usuario establece un nuevo bitmap con el set de la propiedad Bitmap.
    La duda está en que si el Bitmap sigue en uso bien porque la función que llame a establecer el bitmap se quede aún con una referencia o porque se obtuvo con la propiedad bitmap, al hacer el Dispose puede hacer que el programa se la pegue cuando se vuelva a utilizar alguna función del Bitmap.
    ¿O el Dispose tiene encuenta el contador de referencias del objeto Bitmap?

    Añadiré la funcionalidad de ImageLocation y los Load del PictureBox, por conservar la compatibilidad con su modo de funcionamiento.
    _________________________________
    Bueno, ya está acabado.
    Lo he subido al svn.
    No lo tocaré más hasta que Manuel lo integré con el resto de los cambios en la aplicación.
    _________________________________
    ¡¡Ah!! un último detalle Manuel.
    En el OnMouseWheel no me gusta cómo tengo implementado la detección de en qué control del formulario se produce el evento.
    Está hecho con la variable vista que tú tenías y los eventos OnMouse.
    La mayor parte de esos eventos ya no hacen nada salvo establecer la variable vista.

    Lo suyo sería que en el OnMouseWheel del formulario se pudiera comprobar (por las coordenadas del ratón que vienen en el MouseEventArg) sobre qué control se produjo el evento.
    Pero no sé qué función puede hacer esto. Creo que existirá una que pasadas unas coordenadas nos diga a qué control de un formulario corresponden.
    ¿La conoces?

    Bueno, he arreglado esto también. He utilizado el método del formulario GetChildAtPoint en el evento OnMouseWheel, que nos devuelve el control hijo sobre el que cae un punto. Luego se comprueba que sea un control de tipo PerfectView y en caso de serlo se procede con la realización del zoom. Si no lo es, no se hace nada.

    Esto además evita que se escale la última vista sobre la que estuvo el ratón, que era lo que ocurría antes. Si el ratón no está sobre una de las vistas, no se hace nada.
    El código queda más limpio al poder quitar los eventos onMouse y la variable vista.
    _________________________________
    En el Issue correspondiente de google code he marcado esta tarea como Fixed a la espera de ser cerrada por el supervisor (Manuel)
    Última edición por ariznaf; 18/05/2008 a las 00:08 Razón: Fusión automática de mensajes para prevenir autosubir post

  12. #12
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    La duda está en que si el Bitmap sigue en uso bien porque la función que llame a establecer el bitmap se quede aún con una referencia o porque se obtuvo con la propiedad bitmap, al hacer el Dispose puede hacer que el programa se la pegue cuando se vuelva a utilizar alguna función del Bitmap. ¿O el Dispose tiene encuenta el contador de referencias del objeto Bitmap?
    En teoría, si haces un Dispose debes liberar cuanto antes las referencias al mismo. Creo que las referencias a un objeto marcado por Dispose no se pueden usar. En cualquier caso no hagas un Dispose de los objetos que pases fuera de la clase por referencia si no es en el destructor de la clase, o si estás seguro de que sustituyes un objeto antiguo por otro más moderno, por ejemplo, cuando hago esto:

    if(pictureBox.Image!=null) pictureBox.Image.Dispose();
    pictureBox.Image=bmp;


    Aquí estoy seguro de que nadie quiere la Image anterior a la que acabo yo de poner. Además las referencias antiguas apuntan ahora a la nueva, por lo que puedo cepillarme la antigua tranquilamente. Sin embargo, el Dispose de la última imagen habrá que hacerlo en el destructor de la clase. No sé si me he explicado.

    Cita Iniciado por ariznaf Ver mensaje
    No lo tocaré más hasta que Manuel lo integré con el resto de los cambios en la aplicación.
    Antes de eso te pasaré cambios para que los incluyas, hay que meter el parpadeo y la división de vistas.

    Cita Iniciado por ariznaf Ver mensaje
    El código queda más limpio al poder quitar los eventos onMouse y la variable vista.

    Ya sabía yo que ibas a dejar el tema limpio. Lo digo de verdad, eres un tío puntilloso y eso es lo ideal para la fase en la que está el proyecto. Yo soy un poco más chapucero. Me gusta probar esto y aquello, pero luego me falta empuje para rematarlo todo bien. Tú no has parado hasta que lo has dejado como tú querías que estuviera, yo me conformo con que funcione.

    Cita Iniciado por ariznaf Ver mensaje
    En el Issue correspondiente de google code he marcado esta tarea como Fixed a la espera de ser cerrada por el supervisor (Manuel)
    Lo que te digo. Puntilloso . Sí te parece lo cierro, pero queda añadir la vista dividida y el parpadeo.

    Un saludo:
    Manuel Llorens

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

  13. #13
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    No creas Manuel, yo soy más bien chapucitas... lo que pasa es que no tengo tantas cosas que hacer en el código como tú y me dedico a juguetear con lo que hice :X

    De acuerdo con lo del Dispose, era lo que me imaginaba. Como he puesto un método para devolver el Bitmap y alguien pudiera estar enlazando referencias externas no podré controlar muy bien si desde fuera se mantiene el Bitmap activo.
    En el destructor parece claro que hay que hacerlo suponiendo que cuando se destruye el PerfectView ya no se use más el bitmap. Pero cuando lamman al set de la Propiedad Bitmap para crear uno nuevo, yo también lo hago y es similar a lo que tu haces con el Image, pero podría ser que se mantuvieran referencias al Bitmap anterior.

    Si no hago el Dispose, consumiremos más memoria si se hacen cambios del Bitmap almacenado (cada vez que haya una imagen nueva revelado hay dos Bitmap que se crean y dos que se destruyen) que no se recuperará hasta que actúe el recolector y eso puede tardar bastante.

    Lo ideal reproducir el funcionamiento exacto de PictureBox, lo que él hace cuando llamas al set de Image o cuando un PictureBox se destruye, pero no lo conozco con detalle. A ver qué leo al respecto.

    Me fastidia esto del Dispose, porque la gran ventaja de C# sobre C++ (a parte de una sintaxis más limpia que no obliga a escribir tanto) es no tener que ocuparnos tanto del control de la memoria. Con lo del Dispose Microsoft ha introducido nuevamente en las tareas del programado la preocupación por la liberación de los objetos y lo que se conocía como DLL HELL.
    Estos de MS siempre hacen lo mismo: plantean algo que parece muy sencillo y una idea magnífica y cuando profundizas un poquito te encuentras con los problemas y muchas veces mayores que lo que se suponía que arreglaba "su idea".

    Pásame lo de la vista con parpadeo y a ver si lo pongo y cerramos el tema.

  14. #14
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Dado que finalmente estamos desarrollando este control en OpenGL y todo lo de arriba ya no es aplicable, cierro el hilo.
    Manuel Llorens

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


 

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
  •