Page 2 of 3

Re: Leer pixeles de un bitmap monocromo

PostPosted: Fri Jul 24, 2015 9:19 am
by jmartial
Respondo por partes:

Este es código Antonio:

Code: Select all  Expand view


    hBitmap es el handle después de cargar el bmp desde disco

    hDC        := CreateDC("DISPLAY",NIL,NIL,NIL)
    hDCMem     := CreateCompatibleDC( 0 ) //hDC )
    hDCMemDest := CreateCompatibleDC( 0 )
    hOldBmp    := SelectObject( hDCMem, hBitmap )

   newHeight := 100 // Nueva altura por ejemplo

   BitBlt( hDCMem, 0, 0, :nWidth, newHeight, hDCMemDest, 0, 0, SRCCOPY )

   // Ahora necesito guardar hDCMem como un nuevo bitmap en disco
   //--------- Con FreeLibrary ---------
      nFormat := FI_GETFILETYPE( cFile, 0 )
      hDib       := FI_LOAD( nFormat, cFile, 0 )
      hInfoH    := FI_GETINFOHEADER( hDib )
      hInfo      := FI_GETINFO( hDib )
      hBits      := FI_GETBITS( hDib )

     hBmp = CreateDiBitmap( hDCMemDest, hInfoH, CBM_INIT, hBits, hInfo, DIB_RGB_COLORS )
 
     // hBmp devuelve 0, no lo crea

    Y aquí me he quedado...
 
 



Manuel, lo que pretendo es teniendo un bitmap monocromo en disco con altura 1000 pixeles, copiarlo a disco recortándolo a 300 pixeles de altura.
Me gustaría hacerlo sin GDI+, tengo FWH de final de 2014 y me gustaría que fuera lo más fácil posible.

También podría hacerlo con freeImage, pero no he encontrado la forma.

Gracias,
Joaquín Martínez

Re: Leer pixeles de un bitmap monocromo

PostPosted: Fri Jul 24, 2015 9:45 am
by Antonio Linares
Joaquín,

Prueba asi, teniendo seleccionado el bitmap original en hDC:

HDC hDCMem = CreateCompatibleDC( hDC );
HBITMAP hBmp = CreateCompatibleBitmap( hDC, rc->right - rc->left, rc->bottom -
rc->top );
HBITMAP hBmpOld = ( HBITMAP ) SelectObject( hDCMem, hBmp );
BitBlt( hDCMem, 0, 0, rc->right, rc->bottom, hDC, 0, 0, SRCCOPY );
SelectObject( hDCMem, hBmpOld );
DeleteDC( hDCMem );

Re: Leer pixeles de un bitmap monocromo

PostPosted: Fri Jul 24, 2015 9:47 am
by Antonio Linares
Para un bitmap monocromo sería asi:

hBmpMono = CreateBitmap( rc->right - rc->left, rc->bottom - rc->top, 1, 1, NULL );

Re: Leer pixeles de un bitmap monocromo

PostPosted: Fri Jul 24, 2015 9:55 am
by Antonio Linares
Prueba asi:

Se le podria pasar la cantidad a disminuir la altura como un segundo parámetro

Code: Select all  Expand view
HB_FUNC( BMPCOPY ) // hBitmap --> hNewBitmap
{
   HBITMAP hBmpMem, hOldBmp, hOldBmp2;
   HDC hDC     = CreateDC("DISPLAY", 0, 0, 0);
   HDC hDCMem  = CreateCompatibleDC( hDC );
   HDC hDCMem2 = CreateCompatibleDC( hDC );
   HBITMAP hBitmap = (HBITMAP) hb_parnl( 1 );
   BITMAP bm;

   GetObject( ( HGDIOBJ ) hBitmap, sizeof( BITMAP ), ( LPSTR ) &bm );

   bm.bmHeight -= cantidad que quieras disminuir la altura;

   hBmpMem = CreateBitmap( bm.bmWidth, bm.bmHeight, 1, 1, NULL );
   hOldBmp = (HBITMAP) SelectObject( hDCMem, hBmpMem );
   hOldBmp2 = (HBITMAP) SelectObject( hDCMem2, hBitmap );

   BitBlt( hDCMem, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem2, 0, 0, SRCCOPY );

   SelectObject( hDCMem, hOldBmp );
   SelectObject( hDCMem2, hOldBmp2 );
   DeleteDC( hDCMem );
   DeleteDC( hDCMem2 );
   DeleteDC( hDC );

   hb_retnl( (LONG) hBmpMem );
}
 

