PDA

View Full Version : سوال: به دست آوردن طول و عرض فایل gif



mbshareat
شنبه 11 آبان 1398, 23:49 عصر
سلام
من از دلفی قدیمی استفده می کنم که از فایل gif پشتیبانی نمی کنه.بعد از هزار زحمت دارم از GDI+ برای ترسیم این فایل استفاده می کنم.متاسفانه راهی که بهش رسیدم طول وعرض تصویر رو تعیین نمی کنه.باید یک اندازه برای کانواس داشته باشم که تصویر کامل در اون ترسیم بشه.میتونم اندازه رو خیلی بزرگ بگیرم ولی سرعت پایین میاد.
یه کد پیدا کردم.تا حالا خوب کار می کرد ولی این کد هم در مورد یک فایل ایراد داره.
procedure GetGIFSize(const sGIFFile: string; var wWidth, wHeight: Word);type
TGIFHeader = record
Sig: array[0..5] of char;
ScreenWidth, ScreenHeight: Word;
Flags, Background, Aspect: Byte;
end;


TGIFImageBlock = record
Left, Top, Width, Height: Word;
Flags: Byte;
end;
var
f: file;
Header: TGifHeader;
ImageBlock: TGifImageBlock;
nResult: integer;
x: integer;
c: char;
DimensionsFound: boolean;
begin
wWidth := 0;
wHeight := 0;


if sGifFile = '' then
Exit;


{$I-}
FileMode := 0; { read-only }
AssignFile(f, sGifFile);
reset(f, 1);
if IOResult <> 0 then
{ Could not open file }
Exit;


{ Read header and ensure valid file. }
BlockRead(f, Header, SizeOf(TGifHeader), nResult);
if (nResult <> SizeOf(TGifHeader)) or (IOResult <> 0) or
(StrLComp('GIF', Header.Sig, 3) <> 0) then
begin
{ Image file invalid }
Close(f);
Exit;
end;


{ Skip color map, if there is one }
if (Header.Flags and $80) > 0 then
begin
x := 3 * (1 shl ((Header.Flags and 7) + 1));
Seek(f, x);
if IOResult <> 0 then
begin
{ Color map thrashed }
Close(f);
Exit;
end;
end;


