Pintar un pixel sobre un Bmp

Post Reply
User avatar
Rafael Clemente
Posts: 365
Joined: Sat Oct 08, 2005 7:59 pm
Location: Barcelona, Spain

Pintar un pixel sobre un Bmp

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

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

Antonio Linares
www.fivetechsoft.com
User avatar
Rafael Clemente
Posts: 365
Joined: Sat Oct 08, 2005 7:59 pm
Location: Barcelona, Spain

Post 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
User avatar
Rafael Clemente
Posts: 365
Joined: Sat Oct 08, 2005 7:59 pm
Location: Barcelona, Spain

Post 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
User avatar
Paco Garcia
Posts: 172
Joined: Fri Oct 07, 2005 12:00 pm
Contact:

Post 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
User avatar
Rafael Clemente
Posts: 365
Joined: Sat Oct 08, 2005 7:59 pm
Location: Barcelona, Spain

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

Post by Antonio Linares »

Rafael,

Code: Select all

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

Antonio Linares
www.fivetechsoft.com
User avatar
Rafael Clemente
Posts: 365
Joined: Sat Oct 08, 2005 7:59 pm
Location: Barcelona, Spain

Post 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
User avatar
Paco Garcia
Posts: 172
Joined: Fri Oct 07, 2005 12:00 pm
Contact:

Post by Paco Garcia »

hDib := DibFromBitmap( hBmp )

DibWrite( "dibujo.bmp", hDib )

GlobalFree( hDib )
User avatar
Rafael Clemente
Posts: 365
Joined: Sat Oct 08, 2005 7:59 pm
Location: Barcelona, Spain

Post 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
User avatar
JmGarcia
Posts: 654
Joined: Mon May 29, 2006 3:14 pm
Location: Madrid - ESPAÑA

Post 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.
Mi abuelo decía: Los aviones vuelan porque Dios quiere, y los helicópteros ni Dios sabe porque vuelan.
FWH 16.02, xHarbour 1.2.3, Harbour 3.2.0, WorkShop 4.5, AJ Make 0.30, Borlan BCC 7.00, VisualStudio 2013
Post Reply