# Native Code > برنامه نویسی در Delphi > مباحث عمومی دلفی و پاسکال > سوال: به دست آوردن طول و عرض فایل gif

## mbshareat

سلام
من از دلفی قدیمی استفده می کنم که از فایل 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;

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

----------


## یوسف زالی

سلام
فایلی که فرستادی JPEG هست نه GIF

----------


## mbshareat

اولش جستجو دادم چیزی پیدا نکردم.
یه جور دیگه جستجو دادم به چنین کدی رسیدم.امیدوارم این دیگه قاطی نکنه.(با توجه به اینکه کد دست نیافتن به اطلاعات رو پیش بینی کرده بهش اطمینان ندارم)
اگر کسی کد دیگه ای سراغ داره که خیلی تست شده لطفا بذاره.کد قبلی رو خیلی امتحان کرده بودم.نمی دونم چرا  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

عجب
از کجا فهمیدید؟
آخه ظاهرا مسئول بخشمون روی تصاویر نظارت داره.یه بار هم یه فایل خیلی بزرگ بین تصاویر کتاب بود.نمی دونم چطور کار می کنه.اگر تصویر رو دیده باشید انگار در تصویر دست هم بردند.
در هر صورت ، کد دوم مقدار رو درست برگردوند!

----------


## mbshareat

می بخشید می تونید بهم کدی بدید که متوجه بشه فایل gif هست یا jpg؟ در سایتی که کد رو برداشتم کد برای 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;

----------


## یوسف زالی

کافیه هدر فایل رو بخونید.
در JPEG کافیه 16 تاش رو بخونید، برای مطمئن شده 20 بایت اول رو بخونید، بگردید دنبال امضای فرمت فایل، مثلا 89a یا jfif یا همچین چیزایی، از روی اینا تشخیص می دید فرمت چیه، از روی فرمت می فهمید کدوم بایت ها رو باید بخونید و باقی ماجرا.

----------


## mbshareat

ممنون.ولی اگر کد رو ببینید می بینید امضا رو هم بررسی کرده.

----------


## mbshareat

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

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

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

----------

