Recent

Author Topic: Autosize and scaling image.  (Read 593 times)

Birger52

  • Sr. Member
  • ****
  • Posts: 299
Autosize and scaling image.
« on: September 02, 2020, 12:34:38 pm »
I have a "constuction" like in the image...
2 panels - one with a number of TLabels at the bottom. Labels are anchored to each other and Panel is Autosizing to accomodate the text.
Another TPanel at the top - anchored to the one below, so when text changes or form is resized, both panels change size.
The top panel contains two other panels, that each holds a TImage (as I want the panel borders around the images).
The image-panel on the right is set to anchor to the top right and bottom (or align alRight - same result), and the one on the left to fill up the rest of the space (anchored top left bottom and right to the containing panel, or alCLient - same result).
The image on the left, is set to fill the panel it is on; AutoSize, Center, Proportional, Stretch and StretchInEnabled set true.
The image on the right, is anchored to top right and bottom of the panel it is on, and it also has AutoSize, Center, Proportional, Stretch and StretchInEnabled set to true.

And it kind of all functions as expected, except for one thing:
The image on the right does not keep to the right; the TImage control always takes the width of the original image - not the scaled one, as it should when AutoSize is true - so if the original image is too big to fit the space, there is always "empty" space around it - either top/bottom which is OK, or left/right, which is not OK and should not occur. .
If I set Center to false, the image is actually to the left in the panel, which to me indicates, that the TImage does not take the width of the content (AutoSize) but the width of the original image.

Is there a way around this, other than manually calculating the correct width for the image/panel?
Lazarus 2.0.8 FPC 3.0.4
Win7 64bit
Playing and learning - strictly for my own pleasure.

jamie

  • Hero Member
  • *****
  • Posts: 3797
Re: Autosize and scaling image.
« Reply #1 on: September 02, 2020, 01:09:40 pm »
maybe it's maintaining an aspect ratio of the image ?

If you have borders set on the Panel it could be using those borders as a limit and trying to avoid over writing them.
 
I don't know how the aspect ratio is calculated in the Timage but I do it manually in an app I have and I do keep the aspect ration of the image to avoid misshaped images.

 you may need to do that same, use  TPaintBox instead and in the OnPaint cycle draw the image.
The only true wisdom is knowing you know nothing

Birger52

  • Sr. Member
  • ****
  • Posts: 299
Re: Autosize and scaling image.
« Reply #2 on: September 02, 2020, 05:24:54 pm »
OK thx.
Will look at that. Not sure about drawing an image manually, but can probably find a description somewhere....

Tried to manually correct the size of the TImage - but it appears to ignore as well Proportinal as AutoSize.

Attached image shows, the attempt to set width manually, is ignored (Width is set to 147 - but it is 172) even tho there is nothing else determining the width.... (Panel containing TImage is 222 heigh - minus 2 space around TImage and 1 for border, leave 216 pixel for the TImage height - this is correct. With the scaling and proportion settings, TImage should set the width to 147 by itself, but it don't allow anything other than the original width of the image - 172)
Proprtions of the original image is W/H 172/252 - and the proportions of TImage is 172/216 so the size of the TImage Control is not proportional.
Scaled down image is 147x216 - TImage is 172x216 - so AutoSize (Setting size to fit contens) is not functioning either.
Lazarus 2.0.8 FPC 3.0.4
Win7 64bit
Playing and learning - strictly for my own pleasure.

wp

  • Hero Member
  • *****
  • Posts: 7760
Re: Autosize and scaling image.
« Reply #3 on: September 02, 2020, 06:05:53 pm »
There are serveral contraditing properties in TImage. TImage.AutoSize requires the right and bottom sides of the component to be non-anchored so that they can freely adjust to the size of image content.

The properties related to stretching (Stretch, Proportional, stretchInEnabled, StretchOutEnabled) are not effective any more when AutoSize has been set.

What exactly do you want to achieve? Do you want to scale the right image so that it fully fits into the interior of its container, the right panel? What with the left panel then? Should it have the same height as the right panel? And what with the image in the left panel? It certainly will not fit into the panel width any more. Will the width of the left panel have to be adjusted as well? But then probably the height of the top panel (which contains the left and right image panels) needs adjustment, too, as well as the entire form.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

jamie

  • Hero Member
  • *****
  • Posts: 3797
Re: Autosize and scaling image.
« Reply #4 on: September 02, 2020, 06:09:31 pm »
I would need to look a the code for the Tmage , Like I said it may not be properly calculating the sides verses the top/bottom

 What I do is find which side fits the square or which side is the largest and from there calculate the ratio of aspect and reduce the image size using that ratio for the over all image not just one angle.

 so for example if the image is 25% too high for the square I deduce the image 25% all around.., This will of course cause margins to appear but there is not getting out of that..
 
  You could also use a Tscrollbox and not reduce the image size at all or have an optional view of it.

The only true wisdom is knowing you know nothing

Birger52

  • Sr. Member
  • ****
  • Posts: 299
Re: Autosize and scaling image.
« Reply #5 on: September 02, 2020, 06:38:48 pm »
I have no problem with the width, so only scale after height.

So end up with something this:
Code: Pascal  [Select][+][-]
  1. procedure TCardForm.CardPaintBoxPaint(Sender: TObject);
  2. var
  3.   aCard : string;
  4. begin
  5.   aCard := CardsTable.GetSelectedText;  // Finds the name of the card, that has been selected elsewhere
  6.   if aCard <> '' then ShowCardImage(aCard);
  7. end;
  8.  
  9. procedure TCardForm.ShowCardImage(aCard:string);
  10. var
  11.   cimg : string;
  12.   aImg : TPicture;
  13.   sz : double;
  14.   fW, fH : integer;
  15. begin
  16.   cImg := GetCardImage(Settings.Folder, aCard);  // FInd name of img (.jpg) to show
  17.   aImg := TPicture.Create;
  18.   aImg.LoadFromFile(cImg);
  19.   fW := aImg.Width;
  20.   fH := aImg.Height;
  21.   CardPaintBox.Height := CardImgPanel.Height-6;
  22.   sz := (CardPaintBox.Height)/fH;
  23.   if sz < 1 then begin
  24.     fW := Round(fW*sz);
  25.     fH := Round(fH*sz);
  26.   end;
  27.   CardPaintBox.Width := fW;
  28.   CardPaintBox.Canvas.StretchDraw(Rect(0,0,fW,fH), aImg.Graphic);
  29.   aImg.Free;
  30. end;
  31.  

And it functions a expected - thx ;)

