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.