Format PFI
Publié : 11 nov. 2005 11:27
Les sources ci-dessous permettent de lire les propriétés, la miniature et le calque de fond dans un fichier PFI (Image PhotoFiltre Studio). Pour le moment, j'utilise un format RGB qui est plus rapide et plus simple. La couche Alpha sera gérée dans la prochaine version.
Code : Tout sélectionner
// Format PFI - PhotoFiltre Studio
// Antonio DA CRUZ - Novembre 2005
// Dernière modification : 10/11/2005
unit PFImage;
interface
uses
Windows, Classes, Graphics;
type
TPFProperties = record
Version: Integer;
Width: Integer;
Height: Integer;
DPI: Double;
Comment: string;
ColorCount: Integer;
end;
TPFImage = class(TBitmap)
private
FProperties: TPFProperties;
public
procedure LoadFromStream(Stream: TStream); override;
procedure LoadPropertiesFromStream(Stream: TStream);
procedure LoadPropertiesFromFile(const FileName: string);
procedure LoadThumbFromStream(Stream: TStream);
procedure LoadThumbFromFile(const FileName: string);
property Properties: TPFProperties read FProperties;
end;
function IsPfiFile(const FileName: string): Boolean;
implementation
uses
SysUtils;
// Pour le moment, une seule extension -----------------------------------------
function IsPfiFile(const FileName: string): Boolean;
begin
Result := LowerCase(ExtractFileExt(FileName)) = '.pfi';
end;
// Permet de charger les données RGB brutes ------------------------------------
// (compression non gérée pour le moment)
procedure LoadRGBFromStream(Bmp: TBitmap; Stream: TStream);
var
I, LineSize: Integer;
begin
Bmp.Assign(nil);
Bmp.PixelFormat := pf24bit;
// dimensions
Stream.ReadBuffer(I, SizeOf(I));
Bmp.Width := I;
Stream.ReadBuffer(I, SizeOf(I));
Bmp.Height := I;
// lignes
LineSize := Bmp.Width * 3;
for I := 0 to Bmp.Height - 1 do
Stream.ReadBuffer(Bmp.ScanLine[I]^, LineSize);
end;
// Charge les propriétés -------------------------------------------------------
procedure TPFImage.LoadPropertiesFromStream(Stream: TStream);
var
I: Integer;
Buffer: array[0..255] of Char;
begin
// signature
Stream.ReadBuffer(Buffer, 17);
if StrLComp(Buffer, 'PhotoFiltre Image', 17) <> 0 then
raise EStreamError.Create('');
// version
Stream.ReadBuffer(Buffer, 1);
FProperties.Version := Ord(Buffer[0]);
// dimensions du fond
Stream.ReadBuffer(I, SizeOf(I));
FProperties.Width := I;
Stream.ReadBuffer(I, SizeOf(I));
FProperties.Height := I;
// résolution
Stream.ReadBuffer(I, SizeOf(I));
FProperties.DPI := I / 1000;
// reservé
Stream.ReadBuffer(I, SizeOf(I));
// commentaire (256 caractères)
Stream.ReadBuffer(Buffer, 256);
FProperties.Comment := Buffer;
// ColorCount
Stream.ReadBuffer(I, SizeOf(I));
FProperties.ColorCount := I;
end;
procedure TPFImage.LoadPropertiesFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadPropertiesFromStream(Stream);
finally
Stream.Free;
end;
end;
// Charge la miniature ---------------------------------------------------------
procedure TPFImage.LoadThumbFromStream(Stream: TStream);
var
I: Integer;
Buffer: array[0..8] of Char;
begin
LoadPropertiesFromStream(Stream);
// taille en octets de la zone miniature
Stream.ReadBuffer(I, SizeOf(I));
// signature
Stream.ReadBuffer(Buffer, 9);
if StrLComp(Buffer, 'Thumbnail', 9) <> 0 then
raise EStreamError.Create('');
// réservé
Stream.ReadBuffer(I, SizeOf(I));
// données RGB de la miniature
LoadRGBFromStream(Self, Stream);
end;
procedure TPFImage.LoadThumbFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadThumbFromStream(Stream);
finally
Stream.Free;
end;
end;
// Charge le fond (premier calque ) --------------------------------------------
procedure TPFImage.LoadFromStream(Stream: TStream);
var
I: Integer;
Buffer: array[0..255] of Char;
begin
LoadPropertiesFromStream(Stream);
// taille en octets de la zone miniature
Stream.ReadBuffer(I, SizeOf(I));
// saute la zone miniature
Stream.Seek(I - SizeOf(I), soFromCurrent);
// nombre de calques
Stream.ReadBuffer(I, SizeOf(I));
// propriétés du calque (non détaillées ici)
Stream.ReadBuffer(I, SizeOf(I));
Stream.ReadBuffer(Buffer, I);
Stream.Seek(38, soFromCurrent);
// données RGB du fond
LoadRGBFromStream(Self, Stream);
// transparence
Stream.ReadBuffer(Buffer, 1);
Transparent := Buffer[0] <> #0;
Stream.ReadBuffer(I, SizeOf(I));
TransparentColor := TColor(I);
end;
end.