Browse Source

--- Merging r31942 into '.':
U packages/fcl-image/src/fpreadtiff.pas
--- Recording mergeinfo for merge of r31942 into '.':
U .
--- Merging r32813 into '.':
U packages/fcl-image/src/fpwritepng.pp
--- Recording mergeinfo for merge of r32813 into '.':
G .
--- Merging r33464 into '.':
U packages/fcl-image/src/fpimage.inc
--- Recording mergeinfo for merge of r33464 into '.':
G .
--- Merging r33465 into '.':
U packages/fcl-image/src/fpreadjpeg.pas
--- Recording mergeinfo for merge of r33465 into '.':
G .
--- Merging r33466 into '.':
U packages/fcl-image/src/fphandler.inc
--- Recording mergeinfo for merge of r33466 into '.':
G .
--- Merging r33467 into '.':
G packages/fcl-image/src/fpimage.inc
--- Recording mergeinfo for merge of r33467 into '.':
G .
--- Merging r33471 into '.':
G packages/fcl-image/src/fphandler.inc
G packages/fcl-image/src/fpreadjpeg.pas
G packages/fcl-image/src/fpimage.inc
--- Recording mergeinfo for merge of r33471 into '.':
G .
--- Merging r33472 into '.':
U packages/fcl-image/src/fpreadpng.pp
--- Recording mergeinfo for merge of r33472 into '.':
G .
--- Merging r33473 into '.':
G packages/fcl-image/src/fpimage.inc
U packages/fcl-image/src/fpimage.pp
U packages/fcl-image/src/fphandler.inc
--- Recording mergeinfo for merge of r33473 into '.':
G .
--- Merging r33474 into '.':
G packages/fcl-image/src/fpimage.pp
G packages/fcl-image/src/fpreadjpeg.pas
G packages/fcl-image/src/fphandler.inc
--- Recording mergeinfo for merge of r33474 into '.':
G .

# revisions: 31942,32813,33464,33465,33466,33467,33471,33472,33473,33474

git-svn-id: branches/fixes_3_0@33580 -

marco 9 years ago
parent
commit
362fce04c9

+ 26 - 0
packages/fcl-image/src/fphandler.inc

@@ -252,6 +252,32 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TFPCustomImageReader.InternalSize(Str: TStream): TPoint;
+
+begin
+  Result.X:=-1;
+  Result.Y:=-1;
+end;
+
+function TFPCustomImageReader.ImageSize(Str: TStream): TPoint;
+var InRead : boolean;
+    P : Int64;
+begin
+  InRead := assigned(FStream);
+  if not assigned(Str) then
+    raise FPImageException.Create(ErrorText[StrNoStream]);
+  try
+    FStream := Str;
+    P:=Str.Position;
+    result := InternalSize (Str);
+    Str.Position:=P;
+  finally
+    if not InRead then
+      FStream := nil;
+  end;
+end;
+
+
 { TFPCustomImageWriter }
 { TFPCustomImageWriter }
 
 
 procedure TFPCustomImageWriter.ImageWrite (Str:TStream; Img:TFPCustomImage);
 procedure TFPCustomImageWriter.ImageWrite (Str:TStream; Img:TFPCustomImage);

+ 99 - 72
packages/fcl-image/src/fpimage.inc

@@ -71,47 +71,30 @@ begin
   end
   end
 end;
 end;
 
 
-procedure TFPCustomImage.SaveToFile (const filename:String);
+function TFPCustomImage.SaveToFile (const filename:String):boolean;
 
 
-var e,s : string;
-    r : integer;
-    f : TFileStream;
-    h : TFPCustomImageWriterClass;
+var h : TFPCustomImageWriterClass;
     Writer : TFPCustomImageWriter;
     Writer : TFPCustomImageWriter;
-    d : TIHData;
     Msg : string;
     Msg : string;
 
 
 begin
 begin
-  e := lowercase (ExtractFileExt(filename));
-  if (e <> '') and (e[1] = '.') then
-    delete (e,1,1);
-  with ImageHandlers do
-    begin
-    r := count-1;
-    s := e + ';';
-    while (r >= 0) do
+  Msg := '';
+  try
+    h := FindWriterFromFileName(filename);
+    Result := assigned (h);
+    if Result then
       begin
       begin
