Recent

Author Topic: BGRABitmap + BCRoundedImage + .TextOut = garbage  (Read 1018 times)

r.lukasiak

  • Jr. Member
  • **
  • Posts: 82
BGRABitmap + BCRoundedImage + .TextOut = garbage
« on: June 07, 2022, 03:53:22 am »
Hi everyone!

I use BCRoundedImage to display graphics I create in BGRABitmap, everything goes smoothly till I use .TextOut. Using .TextOut makes the graphics very defective (pic #1). On Windows it happens even without using .TextOut (pic #2).

I create the component dynamically:
Code: Pascal  [Select][+][-]
  1. var bubble: TBCRoundedImage;
  2. begin
  3.   bubble:=TBCRoundedImage.Create(Self);
  4.   bubble.Parent:=ChatsTab;
  5.   bubble.Style:=isSquare;
  6.   bubble.Top:=60*(ChatsTab.ControlCount-1);
  7.   bubble.Left:=0;
  8.   bubble.Width:=ChatsTab.ClientWidth;
  9.   bubble.Height:=60;
  10.   bubble.Tag:=ChatsTab.ControlCount;
  11.   bubble.Picture.Assign(ChatListBubble(bubble.Width,bubble.Height,'Some text',IntToStr(bubble.Tag),StrToTime('16:00')));
  12. end;  

and that's how I draw the image
Code: Pascal  [Select][+][-]
  1. var
  2.   TBit: TBitmap;
  3.   Lmargin: integer =5;
  4.   Rmargin: integer =5;
  5.   Tmargin: integer =3;
  6.   Bmargin: integer = 0;
  7.  
  8. begin
  9.   TBit := TBitmap.Create;
  10.   TBit.PixelFormat := pf24bit;
  11.   TBit.Width := w;
  12.   TBit.Height := h;
  13.  
  14.   bmp:=TBGRABitmap.Create(w,h,BGRA(0,0,0,0));
  15.   bmp.draw(TBit.Canvas, 0,0,true);
  16.   bmp.RoundRect(Lmargin, Tmargin, w-Rmargin, h-Bmargin, 15, 15, $00FF9900, BGRA(128,128,128,255), dmDrawWithTransparency, 8192);
  17.   bmp.RoundRect(Lmargin+5, Tmargin+5, 55, 55, 15,15, $00FF9900,dmDrawWithTransparency,32768);
  18.   bmp.FontHeight:=15;
  19.   bmp.FontStyle:=[fsBold];
  20.   bmp.textout(Lmargin+5+50+10, Tmargin+10, name, $cccccc,);
  21.   bmp.FontHeight:=14;
  22.   bmp.FontStyle:=[fsItalic];
  23.   bmp.TextOut(Lmargin+5+50+10, h-Bmargin-10-bmp.TextSize(lastmsg).cy , lastmsg, $cccccc);
  24.   Result:=bmp;
  25. end;          

Am I doing something wrong or what's the problem?

thanks in advance for any clue.
« Last Edit: June 07, 2022, 04:23:47 am by r.lukasiak »

circular

  • Hero Member
  • *****
  • Posts: 3845
    • Personal webpage
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #1 on: June 07, 2022, 07:30:42 am »
Hi!

The code seems incomplete so it is not easy to analyze what happens. How you transfer the image is important in this case. Can you provide more code, something that one could try to run?

I am wondering what is the TBit object for. Note that setting the PixelFormat property is a bit buggy as far as I know.

Also I don't understand the need for a TBCRoundedImage if you set it to square. I would presume that you would like to draw an opaque bitmap with gray background inside this component, and let the component make the rounded borders.

When you do bubble.Picture.Assign it doesn't seem like the original image object is freed.
Conscience is the debugger of the mind

r.lukasiak

  • Jr. Member
  • **
  • Posts: 82
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #2 on: June 07, 2022, 03:56:17 pm »
The Tbit is just remnants of my trials with Timage. I removed it right after I posted it, but it didn't change anything.
I need RoundedImage only to display BGRABitmap directly, not through 'On' events. You example from the previous post works perfectly but I'd have to generate images on events and it makes things a bit different.

here I create the RoundedImage dynamically:
Code: Pascal  [Select][+][-]
  1. procedure TApp.BCLabel4Click(Sender: TObject);
  2. var bubble: TBCRoundedImage;
  3. begin
  4.   bubble:=TBCRoundedImage.Create(Self);
  5.   bubble.Parent:=ChatsTab;
  6.   bubble.Style:=isSquare;
  7.   bubble.Top:=60*(ChatsTab.ControlCount-1);
  8.   bubble.Left:=0;
  9.   bubble.Width:=ChatsTab.ClientWidth;
  10.   bubble.Height:=60;
  11.   bubble.Tag:=ChatsTab.ControlCount;
  12.   bubble.Picture.Assign(ChatListBubble(bubble.Width,bubble.Height,'Some text',IntToStr(bubble.Tag),StrToTime('16:00'),msNone));
  13.   bmp.Free;
  14. end;      

ChatListBubble generates the needed image, and it's like:
Code: Pascal  [Select][+][-]
  1. function ChatListBubble(w: integer; h: integer; name: string; lastmsg: string; time: TDateTime; status: TMsgStatus):TBGRABitmap;
  2. var
  3.   bmp:   TBGRABitmap;
  4.   Lmargin: integer =5;
  5.   Rmargin: integer =5;
  6.   Tmargin: integer =3;
  7.   Bmargin: integer = 0;
  8.  
  9. begin
  10.   bmp:=TBGRABitmap.Create(w,h,BGRA(0,0,0,0));
  11.   bmp.RoundRect(Lmargin, Tmargin, w-Rmargin, h-Bmargin, 15, 15, $00FF9900, BGRA(128,128,128,255), dmDrawWithTransparency, 8192);
  12.   bmp.RoundRect(Lmargin+5, Tmargin+5, 55, 55, 15,15, $00FF9900,dmDrawWithTransparency,32768);
  13.   bmp.FontHeight:=15;
  14.   bmp.FontStyle:=[fsBold];
  15.   bmp.textout(Lmargin+5+50+10, Tmargin+10, name, $cccccc);
  16.   bmp.FontHeight:=14;
  17.   bmp.FontStyle:=[fsItalic];
  18.   bmp.TextOut(Lmargin+5+50+10, h-Bmargin-10-bmp.TextSize(lastmsg).cy , lastmsg, $cccccc);
  19.   Result:=bmp;
  20. end;            

Quote
Also I don't understand the need for a TBCRoundedImage if you set it to square
I don't need my image to be rounded, I use this component as a substitute for TImage since I didn't get it to be transparent.

r.lukasiak

  • Jr. Member
  • **
  • Posts: 82
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #3 on: June 07, 2022, 05:23:38 pm »
I've just tried TImage again and it works perfectly....  :-[ both, Linux Qt5 and Windows...

circular

  • Hero Member
  • *****
  • Posts: 3845
    • Personal webpage
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #4 on: June 07, 2022, 07:08:20 pm »
Cool.

Just one remark, I think there is a memory leak here:
Code: Pascal  [Select][+][-]
  1. bubble.Picture.Assign(ChatListBubble(bubble.Width,bubble.Height,'Some text',IntToStr(bubble.Tag),StrToTime('16:00'),msNone));

What you would need to do here would be:
Code: Pascal  [Select][+][-]
  1. tempBgra := ChatListBubble(bubble.Width,bubble.Height,'Some text',IntToStr(bubble.Tag),StrToTime('16:00'),msNone);
  2. bubble.Picture.Assign(tempBgra);
  3. tempBgra.Free;

This may cause some problem. If you don't really need transparency, like with a solid background, you could do:
Code: Pascal  [Select][+][-]
  1. tempBgra := ChatListBubble(bubble.Width,bubble.Height,'Some text',IntToStr(bubble.Tag),StrToTime('16:00'),msNone);
  2. tempBmp := tempBgra.MakeBitmapCopy(clBlack); // the background color
  3. tempBgra.Free;
  4. bubble.Picture.Assign(tempBmp);
  5. tempBmp.Free;

If you need transparency, you can assign the bitmap to a TBGRAGraphicControl like this:
Code: Pascal  [Select][+][-]
  1. tempBgra := ChatListBubble(bubbleGraphicControl.Width,bubbleGraphicControl.Height,'Some text',IntToStr(bubble.Tag),StrToTime('16:00'),msNone);
  2. bubbleGraphicControl.Bitmap.Assign(tempBgra);
  3. bubbleGraphicControl.Invalidate;
  4. tempBgra.Free;

In fact, thinking about it, the last method is probably the best.
Conscience is the debugger of the mind

r.lukasiak

  • Jr. Member
  • **
  • Posts: 82
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #5 on: June 07, 2022, 09:34:48 pm »
Quote
What you would need to do here would be:
it's still giving the same result :|

Quote
If you don't really need transparency, like with a solid background, you could do:
I do need transparency. As a matter of fact I have more issues with transparency. TBCPanel is beautifully transparent on Linux but not on Windows, but I guess it's a topic for a separate post :D

Quote
If you need transparency, you can assign the bitmap to a TBGRAGraphicControl like this:
this solution works perfectly. Thank you!

r.lukasiak

  • Jr. Member
  • **
  • Posts: 82
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #6 on: June 07, 2022, 10:09:31 pm »
...and a question, not completely related to the topic...
how could I squeeze a photo (let's say from a file) into that rounded square? I'm trying to round it in BDRoundedImage and copy to that BGRABitmap but no success so far :|

winni

  • Hero Member
  • *****
  • Posts: 3134
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #7 on: June 07, 2022, 11:07:21 pm »
...and a question, not completely related to the topic...
how could I squeeze a photo (let's say from a file) into that rounded square? I'm trying to round it in BDRoundedImage and copy to that BGRABitmap but no success so far :|

Hi!

All that component-stuff ....

* Load your photo-file into a BGRAbitmap
* Resample it to the destination size: BGRAreplace (MyPhoto, MyPhoto.resample (NewWidth, NewHeight));
* Create a temporary transparent BGRAbitmap of the same size, we call it tmp
* tmp.RoundRectAntialias(......, MyPhoto, ........);
* Draw tmp on any canvas you like OR do a putimage on a BGRAbitmap
* free the tmp

Done

Winni

circular

  • Hero Member
  • *****
  • Posts: 3845
    • Personal webpage
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #8 on: June 08, 2022, 12:01:01 am »
Indeed, you don't need to go through components. As winni suggests, you can pass an image instead of a color to any drawing function and it will fill using the image.

You can use temporary images to do things, apply masks etc.

In this simple case, you can adjust the position of the image by changing the ScanOffset property of the image, and use it to draw directly. In your ChatListBubble bubble, you could do:
Code: Pascal  [Select][+][-]
  1. squeezedPhoto := originalPhoto.Resample(20, 20);
  2. squeezedPhoto.ScanOffset := Point(-10, -10);
  3. bmp.RoundRectAntialias(10, 10, 10 + 20 - 1, 10 + 20 - 1, 5, 5, squeezedPhoto);
  4. squeezedPhoto.Free;
Conscience is the debugger of the mind

r.lukasiak

  • Jr. Member
  • **
  • Posts: 82
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #9 on: June 08, 2022, 01:20:59 am »
thank you both!

I tried it and indeed, it's rounded but the pic is not exactly inside the "frame", it looks like the picture is the frame itself.
There was missing one parameter for RoundRectAntialias, "w" - I assume it the "frame" thickness.

First I set it to 1 (pic #1) and then to 25 (pic #2)

My code including you solution:
Code: Pascal  [Select][+][-]
  1. function ChatListBubble(w: integer; h: integer; name: string; lastmsg: string; time: TDateTime; status: TMsgStatus):TBGRABitmap;
  2. var
  3.   Lmargin: integer =5;
  4.   Rmargin: integer =5;
  5.   Tmargin: integer =3;
  6.   Bmargin: integer = 0;
  7.   squeezedPhoto: TBGRABitmap;
  8.   originalPhoto: TBGRABitmap;
  9. begin
  10.   bmp:=TBGRABitmap.Create(w,h,BGRA(0,0,0,0));
  11.  
  12.   originalPhoto:=TBGRABitmap.Create('gfx/nophoto.jpeg');
  13.   squeezedPhoto:=TBGRABitmap.Create(40,40);
  14.   squeezedPhoto := originalPhoto.Resample(40, 40);
  15.   squeezedPhoto.ScanOffset := Point(-10, -10);
  16.  
  17.   bmp.RoundRect(Lmargin, Tmargin, w-Rmargin, h-Bmargin, 15, 15, $00FF9900, BGRA(128,128,128,255), dmDrawWithTransparency, 8192);
  18.  
  19.   bmp.RoundRectAntialias(10, 10, 10 + 40 - 1, 10 + 40 - 1, 5, 5, squeezedPhoto, 25); <-it was asking for an extra parameter
  20.  
  21.   originalPhoto.Free;
  22.   squeezedPhoto.Free;
  23.  
  24.   //bmp.RoundRect(Lmargin+5, Tmargin+5, h-5, h-5, 15,15, $00FF9900,dmDrawWithTransparency,32768);
  25.  
  26.   bmp.FontHeight:=15;
  27.   bmp.FontStyle:=[fsBold];
  28.   bmp.textout(Lmargin+5+(h-5), Tmargin+5, name, $cccccc);
  29.   bmp.FontHeight:=14;
  30.   bmp.FontStyle:=[fsItalic];
  31.   bmp.TextOut(Lmargin+5+(h-5), h-Bmargin-5-bmp.TextSize(lastmsg).cy , lastmsg, $cccccc);
  32.   Result:=bmp;
  33. end;          


r.lukasiak

  • Jr. Member
  • **
  • Posts: 82
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #10 on: June 08, 2022, 02:38:35 am »
I followed @winni's instruction and I got it, however there is something I had noticed when I was playing around with RoundedImage, the "rounding" is different. The picture and the frame are set to 15 but they don't match (pic #1). How comes? :D

My "working" code:
Code: Pascal  [Select][+][-]
  1. function ChatListBubble(w: integer; h: integer; name: string; lastmsg: string; time: TDateTime; status: TMsgStatus):TBGRABitmap;
  2. var
  3.   Lmargin: integer =5;
  4.   Rmargin: integer =5;
  5.   Tmargin: integer =3;
  6.   Bmargin: integer = 0;
  7.   squeezedPhoto: TBGRABitmap;
  8.   originalPhoto: TBGRABitmap;
  9. begin
  10.   bmp:=TBGRABitmap.Create(w,h,BGRA(0,0,0,0));
  11.  
  12.   originalPhoto:=TBGRABitmap.Create('gfx/nophoto.jpeg');
  13.   BGRAreplace(originalPhoto,originalPhoto.Resample(37,37));
  14.  
  15.   squeezedPhoto:=TBGRABitmap.Create(37,37,BGRA(0,0,0,0));
  16.   squeezedPhoto.RoundRectAntialias(0,0,36,36,15,15,originalPhoto,0,originalPhoto);
  17.  
  18.   bmp.RoundRect(Lmargin, Tmargin, w-Rmargin, h-Bmargin, 15, 15, $00FF9900, BGRA(128,128,128,255), dmDrawWithTransparency, 8192);
  19.   bmp.PutImage(Lmargin+5,Tmargin+5,squeezedPhoto,dmDrawWithTransparency);
  20.  
  21.   originalPhoto.Free;
  22.   squeezedPhoto.Free;
  23.  
  24.   bmp.RoundRect(Lmargin+5, Tmargin+5, Lmargin+5+36, Tmargin+5+36, 15,15, $00FF9900,dmDrawWithTransparency,32768);
  25.  
  26.   bmp.FontHeight:=15;
  27.   bmp.FontStyle:=[fsBold];
  28.   bmp.textout(Lmargin+5+(h-5), Tmargin+5, name, $cccccc);
  29.   bmp.FontHeight:=14;
  30.   bmp.FontStyle:=[fsItalic];
  31.   bmp.TextOut(Lmargin+5+(h-5), h-Bmargin-5-bmp.TextSize(lastmsg).cy , lastmsg, $cccccc);
  32.   Result:=bmp;
  33. end;        
  34.  

------------------
Edit:
RoundRectAntialias and RoundRect produce different rounding shape.
« Last Edit: June 08, 2022, 02:46:21 am by r.lukasiak »

winni

  • Hero Member
  • *****
  • Posts: 3134
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #11 on: June 08, 2022, 04:12:38 pm »
Hi!

Perhaps it has to do with the different positions of integer and floating points.

Read this for the basic definitions:

https://wiki.freepascal.org/BGRABitmap_tutorial_13

And for BGRA(0,0,0,0) there is a constant defined in BGRAbitmapTypes called

BGRAPixelTransparent

Winni



r.lukasiak

  • Jr. Member
  • **
  • Posts: 82
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #12 on: June 09, 2022, 05:27:06 am »
Quote
https://wiki.freepascal.org/BGRABitmap_tutorial_13
ohh cool, it's interesting :D

Code: Pascal  [Select][+][-]
  1. BGRAPixelTransparent
it's good to know. I'll try it next time, even though BGRA(0,0,0,0) is kinda easier to type :D

thank you very much for all the help!

circular

  • Hero Member
  • *****
  • Posts: 3845
    • Personal webpage
Re: BGRABitmap + BCRoundedImage + .TextOut = garbage
« Reply #13 on: June 09, 2022, 10:05:44 pm »
Oops it is FillRoundRectAntialias instead
Conscience is the debugger of the mind

 

TinyPortal © 2005-2018