无法使用wkhtmltoimage(Pascal)的c-bindings保存png

时间:2017-07-14 16:05:08

标签: html binding pascal wkhtmltopdf wkhtmltoimage

我需要在我的实际pascal项目中将网站转换为透明图像。因此,我将wkhtmltoimage的c-bindings翻译成pascal(FPC / Lazarus IDE)。这是翻译:

// Copyright 2017 Thorsten Zahn
//   translation of wkhtmltox-0.12.4/include/wkhtmltox/image.h - 
//   Copyright 2010, 2011 wkhtmltopdf authors
//
// pas_libwkhtmltoimage is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// pas_libwkhtmltoimage is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

unit pas_libwkhtmltoimage;
interface

uses
  {$IFDEF UNIX}dynlibs,{$ENDIF}
  SysUtils, Dialogs;

procedure init_wkhtmltoimage();
procedure init_wkhtmltoimage(install_file: string);

type
  PInteger = ^Integer;

  wkhtmltoimage_global_settings = record end;
  Pwkhtmltoimage_global_settings = ^wkhtmltoimage_global_settings;

  wkhtmltoimage_converter = record end;
  Pwkhtmltoimage_converter = ^wkhtmltoimage_converter;

  wkhtmltoimage_str_callback  = procedure (converter:Pwkhtmltoimage_converter; const str:PChar  ) cdecl;
  wkhtmltoimage_int_callback  = procedure (converter:Pwkhtmltoimage_converter; const val:Integer) cdecl;
  wkhtmltoimage_void_callback = procedure (converter:Pwkhtmltoimage_converter                   ) cdecl;

var
  wkhtmltoimage_init                         : function (use_graphics: Integer)                                                           : Integer                       ; cdecl;
  wkhtmltoimage_deinit                       : function ()                                                                                : Integer                       ; cdecl;
  wkhtmltoimage_extended_qt                  : function ()                                                                                : Integer                       ; cdecl;
  wkhtmltoimage_version                      : function ()                                                                                : PChar                         ; cdecl;
  wkhtmltoimage_create_global_settings       : function ()                                                                                : Pwkhtmltoimage_global_settings; cdecl;
  wkhtmltoimage_set_global_setting           : function (settings: Pwkhtmltoimage_global_settings; name: PChar; value: PChar)             : Integer                       ; cdecl;
  wkhtmltoimage_get_global_setting           : function (settings: Pwkhtmltoimage_global_settings; name: PChar; value: PChar; vs: Integer): Integer                       ; cdecl;
  wkhtmltoimage_create_converter             : function (settings: Pwkhtmltoimage_global_settings; data: PChar)                           : Pwkhtmltoimage_converter      ; cdecl;
  wkhtmltoimage_destroy_converter            : procedure(converter: Pwkhtmltoimage_converter)                                                                             ; cdecl;
  wkhtmltoimage_set_warning_callback         : procedure(converter: Pwkhtmltoimage_converter; cb: wkhtmltoimage_str_callback)                                             ; cdecl;
  wkhtmltoimage_set_error_callback           : procedure(converter: Pwkhtmltoimage_converter; cb: wkhtmltoimage_str_callback)                                             ; cdecl;
  wkhtmltoimage_set_phase_changed_callback   : procedure(converter: Pwkhtmltoimage_converter; cb: wkhtmltoimage_void_callback)                                            ; cdecl;
  wkhtmltoimage_set_progress_changed_callback: procedure(converter: Pwkhtmltoimage_converter; cb: wkhtmltoimage_int_callback)                                             ; cdecl;
  wkhtmltoimage_set_finished_callback        : procedure(converter: Pwkhtmltoimage_converter; cb: wkhtmltoimage_int_callback)                                             ; cdecl;
  wkhtmltoimage_convert                      : function (converter: Pwkhtmltoimage_converter)                                             : Integer                       ; cdecl;
  wkhtmltoimage_current_phase                : function (converter: Pwkhtmltoimage_converter)                                             : Integer                       ; cdecl;
  wkhtmltoimage_phase_count                  : function (converter: Pwkhtmltoimage_converter)                                             : Integer                       ; cdecl;
  wkhtmltoimage_phase_description            : function (converter: Pwkhtmltoimage_converter; phase: Integer)                             : PChar                         ; cdecl;
  wkhtmltoimage_progress_string              : function (converter: Pwkhtmltoimage_converter)                                             : PChar                         ; cdecl;
  wkhtmltoimage_http_error_code              : function (converter: Pwkhtmltoimage_converter)                                             : Integer                       ; cdecl;
  wkhtmltoimage_get_output                   : function (converter: Pwkhtmltoimage_converter; _para2: PPbyte)                             : Integer                       ; cdecl;


implementation

var
  lib_handle : THandle;


procedure handle_error(error: string);
begin
  ShowMessage(error);
end;


function lib_get_proc_addr(var addr: Pointer; const name : PAnsiChar) : Boolean;
begin
  {$IFDEF UNIX}
  addr := GetProcedureAddress(lib_handle, name);
  {$ENDIF}
  {$IFDEF MSWINDOWS}
  addr := GetProcAddress(libvlc_handle, name);
  {$ENDIF}
  result := (addr <> NIL);
  if not result then
  begin
    handle_error('Procedure "' + name + '" not found!');
  end;
end;


