Re: [fpc-pascal] why is FPImage dog slow reading jpeg's?

2011-05-31 Thread Bart
On 5/30/11, Ben ben.smith.li...@gmail.com wrote:

 The reason I'm reading in the jpg files is so I can get their Width and
 Height values. Avg. jpeg file sizes are between 35-45KB, and largest
 file size is 65KB.
 Ben.

A bit off-topic (as to the inner workings of FPImage), but I attached
some old code of mine to determine width/height of jpg, gif, bmp, png.
It's probably a little faster...

Bart
unit PicsLib;
{ $DEFINE DEBUG}
interface

uses Windows;

function GetBMPSize(const Fn: String; var Width, Height: dword): Boolean;
function GetGIFSize(const Fn: String; var Width, Height: dword): Boolean;
function GetJPGSize(const Fn: String; var Width, Height: dword): Boolean;
function GetPNGSize(const Fn: String; var Width, Height: dword): Boolean;
function GetImageSize(const Fn: String; var Width, Height: dword): Boolean;




implementation

uses SysUtils, Classes;

type TBitmapFileHeader = Packed Record
   ID: word;
   FileSize: dword;
   Reserved: dword;
   BitmapDataOffset: dword;
 end;
 TBitmapInfo= Packed Record
BitmapHeaderSize: dword;
Width: dword;
Height: dword;
Planes: word;
BitsPerPixel: word;
Compression: dword;
BitmapDataSize: dword;
XpelsPerMeter: dword;
YPelsPerMeter: dword;
ColorsUsed: dword;
ColorsImportant: dword;
  end;

 TGIFHeader= Packed Record
   ID: array[0..5] of char;
   Width, Height: Word;
 end;

 TPNGHeader= Packed Record
   ID: array[0..7] of Char;
   ChunkLength: dword;
   ChunkType: array[0..3] of Char;
   Width: dword;
   Height: dword;
   BitsPerPixel: byte;
   ColorType: byte;
   Compression: byte;
   FilterMethod: byte;
   CRC: dword;
 end;

 TJPGHeader= array[0..1] of Byte; //FFD8 = StartOfImage (SOI)
(*
 TJFIFHeader   = Packed record //APP0 Header
   Len: Word;
   ID: array[0..4] of Char; //JFIF#0
//   Maj, Min: Byte;
//   XYUnits: byte;
//   XDens, YDens: word;
//   ThWidth, ThHeight: byte; //Thumbnail info
 end;
*)
 TSOFHeader= Packed record
   Len: word;
   DataPrecision: byte;
   Height, Width: word;
   NrComponents: byte;
 end;


function MotorolaToIntelDW(DW: dword): dword;
var HiWd, LoWd: word;
begin
  HiWd := HiWord(DW);
  LoWd := LoWord(DW);
  HiWd := Swap(HiWd);
  LoWd := Swap(LoWd);
  Result := HiWd + (LoWd shl 16);
end;


function GetImageSize(const Fn: String; var Width, Height: dword): Boolean;
begin
  if AnsiUpperCase(ExtractFileExt(Fn)) = '.BMP' then
  begin
Result := GetBMPSize(Fn, Width, Height);
  end
  else if AnsiUpperCase(ExtractFileExt(Fn)) = '.GIF' then
  begin
Result := GetGIFSize(Fn, Width, Height);
  end
  else if (AnsiUpperCase(ExtractFileExt(Fn)) = '.JPG')
or (AnsiUpperCase(ExtractFileExt(Fn)) = '.JPEG') then
  begin
Result := GetJPGSize(Fn, Width, Height);
  end
  else if AnsiUpperCase(ExtractFileExt(Fn)) = '.PNG' then
  begin
Result := GetPNGSize(Fn, Width, Height);
  end
  else
  begin
Width := 0;
Height := 0;
Result := False;
  end;  
end;



function GetBMPSize(const Fn: String; var Width, Height: dword): Boolean;
var BitmapFileHeader: TBitmapFileHeader;
BitmapInfo: TBitmapInfo;
F: File;
bRead: Integer;
IDStr: String;
begin
  Result := False;
  Width := 0;
  Height := 0;
  Try
