[Botta&Risposta] Getpixel più veloce

Tutorial, videotutorials ed esempi creati da noi
Rispondi
Avatar utente
Homunculus
Admin
Messaggi: 6840
Iscritto il: 25/11/2007, 20:36
Contatta:

[Botta&Risposta] Getpixel più veloce

Messaggio da Homunculus »

Oggi sono incappato in uno script interessante che permette di estrarre un valore rgb da un file bmp. In pratica, in getpuxel per file salvati su disco basato sul codice binario dei file bmp.

Ci ho costruito attorno un paio di funzioni che potrebbero andare a sostituire le famigerate e lentissime funzioni getpixel di gm.
In base ai test che ho effettuato il mio getpixel risulta circa 7.5 volte più efficiente di quello interno nell'eleborazione di intere immagini. Questo risultato é stato ottenuto testando con immagini da 160x120, 320x240, 640x480, con un getpixel per ogni pixel dell'immagine.

Anche se non ho potuto testare, visti i tempi sotto il millisecondo, una chiamata ad un singlo getpixel. La singola chiamata tuttavia penso sia piu lenta nel mio script rispetto a quello interno, in quanto il mio script alla prima chiamata deve salvare su disco il file e aprirlo in binario.

Ecco gli script (leggete bene le descrizioni per sapere come usarli):

gp_init_scr

Codice: Seleziona tutto

//Descrizione: inizializza il getpixel per un background,uno sprite o una surface. Va chiamato PRIMA di usare gp_get_scr, e una sola volta per ogni risorsa
//Argomenti: tipo,risorsa,(image_index)
//tipo: rappresenta il tipo di risorsa dai cui si vuole ricavare i pixel, 0 = surface, 1 = background, 2 = sprite
//risorsa: la surface, il background o la sprite dal quale si vuole ricavare il pixel
//image_index: nel caso di uno sprite, si puo indicare la sub immagine (lasciare vuoto per surface e background)
var file,bg;

file = temp_directory+"/gp.bmp";

if(file_exists(file)) {file_delete(file);}
switch(argument0) {
    case 0: surface_save(argument1,file); 
        global.gp_w = surface_get_width(argument1);
        global.gp_h = surface_get_height(argument1);
        break;
    case 1: background_save(argument1,file); 
        global.gp_w = background_get_width(argument1);
        global.gp_h = background_get_height(argument1);
        break;
    case 2: sprite_save(argument1,argument2,file); 
        global.gp_w = sprite_get_width(argument1);
        global.gp_h = sprite_get_height(argument1);
        break;
}

global.gp_hd = 54;
global.gp_file = file_bin_open(file,0);
gp_close_scr

Codice: Seleziona tutto

//Descrizione: script da chiamare quando si ha terminato di richiedere pixel ad una risorsa
file_bin_close(global.gp_file);
gp_get_scr

Codice: Seleziona tutto

//Descrizione: ritorna il colore del pixel in posizione x,y della risorsa attualmente aperta utilizzando gp_init_scr().
//Argomenti: x,y
var x_posn,y_posn;

x_posn=argument0
y_posn=global.gp_h-argument1-1

if(x_posn < global.gp_w && y_posn < global.gp_h && x_posn >= 0 && y_posn >= 0){
    var r,g,b,p;
    p=x_posn+(y_posn*global.gp_w);
    file_bin_seek(global.gp_file,global.gp_hd+(p*4));
    b=file_bin_read_byte(global.gp_file);
    g=file_bin_read_byte(global.gp_file);
    r=file_bin_read_byte(global.gp_file);
    return make_color_rgb(r,g,b);
}
else {return 0;}

Avatar utente
maz85
Admin
Messaggi: 8287
Iscritto il: 07/02/2004, 15:57
Specialità: Nientologo
Località: Oblio
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da maz85 »

Bellissimo, non sapevo come si leggeva un file bmp, sapevo solo che salvava posizione+colore.
Per curiosità mi chiarisci un po' la faccenda?

Codice: Seleziona tutto

global.gp_hd = 54;

in pratica è la posizione di quando finisce l'header?

Codice: Seleziona tutto

x_posn=argument0      
y_posn=global.gp_h-argument1-1
hum, non capisco perchè la posizione y è questa... (vabbè deve essere come salva il bmp)