procedure init_wkhtmltoimage();
begin
  if (lib_handle <> 0) then exit;

  init_wkhtmltoimage('<path to lib>/libwkhtmltox.so.0.12.4');
end;

procedure init_wkhtmltoimage(install_file: string);
begin
  if (lib_handle <> 0) then exit;

  //load lib
  {$IFDEF SUPPORTS_UNICODE}
  lib_handle := LoadLibrary(PWideChar(install_file));
  {$ELSE}
  lib_handle := LoadLibrary(PAnsiChar(install_file));
  {$ENDIF}

  //error?
  if (lib_handle = 0) then
    begin
      handle_error(
        'Library not found ' + install_file + ', ' +
        {$IFDEF UNIX}
        'GetLastError() = ' + IntToStr(GetLastOSError())
        {$ENDIF}
        {$IFDEF MSWINDOWS}
        'GetLastError() = ' + IntToStr(GetLastError())
        {$ENDIF}
      );
      exit;
    end;

  //get_proc_addr
  if not lib_get_proc_addr(pointer(wkhtmltoimage_init                         ), 'wkhtmltoimage_init'                         ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_deinit                       ), 'wkhtmltoimage_deinit'                       ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_extended_qt                  ), 'wkhtmltoimage_extended_qt'                  ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_version                      ), 'wkhtmltoimage_version'                      ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_create_global_settings       ), 'wkhtmltoimage_create_global_settings'       ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_set_global_setting           ), 'wkhtmltoimage_set_global_setting'           ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_get_global_setting           ), 'wkhtmltoimage_get_global_setting'           ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_create_converter             ), 'wkhtmltoimage_create_converter'             ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_destroy_converter            ), 'wkhtmltoimage_destroy_converter'            ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_set_warning_callback         ), 'wkhtmltoimage_set_warning_callback'         ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_set_error_callback           ), 'wkhtmltoimage_set_error_callback'           ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_set_phase_changed_callback   ), 'wkhtmltoimage_set_phase_changed_callback'   ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_set_progress_changed_callback), 'wkhtmltoimage_set_progress_changed_callback') then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_set_finished_callback        ), 'wkhtmltoimage_set_finished_callback'        ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_convert                      ), 'wkhtmltoimage_convert'                      ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_current_phase                ), 'wkhtmltoimage_current_phase'                ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_phase_count                  ), 'wkhtmltoimage_phase_count'                  ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_phase_description            ), 'wkhtmltoimage_phase_description'            ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_progress_string              ), 'wkhtmltoimage_progress_string'              ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_http_error_code              ), 'wkhtmltoimage_http_error_code'              ) then exit;
  if not lib_get_proc_addr(pointer(wkhtmltoimage_get_output                   ), 'wkhtmltoimage_get_output'                   ) then exit;
end;

end.

我使用的是libwkhtmltox.so.0.12.4。首先,我尝试使用以下代码创建bmp-image:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, testlib;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Image1: TImage;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

//(callback procedures removed in this example)

procedure TForm1.Button1Click(Sender: TObject);
var
  gs: Pwkhtmltoimage_global_settings;
  c:  Pwkhtmltoimage_converter;
  data: PByte;
  len: Integer;

  stream: TMemoryStream;
  i: Integer;
begin
  init_wkhtmltoimage();

  wkhtmltoimage_init(Integer(false));

  gs := wkhtmltoimage_create_global_settings();
  wkhtmltoimage_set_global_setting(gs, 'in' , 'http://www.google.com/');
  //wkhtmltoimage_set_global_setting(gs, 'fmt', 'jpeg');
  wkhtmltoimage_set_global_setting(gs, 'fmt', 'bmp');
  //wkhtmltoimage_set_global_setting(gs, 'fmt', 'svg');

  c := wkhtmltoimage_create_converter(gs, nil);

  //(callback procedures removed in this example)
  //wkhtmltoimage_set_progress_changed_callback(c, @progress_changed);
  //wkhtmltoimage_set_phase_changed_callback   (c, @phase_changed);
  //wkhtmltoimage_set_error_callback           (c, @error);
  //wkhtmltoimage_set_warning_callback         (c, @warning);

  if not Boolean(wkhtmltoimage_convert(c)) then
    begin
      ShowMessage('Conversion failed!');
      exit;
    end;

  len := wkhtmltoimage_get_output(c, @data);

  stream := TMemoryStream.Create();
  for i:=0 to len-1 do
      stream.Write((data+i)^, 1);

  stream.Position:=0;
  Image1.Picture.LoadFromStream(stream);
  stream.SaveToFile('/home/thorsten/Test.png');

  stream.Free;

  wkhtmltoimage_destroy_converter(c);
  wkhtmltoimage_deinit();
end;

end.

这很好用。格式jpeg和svg也正常工作(对于使用svg,必须引用Image1中的显示)。使用svg,透明背景选项也有效(wkhtmltoimage_set_global_setting(gs, 'transparent', 'true');)。但是,如果我尝试png(wkhtmltoimage_set_global_setting(gs, 'fmt', 'png');),我会收到错误Could not save image(通过回调)。

可能是什么问题?这个问题也存在于c代码中吗?

由于

我也测试了控制台工具(从Ubuntu存储库安装,版本0.12.2.4-1)。这个工具有效。但如果我使用这个工具,我必须保存临时文件。

1 个答案:

答案 0 :(得分:0)

它接缝是版本0.12.4的问题。使用(旧)版本0.12.3,它工作正常。无法加载新版本的0.13.0库(debian-和ubuntu-version)。