AssignFile(F,Fn);
FileMode := fmOpenRead or fmShareDenyWrite;
Reset(F,1);
BlockRead(F,BitmapFileHeader,SizeOf(TBitmapFileHeader),bRead);
if bRead  SizeOf(TBitmapFileHeader) then Raise EInOutError.Create('');
BlockRead(F,BitmapInfo,SizeOf(TBitmapInfo),bRead);
if bRead  SizeOf(TBitmapInfo) then Raise EInOutError.Create('');
CloseFile(F);
IDStr := Char(Lo(BitmapFileHeader.ID)) + Char(Hi(BitmapFileHeader.ID));
//Klopt bestandsopmaak ?
if (not (IDStr = 'BM') or (IDStr = 'BA')) or
  (not (BitmapInfo.BitmapHeaderSize in [$28,$0c,$f0])) or
  (not (BitmapInfo.BitsPerPixel in [1,4,8,16,24,32])) then Exit;

Width := BitmapInfo.Width;

[fpc-pascal] why is FPImage dog slow reading jpeg's?

2011-05-30 Thread Ben
Hi,

I wrote this console utility app in 5 minutes. All it is supposed to do,
is iterate over *.jpg images (65 at the moment) in a folder (no
recursive searches), and generate a snipped of HTML that I need to paste
into my wives website.

I first thought my utility app is in some recursive loop or something
because the output didn't appear instantly - like I thought it would.

I added some debug output between the generate HTML. To my surprise the
FPImage code reading a 35Kb jpg file takes +- 8 seconds and a 65KB file
takes +- 30 seconds - on a Quad Core machine! WTF???

Is this normal? Is FPImage really that slow reading small roughly
650x450 pixel jpg images?  Or am I doing something unbelievably stupid? :-/

The reason I'm reading in the jpg files is so I can get their Width and
Height values. Avg. jpeg file sizes are between 35-45KB, and largest
file size is 65KB.

Here is the relevant code snippet

var
  imgreader: TFPReaderJPEG;
  stream: TFileStream;
  img:TFPCustomImage;



  writeln('processing file: ', filelist[i]);
  stream := TFileStream.Create(filelist[i], fmOpenRead);
  writeln(1);
  imgreader := TFPReaderJPEG.Create;
  writeln(2, FormatDateTime(' hh:mm:ss.zz', Now) + '  (start reading)');
  img := imgreader.ImageRead(stream, nil);
  writeln(3, FormatDateTime(' hh:mm:ss.zz', Now) + '  (done)');




Here is the program output... Note the timestamps between start reading
and done reading (lines marked with '2' and '3').


---[ start ]---
$ ./project1 img/babies/full
Finished search. Found 65 matches
---
div id=thumbnails
table cellspacing=10
tr align=center valign=middel !--  Row starts  --
td
processing file: img/babies/full/babies.01.jpg
1
2 16:00:30.210  (start reading)
3 16:00:38.338  (done)
img src=img/babies/full/babies.01.jpg alt= id=screen1
class=imglarge onmouseout=reducethumb(1); return false;
onclick=reducethumb(1); return false;
img src=img/babies/thumbs/babies.01.jpg alt= class=imgsmall
id=thumb1 onclick=expandthumb(1, 650, 413);
/td
/tr
tr align=center valign=middel !--  Row starts  --
td
processing file: img/babies/full/babies.02.jpg
1
2 16:00:38.338  (start reading)
3 16:01:10.447  (done)
img src=img/babies/full/babies.02.jpg alt= id=screen2
class=imglarge onmouseout=reducethumb(2); return false;
onclick=reducethumb(2); return false;
img src=img/babies/thumbs/babies.02.jpg alt= class=imgsmall
id=thumb2 onclick=expandthumb(2, 650, 435);
/td
/tr
tr align=center valign=middel !--  Row starts  --
td
processing file: img/babies/full/babies.03.jpg
1
2 16:01:10.447  (start reading)
3 16:01:28.859  (done)
img src=img/babies/full/babies.03.jpg alt= id=screen3
class=imglarge onmouseout=reducethumb(3); return false;
onclick=reducethumb(3); return false;
img src=img/babies/thumbs/babies.03.jpg alt= class=imgsmall
id=thumb3 onclick=expandthumb(3, 405, 650);
/td
/tr
tr align=center valign=middel !--  Row starts  --
td
processing file: img/babies/full/babies.04.jpg
1
2 16:01:28.859  (start reading)

snip
---[ end ]---



-- 

Ben.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal