Recent

Author Topic: [SOLVED] How do deal with "Warning: Symbol "ScanLine" is not portable"  (Read 321 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: 2309
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
Number 1 at blue screen app creations!

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: 887
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: 2309
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...
Number 1 at blue screen app creations!

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 »