Re: Leer pixeles de un bitmap monocromo

PostPosted: Fri Jul 24, 2015 9:58 am
by jmartial
Antonio,

¿para un bitmap monocromo, como indico el HDC original ?

Con CreateCompatibleBitmap sí tiene ese parámetro.

Re: Leer pixeles de un bitmap monocromo

PostPosted: Fri Jul 24, 2015 10:09 am
by jmartial
Antonio,

Muchas gracias, lo corta, pero no se graba bien, se graba totalmente negro. Esto ya me pasó en otras pruebas que hice.

Este es el código que pongo:

Code: Select all  Expand view


   hNewBitmap := bmpCopy( hBmp, newHeight )  // Le he puesto la altura como parámetro
   
   hDib := DibFromBitmap( hNewBitmap )
   dibWrite( "impresoCortado.bmp", hDib )

 


¿ Que me falta ?

Re: Leer pixeles de un bitmap monocromo

PostPosted: Fri Jul 24, 2015 10:39 am
by Antonio Linares
Antes del BitBlt() prueba a hacer:

SetBkColor( hDCMem, GetPixel( hBitmap, 0, 0 ) );

Re: Leer pixeles de un bitmap monocromo

PostPosted: Fri Jul 24, 2015 11:32 am
by jmartial
Antonio,

No ha arreglado nada. Sigue saliendo en negro el bitmap resultante.

No se me ocurre más nada.

Re: Leer pixeles de un bitmap monocromo

PostPosted: Fri Jul 24, 2015 12:37 pm
by jmartial
Antonio,

Gracias, ya funciona.

Tu función bmpCopy() funciona perfecta.

Me salía negro, porque antes había buscado por donde había que cortar seleccionando un hDC y antes de llamar a tu función tenía que restaurarlo poniendo
SelectObject( hDCMem, hOldBmp ).

Pero bueno, que tu función corta perfectamente un bitmap.


Muchas gracias,
Joaquín Martínez

Re: Leer pixeles de un bitmap monocromo

PostPosted: Sat Jul 25, 2015 8:33 am
by Antonio Linares
Muy bien! :-)

Re: Leer pixeles de un bitmap monocromo

PostPosted: Sun Jul 26, 2015 6:04 pm
by antolin
A lo mejor te parece una tontería, pero el fichero, si es un BMP monocromo, se compondrá de una cabecera BITMAPINFOHEADER seguido de los BYTES (8 bits) de la imagen. Un byte 0 es negro y un byte 1 es blanco. Si averiguas cuanto mide la cabecera (medida fija), puedes abrir el fichero con un MEMOWRIT y leer los bytes 0 y 1 con un Substr() empezando por el que sigue a la cabecera. Yo hice hace tiempo algo parecido con un bitmap de 24 bits y me funcionó. Lo que pasa que no recuerdo cuanto mide esa cabecera.

Otra cosa. Las líneas del bitmap han de medir todas una cantidad múltiplo de cuatro. Es decir si el BMP mide 398 pixels de ancho, cada línea del BMP tendrá 400 pixels en ese fichero, los dos últimos bytes serán ceros. Y, por ultimo, a quien diseño los ficheros y su manipulación, se le ocurrió la feliz idea de guardar las línea del BMP en orden inverso. Es decir la primera línea de 400 pixels del supuesto BMP del ejemplo representa a la última línea que se dibuja en pantalla. La segunda es la penúltima, la tercera la antepenúltima, etc. Están en orden inverso las líneas, no los bytes que las forman. Como si coges la primera línea, tal cual, y la pones al final. Después coges la nueva primera línea y la pones delante de la última (la penúltima), etc... no se si me explico.