-      d := GetData(r);
-      if (pos(s,d.Fextension+';') <> 0) then
-        try
-          h := d.FWriter;
-          if assigned (h) then
-            begin
-            Writer := h.Create;
-            try
-              SaveTofile (filename, Writer);
-            finally
-              Writer.Free;
-            end;
-            break;
-            end;
-        except
-          on e : exception do
-            Msg := e.message;
-        end;
-      dec (r);
-      end
-    end;
+      Writer := h.Create;
+      try
+        SaveTofile (filename, Writer);
+      finally
+        Writer.Free;
+      end;
+      end;
+  except
+    on e : exception do
+      Msg := e.message;
+  end;
   if (Msg<>'') then
   if (Msg<>'') then
     FPImgError (StrWriteWithError, [Msg]);
     FPImgError (StrWriteWithError, [Msg]);
 end;
 end;
@@ -123,7 +106,9 @@ var r : integer;
     reader : TFPCustomImageReader;
     reader : TFPCustomImageReader;
     msg : string;
     msg : string;
     d : TIHData;
     d : TIHData;
+    startPos: Int64;
 begin
 begin
+  startPos := str.Position;
   with ImageHandlers do
   with ImageHandlers do
     try
     try
       r := count-1;
       r := count-1;
@@ -139,6 +124,7 @@ begin
             try
             try
               if CheckContents (str) then
               if CheckContents (str) then
                 try
                 try
+                  str.Position := startPos;
                   FStream := str;
                   FStream := str;
                   FImage := self;
                   FImage := self;
                   InternalRead (str, self);
                   InternalRead (str, self);
@@ -149,7 +135,7 @@ begin
                 end;
                 end;
             finally
             finally
               Free;
               Free;
-              str.seek (soFromBeginning, 0);
+              str.Position := startPos;
             end;
             end;
           end;
           end;
         dec (r);
         dec (r);
@@ -165,48 +151,32 @@ begin
       FPImgError (StrReadWithError, [Msg]);
       FPImgError (StrReadWithError, [Msg]);
 end;
 end;
 
 
-procedure TFPCustomImage.LoadFromFile (const filename:String);
-var e,s : string;
-    r : integer;
-    f : TFileStream;
+function TFPCustomImage.LoadFromFile (const filename:String):boolean;
+var f : TFileStream;
     h : TFPCustomImageReaderClass;
     h : TFPCustomImageReaderClass;
     reader : TFPCustomImageReader;
     reader : TFPCustomImageReader;
-    d : TIHData;
     Msg : string;
     Msg : string;
 begin
 begin
-  e := lowercase (ExtractFileExt(filename));
-  if (e <> '') and (e[1] = '.') then
-    delete (e,1,1);
-  with ImageHandlers do
-    begin
-      r := count-1;
-      s := e + ';';
-      while (r >= 0) do
-        begin
-        d := GetData(r);
-        if (pos(s,d.Fextension+';') <> 0) then
-          try
-            h := d.FReader;
-            if assigned (h) then
-              begin
-              reader := h.Create;
-              try
-                loadfromfile (filename, reader);
-              finally
-                Reader.Free;
-              end;
-              break;
-              end;
-          except
-            on e : exception do
-              Msg := e.message;
-          end;
-        dec (r);
-        end
-    end;
+  Msg := '';
+  try
+    h := FindReaderFromFileName(filename);
+    Result := assigned (h);
+    if Result then
+      begin
+      reader := h.Create;
+      try
+        loadfromfile (filename, reader);
+      finally
+        Reader.Free;
+      end;
+      end;
+  except
+    on e : exception do
+      Msg := e.message;
+  end;
   if Msg = '' then
   if Msg = '' then
     begin
     begin
-    if r < 0 then
+    if h = nil then
       begin
       begin
       f := TFileStream.Create (filename, fmOpenRead);
       f := TFileStream.Create (filename, fmOpenRead);
       try
       try
@@ -295,6 +265,63 @@ begin
   result := FExtra.count;
   result := FExtra.count;
 end;
 end;
 
 
