Page 1 of 1

Pintar un pixel sobre un Bmp

Posted: Thu Jan 04, 2007 11:57 am
by Rafael Clemente
Supongamos que tengo un Bmp de -por ejemplo- 3000 x 1200 pixels, o sea, que no cabe entero en pantalla sin redimensionarlo.

Mi pregunta es: Alguien podría darme una receta o función para pintar UN pixel directamente sobre el archivo BMP (NO sobre pantalla) de un color determinado. Algo así: FnPintar(".\MiBmp.bmp", 500, 400, CLR_GREEN)

Muchísimas gracias

Rafael

Posted: Thu Jan 04, 2007 5:50 pm
by Antonio Linares
Rafael,

Para modificar el pixel tienes que cargarlo en un hDC, que no quiere decir que tengas que visualizarlo:

local hOld := SelectObject( oWnd:hDC, hBitmap )

SetPixel( oWnd:hDC, ... )

Guardar el bitmap a disco nuevamente

SelectObject( oWnd:hDC, hOld )

Si explicas un poco más lo que quieres hacer, podemos ver la forma idónea de guardarlo

Posted: Thu Jan 04, 2007 7:38 pm
by Rafael Clemente
Antonio: Gracias por tu sugerencia. Valos a ver si podemos adelantar algo más:

Se trata de diseñar un sistema que permita pintar sobre un plano el trayecto recorrido por un automóvil equipado con un receptor GPS. Ya tengo el sistema que captura las coordenadas del GPS, segundo a segundo. Está hecho con FWPPC y va de maravilla. Ahora se trata de ponerlo en gráfico.

Lo lógico sería utilizar un plano dibujado en AutoCad, o sea, en formato vectorial. El problema es que de ese formato no tengo ni idea, así que pensé que quizás sería más fácil hacerlo con un plano escaneado en forma de bitmap y me pareció que el BMP era el formato más simple. A lo mejor estoy equivocado y alguien sabe cómo hacerlo en vectorial o incluso en formatos más comprimidos como el Jpg.

Para tener una resolución adecuada, el BMP ha de ser muy grande (tengo uno de muestra que tiene casi 100 Mb), así que no es posible presentarlo adecuadamente en pantalla. De ahí mi requisito de marcar pixels directamente sobre el archivo.

¿Qué pixels hay que marcar? Se tratará de interpolar las coordenadas GPS, punto a punto sobre el propio plano tomando como referencia sus vértices, cuyas coordenadas son conocidas. Puede ser un trabajo laborioso pero no parece muy complicado.

En fin, incluso puede ser que exista ya alguna librería que facilite el trabajo aunque preferiría utilizar código propio. Me podrías dar alguna idea o -mejor aún- un esqueleto de programa por donde empezar? Por ejemplo, en tu sugerencia, qué es hBitmap? Si no he visualizado la imagen, cómo obtengo su handle? Y oWnd:hDc, a qué ventana se refiere? Perdona por las preguntas de principiante pero es que esto de SelectObject() y los hDc siempre me ha resultado un poco misterioso.

Gracias y un saludo,

Rafael

Posted: Sat Jan 06, 2007 11:25 am
by Rafael Clemente
Antonio:
Más o menos, ya estoy en camino de resolverlo. Es cuestión a abrir el Bmp con FOPEN(), analizar el header del Bmp (no es complicado), calcular la posición del pixel que quiero pintar (ojo, que en cada línea pueden haber hasta tres bytes 00 de relleno) y hacer un FWRITE() del color apropiado en ese pixel. Laborioso pero después de unas cuantas pruebas, la cosa parece clara.

Por cierto, si alguien quiere intentarlo, le recomiendo que utilice como foto de partida un Bmp en blanco. Así, toda la zona de datos son bytes FF y es mucho más fácil de analizar _

Saludos,

Rafael

Posted: Sat Jan 06, 2007 7:52 pm
by Paco Garcia
Hola Rafael