Codice: Seleziona tutto

p=x_posn+(y_posn*global.gp_w);
file_bin_seek(global.gp_file,global.gp_hd+(p*4));
nemmeno qui (ogni pixel occupa 4 byte?).

Avatar utente
Homunculus
Admin
Messaggi: 6840
Iscritto il: 25/11/2007, 20:36
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Homunculus »

Maz ho specificato che la parte di lettura del file bmp non é farina del mio sacco anche perché anche a me non é particolarmente chiara. Anche io ho le tue stesse domande in proposito.

Il "54" comunque sembrerebbe proprio l'header, in quanto é fisso per ogni lettura.

visto "y_posn=global.gp_h-argument1-1" penso che le coordinate dei pixel nel file bmp siano rappresentato come in un diagramma cartesiano, ovvero con il punto 0,0 in basso a sinistra... ma sono solo supposizioni

Avatar utente
maz85
Admin
Messaggi: 8287
Iscritto il: 07/02/2004, 15:57
Specialità: Nientologo
Località: Oblio
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da maz85 »

Si, penso sia così. Avevo letto hd al posto di h quindi non capivo.
Ci smanetterò un po' sopra...

Avatar utente
Homunculus
Admin
Messaggi: 6840
Iscritto il: 25/11/2007, 20:36
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Homunculus »

Sicuramente lo script non permetterà effetti speciali in tempo reale come la conversione in scala di grigi, però la velocità rispetto al getpixel normale é notevole (un'immagine che richiedeva 13 secondi normalmente per essere salvata in una ds_grid, ne ha impiegati un po' meno di 2).

P.S: non centra col topic, ma non converrebbe fare una sezione apposta per code del genere invece di inserire dei botta&risposta in domane&risposte?

Avatar utente
maz85
Admin
Messaggi: 8287
Iscritto il: 07/02/2004, 15:57
Specialità: Nientologo
Località: Oblio
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da maz85 »

Beh, avendo posizione e colore si può ricreare in una matrice di punti il bitmap, oppure si può ricreare in una stringa composta di draw_point_color(x,y,z) e poi la si usa per disegnare la risorsa. :banapc:

Ot: non so, io i "botta e risposta" li vedo una domanda già risolta, una pillola, non vorrei creare una sezione per niente.
Poi c'è pure la sezione snippet sul sito (magari dove postare il codice e fare riferimento al topic sul forum per discuterne). Posso anche fare un "trova tutti i botta e risposta del forum" e magari metterla nella sezione tutorial o snippet del sito :fapensare:

Avatar utente
Sla
GMI VIP
Messaggi: 3618
Iscritto il: 21/07/2008, 10:11
Specialità: Titanismo
Località: (gm) Italia
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Sla »

Ottimo Homu! Recentemente mi è venuto in mente pure a me di ottenere il colore del pixel dal file immagine, certo non sapevo come
visto che di codice binario non me ne intendo. Credo mi farò aiutare da wiki.
Intanto ho fatto qualcosa per testare i tuoi script, in evento draw questo vi converte la sprite0 in una copia a colori inversi
Spoiler

Codice: Seleziona tutto

if !variable_local_exists("var1")
{
gp_init_scr(2,sprite0)
var1 = 0
global.sprite1 = 0
w = sprite_get_width(sprite0)
h = sprite_get_height(sprite0)
}
draw_sprite(sprite0,0,0,0)

if var1 = 0
{
    i = 0
    line = 0
    while i < w+1
    {
        c = gp_get_scr(i,line)
        draw_point_color(i+w,line,make_color_rgb(255-color_get_red(c),255-color_get_green(c),255-color_get_blue(c)))
        if i = w
        {
            line += 1
            i = 0;
            if line > h
            {
                screen_save_part(temp_directory+"\ciao.bmp",w,0,w,w);
                global.sprite1 = sprite_add(temp_directory+"\ciao.bmp",0,0,0,0,0)
                var1 = 1
                gp_close_scr()
                break;   
            }
        }
        i += 1
    }
}
else
{
    draw_sprite(global.sprite1,0,w,0)
}
edit: ancora però mi chiedo come faccia paint a svolgere questo lavoro in un attimo per ogni dimensione di immagine...
edit2: ah hai ragione homu, ho corretto. (per chi non capisse --> post successivo)
Ultima modifica di Sla il 28/02/2010, 23:41, modificato 2 volte in totale.
eppure mi sembra tutto giusto...

