Leer pixeles de un bitmap monocromo

jmartial
Posts: 457
Joined: Tue Mar 14, 2006 7:26 pm

Re: Leer pixeles de un bitmap monocromo

Post by jmartial »

Respondo por partes:

Este es código Antonio:

Code: Select all


    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
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Leer pixeles de un bitmap monocromo

Post 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 );
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Leer pixeles de un bitmap monocromo

Post by Antonio Linares »

Para un bitmap monocromo sería asi:

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

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Leer pixeles de un bitmap monocromo

Post by Antonio Linares »

Prueba asi:

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

Code: Select all

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 );
}
 
regards, saludos

Antonio Linares
www.fivetechsoft.com
jmartial
Posts: 457
Joined: Tue Mar 14, 2006 7:26 pm

Re: Leer pixeles de un bitmap monocromo

Post by jmartial »

Antonio,

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

Con CreateCompatibleBitmap sí tiene ese parámetro.
Un Saludo,
Joaquín Martínez
jmartial
Posts: 457
Joined: Tue Mar 14, 2006 7:26 pm

Re: Leer pixeles de un bitmap monocromo

Post 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


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

 
¿ Que me falta ?
Un Saludo,
Joaquín Martínez
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Leer pixeles de un bitmap monocromo

Post by Antonio Linares »

Antes del BitBlt() prueba a hacer:

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

Antonio Linares
www.fivetechsoft.com
jmartial
Posts: 457
Joined: Tue Mar 14, 2006 7:26 pm

Re: Leer pixeles de un bitmap monocromo

Post by jmartial »

Antonio,

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

No se me ocurre más nada.
Un Saludo,
Joaquín Martínez
jmartial
Posts: 457
Joined: Tue Mar 14, 2006 7:26 pm

Re: Leer pixeles de un bitmap monocromo

Post 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
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Leer pixeles de un bitmap monocromo

Post by Antonio Linares »

Muy bien! :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
antolin
Posts: 475
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Leer pixeles de un bitmap monocromo

Post 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
Peaaaaaso de foro...
antolin
Posts: 475
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Leer pixeles de un bitmap monocromo

Post 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
Peaaaaaso de foro...
antolin
Posts: 475
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Leer pixeles de un bitmap monocromo

Post 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
Peaaaaaso de foro...
antolin
Posts: 475
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: Leer pixeles de un bitmap monocromo

Post 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í...
Peaaaaaso de foro...
jmartial
Posts: 457
Joined: Tue Mar 14, 2006 7:26 pm

Re: Leer pixeles de un bitmap monocromo

Post 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.
Un Saludo,
Joaquín Martínez
Post Reply