Pintar un pixel sobre un Bmp

Pintar un pixel sobre un Bmp

Postby Rafael Clemente » Thu Jan 04, 2007 11:57 am

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

Postby Antonio Linares » Thu Jan 04, 2007 5:50 pm

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

Postby Rafael Clemente » Thu Jan 04, 2007 7:38 pm

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

Postby Rafael Clemente » Sat Jan 06, 2007 11:25 am

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 los cambios

Saludos,

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

Postby Paco Garcia » Sat Jan 06, 2007 7:52 pm

Hola Rafael

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

Code: Select all  Expand view

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

Postby Rafael Clemente » Tue Jan 16, 2007 10:28 am

Paco:
Aunque con un poco de retraso he probado tu sugerencia pero me da un error de
Code: Select all  Expand view
Error: Unresolved external '_HB_FUN_CREATECOMPATIBLEDC'

¿Por favor, me puedes decir qué me falta?
Rafael
User avatar
Rafael Clemente
 
Posts: 365
Joined: Sat Oct 08, 2005 7:59 pm
Location: Barcelona, Spain

Postby Antonio Linares » Tue Jan 16, 2007 11:34 am

Rafael,
Code: Select all  Expand view
HB_FUNC(  CREATECOMPATIBLEDC )
{
   hb_retnl( ( LONG ) CreateCompatibleDC( ( HDC ) hb_parnl( 1 ) ) );
}
regards, saludos

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

Postby Rafael Clemente » Tue Jan 16, 2007 12:48 pm

Antonio: Gracias. Ya compila. Ahora ¿Cómo puedo crear el Bmp modificato?. Algo así:
Code: Select all  Expand view
...
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
Rafael Clemente
 
Posts: 365
Joined: Sat Oct 08, 2005 7:59 pm
Location: Barcelona, Spain

Postby Paco Garcia » Fri Jan 19, 2007 8:40 am

hDib := DibFromBitmap( hBmp )

DibWrite( "dibujo.bmp", hDib )

GlobalFree( hDib )
User avatar
Paco Garcia
 
Posts: 172
Joined: Fri Oct 07, 2005 12:00 pm

Postby Rafael Clemente » Fri Jan 19, 2007 4:12 pm

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

Postby JmGarcia » Thu Mar 06, 2008 6:05 pm

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


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 55 guests