SoloCodigo

Programación General => C/C++ => Visual C++ => Mensaje iniciado por: kezern en Jueves 9 de Noviembre de 2006, 13:18

Título: Voimage Imagen Desde Memoria
Publicado por: kezern en Jueves 9 de Noviembre de 2006, 13:18
Hola a todos. Estoy usando VOImage para cargar imágenes jpg.
Tengo este código
Código: Text
  1.  
  2.    CVOImage ima;
  3.    CString path = _T("Cliente/img.jpg");
  4.    HDC picDC = ::GetDC(m_ventanaRender->m_hWnd);
  5.    ima.Load(picDC,path);
  6.    ima.Draw(picDC,0,0);
  7.    ReleaseDC( m_ventanaRender->m_hWnd, picDC);
  8.  
  9.  
En el leo la imagen desde un archivo y la muestro por pantalla.
Me gustaría modificar la función Load para leer el jpg desde un buffer de memoria, he cargado el archivo cpp e intentando comprender la función para modificar los parámetros pero no hay forma.
Alguien ha hecho algo parecido?
Agradecería una mano.
Un saludo.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: JuanK en Jueves 9 de Noviembre de 2006, 13:35
Y como vas a modificar la  funcion
ima.Load(picDC,path);

tienes el fuente?

Estas seguro que no hay otro método de esa clase que hace lo que tu quieres?
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Jueves 9 de Noviembre de 2006, 13:38
Si que tengo el fuente. VOImage.cpp y el .h
Ya he estado mirando a ver si otro método me permitía hacer lo que quiero (sería lógico que hubiese) pero no he encontrado nada.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: JuanK en Jueves 9 de Noviembre de 2006, 13:41
Pero sino anexas el fuente es poco lo que podemos llegar a hacer por ti no crees?
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Jueves 9 de Noviembre de 2006, 13:44
Busca el codigo donde se haga la apertura del archivo ... puede que hasta ya esten las funciones hechas ... sino te creas un LoadImageFromBuffer y listo, usas todo el codigo actual excepto la parte de archivos.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Jueves 9 de Noviembre de 2006, 16:22
Aquí adjunto el archivo VOImage.cpp
El código de la función en concreto es
Código: Text
  1.  
  2. BOOL CVOImage::Load(HDC hdc, LPCTSTR pcszFileName)
  3. {
  4.   if(m_hbitmap)
  5.   {
  6.   if(GetFileName().GetLength() && GetFileName() == pcszFileName)
  7.     return TRUE;  // Already Loaded
  8.  
  9.   DeleteObject(m_hbitmap);
  10.   }
  11.  
  12.   if(!m_hdc)
  13.   {
  14.   m_hdc = CreateCompatibleDC(hdc);
  15.  
  16.   HBITMAP  hbitmap = CreateCompatibleBitmap(hdc, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES));
  17.  
  18.   SelectObject(m_hdc, hbitmap);
  19.   }
  20.  
  21.   BYTE    szBuffer[4096] = {0};
  22.   HANDLE hFile = INVALID_HANDLE_VALUE;
  23.  
  24. #ifdef _WIN32_WCE
  25.   HRESULT hr;
  26.  
  27.   DecompressImageInfo  dii;
  28. #endif
  29.  
  30.   hFile = CreateFile(pcszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  31.   if (hFile == INVALID_HANDLE_VALUE)
  32.   return FALSE;
  33.  
  34. #ifdef _WIN32_WCE
  35.   // Fill in the 'DecompressImageInfo' structure
  36.   dii.dwSize = sizeof( DecompressImageInfo );  // Size of this structure
  37.   dii.pbBuffer = szBuffer;      // Pointer to the buffer to use for data
  38.   dii.dwBufferMax = 4096;        // Size of the buffer
  39.   dii.dwBufferCurrent = 0;      // The amount of data which is current in the buffer
  40.   dii.phBM = &m_hbitmap;        // Pointer to the bitmap returned (can be NULL)
  41.   dii.ppImageRender = NULL;      // Pointer to an IImageRender object (can be NULL)
  42.   dii.iBitDepth = GetDeviceCaps(hdc,BITSPIXEL);  // Bit depth of the output image
  43.   dii.lParam = ( LPARAM ) hFile;      // User parameter for callback functions
  44.   dii.hdc = m_hdc;        // HDC to use for retrieving palettes
  45.   dii.iScale = g_iScale;        // Scale factor (1 - 100)
  46.   dii.iMaxWidth = g_iMaxWidth;      // Maximum width of the output image
  47.   dii.iMaxHeight = g_iMaxHeight;      // Maxumum height of the output image
  48.   dii.pfnGetData = GetImageData;      // Callback function to get image data
  49.   dii.pfnImageProgress = ImageProgress;    // Callback function to notify caller of progress decoding the image
  50.   dii.crTransparentOverride = ( UINT ) -1;  // If this color is not (UINT)-1, it will override the
  51.               // transparent color in the image with this color. (GIF ONLY)
  52.  
  53.   // Process and decompress the image data
  54.   hr = DecompressImageIndirect( &dii );
  55. #endif
  56.  
  57.   // Clean up
  58.   CloseHandle( hFile );
  59.  
  60.   HBITMAP hbitmapOld = (HBITMAP)SelectObject(m_hdc, m_hbitmap);
  61.  
  62.   DeleteObject(hbitmapOld);
  63.  
  64.   BITMAP  bmp;
  65.  
  66.   GetObject(m_hbitmap, sizeof(BITMAP), &bmp);
  67.  
  68.   m_dwWidth = bmp.bmWidth;
  69.   m_dwHeight = bmp.bmHeight;
  70.  
  71.   m_strFileName = pcszFileName;
  72.   m_dwResourceID = 0;
  73.   m_hmoduleResource = 0;
  74.  
  75.   return TRUE;
  76. }
  77.  
  78.  
