03/05/2023 - sper ha scritto:
Detto questo ho pensato di leggere gli header dei file e vedere cosa c'è scritto in base al formato di scrittura utilizzato per l'immagine come di seguito […]
Ok, ora la tematica è più chiara, ma non vedo onestamente l'utilità di trasformare quei caratteri in una stringa.
Mi spiego: anche se i primi byte corrispondono di fatto a un testo, così come si vede nella schermata, perché convertirli necessariamente in stringa? E' sufficiente controllare che i primi byte corrispondano alla sequenza attesa, ossia che abbiano i valori che ci si aspetta, per poter decretare di cosa si tratta, senza necessariamente doverli trattare come testo.
Ti riporto qui di seguito una prova fatta al volo di una possibile implementazione che controlla i primi byte del file per accertarsi che sia una GIF:
uses
System.Classes, System.SysUtils;
function IsImageGif(const APath: string): Boolean;
var
LReadBuffer: TBytes;
LReadCount, LHeaderLength: Integer;
LStream: TStream;
const
GifBytes: array[0..4] of Byte = ($47, $49, $46, $38, $39); // GIF89
begin
LStream := TFileStream.Create(APath, fmOpenRead);
try
LHeaderLength := Length(GifBytes);
SetLength(LReadBuffer, LHeaderLength);
LReadCount := LStream.Read(LReadBuffer, LHeaderLength);
if LReadCount < LHeaderLength then
begin
Result := False;
Exit;
end;
Result := CompareMem(LReadBuffer, @GifBytes, LHeaderLength);
finally
LStream.Free;
end;
end;
Nell'esempio si può notare l'uso della classe TFileStream per aprire il file in lettura.
C'è poi la dichiarazione di un array di costanti (valori di tipo byte) inizializzato con quelli che sono i byte che ci si aspetta di trovare all'inizio del file, denominato GifBytes.
Nel codice, si dimensiona un buffer per contenere i primi 5 byte del file (l'equivalente della lunghezza dell'header da controllare) e si cerca di leggerli direttamente dal file.
Se il numero di byte letti (LReadCount) è inferiore a quelli attesi, si restituisce un esito negativo (non è senz'altro una GIF perché il file non è lungo abbastanza nemmeno per la sua intestazione).
Se invece si riesce a leggere il numero necessario di byte, usando CompareMem() si confrontano i due buffer, quello con l'header atteso e quello con i byte dell'header acquisito: il responso è positivo se il contenuto delle due aree di memoria coincidono.
Usando il costrutto try…finally, si garantisce la distruzione dell'oggetto TStream e quindi la chiusura del file sottostante.
Ovviamente, una implementazione analoga può essere riscritta e fattorizzata in chiave OOP per supportare altri formati riducendo la duplicazione del codice, ma è sufficiente a rendere l'idea.