It does flicker quite a bit when form is resized.
To be expected I guess - but the TImage didn't do that...
Lazarus 2.0.8 FPC 3.0.4
Win7 64bit
Playing and learning - strictly for my own pleasure.

wp

  • Hero Member
  • *****
  • Posts: 7760
Re: Autosize and scaling image.
« Reply #6 on: September 02, 2020, 06:44:37 pm »
When you see flicker with a Paintbox you should paint all images into a bitmap, and then draw the bitmap on the canvas of the paintbox. The bitmap should have the same size as the Paintbox, of course.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

Birger52

  • Sr. Member
  • ****
  • Posts: 299
Re: Autosize and scaling image.
« Reply #7 on: September 02, 2020, 06:47:41 pm »
You are correct about your assumption of what I am trying to do - The right image should be shown as large as possible but not be zoomed in - and the left should adjust its size accordingly.
Images on the right are max 180x260 - on the left they are very different, up to 1200x1200. (And not important - just there to fill out the space, actually...)

Will work on the flickering... requires a littel more than just OnPaint, I see... ;)
Lazarus 2.0.8 FPC 3.0.4
Win7 64bit
Playing and learning - strictly for my own pleasure.

Birger52

  • Sr. Member
  • ****
  • Posts: 299
Re: Autosize and scaling image.
« Reply #8 on: September 02, 2020, 07:32:08 pm »
Well...
Quote
There are serveral contraditing properties in TImage. TImage.AutoSize requires the right and bottom sides of the component to be non-anchored so that they can freely adjust to the size of image content.

The properties related to stretching (Stretch, Proportional, stretchInEnabled, StretchOutEnabled) are not effective any more when AutoSize has been set.
So I removed Autosize.
As the panel containing the TImage has AutoSize set, It should make no difference.
And actually nor should it, if the image is left or right anchored:
So as per the quote, I only anchored it at top and left.
Still have to set the width, tho. Once a size have been used, that is smaller than the original image, it does not enlarge to be able to show 1:1 by itself, even if there is room for it.
Also, setting Center to true, gives odd display, (Kind of looks like it keep the top of the image in the middle of the Panel. May be correct, but not quite like I interpret "center".
Anyhow - a few calculations remedies these problems easily.
Code: Pascal  [Select][+][-]
  1. procedure TCardForm.CardImgPanelResize(Sender: TObject);
  2. var
  3.   aCard : string;
  4. begin
  5.   aCard := CardsTable.GetSelectedText;  // The selected card
  6.   CardImage.Visible := aCard <> '';
  7.   if aCard <> '' then ShowCardImage(aCard);
  8. end;
  9.  
  10. procedure TCardForm.ShowCardImage(aCard:string);
  11. var
  12.   cimg : string;
  13.   sz : double;
  14.   fW, fH, offH : integer;
  15. begin
  16.   cImg := GetCardImage(Settings.Folder, aCard);  // The image identifying to the card
  17.   CardImage.Picture.LoadFromFile(cImg);
  18.   fW := CardImage.Picture.Width;
  19.   fH := CardImage.Picture.Height;
  20.   sz := (CardImgPanel.Height - 6)/fH;
  21.   if sz < 1 then begin
  22.     fW := Round(fW*sz);
  23.     fH := Round(fH*sz);
  24.     offH := 0;
  25.   end else
  26.     offH := Round((CardImgPanel.Height - 6 - fH)/2);
  27.   CardImage.BorderSpacing.Top := offH;
  28.   CardImage.Width := fW;
  29. end;
  30.  
And things are functioning as expected - without flickering when resizing.

Thx so much!
(Will look at the TPaintBox later - it seemed to render better quality when scaling images down down. But it will have to wait a while for now)
Lazarus 2.0.8 FPC 3.0.4
Win7 64bit
Playing and learning - strictly for my own pleasure.

lazimiri

  • New member
  • *
  • Posts: 7
Re: Autosize and scaling image.
« Reply #9 on: September 14, 2020, 08:15:21 am »
Interesting! I didn´t knew you could do that. It´s so cool the see all of the possible tricks and things you can do!

 

TinyPortal © 2005-2018