Ya me he fijado en la línea de la función CreateFile pero no se cómo cambiar para que la fuente sea el buffer de memoria
Gracias por vuestra ayuda
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Jueves 9 de Noviembre de 2006, 16:26
Tenes que ver DecompressImageIndirect que es donde se usa el archivo.

Código: Text
  1.  
  2.  hFile = CreateFile(pcszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  3.  ...
  4.  dii.lParam = ( LPARAM ) hFile;
  5.  ...
  6.  hr = DecompressImageIndirect( &dii );
  7.  
  8.  
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Jueves 9 de Noviembre de 2006, 16:28
Si es para Windows CE y esa es una API del S.O. entonces vas a tener que buscar otra API u otro metodo ...
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Jueves 9 de Noviembre de 2006, 16:56
He buscado la función DecompressImageIndirect en los archivos del proyecto y sólo encuentro llamadas a ella o su definición en un archivo cpp, pero no veo su código por ningún sitio. ¿Estará entonces la función compilada dentro de la dll y yo no puedo modificarla? LLevo bastante tiempo buscando librerías que me permitan mostrar una imagen jpg en el display del pocket pc y sólo había encontrado esto.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Jueves 9 de Noviembre de 2006, 18:08
Cita de: "kezern"
He buscado la función DecompressImageIndirect en los archivos del proyecto y sólo encuentro llamadas a ella o su definición en un archivo cpp, pero no veo su código por ningún sitio. ¿Estará entonces la función compilada dentro de la dll y yo no puedo modificarla? LLevo bastante tiempo buscando librerías que me permitan mostrar una imagen jpg en el display del pocket pc y sólo había encontrado esto.
"... si ... es una API del S.O. entonces vas a tener que buscar otra API u otro metodo"
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Jueves 9 de Noviembre de 2006, 18:11
Pues usa la librería imgdecmp.dll, creo que si que pertenece al S.O. Así que la he hecho buena. Conoces tu alguna otra API (que esté ya portada o pueda portar yo) a PocketPC? Y si no pues... a seguir googleando.
Un saludo y gracias.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Jueves 9 de Noviembre de 2006, 18:26
Cita de: "kezern"
Pues usa la librería imgdecmp.dll, creo que si que pertenece al S.O. Así que la he hecho buena. Conoces tu alguna otra API (que esté ya portada o pueda portar yo) a PocketPC? Y si no pues... a seguir googleando.
Un saludo y gracias.
Aca hay muy buena informacion:
http://www.unsupportedsoftware.com/products/dev/imgdecmp.htm (http://www.unsupportedsoftware.com/products/dev/imgdecmp.htm)

Ya entendi como funciona gracias a esa pagina, hay 2 funciones de tipo callback (te llaman desde la DLL) y tenes que reemplazar la de GetImageData. En vez de usar ReadFile lleva un puntero y devolve los datos de tu buffer  :ph34r:  B)
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Viernes 10 de Noviembre de 2006, 10:22
Si he entendido bien esa función lo que hace es leer el archivo y devolver el número de bytes leidos? Como devuelvo la direccion de comienzo? Es decir, el puntero que me indica donde está la imagen? Estoy un poco liado.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Viernes 10 de Noviembre de 2006, 10:53
Cita de: "kezern"
Si he entendido bien esa función lo que hace es leer el archivo y devolver el número de bytes leidos? Como devuelvo la direccion de comienzo? Es decir, el puntero que me indica donde está la imagen? Estoy un poco liado.
Lo que tenes que hacer es simular todo ese proceso de lectura del archivo. Guardar un puntero al buffer original y tener otro que vaya adelantando de acuerdo a los bytes que te pidan leer, obviamente este ultimo puntero tendra que recuperar el valor del buffer original cuando vuelvas a llamar a DecompressImageIndirect ... teniendo en cuenta como funciona esto podrias hacerlo incluso mas simple.

