2
votes

I am creating an Android app in Delphi XE5 using Firemonkey, and for one of my forms I need a TImage that will fill the entire form where I can draw on it's Bitmap.

What I did was this:

  1. I added a TImage component to my form and set it's Align := alClient. In the designer it fills the entire form.

  2. In my FormCreate procedure I initialized the Bitmap of the TImage by setting it's size to the size of the TImage

    procedure TDrawForm.FormCreate(Sender: TObject);
    begin
        Image1.Bitmap.SetSize(Trunc(Image1.Width), Trunc(Image1.Height));
        DrawFromList(Image1);
    end;
    
  3. Then I draw on the TImage's Bitmap.Canvas

    procedure TDrawForm.DrawFromList(image: TImage);
    var draw: TDraw;
    begin
       image.Bitmap.Canvas.BeginScene;
       image.Bitmap.Canvas.Clear(claBlue);
       image.Bitmap.Canvas.Stroke.Color := claBlack;
       image.Bitmap.Canvas.Fill.Color := claYellow;
       for draw in DrawList do
       begin
          image.Bitmap.Canvas.FillPath(draw.fpath, 1);
          image.Bitmap.Canvas.DrawPath(draw.fpath, 1);
       end;
       image.Bitmap.Canvas.EndScene;
    end;
    

This code draws just fine on my Nexus 7 tablet, but it does not fill the entire screen:

enter image description here

In the second picture I used

Image1.Bitmap.SetSize(Trunc(Image1.Width * 1.34), Trunc(Image1.Height * 1.34));

where 1.34 was found by trial and error, to make it fill the entire screen.

I then tried to print out the size of the image and the screen. For my Nexus 7 (which is 1280 x 800 pixels) the TImage component which fills the entire screen, has a width of 601 and a height of 880. Thus, when I set the size of the Bitmap to be the size of my TImage, the Bitmap is also 601 x 880, which explains why I needed to scale the Bitmap to make it fill the entire screen. The screen size is reported as 600 x 905 (using Screen.Size).

My question is why is the size of the TImage component only 601 x 880 (and the screen only 600 x 905) when the actual resolution of my device is 800 x 1280? If these sizes are not pixels, then what are they? And more importantly, how do I convert from these numbers to actual screen pixels (bear in mind, 1.34 only works for Nexus 7 - on my HTC Sensation it needed to be even bigger)?

One of my co-workers suggested that it might have to do with the DPI of the screen, but I couldn't find any method that will give me the DPI of the current device.

I have also tried updating the size of the bitmap in the FormResize procedure, but that doesn't make a difference.

1
Is the TImage really the final size in FormCreate, or does it adjust again to fit later? In the FormCreate, log the size of the TImage, then do it again later. Anyway, if this is the case, rather than resizing the bitmap, try using the TImage.WrapMode to auto scale the image.Marcus Adams
@MarcusAdams I made a button that prints out the values, and they do not change. So I would say that the TImage has it's final size already in the FormCreate. Note that the Screen.Size property also gives weird numbers (600 x 905 instead of 800 x 1280).Daniel

1 Answers

2
votes

I found a solution to my problem. Apparently there are, on the component, two properties that will return a scale. Luckily, this scale multiplied with the width and height of the component will return the width and height in pixels.

Image1.Scene.GetSceneScale
Image1.Canvas.Scale

In my case, I had to initialize my Bitmap like this:

Image1.Bitmap.SetSize(Trunc(Image1.Width * Image1.Canvas.Scale), 
                      Trunc(Image1.Height * Image1.Canvas.Scale));

This makes the Bitmap of my Image1 fill the entire screen since the image is set to Align := alClient.

I still don't know what the original size returned by Image1.Width and Image1.Height (or Screen.Size for that matter) is measured in, but it is not always pixels. It would have saved me about two weeks of headache if this was documented somewhere.