Cara mendapatkan semua format file yang terdaftar dari VCL.Graphics tetapi 64bit

Dalam aplikasi 32bit saya menggunakan unit FindRegisteredPictureFileFormats yang disediakan oleh Cosmin Prund => (Bagaimana cara mendapatkan semua format file yang didukung dari unit Grafik?).

Saya memerlukan hal yang sama tetapi untuk 64bit. David Heffernan menjawab itu sudah versi 64bit. Bisakah kode ini dipublikasikan?

Terima kasih banyak !!


person Frédéric SCHENCKEL    schedule 04.03.2016    source sumber
comment
Solusi Remy (jawaban yang diterima untuk pertanyaan tertaut) akan berfungsi dengan baik dalam kode 64-bit. Apakah ada alasan Anda memilih jawaban yang lebih hacky yang diposting Cosmin daripada jawaban Remy?   -  person Ken White    schedule 04.03.2016
comment
Karena saya memiliki grafik dalam aliran, saya memerlukan kelas grafis untuk memuatnya dengan benar. Saya tidak dapat menggunakan trik dengan memuat file dan melihat kelas grafis mana yang digunakan... Saya tahu FindRegisteredPictureFileFormats adalah peretasan tetapi berfungsi dengan baik dalam 32bit. Tetapi jika saya bisa mendapatkan hasilnya melalui cara lain, tentu saja saya dapat mengadaptasi kode saya!   -  person Frédéric SCHENCKEL    schedule 05.03.2016
comment
Anda dapat memodifikasi kode Remy untuk memuat dari aliran alih-alih dari file dan menggunakan metode yang sama, tanpa menggunakan kode perakitan yang bukan lintas platform (dan itu mencakup Windows 32/64 bit).   -  person Ken White    schedule 05.03.2016
comment
Dari mana Anda mendapatkan alirannya? Basis Data, Sumber Daya, ...?   -  person Sir Rufo    schedule 05.03.2016
comment
Tahukah Anda format apa yang didukung? Atau apakah Anda menulis kode yang dicolokkan ke aplikasi host?   -  person David Heffernan    schedule 05.03.2016
comment
Wah, banyak sekali komentar yang berisik di sini. Jawaban Remy tampaknya mengatasi masalah XY yang dinyatakan dalam komentar yang dihapus.   -  person Free Consulting    schedule 05.03.2016
comment
Ya, aplikasi ini disusun oleh plugin sehingga format gambar yang tersedia dapat bervariasi dari aplikasi yang menulis streaming dan aplikasi yang menggunakannya. Saya harus memilih yang tersedia dari platform baca dan tidak perlu yang dari platform tulis. Tentu saja saya dapat mengubah perilaku ini tetapi ini berarti saya akan kehilangan sedikit fleksibilitas dan platform Win32 berperilaku berbeda dari Win64.   -  person Frédéric SCHENCKEL    schedule 05.03.2016
comment
@Ken, Sejauh yang saya tahu itu LoadFromFile yang memeriksa kelas yang tepat, LoadFromStream membutuhkan kelas yang tepat secara langsung atau apakah saya salah? Tentu saja kompatibilitas lintas platform juga akan baik-baik saja!!!   -  person Frédéric SCHENCKEL    schedule 05.03.2016
comment
Memodifikasi unit Graphics.pas juga bukan solusi yang paling menarik karena saya menggunakan paket, akan agak sulit membuat semua paket mengandalkan Graphics.pas yang saya modifikasi.   -  person Frédéric SCHENCKEL    schedule 05.03.2016


Jawaban (1)


Saya yakin unit ini melakukan apa yang Anda cari. Saya sudah mengujinya pada Windows 32 bit dan 64 bit, dengan paket runtime dan tanpa. Saya belum mengujinya dengan alokasi memori top-down, tapi saya tidak yakin ada bug pemotongan pointer.

unit FindRegisteredPictureFileFormats;

{$POINTERMATH ON}

interface

uses Classes, Contnrs;

// Extracts the file extension + the description; Returns True if the hack was successful,
// False if unsuccesful.
function GetListOfRegisteredPictureFileFormats(List: TStrings): Boolean;