Avatar utente
Homunculus
Admin
Messaggi: 6840
Iscritto il: 25/11/2007, 20:36
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Homunculus »

Ottimo slascio, magari se hai voglia testa la differenza in tempo tra getpixel interno e questo.

P.S: hai dimenticato gp_close_scr(); che chiude il file

Avatar utente
BaronVsCorsar
GMI VIP
Messaggi: 4699
Iscritto il: 14/02/2004, 12:05
Specialità: Saccenza
Uso: GameMaker 8.1
Località: Ferrara
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da BaronVsCorsar »

http://it.wikipedia.org/wiki/Windows_bitmap per la composizione del file bitmap
54 byte: header.

ogni pixel occupa un numero di byte variabile dipende dal numero di colori che si usano in tavolozza (4, 16, 32, 256 ...)
4 byte= 4 milioni e rotti.
ImmagineSchiva questo - http:\\baronvscorsar.altervista.org
by Lego: Vado in un bar e faccio "votiamo che quel tizio la in fondo venga buttato fuori", ma perché?

Jak
Admin
Messaggi: 12355
Iscritto il: 19/08/2009, 16:20
Specialità: Programmazione 3D
Uso: GM:Studio 2
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Jak »

Interessante :fapensare: Mi viene voglia di provare a farle una dll in c per renderlo ancora più veloce.
Time to feel, time to believe
Dare to see what may come of our future
Lift your head, broaden your gaze
Speak your mind and your thoughts they will follow you

Avatar utente
Homunculus
Admin
Messaggi: 6840
Iscritto il: 25/11/2007, 20:36
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Homunculus »

Jak ha scritto:Interessante :fapensare: Mi viene voglia di provare a farle una dll in c per renderlo ancora più veloce.
Potrebbe in effetti diventare piu veloce, ma dipende anche dal tempo richiesto a gm per richiamare una funziona in una dll. Fammi sapere se provi, casomai si potrebbe anche estendere il primo post in modo che contenga la soluzione script e la tua con dll

Jak
Admin
Messaggi: 12355
Iscritto il: 19/08/2009, 16:20
Specialità: Programmazione 3D
Uso: GM:Studio 2
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Jak »

Effettivamente tra il definirla ed il chiamarla il tuo script ha già fatto tutto.
Time to feel, time to believe
Dare to see what may come of our future
Lift your head, broaden your gaze
Speak your mind and your thoughts they will follow you

Jak
Admin
Messaggi: 12355
Iscritto il: 19/08/2009, 16:20
Specialità: Programmazione 3D
Uso: GM:Studio 2
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Jak »

Xeryan ha scritto:mi sembra di qualche secondo più veloce
Qualche secondo? E non ti basta?
Time to feel, time to believe
Dare to see what may come of our future
Lift your head, broaden your gaze
Speak your mind and your thoughts they will follow you

Jak
Admin
Messaggi: 12355
Iscritto il: 19/08/2009, 16:20
Specialità: Programmazione 3D
Uso: GM:Studio 2
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Jak »

Xeryan ha scritto:dovresti sapere che il tempo anche in frazioni di secondo è prezioso
Per questo dicevo che qualche secondo non è poco. Credi che io non lo sappia(vedi il mio pc) quanto contano i tempi?
Time to feel, time to believe
Dare to see what may come of our future
Lift your head, broaden your gaze
Speak your mind and your thoughts they will follow you

Avatar utente
Homunculus
Admin
Messaggi: 6840
Iscritto il: 25/11/2007, 20:36
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Homunculus »

Xeryan ha scritto:certo, grazie ad homunculus il programma è migliorato di parecchio ma non basta, per immagini più grandi si blocca completamente quindi devo mettere un controllo sulle dimensioni e poi jak dovresti sapere che il tempo anche in frazioni di secondo è prezioso, specialmente nel computer.
Penso che le operazioni pixel per pixel con gm ormai non possano essere fatte in tempi decenti... In ogni caso per evitare che il programma si "blocchi", nel senso che esce il puntatore di caricamento e non puoi chiudere/spostare la finestra dovresti chiamare la funzione io_handle() OGNI TANTO durante il ciclo (per esempio ogni 1000 cicli, o 10000 se con 1000 rallenta troppo);

