Recent

Author Topic: [SOLVED] How do deal with "Warning: Symbol "ScanLine" is not portable"  (Read 654 times)

TTL

  • Newbie
  • Posts: 3
Hello,
I found a way to improve the performance of my code using scanline, but now I get a warning about missing portability. Are there any information available under which circumstances my code might fail? And is there a way to use my slower code as fallbacks for such platforms like using some {$IfDef <platform>}

Snippet from the slow code (Xorg uses 90% CPU, and my application 20% while executing):
Code: Pascal  [Select][+][-]
  1.       sourcedata := obj.FirstChild.FirstChild.NodeValue;
  2.       InputStream := TStringStream.Create(sourcedata);
  3.       Decoder := TBase64DecodingStream.Create(InputStream);
  4.       readerPicture := TPortableNetworkGraphic.Create;
  5.       readerPicture.LoadFromStream(Decoder);
  6.       inputmaxX := readerPicture.Width;
  7.       inputmaxY := readerPicture.Height;
  8.       wptr := 0;
  9.       for y := 0 to (py-1) do begin
  10.         for x := 0 to (px-1) do begin
  11.           if (x < sx) and (y < sy) and (x < inputmaxX) and (y < inputmaxY) then begin
  12.             tempdata[wptr] := readerPicture.Canvas.pixels[x, y]; //more than 10x slower
  13.           end else begin //source image is smaller than target image -> fill with zeros
  14.             tempdata[wptr] := 0;
  15.           end;
  16.           inc(wptr);
  17.           if (wptr >= maxmem) then begin
  18.             showmessage('Error, Image' +getnodeident(obj)+ ' too big');
  19.             break;
  20.           end;
  21.         end;
  22.         if (wptr >= maxmem) then begin
  23.           break;
  24.         end;
  25.       end;
  26.  

And ~28x faster (when running multiple instances at the same time):
Code: Pascal  [Select][+][-]
  1.       sourcedata := obj.FirstChild.FirstChild.NodeValue;
  2.       InputStream := TStringStream.Create(sourcedata);
  3.       Decoder := TBase64DecodingStream.Create(InputStream);
  4.       readerPicture := TPortableNetworkGraphic.Create;
  5.       readerPicture.LoadFromStream(Decoder);
  6.       inputmaxX := readerPicture.Width;
  7.       inputmaxY := readerPicture.Height;
  8.       wptr := 0;
  9.       for y := 0 to (py-1) do begin
  10.         if (y < inputmaxY) then begin
  11.           ScanData := readerPicture.ScanLine[y];
  12.         end;
  13.         for x := 0 to (px-1) do begin
  14.           if (x < sx) and (y < sy) and (x < inputmaxX) and (y < inputmaxY) then begin
  15.             if (scanData <> nil) then begin
  16.               r := ScanData^.rgbRed;
  17.               g := ScanData^.rgbGreen;
  18.               b := ScanData^.rgbBlue;
  19.               inc(ScanData);
  20.               tempdata[wptr] := (b shl 16) or (g shl 8) or r;
  21.             end else begin //fallback
  22.               tempdata[wptr] := readerPicture.Canvas.pixels[x, y]; //more than 10x slower
  23.             end;
  24.           end else begin //source image is smaller than target image -> fill with zeros
  25.             tempdata[wptr] := 0;
  26.           end;
  27.           inc(wptr);
  28.           if (wptr >= maxmem) then begin
  29.             showmessage('Error, Image' +getnodeident(obj)+ ' too big');
  30.             break;
  31.           end;
  32.         end;
  33.         if (wptr >= maxmem) then begin
  34.           break;
  35.         end;
  36.       end;
  37.  
« Last Edit: February 16, 2020, 11:23:35 am by TTL »

jamie

  • Hero Member
  • *****
  • Posts: 3532
Re: How do deal with "Warning: Symbol "ScanLine" is not portable"
« Reply #1 on: February 13, 2020, 11:31:37 pm »
The Tbitmap has a RasterImge .. RawImage..

The RawImage is direct access to the memory