Para pintar en un bitmap como bien dice Antonio debes hacer esto:

Code: Select all


local hBmp := ReadBitmap( 0, cBitmap )
local hDC := CreateDC( "DISPLAY",0,0,0)
local hDCMem := CreateCompatibleDC( hDC )
local hOldBmp := SelectObject( hDCMem, hBmp )
local nWBmp := nBmpWidth( hBmp )
local nHBmp := nBmpHeight( hBmp )

DeleteDC( hDC )

// ya tienes todo lo necesario
// ahora pintar

Moveto( hDCmem, 10, 10 )
Lineto( hDCMem, 100, 100 )

SelectObject( hDCMem, hOldBmp )
DeleteDC( hDCMem )

// si quieres guardar el bmp otra vez pues pasalo a Dib y luego a disco

Return hbmp // o lo que quieras

Si necesitas algo mas, pues cuenta

Podrias tambien investigar los Metafiles. Eso sería dibujo vectorial y ocupan poco. Un metafile es básicamente hacer el CreateMetafile y las funciones de dibujo de toda la vida. Luego estas llamadas a funciones se quedan almacenadas dentro del metafile como si de un dbf se tratase lo único que ocupa menos que un bitmap.

Paco

Posted: Tue Jan 16, 2007 10:28 am
by Rafael Clemente
Paco:
Aunque con un poco de retraso he probado tu sugerencia pero me da un error de

Code: Select all

Error: Unresolved external '_HB_FUN_CREATECOMPATIBLEDC'
¿Por favor, me puedes decir qué me falta?
Rafael

Posted: Tue Jan 16, 2007 11:34 am
by Antonio Linares
Rafael,

Code: Select all

HB_FUNC(  CREATECOMPATIBLEDC )
{
   hb_retnl( ( LONG ) CreateCompatibleDC( ( HDC ) hb_parnl( 1 ) ) );
}

Posted: Tue Jan 16, 2007 12:48 pm
by Rafael Clemente
Antonio: Gracias. Ya compila. Ahora ¿Cómo puedo crear el Bmp modificato?. Algo así:

Code: Select all

...
hBmp    := ReadBitmap( 0, cBitmap )
hDC     := CreateDC( "DISPLAY",0,0,0)
hDCMem  := CreateCompatibleDC( hDC )
hOldBmp := SelectObject( hDCMem, hBmp )
nWBmp   := nBmpWidth( hBmp )
nHBmp   := nBmpHeight( hBmp )

DeleteDC( hDC )

MoveTo(hDCmem, 10, 10 )
Lineto( hDCMem, 100, 100 )         // Hasta aquí, parece que va bien
DibWrite(".\prueba.bmp", hDcMem)   // <---- Aquí me da un GPF ¿cómo lo hago?
SelectObject( hDCMem, hOldBmp )
DeleteDC( hDCMem )
...
Rafael

Posted: Fri Jan 19, 2007 8:40 am
by Paco Garcia
hDib := DibFromBitmap( hBmp )

DibWrite( "dibujo.bmp", hDib )

GlobalFree( hDib )

Posted: Fri Jan 19, 2007 4:12 pm
by Rafael Clemente
Paco:
Muchas gracias. Para imágenes pequeñas (30 K) tu programa funciona perfecto; para las grandes (lo he probado con un bmp de 9 M) da un error en DibWrite() pero supongo que eso es normal tratándose de archivos tan grandes.

Entretanto, yo he estado experimentando en pintar directamente pixels sobre el archivo Bmp y por ahora funciona bastante bien. Claro que es mucho más engorroso pero para salir del paso ya me sirve

Gracias otra vez y un saludo,

Rafael

Posted: Thu Mar 06, 2008 6:05 pm
by JmGarcia
Rafael Clemente wrote:...Lo lógico sería utilizar un plano dibujado en AutoCad, o sea, en formato vectorial...
Los ficheros de AutoCad son "texto", añadir mas texto (o insertar) no seria complicado. Digo yo.