Jump to content

Shrinavat

Members
  • Content Count

    73
  • Joined

  • Last visited

  • Days Won

    4

Posts posted by Shrinavat


  1. Hello,

    I know there are advanced Clever Internet Suite users here who might be able to help me with advice.

    To send an image to a Telegram channel, I use the following code:

    const
      urlTGSendPhoto   = 'https://api.telegram.org/bot%s/sendPhoto';
      BOT_API_KEY      = 'xxxxxxxxxxxxxx';
      CHANNEL_NAME     = 'xxxxxxxxxxxxxx';  
    ...
    clHttpRequest.AddFormField('chat_id', CHANNEL_NAME);
    clHttpRequest.AddSubmitFile('photo', 'chart.png');
    var s := clHttpTG.Post(Format(urlTGSendPhoto, [BOT_API_KEY]), clHttpRequest);

    where 'chart.png' is the name of the image file on disk. It works great.

    Can someone please tell me how to use a stream (TMemoryStream/TFileStream) or TPngImage/TJPEGImage/TBitmap instead of a file (that is, without the need to save the file to disk)?


  2. There is current code, in which I think the use of dictionaries is redundant:

    const
      N = $1;
      S = $2;
      E = $4;
      W = $8;
      
    var
      DX, DY, OPPOSITE: TDictionary<Integer, Integer>;
    
    // init dictionares
      DX := TDictionary<Integer, Integer>.Create;
      DX.Add(E, 1);
      DX.Add(W, -1);
      DX.Add(N, 0);
      DX.Add(S, 0);
      DY := TDictionary<Integer, Integer>.Create;
      DY.Add(E, 0);
      DY.Add(W, 0);
      DY.Add(N, -1);
      DY.Add(S, 1);
      OPPOSITE := TDictionary<Integer, Integer>.Create;
      OPPOSITE.Add(E, W);
      OPPOSITE.Add(W, E);
      OPPOSITE.Add(N, S);
      OPPOSITE.Add(S, N);
    
    // Usage of these dictionaries is shown below in the example code:
      var nx := x + DX[dir];  
      var ny := y + DY[dir];
      grid[ny, nx] := grid[ny, nx] or OPPOSITE[dir];

    To improve performance, I would like to avoid using dictionaries and use a simpler code instead... but I don't know which one?

    Any help in this arena would be greatly appreciated.


  3. I have a pipeline for downloading files to a specific database.

    FFileDownloader := Parallel.Pipeline
      .Stage(Asy_URLBuilder)
      .Stage(Asy_URLRetriever)
      .Stage(Asy_DBInserter, Parallel.TaskConfig.OnMessage(Self))
      .Run;
    
    procedure Asy_URLBuilder(const input, output: IOmniBlockingCollection);
    var
      ovIN, ovOUT: TOmniValue;
    begin
      for ovIN in input do begin
        // ... compose url for downloading
    	output.TryAdd(ovOUT); // url is in ovOUT
      end;
    end;
    
    procedure Asy_URLRetriever(const input, output: IOmniBlockingCollection);
    var
      ovIN, ovOUT: TOmniValue;
    begin
      for ovIN in input do begin
        // ... downloading
    	output.TryAdd(ovOUT); // downloaded file is in ovOUT
      end;
    end;
    
    procedure Asy_DBInserter(const input, output: IOmniBlockingCollection; const task: IOmniTask);
    var
      ovIN: TOmniValue;
      DB: TxxxDatabase;
    begin
      DB := TxxxDatabase.Create(nil);
      DB.DatabaseName := ??? ;
      DB.Open;
      
      for ovIN in input do begin
    	// ... insert downloaded file in specific database
      end;
    
      DB.Commit;
      task.Comm.Send(WM_TASK_COMPLETED);
    end;

    I run a pipeline for various databases. I need to pass DatabaseName to the third stage of the pipeline. How can I do that?

    Can I use the SetParameter method of Task controller when creating a pipeline? And if so, how?

    Any help will be appreciated!


  4. I hope this is the right place to ask this... Is there a Delphi wrapper for libpng?

    I would very much like to use it, but I couldn't find it anywhere. Please share if you know anything. If someone got working wrapper for libpng and wants to share it at here would be cool.

    Thanks!


  5. On 1/31/2019 at 1:58 PM, Primož Gabrijelčič said:

    `workItem.Result` is a record property. Because of that, this code:

    
     workItem.Result.AsOwnedObject := TBitmap32.Create(256,256);

    is equivalent to running:

    
    var tmp: TOmniValue;
    
    tmp := workItem.Result;
    tmp.AsOwnedObject := TBitmap32.Create(256,256);

    And that fails. You should change the code to:

    
    var tmp: TOmniValue;
    
    tmp.AsOwnedObject := TBitmap32.Create(256,256);
    workItem.Result := tmp;

    I'll see if I can change the implementation of `IOmniWorkitem` to prevent such problems. 

    @Primož Gabrijelčič Do you have any progress for this issue fix? There are no new commits on github. Current workaround with using extra variable is not very elegant, although it works. 


  6. Here is the simplest code:



    unit Unit1;

    interface

    uses
      System.SysUtils,
      System.Classes,
      Vcl.Graphics,
      Vcl.Imaging.jpeg,
      Vcl.Controls,
      Vcl.Forms,
      Vcl.StdCtrls,
      OtlParallel,
      OtlTask;

    type
      TForm1 = class(TForm)
        btnReadInOTL: TButton;
        btnReadInGUI: TButton;
        procedure btnReadInGUIClick(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure btnReadInOTLClick(Sender: TObject);
      private
        FMS: TMemoryStream;
        FTestWorker: IOmniBackgroundWorker;
        procedure Asy_Test(const workItem: IOmniWorkItem);
        procedure HandleRequestDone(const Sender: IOmniBackgroundWorker; const
            workItem: IOmniWorkItem);
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      FMS := TMemoryStream.Create;
      FMS.LoadFromFile('test.jpg');

      FTestWorker := Parallel.BackgroundWorker
        .Execute(Asy_Test)
        .OnRequestDone(HandleRequestDone);
    end;

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      FMS.Free;
      FTestWorker.CancelAll;
      FTestWorker.Terminate(INFINITE);
      FTestWorker := nil;
    end;


    procedure TForm1.Asy_Test(const workItem: IOmniWorkItem);
    var
      wic: TWICImage;
      jpg: TJPEGImage;
      bs: TBytesStream;
    begin
      bs := TBytesStream.Create;
      try
        bs.Write(FMS.Memory^, FMS.Size);
        bs.Position := 0;
        wic := TWICImage.Create;
    //    jpg := TJPEGImage.Create;
        try
          wic.LoadFromStream(bs);
    //      jpg.LoadFromStream(bs);
    //      jpg.SaveToFile('TJPEGImage.jpg');
        finally
          FreeAndNil(wic);
    //      FreeAndNil(jpg);
        end;
      finally
        FreeAndNil(bs);
      end;
    end;

    procedure TForm1.HandleRequestDone(const Sender: IOmniBackgroundWorker; const
        workItem: IOmniWorkItem);
    begin
      if workItem.IsExceptional then
        Application.MessageBox(PChar(workItem.FatalException.Message), '')
    end;

    procedure TForm1.btnReadInGUIClick(Sender: TObject);
    var
      wic: TWICImage;
      bs: TBytesStream;
    begin
      bs := TBytesStream.Create;
      try
        bs.Write(FMS.Memory^, FMS.Size);
        bs.Position := 0;
        wic := TWICImage.Create;
        try
          wic.LoadFromStream(bs);
          Application.MessageBox('All is OK', '');
        finally
          FreeAndNil(wic);
        end;
      finally
        FreeAndNil(bs);
      end;
    end;

    procedure TForm1.btnReadInOTLClick(Sender: TObject);
    begin
      FTestWorker.Schedule(FTestWorker.CreateWorkItem(0));
    end;

    end.

    When I click on the button "Read Image in GUI Thread", then everything is fine. TWICImage loads the image from the stream.

    However, the same code does not work in the thread (click on the button "Read Image in OTL Thread"), I get AV "Access violation at address 0050316F in module 'Project1.exe'. Read of address 00000000".

    If you use TJPEGImage instead of TWICImage, then everything works fine in both cases.

    I don't get what the problem is. Can someone explain to me in simple terms what should I do in order for TWICImage to work in the thread? I want to use TWICImage because it allows you to download a wide variety of image formats, not just jpeg.

     

    Delphi 10.2.3, Win7SP1 x64. Project full source is in attachment

     

    test_OTL_read_from_memory.zip

×