0

I have requirement to load an advertisement image in my app and these are usually logos of companies.

The thing about logos is that while they can be of a specific height, their width would change.

So I started with a very simple solution, I uploaded a 90 x 20 png image in Firebase storage and then used the simples code:

Image(uiImage: image) and this rendered the rendered the image at 90 x 20.

Some details left out is that I make a network request in the background to download this image and then - I feel this might be not relevant but can add code if needed.

The issue is that on an iPhone 16 (regular and pro) device, these image get really blurry.

So what I did was upload a 3x image but that previous code made the image grow massively as now the image dimensions were 270 x 60.

So to render the high quality image at the previous dimensions, I did the following:

Image(uiImage: image)
    .resizable()
    .renderingMode(.template)
    .scaledToFit()
    .frame(height: 20)

// The width of the parent view hosting this had a max width of infinity

Now this worked and the images were sharper. The issue with specifying a hardcoded height of 20, we ran into the issue with some company's logos being a bit taller so then we came up with a rule where the max height of the logo should be 28 so:

  1. If I upload 90 x 20, the images height would be 20
  2. If I uploaded 360 x 80, the image height would be 28

I achieve this via:

Image(uiImage: image)
    .resizable()
    .renderingMode(.template)
    .tint(Constants.Colors.logo)
    .scaledToFit()
    .frame(height: min(image.size.height, 28))

This works for most of the use cases, however, if I want an image to render at 90 x 20 but at a high quality, and if I upload an image at 3x 270 x 60, it would not render at 90 x 20 but rather at 126 x 28 because 28 is the max height

While this might be acceptable, what would be a good way to render the 2x and 3x images at its original dimension rather than making the image grow to the 28 max height.

5
  • If I understand correctly, you should create a UIImage using this initialiser which allows you to specify a scale, and you shouldn’t need to resize the image at all. Commented Mar 29 at 9:58
  • Thank you so much @Sweeper - this is what I needed. This should work, I'm guessing there is no automatic detection if one image was 2x and another was 3x - my thought is that we need to send this back via an API as to what the scale factor should be. Commented Mar 29 at 10:35
  • Yes. You need to know what scale the image is. Commented Mar 29 at 10:44
  • I read the question again and this confused me: why should the 360 x 80 image displayed with a height of 28? How do you differentiate between "this image should be taller" and "this is just a 4x scale image and should still be displayed with a height of 20pt"? Commented Mar 29 at 12:03
  • @Sweeper - It does not need to be 28. I just set a max height of 28 as the logos would never be taller than this. I would like the 360 x 80 to scale to 90 x 20, but before you shared the init with me, that image would automatically scale to 126 x 28 as 28 is the max height and the image would take all the space it can get. Commented Mar 29 at 20:32

1 Answer 1

1

You should create the UIImage using init(data:scale:). This initialiser allows you to specify the scale and it will be scaled accordingly when it is displayed.

Alternatively, create a CGDataProvider using the Data you got, then create a CGImage from that (e.g. this initialiser for pngs). This CGImage allows you to access the width and height in pixels, which you can use to calculate the scale. Finally, create a SwiftUI Image using init(_:scale:orientation:label:), pass in the CGImage and the scale. The label is for accessibility.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.