+class function TFPCustomImage.FindHandlerFromExtension(extension: String
+  ): TIHData;
+var s : string;
+    r : integer;
+begin
+  extension := lowercase (extension);
+  if (extension <> '') and (extension[1] = '.') then
+    delete (extension,1,1);
+  with ImageHandlers do
+    begin
+      r := count-1;
+      s := extension + ';';
+      while (r >= 0) do
+        begin
+        Result := GetData(r);
+        if (pos(s,Result.Fextension+';') <> 0) then
+          Exit;
+        dec (r);
+        end;
+    end;
+  Result := nil;
+end;
+
+class function TFPCustomImage.FindReaderFromExtension(const extension: String
+  ): TFPCustomImageReaderClass;
+var d : TIHData;
+begin
+  d := FindHandlerFromExtension(extension);
+  if d<>nil then
+    Result := d.FReader
+  else
+    Result := nil;
+end;
+
+class function TFPCustomImage.FindReaderFromFileName(const filename: String
+  ): TFPCustomImageReaderClass;
+begin
+  Result := FindReaderFromExtension(ExtractFileExt(filename));
+end;
+
+class function TFPCustomImage.FindWriterFromExtension(const extension: String
+  ): TFPCustomImageWriterClass;
+var d : TIHData;
+begin
+  d := FindHandlerFromExtension(extension);
+  if d<>nil then
+    Result := d.FWriter
+  else
+    Result := nil;
+end;
+
+class function TFPCustomImage.FindWriterFromFileName(const filename: String
+  ): TFPCustomImageWriterClass;
+begin
+  Result := FindWriterFromExtension(ExtractFileExt(filename));
+end;
+
 procedure TFPCustomImage.RemoveExtra (const key:string);
 procedure TFPCustomImage.RemoveExtra (const key:string);
 var p : integer;
 var p : integer;
 begin
 begin

+ 16 - 6
packages/fcl-image/src/fpimage.pp

@@ -22,7 +22,10 @@ uses sysutils, classes;
 type
 type
 
 
   TFPCustomImageReader = class;
   TFPCustomImageReader = class;
+  TFPCustomImageReaderClass = class of TFPCustomImageReader;
   TFPCustomImageWriter = class;
   TFPCustomImageWriter = class;
+  TFPCustomImageWriterClass = class of TFPCustomImageWriter;
+  TIHData = class;
   TFPCustomImage = class;
   TFPCustomImage = class;
 
 
   FPImageException = class (exception);
   FPImageException = class (exception);
@@ -125,14 +128,20 @@ type
       constructor create (AWidth,AHeight:integer); virtual;
       constructor create (AWidth,AHeight:integer); virtual;
       destructor destroy; override;
       destructor destroy; override;
       procedure Assign(Source: TPersistent); override;
       procedure Assign(Source: TPersistent); override;
+      // Image handlers
+      class function FindHandlerFromExtension(extension:String): TIHData;
+      class function FindReaderFromFileName(const filename:String): TFPCustomImageReaderClass;
+      class function FindReaderFromExtension(const extension:String): TFPCustomImageReaderClass;
+      class function FindWriterFromFileName(const filename:String): TFPCustomImageWriterClass;
+      class function FindWriterFromExtension(const extension:String): TFPCustomImageWriterClass;
       // Saving and loading
       // Saving and loading
       procedure LoadFromStream (Str:TStream; Handler:TFPCustomImageReader);
       procedure LoadFromStream (Str:TStream; Handler:TFPCustomImageReader);
       procedure LoadFromStream (Str:TStream);
       procedure LoadFromStream (Str:TStream);
       procedure LoadFromFile (const filename:String; Handler:TFPCustomImageReader);
       procedure LoadFromFile (const filename:String; Handler:TFPCustomImageReader);
-      procedure LoadFromFile (const filename:String);
+      function LoadFromFile (const filename:String): Boolean;
       procedure SaveToStream (Str:TStream; Handler:TFPCustomImageWriter);
       procedure SaveToStream (Str:TStream; Handler:TFPCustomImageWriter);
       procedure SaveToFile (const filename:String; Handler:TFPCustomImageWriter);
       procedure SaveToFile (const filename:String; Handler:TFPCustomImageWriter);
