PDA

Visualizza la versione completa : [DELPHI] Allocare immagine in memoria ed eseguire FloodFill


CaMpIoN
01-08-2011, 21:33
Ciao, voglio creare una dll che deve salvare un'immagine che applica il floodfill, il programma (Game Maker) deve salvare un'immagine in una cartella indicando poi alla dll con la funzione apposita di aprire quel file inserirlo in un TGraphics, applicarli il floodfill dove indico con il programma, salvare di nuovo l'immagine poi il processo tocca al programma riaprirlo, e siccome in una dll non ce la form come posso salvare un TGraphics in memoria per poi fare cio' che ho detto?

alka
01-08-2011, 21:40
Per caricare l'immagine, usa la classe TBitmap (http://docwiki.embarcadero.com/VCL/en/Graphics.TBitmap) (o equivalente, in base al formato dell'immagine) creandone una istanza e applica il "flood fill" usando il metodo Canvas.FloodFill (http://docwiki.embarcadero.com/VCL/en/Graphics.TCanvas.FloodFill) dell'oggetto immagine che hai creato.

Per caricare l'immagine e salvarla, l'oggetto dispone rispettivamente dei metodi LoadFromFile (http://docwiki.embarcadero.com/VCL/en/Graphics.TGraphic.LoadFromFile) e SaveToFile (http://docwiki.embarcadero.com/VCL/en/Graphics.TGraphic.SaveToFile) (ereditati dalla classe base TGraphics (http://docwiki.embarcadero.com/VCL/en/Graphics.TGraphic), che è astratta).

Ciao! :ciauz:

CaMpIoN
02-08-2011, 03:13
Bene ho capito come fare, ma provando mi da un problema, e cioè che il programma si blocca, ora posto il codice che ho inserito, la domanda è: è il programma che non funziona o e il codice:


library FloodFill;

uses
SysUtils, Windows, Classes, Graphics;

var
FloodGriglia: TBitmap;

function HexToTColor(sColor : string) : TColor;
begin
Result :=
RGB(
StrToInt('$'+Copy(sColor, 1, 2)),
StrToInt('$'+Copy(sColor, 3, 2)),
StrToInt('$'+Copy(sColor, 5, 2))
) ;
end;

procedure Flood(x,y: integer; Color,FileName: string);
begin
FloodGriglia.LoadFromFile(FileName);
FloodGriglia.Canvas.FloodFill(x,y,HexToTColor(Colo r),fsBorder);
FloodGriglia.SaveToFile(FileName);
end;

exports Flood;

{$R *.res}

begin
FloodGriglia:=TBitmap.Create;
end.
Allora ho dovuto prendere un funzione da internet che convertisse stringa esadecimale (una stringa che contenga il colore esadecimale) in TColor perchè il programma che uso può fornire solo stringe e numeri reali, string e real, e quindi il TColor non lo posso usare...

alka
02-08-2011, 11:01
Originariamente inviato da CaMpIoN
Bene ho capito come fare, ma provando mi da un problema, e cioè che il programma si blocca

Innanzitutto dovresti essere più specifico e definire cosa intendi con "mi da un problema" oppure "il programma si blocca", descrivendo accuratamente ciò che avviene e come testi la tua libreria.

Ne approfitto per suggerire di utilizzare la libreria in Delphi con un progetto di prova, prima di impiegarla nel programma che ne deve fare uso.

In merito al codice che hai postato, non capisco perché l'oggetto TBitmap venga creato al di fuori della funzione implementata: sposta la sua creazione all'interno della funzione, garantendo la distruzione dell'istanza con il costrutto Try...Finally:



var
Bmp: TBitmap;
begin
Bmp := TBitmap.Create;
try
Bmp.LoadFromFile(...);
Bmp.Canvas.FloodFill(...);
Bmp.SaveToFile(...);
finally
Bmp.Free;
end;
end;


Cosa più importante, non puoi usare il tipo string nella funzione, poiché quel tipo è specifico di Delphi: devi usare PChar (o PAnsiChar, a seconda di come lavora il programma chiamante, se lavori con una versione di Delphi recente che si basa su Unicode).

Ciao! :ciauz:

CaMpIoN
02-08-2011, 11:47
Ho capito come funziona il FloodFill e ora mi funziona in delphi, mentre nel programma no, ho provato con un'altra funzione che restituisce semplicemente un numero, e anche quello non funziona, quindi è la struttura della dll per quel programma che è sbagliata, devo capire cosa ce di sbagliato, è possibile che un programma non accetti procedure ma solo funzioni?

alka
02-08-2011, 11:56
Originariamente inviato da CaMpIoN
Ho provato come dici tu a eseguire la libreria da delphi, è mi succede che il file che dovrebbe essere rimpiazzato diventa bianco e non viene applicato il flood fill

Sei sicuro di aver compreso le indicazioni fornite nella documentazione in merito al metodo FloodFill (http://docwiki.embarcadero.com/VCL/en/Graphics.TCanvas.FloodFill)?

Te lo chiedo perché mi sembri stupito dell'esito che ottieni dopo aver impostato Brush, che invece è la normalità, così come non sono sicuro che sia chiaro il funzionamento del metodo stesso, in particolare la logica seguita nell'indicazione dei confini dell'area da riempire. :confused:

CaMpIoN
02-08-2011, 12:52
Ci siamo quasi, è come ho pensato il problema è che le procedure nel programma non vanno, solo funzioni, forse per il fatto che il programma ha bisogno di ricevere un valore dalle dll..
mettendo function il programma non mi crasha più, però mi succede che se appena apro il programma e senza disegnare linee o altro sopra, usando direttamente il flood fill, l'immagine si colora tutta con il colore scelto, però se invece ci disegno linee sopra no.

ecco il codice completo della dll:



library FloodFill;

uses
SysUtils, Windows, Classes, Graphics;

function HexToTColor(sColor : PChar) : TColor;
begin
Result :=
RGB(
StrToInt('$'+Copy(sColor, 1, 2)),
StrToInt('$'+Copy(sColor, 3, 2)),
StrToInt('$'+Copy(sColor, 5, 2))
) ;
end;

function Flood(x,y: real; ColorBack,FileName: PChar): real; stdcall;
var FloodGriglia: TBitmap;
begin
FloodGriglia:=TBitmap.Create;
try
FloodGriglia.LoadFromFile(FileName);
FloodGriglia.Canvas.Brush.Color:=clRed;
FLoodGriglia.Canvas.Brush.Style:=bsSolid;
FloodGriglia.Canvas.FloodFill(trunc(x),trunc(y),He xToTColor(ColorBack),fsBorder);
FloodGriglia.SaveToFile(FileName);
finally
FloodGriglia.Free;
end;
Result:=1;
end;

exports Flood;

{$R *.res}

begin
end.

Nel programma ho messo anche un drawline proprio per verificare se ci sono problemi del genere.

alka
02-08-2011, 13:00
Originariamente inviato da CaMpIoN
Ci siamo quasi, è come ho pensato il problema è che le procedure nel programma non vanno, solo funzioni, forse per il fatto che il programma ha bisogno di ricevere un valore dalle dll..

Su questo ovviamente non posso essere d'aiuto: sai tu se il programma chiamante ha bisogno o meno di ricevere un valore di ritorno dalla routine della DLL.


Originariamente inviato da CaMpIoN
però mi succede che se appena apro il programma e senza disegnare linee o altro sopra, usando direttamente il flood fill, l'immagine si colora tutta con il colore scelto


Questo mi pare normale: in fondo, stai facendo un "flood fill".


Originariamente inviato da CaMpIoN
però se invece ci disegno linee sopra no.


Cioè? In quel caso, cosa succede? E cosa vorresti invece ottenere?

CaMpIoN
02-08-2011, 13:17
In quel caso non succede nulla, l'immagine rimane invariata, e vorrei che si applicasse il flood fill (secchiello di paint, prova a disegnare un cerchio, prendere il secchiello e cliccarci dentro, voglio ottenere quello che succede nel paint), mah è strano che si applica solo quando non disegno xDxD..

alka
02-08-2011, 13:34
Originariamente inviato da CaMpIoN
In quel caso non succede nulla, l'immagine rimane invariata, e vorrei che si applicasse il flood fill (secchiello di paint, prova a disegnare un cerchio, prendere il secchiello e cliccarci dentro, voglio ottenere quello che succede nel paint), mah è strano che si applica solo quando non disegno xDxD..

Secondo me, sbagli a specificare i colori di riferimento.

Dove hai specificato il colore che vuoi usare per il riempimento?
E dove hai indicato il colore che deve essere "campionato" affinché il riempimento sappia quando fermarsi?

Loading