Using GetLinePoitner or something like that is the same as Scanline.
https://wiki.freepascal.org/Developing_with_Graphics
The only true wisdom is knowing you know nothing

TTL

  • Newbie
  • Posts: 3
Re: How do deal with "Warning: Symbol "ScanLine" is not portable"
« Reply #2 on: February 15, 2020, 11:26:21 pm »
Thanks for pointing me to the differences between native and non native image classes.
As I dont want to show the result on a screen anyway (at least not on the image processing computer), I think I should only use the non native classes. By more or less try and error (I found an example how to connect a TLazReaderXPM in the source of intfgraphics.pas), I managed to get pixel Data, but the colors dont fit. It seems like lRawImage.Description. changes the format - at least I can change the image to black/white there. So which format should I use? Which format does TLazReaderPNG deliver?

Code: Pascal  [Select][+][-]
  1.  
  2.     pngConverter: TLazReaderPNG;
  3.     t: TLazIntfImage;
  4.     lRawImage: TRawImage;  
  5.  
  6. ...
  7.  
  8.       sourcedata := obj.FirstChild.FirstChild.NodeValue;
  9.       InputStream := TStringStream.Create(sourcedata);
  10.       Decoder := TBase64DecodingStream.Create(InputStream);
  11.       pngConverter := TLazReaderPNG.Create;
  12.       t := TLazIntfImage.Create(0,0);
  13.       lRawImage.Init;
  14.       lRawImage.Description.Init_BPP24_B8G8R8_BIO_TTB(0, 0);
  15.       lRawImage.CreateData(True);
  16.       t.SetRawImage(lRawImage);
  17.       t.LoadFromStream(Decoder, pngConverter);
  18.       inputmaxX := t.Width;
  19.       inputmaxY := t.height;
  20.  
  21. ....
  22.  
  23.             r := t.Colors[x, y].red;
  24.             g := t.Colors[x, y].green;
  25.             b := t.Colors[x, y].blue;
  26.             temppixel := (b shl 16) or (g shl 8) or r;
  27.             tempdata[wptr] := temppixel;
  28.  
  29.  

winni

  • Hero Member
  • *****
  • Posts: 1806
Re: How do deal with "Warning: Symbol "ScanLine" is not portable"
« Reply #3 on: February 16, 2020, 12:48:29 am »
Hi!
I don't quiet understand what you want to achieve.

You get the picture data from a base64 stream. And then??

Save it to a file ? Display it on the screen?

Write a little about it.

Winni

jamie

  • Hero Member
  • *****
  • Posts: 3532
Re: How do deal with "Warning: Symbol "ScanLine" is not portable"
« Reply #4 on: February 16, 2020, 05:14:19 am »
I too am not sure what you really want but!

TPicture will let you do all sorts of things with files and streams and it supports PNG, JPG etc...
The only true wisdom is knowing you know nothing

TTL

  • Newbie
  • Posts: 3
Re: How do deal with "Warning: Symbol "ScanLine" is not portable"
« Reply #5 on: February 16, 2020, 11:23:04 am »
Today i found my error. t.Colors[x, y].red; gives me a 16bit value, but I expected 8.
So with
Code: Pascal  [Select][+][-]
  1.             tempColor := internalImage.Colors[x, y];
  2.             r := tempColor.red shr 8;
  3.             g := tempColor.green shr 8;
  4.             b := tempColor.blue shr 8;
  5.  
its now working without warnings, no pointer usage, proper colors and satisfying speed.  :D

I am still wondering what the different type of image formats are meaning:
https://lazarus-ccr.sourceforge.io/docs/lazutils/graphtype/trawimagedescription-3.html
There is no description. I can only guess R, G, B are the number of used bits for each color and A is transparency. But M1 and BIO? Whats the difference?

I am using the data later to further process them to different image formats and then write them to a binary which is finally flashed into a microcontroller. If you are curious: https://sourceforge.net/projects/menudesigner/
« Last Edit: February 16, 2020, 11:36:35 am by TTL »

 

TinyPortal © 2005-2018