Nunca he trabajado con BMP´s monocromos, así que a lo mejor, en lugar de BYTES, la imagen se guarda como BITS. Pero seguramente cada línea tendrá que medir múltiplo de 4 y las líneas irán en orden inverso.

Es cuestión de que investigues un poco en internet et voilà.

Un saludo

Re: Leer pixeles de un bitmap monocromo

PostPosted: Sun Jul 26, 2015 6:24 pm
by antolin
A lo mejor te parece una tontería, pero: tu fichero, si es un BMP monocromo se compondrá de una cabecera BITMAPINFOHEADER seguido de los BYTES (8 BITS) de la imagen. Por la tanto, si averiguas cuánto mide esa cabecera podrás abrir el fichero con MEMOWRIT y leer los bytes de la imagen con Substr(). Un byte a 0 significa color negro y un byte 1 color blanco (creo). Yo lo hice hace algunos años con un bitmap de 24 bits y me fue muy bien.

Sólo tienes que tener en cuenta dos cosas.

1 .- Cada línea del bitmap tiene que medir una cantidad de bytes múltiplo de 4. Por ejemplo si la imagen mide 398 pixels de ancho, cada línea ocupará 400 bytes en el fichero. Los dos últimos bytes serán ceros.

2 .- A quien diseño los ficheros BMP se le ocurrió la feliz idea de guardar las líneas en orden inverso. Las líneas, no los bytes que las componen. Significa que tras la cabecera estará la información de la última línea de la imagen, seguida de la información de la penúltima, la antepenúltima, etc. Por lo tanto,el primer byte tras la cabecera representa el color del primer pixel de la última línea de la imagen. Seguido del segundo pixel de la última línea, y así hasta el final. El último byte del fichero será el último byte de la primera línea de la imagen, o uno, dos o tres ceros de relleno para que la línea mida una cantidad múltiplo de 4. Por lo tanto en esa imagen de 398 pixels de ancho, los dos últimos bytes serán 00 y el antepenúltimo será el color del último byte de la primera línea de la imagen. El primer byte de la primera línea estará en la posición: longitud del fichero menos 400.

Nunca he trabajado con BMP's monocromos. Por lo tanto puede ocurrir que en lugar de guardar la imagen en BYTES lo haga en BITS. Pero seguramente cada línea medirá una cantidad múltiplo de 4 y las líneas se habrán guardado en orden inverso.

Un saludo

Re: Leer pixeles de un bitmap monocromo

PostPosted: Sun Jul 26, 2015 6:35 pm
by antolin
Perdona jmarcial. No había visto que había una segunda página de posts y pensé que no había mandado el mensaje, por eso está duplicado.

Aquí te lo explican de forma muy sencilla:
http://es.ccm.net/contents/719-el-forma ... te-fichier
Y sí se guarda como BITS y no como BYTES.

Un saludo

Re: Leer pixeles de un bitmap monocromo

PostPosted: Sun Jul 26, 2015 6:47 pm
by antolin
He estado mirando por encima y resulta que el BITMAPINFOHEADER mide 40 bytes, pero los ficheros, además de eso tienen, delante, tienen un BITMAPFILEHEADER que mide 14 bytes. Luego, la información de la imagen debería empezar en el 55º byte. Suponiendo que utilice paleta. Claro que un bitmap monocromo, no creo que utilice paleta, ni tabla de colores.... Pero, y si sí...

Re: Leer pixeles de un bitmap monocromo

PostPosted: Mon Jul 27, 2015 7:27 am
by jmartial
Gracias Antolin,

Pero haciéndolo con las funciones del API de windows para cargar el bitmap y buscando el color con getPixel(), creo que es más limpio, seguro y rápido.

Lo que planteas está bien pero, vamos un poco a ciegas, contando que luego para cortarlo exactamente en un número de pixeles, creo que es más problemático, además de que hay que calcular mucho innecesariamente, ya que como te digo, usando el API no te tienes que preocupar de todo eso.