En lParam en vez de pasar un HANDLE al archivo, del cual ya tenes en memoria su contenido, pasas un doble puntero al comienzo del buffer. Entonces en GetImageData devolves los bytes requeridos y adelantas este doble puntero exactamente por esa cantidad de bytes.

Aca tenes un ejemplo tonto de programa, sin ningun tipo de comprobacion de limites:

Código: Text
  1.  
  2. #include <windows.h>
  3. #include <stdio.h>
  4.  
  5. static DWORD CALLBACK GetImageData( LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam )
  6. {
  7.   char **buff = (char**)lParam;
  8.   memcpy(szBuffer, *buff, dwBufferMax);
  9.   *buff += dwBufferMax;
  10.   return dwBufferMax;
  11. }
  12.  
  13. void main()
  14. {
  15.   HANDLE hFile = CreateFile("c:\\boot.ini", GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
  16.   if (hFile != INVALID_HANDLE_VALUE)
  17.   {
  18.     DWORD DSize = GetFileSize(hFile, 0);
  19.     char *buff = (char*)malloc(DSize + 1);
  20.     char **pass = &buff;
  21.     ZeroMemory(buff, DSize + 1);
  22.     DWORD read = 0;
  23.     ReadFile(hFile, buff, DSize, &read, 0);
  24.     CloseHandle(hFile);    
  25.     for (int x = 0; x < 3; x++)
  26.     {
  27.       char raw[17];
  28.       ZeroMemory(raw, 17);
  29.       GetImageData((LPSTR)&raw, 16, (LPARAM)pass);
  30.       printf("%s\r\n", raw);
  31.     }
  32.     free(buff);
  33.   }
  34. }
  35.  
  36.  
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Viernes 10 de Noviembre de 2006, 13:10
La imagen que quiero mostrar la recibo a través de un socket desde otro pocket pc de forma que en mf.data tengo la imagen y en mf.size tengo el tamaño de esa imagen.
Por lo que veo en tu código lo que estás haciendo es crear un archivo y luego manejar un buffer. A mi lo que me gustaría seria evitar crear ese archivo. Lo que estoy recibiendo por el socket son fotogramas de un vídeo y tengo que ahorrar el máximo proceso posible.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Viernes 10 de Noviembre de 2006, 13:13
Estoy abriendo un archivo pero eso es lo de menos, esa parte es solo para probar la funcion de callback que es en lo que deberias concentrarte. En tu caso en vez de obterner el buffer del boot.ini lo obtendrias del socket ...
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Martes 14 de Noviembre de 2006, 12:20
Lo siento Eternal Idol, estoy completamente perdido.
Me he creado una callback a la que he llamado GetImageDataBuffer para no modificar la original y también he cambiado dii.pfnGetData para que apunte a la nueva función.
En la nueva función intento abrir el buffer y rellenar szBuffer pero no me funciona.
No se que estoy pasando por alto.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Martes 14 de Noviembre de 2006, 13:28
¿Que queres decir exactamente con abrir el buffer? Mejor pone el codigo que estas usando ... antes de llamar a la funcion tenes que tenes ya el archivo cargado en el buffer para que todo esto tenga sentido.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Martes 14 de Noviembre de 2006, 13:37
Ahora mismo lo que estoy haciendo es simular que trabajo con un buffer. Abro la imagen desde un archivo guardándola en un buffer y trabajo con ese buffer de memoria.
He declarado una variable global de tipo MemoryFile y la abro en la función Load
Código: Text
  1.  
  2. BOOL CVOImage::Load(HDC hdc, LPCTSTR pcszFileName)
  3. {
  4. .....
  5.          mf.load("Cliente/buffer.jpg");
  6.   // Fill in the 'DecompressImageInfo' structure
  7.   dii.dwSize = sizeof( DecompressImageInfo );    // Size of this structure
  8.   dii.pbBuffer = szBuffer;        // Pointer to the buffer to use for data
  9. ...
  10.  
  11.  
y después en la función que he creado GetImageDataBuffer
Código: Text
  1.  
  2. DWORD CALLBACK CVOImage::GetImageDataBuffer(LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam )
  3. {
  4.      memcpy(szBuffer,mf.data,mf.size);
  5.      return mf.size;
  6. }
  7.  
  8.  
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Martes 14 de Noviembre de 2006, 15:04
Eso siempre devuelve los bytes del principio ...
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Martes 14 de Noviembre de 2006, 15:32
He cambiado la función para que vaya incrementando la posición de memoria que lee y ahora la tengo así:
Código: Text
  1.  
  2. DWORD CALLBACK CVOImage::GetImageDataBuffer(LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam )
  3. {
  4.   memcpy(szBuffer + start,mf.data + start,dwBufferMax);
  5.   start = start + dwBufferMax;
  6.         return dwBufferMax;
  7. }
  8.  
  9.  
Al ejecutar el programa y pulsar en el botón para que ejecute la función, muestra una pantalla en blanco durante un instante y luego sale del programa (no debería salir del programa sino mostrar la imagen hasta que pulse yo en la pantalla).
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Martes 14 de Noviembre de 2006, 15:49
Código: Text
  1.  
  2. memcpy(szBuffer + start,mf.data + start,dwBufferMax);
  3.  
  4.  

Esto esta mal, szBuffer es el buffer de el y no podes escribir en cualquier lado una X cantidad de bytes, tenes que escribir esa X cantidad (dwBufferMax) desde el principio, asi:

Código: Text
  1.  
  2. memcpy(szBuffer, mf.data + start, dwBufferMax);
  3.  
  4.  

Por cualquier problema que encuentres vas a tener que depurar el programa, es casi imposible solucionarlo on line.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Martes 14 de Noviembre de 2006, 16:15
He seguido mirando y he vuelto a hacer cambios. Ahora la función la tengo así:
Código: Text
  1.  
  2. DWORD CALLBACK CVOImage::GetImageDataBuffer(LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam )
  3. {
  4.         int size = min(mf.size - start, (int)dwBufferMax);
  5.   memcpy(szBuffer,mf.data + start,size);
  6.   start += size;
  7.         return size;
  8. }
  9.  
  10.  
De esta forma controlo que no se lean más bytes de los necesarios y también voy incrementando la dirección de memoria donde voy guardando los datos.
Ahora me muestra la imagen durante un instante y después se vuelve negro.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Martes 14 de Noviembre de 2006, 16:33
Depuralo ... y sino para hacerlo mas simple podes empezar usando printf's asi por ejemplo:

Código: Text
  1.  
  2. DWORD CALLBACK CVOImage::GetImageDataBuffer(LPSTR szBuffer, DWORD dwBufferMax, LPARAM lParam )
  3. {
  4.   int size = min(mf.size - start, (int)dwBufferMax);
  5.   printf("dwBufferMax::%d min::%d start::%d\r\n", dwBufferMax, min, start);
  6.   memcpy(szBuffer,mf.data + start,size);
  7.   start += size;
  8.   return size;
  9. }
  10.  
  11.  
Título: Re: Voimage Imagen Desde Memoria
Publicado por: kezern en Martes 14 de Noviembre de 2006, 17:06
He encontrado el problema. Tenía la función dentro de un timer porque quiero refrescar la imagen y lo que hacía en la segunda vuelta del timer era dibujarme la pantalla en negro.
Muchas gracias.
Título: Re: Voimage Imagen Desde Memoria
Publicado por: Eternal Idol en Martes 14 de Noviembre de 2006, 17:08
Cita de: "kezern"
He encontrado el problema. Tenía la función dentro de un timer porque quiero refrescar la imagen y lo que hacía en la segunda vuelta del timer era dibujarme la pantalla en negro.
Muchas gracias.
De nada, mf.data tendrias que pasarlo en LPARAM lParam en vez de el handle a un archivo que ya no abris, asi automaticamente usarias cada vez que refrescaras la imagen desde el comienzo (si buscas los mensajes anteriores vas a ver como hacerlo).