Jak
Admin
Messaggi: 12355
Iscritto il: 19/08/2009, 16:20
Specialità: Programmazione 3D
Uso: GM:Studio 2
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Jak »

Io non ho mai capito. io_handle() e io_clear() a cosa servono?
Time to feel, time to believe
Dare to see what may come of our future
Lift your head, broaden your gaze
Speak your mind and your thoughts they will follow you

Avatar utente
Homunculus
Admin
Messaggi: 6840
Iscritto il: 25/11/2007, 20:36
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Homunculus »

Jak ha scritto:Io non ho mai capito. io_handle() e io_clear() a cosa servono?
io_handle(); aggiorna lo stato del mouse e della tastiera, anche a livello di finestra. Viene eseguito automaticamente a ogni step, ma se si sta eseguendo un processo particolarmente lungo deve essere chiamato manualmente, altrimenti il programma non riceve piu input dall'utente e windows pensa che sia bloccato (su xp crasha).

io_clear mai usato

Avatar utente
BaronVsCorsar
GMI VIP
Messaggi: 4699
Iscritto il: 14/02/2004, 12:05
Specialità: Saccenza
Uso: GameMaker 8.1
Località: Ferrara
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da BaronVsCorsar »

io_handle() aggiorna lo stato della tastiera (e credo pure dei joystick, non ricordo) vista da GM.
Automaticamente è chiamato tra uno step ed un altro (quindi non potrà mai essere che in begin_step risulta premuto il pulsante A e in end_step risulta non premuto).

Es di uso:
Se hai un ciclo while che dura 10 secondi e vuoi renderlo interrompibile potresti chiamare un io_handle() dentro al tuo ciclo while (o chiamarlo ogni 100 esecuzioni del ciclo ad esempio), e verificare se il tasto esc è premuto.
Senza chiamare io_handle gm vede sempre lo stesso stato per il pulsante esc, a prescindere dallo stato fisico.

io_clear() cancella lo stato dei tasti premuti (nessun tasto premuto).
Serve in casi rari, in cui la pressione dei tasti è gestita dall'utente e non dalgli eventi gm. E' raro averne necessità - mi è capitato nel caso di generazione di "bottoni" tramite codice (l'oggetto esisteava già, abilitavo delle sue zone come sensibili al click del mouse).
Il bottone veniva generato tramite un mouse_button_pressed. Cliccando sopra al button il bottone si distruggeva. Se il bottone veniva generato esattamente sotto il mouse mi trovavo al volo un evento mouse button pressed (lo stesso che lo aveva generato...) distruggnedolo. Risolto facendo un io_clear() dopo aver generato un bottone.
Non so se genera gli eventi di key realeased.
ImmagineSchiva questo - http:\\baronvscorsar.altervista.org
by Lego: Vado in un bar e faccio "votiamo che quel tizio la in fondo venga buttato fuori", ma perché?

Avatar utente
Peppo95
GMI Advanced
Messaggi: 1613
Iscritto il: 05/11/2008, 19:10
Specialità: C Sharp - GML - C
Contatta:

Re: [Botta&Risposta] Getpixel più veloce

Messaggio da Peppo95 »

a me succede che se faccio un bottone per esempio, e ci metto che fa un suono quando ci è sopra,se rimpicciolisco la finestra e vado nelle stesse coordinate dei bottoni (sempre a finestra del gioco rimpicciolita) mi si sente il suono, come se ci passassi sopra :?
è fastidioso perchè non posso tenere il programma rimpicciolito mentre faccio altre robe, perchè se ci "passo" sopra si sente il suono dei pulsanti :spat: :furiosomedio:
Solite liste mie:
1) QUESTO POST NON E' FLAME


Chi lo riterrà tale verrà aspirato da un calamaro gigante.Esattamente questa notte... Muhahaha.

Immagine
Immagine

Rispondi

Chi c’è in linea

Visitano il forum: Bing [Bot] e 55 ospiti