-      procedure SaveToFile (const filename:String);
+      function SaveToFile (const filename:String): Boolean;
       // Size and data
       // Size and data
       procedure SetSize (AWidth, AHeight : integer); virtual;
       procedure SetSize (AWidth, AHeight : integer); virtual;
       property  Height : integer read FHeight write SetHeight;
       property  Height : integer read FHeight write SetHeight;
@@ -164,7 +173,7 @@ type
   PFPIntegerArray = ^TFPIntegerArray;
   PFPIntegerArray = ^TFPIntegerArray;
 
 
   TFPMemoryImage = class (TFPCustomImage)
   TFPMemoryImage = class (TFPCustomImage)
-    private
+    protected
       function GetInternalColor(x,y:integer):TFPColor;override;
       function GetInternalColor(x,y:integer):TFPColor;override;
       procedure SetInternalColor (x,y:integer; const Value:TFPColor);override;
       procedure SetInternalColor (x,y:integer; const Value:TFPColor);override;
       procedure SetUsePalette (Value:boolean);override;
       procedure SetUsePalette (Value:boolean);override;
@@ -199,16 +208,18 @@ type
     protected
     protected
       procedure InternalRead  (Str:TStream; Img:TFPCustomImage); virtual; abstract;
       procedure InternalRead  (Str:TStream; Img:TFPCustomImage); virtual; abstract;
       function  InternalCheck (Str:TStream) : boolean; virtual; abstract;
       function  InternalCheck (Str:TStream) : boolean; virtual; abstract;
+      function  InternalSize  (Str:TStream): TPoint; virtual; 
     public
     public
       constructor Create; override;
       constructor Create; override;
       function ImageRead (Str:TStream; Img:TFPCustomImage) : TFPCustomImage;
       function ImageRead (Str:TStream; Img:TFPCustomImage) : TFPCustomImage;
       // reads image
       // reads image
       function CheckContents (Str:TStream) : boolean;
       function CheckContents (Str:TStream) : boolean;
-      // Gives True if contents is readable
+      // Returns true if the content is readable
+      function ImageSize(Str:TStream): TPoint;
+      // returns the size of image in stream without loading it completely. -1,-1 means this is not implemented.
       property DefaultImageClass : TFPCustomImageClass read FDefImageClass write FDefImageClass;
       property DefaultImageClass : TFPCustomImageClass read FDefImageClass write FDefImageClass;
       // Image Class to create when no img is given for reading
       // Image Class to create when no img is given for reading
   end;
   end;
-  TFPCustomImageReaderClass = class of TFPCustomImageReader;
 
 
   TFPCustomImageWriter = class (TFPCustomImageHandler)
   TFPCustomImageWriter = class (TFPCustomImageHandler)
     protected
     protected
@@ -217,7 +228,6 @@ type
       procedure ImageWrite (Str:TStream; Img:TFPCustomImage);
       procedure ImageWrite (Str:TStream; Img:TFPCustomImage);
       // writes given image to stream
       // writes given image to stream
   end;
   end;
-  TFPCustomImageWriterClass = class of TFPCustomImageWriter;
 
 
   TIHData = class
   TIHData = class
     private
     private

+ 40 - 4
packages/fcl-image/src/fpreadjpeg.pas

@@ -64,6 +64,7 @@ type
   protected
   protected
     procedure InternalRead(Str: TStream; Img: TFPCustomImage); override;
     procedure InternalRead(Str: TStream; Img: TFPCustomImage); override;
     function  InternalCheck(Str: TStream): boolean; override;
     function  InternalCheck(Str: TStream): boolean; override;
+    function  InternalSize(Str:TStream): TPoint; override;
   public
   public
     constructor Create; override;
     constructor Create; override;
     destructor Destroy; override;
     destructor Destroy; override;