// This returns the list of TGraphicClass registered; True for successful hack, false
// for unsuccesful hach
function GetListOfRegisteredPictureTypes(List: TClassList): Boolean;

implementation

uses Graphics;

type
  TRelativeCallOpcode = packed record
    OpCode: Byte;
    Offset: Integer;
  end;

  PRelativeCallOpcode = ^TRelativeCallOpcode;

  TLongAbsoluteJumpOpcode = packed record
    OpCode: array [0 .. 1] of Byte;
    Destination: Cardinal;
  end;

  PLongAbsoluteJumpOpcode = ^TLongAbsoluteJumpOpcode;

  TReturnTList = function: TList;

  // Structure copied from Graphics unit.
  PFileFormat = ^TFileFormat;

  TFileFormat = record
    GraphicClass: TGraphicClass;
    Extension: string;
    Description: string;
    DescResID: Integer;
  end;

function FindFirstRelativeCallOpcode(StartOffset: NativeUInt): NativeUInt;
var
  Ram: ^Byte;
  i: Integer;
  PLongJump: PLongAbsoluteJumpOpcode;
begin
  Ram := nil;

  PLongJump := PLongAbsoluteJumpOpcode(@Ram[StartOffset]);
  if (PLongJump^.OpCode[0] = $FF) and (PLongJump^.OpCode[1] = $25) then
{$IF Defined(WIN32)}
    Result := FindFirstRelativeCallOpcode(PNativeUInt(PLongJump^.Destination)^)
{$ELSEIF Defined(Win64)}
    Result := FindFirstRelativeCallOpcode(PNativeUInt(PLongJump^.Destination + StartOffset + SizeOf(PLongJump^))^)
{$ELSE}
    {$MESSAGE Fatal 'Architecture not supported'}
{$ENDIF}
  else
  begin
    for i := 0 to 64 do
      if PRelativeCallOpcode(@Ram[StartOffset + i])^.OpCode = $E8 then
        Exit(StartOffset + i + PRelativeCallOpcode(@Ram[StartOffset + i])
          ^.Offset + 5);
    Result := 0;
  end;
end;

procedure FindGetFileFormatsFunc(out ProcAddr: TReturnTList);
var
  Offset_from_RegisterFileFormat: NativeUInt;
  Offset_from_RegisterFileFormatRes: NativeUInt;
begin
  Offset_from_RegisterFileFormat := FindFirstRelativeCallOpcode(NativeUInt(@TPicture.RegisterFileFormat));
  Offset_from_RegisterFileFormatRes := FindFirstRelativeCallOpcode(NativeUInt(@TPicture.RegisterFileFormatRes));

  if (Offset_from_RegisterFileFormat = Offset_from_RegisterFileFormatRes) then
    ProcAddr := TReturnTList(Pointer(Offset_from_RegisterFileFormat))
  else
    ProcAddr := nil;
end;

function GetListOfRegisteredPictureFileFormats(List: TStrings): Boolean;
var
  GetListProc: TReturnTList;
  L: TList;
  i: Integer;
begin
  FindGetFileFormatsFunc(GetListProc);
  if Assigned(GetListProc) then
  begin
    Result := True;
    L := GetListProc;
    for i := 0 to L.Count - 1 do
      List.Add(PFileFormat(L[i])^.Extension + '=' + PFileFormat(L[i])
        ^.Description);
  end
  else
    Result := False;
end;

function GetListOfRegisteredPictureTypes(List: TClassList): Boolean;
var
  GetListProc: TReturnTList;
  L: TList;
  i: Integer;
begin
  FindGetFileFormatsFunc(GetListProc);
  if Assigned(GetListProc) then
  begin
    Result := True;
    L := GetListProc;
    for i := 0 to L.Count - 1 do
      List.Add(PFileFormat(L[i])^.GraphicClass);
  end
  else
    Result := False;
end;

end.
person David Heffernan    schedule 05.03.2016
comment
Terima kasih banyak ini berhasil!! Catatan: Pemeriksaan overflow dan debug Dcu perlu dinonaktifkan. Dengan debug Dcus yang diaktifkan, pengujian Offset_from_RegisterFileFormat = Offset_from_RegisterFileFormatRes menjadi salah. - person Frédéric SCHENCKEL; 07.03.2016