DimensionsFound := False;
FillChar(ImageBlock, SizeOf(TGIFImageBlock), #0);
{ Step through blocks. }
BlockRead(f, c, 1, nResult);
while (not EOF(f)) and (not DimensionsFound) do
begin
case c of
',': { Found image }
begin
BlockRead(f, ImageBlock, SizeOf(TGIFImageBlock), nResult);
if nResult <> SizeOf(TGIFImageBlock) then
begin
{ Invalid image block encountered }
Close(f);
Exit;
end;
wWidth := ImageBlock.Width;
wHeight := ImageBlock.Height;
DimensionsFound := True;
end;
'?': { Skip }
begin
{ NOP }
end;
{ nothing else. just ignore }
end;
BlockRead(f, c, 1, nResult);
end;
Close(f);
{$I+}
end;


procedure TForm1.FormCreate(Sender: TObject);
var
W,H:Word;
begin
GetGIFSize('1.gif',W,H);
ShowMessage(IntToStr(W)+#13+IntToStr(H));
end;

این هم فایل:
150898
طول و عرض رو 44646و45717 بر می گردونه در حالیکه باید 635و954 برگردونه.
کسی کد دیگه ای سراغ نداره که قابل اطمینان باشه؟
در این صفحه هم اطلاعات اومده که ازشون سر در نمیارم(بماند که بلد نیستم یه بایت از فایل بخونم!)
http://www.onicos.com/staff/iz/formats/gif.html

یوسف زالی
یک شنبه 12 آبان 1398, 00:04 صبح
سلام
فایلی که فرستادی JPEG هست نه GIF

mbshareat
یک شنبه 12 آبان 1398, 00:12 صبح
اولش جستجو دادم چیزی پیدا نکردم.
یه جور دیگه جستجو دادم به چنین کدی رسیدم.امیدوارم این دیگه قاطی نکنه.(با توجه به اینکه کد دست نیافتن به اطلاعات رو پیش بینی کرده بهش اطمینان ندارم)
اگر کسی کد دیگه ای سراغ داره که خیلی تست شده لطفا بذاره.کد قبلی رو خیلی امتحان کرده بودم.نمی دونم چرا gif کلا فایل مشکل سازی هست.
Procedure GetGifSize(FileName:String; var width, height: Word); function GetWH(a: array of byte): boolean;
begin
Result := (a[1] = $47) and (a[2] = $49) and (a[3] = $46); //'GIF' Signature
width := a[8] * 256 + a[7];
height := a[10] * 256 + a[9];
end;
var
f: file;
i, x, y: integer;
a: array of byte;
begin
assignfile(f,FileName);
reset(f, 1);
i := filesize(f);
setlength(a, i);
blockread(f, a[1], i);
if GetWH(a)=false then
ShowMessage('Error Get Gif Dimension!');
closefile(f);
end;




procedure TForm1.FormCreate(Sender: TObject);
var
W,H:Word;
Begin
GetGifSize('1.gif',W,H);
ShowMessage('Width '+IntToStr(W)+' Height '+IntToStr(H))
End;

mbshareat
یک شنبه 12 آبان 1398, 00:15 صبح
عجب
از کجا فهمیدید؟
آخه ظاهرا مسئول بخشمون روی تصاویر نظارت داره.یه بار هم یه فایل خیلی بزرگ بین تصاویر کتاب بود.نمی دونم چطور کار می کنه.اگر تصویر رو دیده باشید انگار در تصویر دست هم بردند.
در هر صورت ، کد دوم مقدار رو درست برگردوند!

mbshareat
یک شنبه 12 آبان 1398, 00:18 صبح
می بخشید می تونید بهم کدی بدید که متوجه بشه فایل gif هست یا jpg؟ در سایتی (http://delphi.cjcsoft.net/viewthread.php?tid=44836)که کد رو برداشتم کد برای gif و jpeg جدا بود.چطور از کد gif تونستم برای به دست اوردن ابعاد استفاده کنم؟

علاوه بر اینکه کد بالا فکر کنم خیلی کند باشه.کد رو که می بینم هیچ ضرورتی برای خوندن همه اطلاعات فایل نمی بینم.به نظرم فقط باید ده بایت خونده بشه نه اینکه اندازه فایل رو به دست بیاریم و همه اش رو لود کنیم.
و ساده بودن کد که اطلاعات طول و عرض در بایت خاصی باشه برام مشکوکه.کسی در این زمینه اطلاعاتی داره؟

کد رو اینطور تغییر دادم باز جواب داد.ممکنه ببینید اشکالی نداشته باشه؟
Procedure GetGifSize(const sGIFFile: string; var width, height: Word);
function GetWH(a: array of byte): boolean;
begin
Result := (a[1] = $47) and (a[2] = $49) and (a[3] = $46); //'GIF' Signature
width := a[8] * 256 + a[7];
height := a[10] * 256 + a[9];
end;
var
f: file;
a: array of byte;
begin
assignfile(f,sGIFFile);
reset(f, 1);
setlength(a, 10);
blockread(f, a[1], 10);
if GetWH(a)=false then
ShowMessage('Bad Gif File!');
closefile(f);
end;

یوسف زالی
یک شنبه 12 آبان 1398, 10:41 صبح
کافیه هدر فایل رو بخونید.
در JPEG کافیه 16 تاش رو بخونید، برای مطمئن شده 20 بایت اول رو بخونید، بگردید دنبال امضای فرمت فایل، مثلا 89a یا jfif یا همچین چیزایی، از روی اینا تشخیص می دید فرمت چیه، از روی فرمت می فهمید کدوم بایت ها رو باید بخونید و باقی ماجرا.

mbshareat
دوشنبه 20 آبان 1398, 23:29 عصر
ممنون.ولی اگر کد رو ببینید می بینید امضا رو هم بررسی کرده.

mbshareat
پنج شنبه 28 آذر 1398, 21:09 عصر
می بخشید این {$I-} چیه؟
من متن با فرمت t میخونم و تصویر مربوطه با فرمت Gif رو هم میخونم.یه بار دیدم نتونست فایل Gif رو بخونه فایل متن رو حذف کرد.
جدیدا هم یه کد رو تغییر دادم اومد به Close(f) گیر داد که too many actual parameters .در حالی که همون تغییر رو در یه برنامه مشابه داده بودم که از همون کد اول صفحه هم استفاده می کرد و مشکل نداشت.
یه بار هم اومدم از پروسیجر اول صفحه از یه پنجره دیگه استفاده کنم، باز گیر داد.همون پروسیجر رو اوردم در پنجره ای که میخواستم GetGIFSize رو ازش فراخوانی کنم کپی کردم دیگه گیر نداد.
میترسم حذف غیر مترقبه گاهگاه بعضی از فایلهای متن هم تقصیر همین دستور کامپایلر باشه.

جالبه بدونید از GetGIFSize دوم که استفاده کردم برنامه موفق نشد.اون طور که فهمیدم شبکه اجازه دریافت ده بایت از فایل رو نمیداد.نمی دونم اگر همه بایتها رو به روش دوم بخونم کار می کنه.

یه بار میخواستم ببینم تصویر با شماره منفی در پوشه تصاویر هست یا نه از FileListBox یه پنجره دیگه استفاده کردم اومد اولین فایل متن رو از بین برد.دارم فکر می کنم نکنه Close دقیق نیست و نباید از کامپوننت FileListBox در پنجره دیگه استفاده کرد.