@@ -450,12 +451,47 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TFPReaderJPEG.InternalSize(Str: TStream): TPoint;
+var
+  JInfo: jpeg_decompress_struct;
+  JError: jpeg_error_mgr;
+
+  procedure SetSource;
+  begin
+    jpeg_stdio_src(@JInfo, @Str);
+  end;
+
+  procedure ReadHeader;
+  begin
+    jpeg_read_header(@JInfo, TRUE);
+    Result.X := JInfo.image_width;
+    Result.Y := JInfo.image_height;
+  end;
+
+begin
+  FillChar(JInfo,SizeOf(JInfo),0);
+  if Str.Position < Str.Size then begin
+    JError:=jpeg_std_error;
+    JInfo.err := @JError;
+    jpeg_CreateDecompress(@JInfo, JPEG_LIB_VERSION, SizeOf(JInfo));
+    try
+      SetSource;
+      ReadHeader;
+    finally
+      jpeg_Destroy_Decompress(@JInfo);
+    end;
+  end;
+end;
+
 function TFPReaderJPEG.InternalCheck(Str: TStream): boolean;
 function TFPReaderJPEG.InternalCheck(Str: TStream): boolean;
+var
+  Buf: array[0..1] of Byte = (0, 0);
+  p: Int64;
 begin
 begin
-  // ToDo: read header and check
-  Result:=false;
-  if Str=nil then exit;
-  Result:=true;
+  if Str=nil then exit(false);
+  p:=Str.Position;
+  Result := (Str.Read(Buf, 2)=2) and (Buf[0]=$FF) and (Buf[1]=$D8); // byte sequence FFD8 = start of image
+  Str.Position:=p;
 end;
 end;
 
 
 constructor TFPReaderJPEG.Create;
 constructor TFPReaderJPEG.Create;

+ 1 - 1
packages/fcl-image/src/fpreadpng.pp

@@ -846,7 +846,7 @@ begin
     for r := 0 to 7 do
     for r := 0 to 7 do
     begin
     begin
       If SigCheck[r] <> Signature[r] then
       If SigCheck[r] <> Signature[r] then
-        raise PNGImageException.Create('This is not PNG-data');
+        Exit(false);
     end;
     end;
     // Check IHDR
     // Check IHDR
     ReadChunk;
     ReadChunk;

+ 12 - 3
packages/fcl-image/src/fpreadtiff.pas

@@ -1486,11 +1486,20 @@ begin
   if EntryType<>2 then
   if EntryType<>2 then
     TiffError('asciiz expected, but found '+IntToStr(EntryType));
     TiffError('asciiz expected, but found '+IntToStr(EntryType));
   EntryCount:=ReadDWord;
   EntryCount:=ReadDWord;
-  EntryStart:=ReadDWord;
-  SetStreamPos(EntryStart);
   SetLength(Result,EntryCount-1);
   SetLength(Result,EntryCount-1);
-  if EntryCount>1 then
+  if EntryCount>4 then begin
+    // long string -> next 4 DWord is the offset
+    EntryStart:=ReadDWord;
+    SetStreamPos(EntryStart);
     s.Read(Result[1],EntryCount-1);
     s.Read(Result[1],EntryCount-1);
+  end else begin
+    // short string -> stored directly in the next 4 bytes
+    if Result<>'' then
+      s.Read(Result[1],length(Result));
+    // skip rest of 4 bytes
+    if length(Result)<4 then
+      s.Read(EntryStart,4-length(Result));
+  end;
 end;
 end;
 
 
 function TFPReaderTiff.ReadByte: Byte;
 function TFPReaderTiff.ReadByte: Byte;

+ 1 - 1
packages/fcl-image/src/fpwritepng.pp

@@ -2,7 +2,7 @@
     This file is part of the Free Pascal run time library.
     This file is part of the Free Pascal run time library.
     Copyright (c) 2003 by the Free Pascal development team
     Copyright (c) 2003 by the Free Pascal development team
 
 
-    XPM writer class.
+    PNG writer class.
 
 
     See the file COPYING.FPC, included in this distribution,
     See the file COPYING.FPC, included in this distribution,
     for details about the copyright.
     for details about the copyright.

+ 1 - 1
utils/fpcm/revision.inc

@@ -1 +1 @@
-'2015-10-06 rev 31969'
+'2016-04-05 rev 33425'