关于获取图片的大小等属性(100分)

  • 主题发起人 主题发起人 墨剑
  • 开始时间 开始时间

墨剑

Unregistered / Unconfirmed
GUEST, unregistred user!
在xp中,打开一个装了很多jpg图片文件的文件夹,如果选取的察看方式是详细信息,那有一栏就叫“尺寸‘,显示的是每一张图片的宽度和高度。 据我所之,或者在论坛中看到的取图片文件大小的方法都是先读取出这个文件到内存然后才计算。于是我在想,为什么资源管理器得到文件大小会这么快呢? 就好些取得后缀名一样快,所以不可能是通过把每一张图片都读进内存来计算的。 到底是什么方法? 各位有知道的可否拿出来大家学习学习?
 
先读取出这个文件到内存然后才计算,这种方法很慢吗?
 
XP 一样,ACDSEE也一样,第一次读文件的时候都是慢的,无非是以后再读时,已经在缓存中有数据了,所以就快了。
 
将文件夹的文件进行循环
type
TShellItem = record
DisplayName,
Size,
typesName,
ModDate: string;
ImgIndex: integer;
end;

function GetFileinfo(const FileName: string): TShellItem;
var
SearchRec: TSearchRec;
SHFileInfo: TSHFileInfo;
begin
FillChar(SHFileInfo, SizeOf(SHFileInfo), #0);
if FindFirst(ExpandFileName(FileName), faAnyFile, SearchRec) = 0 then
begin
Result.Size := IntToStr((SearchRec.Size + 1023) div 1024) + 'KB';//文件的大小
Result.DisplayName := SearchRec.Name;//文件名称
Result.ImgIndex := SHGetFileInfo(PChar(FileName), 0, SHFileInfo, SizeOf(SHFileInfo), SHGFI_LARGEICON or SHGFI_SYSICONINDEX or SHGFI_TYPENAME or SHGFI_OPENICON);//文件图标号
Result.ImgIndex := SHFileInfo.iIcon;//文件图标号
Result.typesName := SHFileInfo.szTypeName;//文件类型名称
Result.ModDate := DateTimeToStr(CovFileDate(SearchRec.FindData.ftLastWriteTime));//文件修改时间
//这里还可以增加很多信息,看自己的需要
end;
FindClose(SearchRec);
end;
 
对于nanshan的方法,得到文件的一些通用属性是可以的。 但是得不到图片文件的长宽分辨率等信息。 网上的做法一般都是把图片读入内存来计算。
最简单的方法是用Timage控件读取文件(AutoSize=true,Stretch=False),然后根据他的width和height来计算。这是最简单也是最慢的方法。
另一种方法是用Stream读取图片文件入内存,然后根据文件的格式来读取存放尺寸的字节。这种方法应该是目前我所之的最快的一种。 但不知道windows资源管理器是用的什么方法,非常快。
 
function ReadPicinfo(const PicFileName: string): TBitmapInfoHeader;
var
DIB: TDIBSection;
Bitmap: TBitmap;
StrExt: string;
jpg: TJPEGImage;
begin
Bitmap := TBitmap.Create;
StrExt := ExtractFileExt(UpperCase(PicFileName));
if StrExt = '.BMP' then
begin
Bitmap.LoadFromFile(PicFileName);
end;
if (StrExt = '.JPG') or (StrExt = '.JPEG') then
begin
jpg := TJPEGImage.Create;
jpg.LoadFromFile(PicFileName);
Bitmap := TBitmap.Create;
Bitmap.Assign(jpg);
jpg.Free;
end;
GetObject(Bitmap.Handle, SizeOf(DIB), @DIB);
Result := DIB.dsBmih;
Bitmap.Free;
end;
 
Bitmap.LoadFromFile,这句语句应该会慢。
 
我这样做,也就是我说的第2种方式,感觉还是非常快的。
procedure TForm1.GetJPGSize(const sFile: string; var wWidth,
wHeight: word);
const
ValidSig : array[0..1] of byte = ($FF, $D8);
Parameterless = [$01, $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7];
var
Sig: array[0..1] of byte;
f: TFileStream;
x: integer;
Seg: byte;
Dummy: array[0..15] of byte;
Len: word;
ReadLen: LongInt;
begin
FillChar(Sig, SizeOf(Sig), #0);
f := TFileStream.Create(sFile, fmOpenRead);
try
ReadLen := f.Read(Sig[0], SizeOf(Sig));
for x := Low(Sig) to High(Sig) do
if Sig[x] <> ValidSig[x] then ReadLen := 0;

if ReadLen > 0 then
begin
ReadLen := f.Read(Seg, 1);
while (Seg = $FF) and (ReadLen > 0) do
begin
ReadLen := f.Read(Seg, 1);
if Seg <> $FF then
begin
if (Seg = $C0) or (Seg = $C1) then
begin
ReadLen := f.Read(Dummy[0], 3); { don't need these bytes }
wHeight := ReadMWord(f);
wWidth := ReadMWord(f);
end else begin
if not (Seg in Parameterless) then
begin
Len := ReadMWord(f);
f.Seek(Len-2, 1);
f.Read(Seg, 1);
end else
Seg := $FF; { Fake it to keep looping. }
end;
end;
end;
end;
finally
f.Free;
end;
end;


function TForm1.ReadMWord(f: TFileStream): word;
type
TMotorolaWord = record
case byte of
0: (Value: word);
1: (Byte1, Byte2: byte);
end;
var
MW: TMotorolaWord;
begin
f.Read(MW.Byte2, SizeOf(Byte));
f.Read(MW.Byte1, SizeOf(Byte));
Result := MW.Value;
end;
 
给你一个快的,我只知道BMP格式的,我想其他格式也应该有类似的方式。
function GetBitmapInfo(const FileName: string): TBitmapInfoHeader;
var
Fileid: Integer;
FileHead: TBitmapFileHeader;
begin
Fileid := FileOpen(FileName, fmOpenRead or fmShareDenyNone);
FileRead(Fileid, FileHead, SizeOf(FileHead));
FileRead(Fileid, Result, SizeOf(Result));
FileClose(Fileid);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
BmpInfo: TBitmapInfoHeader;
begin
BmpInfo := GetBitmapInfo('C:/1.bmp');
Memo1.Lines.Add('图片信息:' + IntToStr(BmpInfo.biWidth) + '*' + IntToStr(BmpInfo.biHeight) + ' ' + IntToStr(BmpInfo.biBitCount) + '位');
end;
 
后退
顶部