Brosteins

Developers, Technology Evangelists, Bros.

Resizing Images for a NativeScript App

I recently posted about a small weekend project with my sons: building an iOS soundboard app using NativeScript and a text-to-speech engine. In this post, I wanted to dive a bit deeper into resizing images for a NativeScript App, and how I went about integrating static images into my app.

Using XML and CSS to Add Images to your App

In my app, I embedded images for the profile pictures on the main page:

home page profile images

Planning ahead, I wanted to tap each image and perform an action. usually in nativeScript, you would use an Image tag to display an image; however, Images don’t have a tap event, so I had to use a Button control, with a background image set via CSS. For example, the markup and CSS for my image looks like this:

You’ll notice the button markup includes a row and col attribute, used to position the Button in a Grid Layout. You’ll also notice the tap event of the button is data bound to a function on my view model, named “onTap”. In the CSS, notice the how I set common button size and background image attributes with the Button {…} styles.

If you’re familiar with CSS, all of these elements shouldn’t seem out of the ordinary (which is why I love NativeScript, b/c I can leverage my existing web skills to build a truly native app). You will also see the #mike id selector, which sets the actual background image of the button. Most of this syntax should be familiar, with the exception of the res://mike syntax. This syntax tells NativeScript to use an app resource for the image source.

Image resources are a convention-based way to have the NativeScript runtime auto-select an appropriate image based upon the device (i.e., screen resolution and pixel density). For example, this app may run on an iPhone 4s or an iPad Mini with retina display. The usual problem is screen resolution and accounting for that in your images. The NativeScript docs have a great write-up on how to handle this through their conventions; however, as an app writer, you need to supply the runtime with image assets of multiple resolutions. Yuck.

I’ve written about this problem before, and previously created a website to automatically resize images for iOS and Android apps. This was my first opportunity to use the website, and let me say, it saved me tons of time.

Planning for Different Device Resolutions

When I started planning for this app, I knew I wanted to support multiple form factors: iPhone, iPad, iPad Mini 2 (retina), so I needed to start planning my images early. As a general rule of thumb, I always plan for the maximum device resolution and scale down my images accordingly. On the home page of my app, I wanted to show an image of each person in the family:

home page profile images

Knowing that I wanted to support the iPad Mini 2 (retina), my max screen resolution was 2048 x 1536. So with some quick math, the max size of each image should be 768 x 768. But, there’s a catch: this image size is for an iPad retina, which is considered an @2x image size. Planning ahead, I know I want to support higher pixel densities (@3x), so I needed to scale the dimensions of the original image up to 1.5x of the 768 x 768 size. The size I needed to start from was actually 1152 x 1152 to support the iPhone 6 plus.

With my image dimensions in mind, I began cropping a high-res JPG from my recent visit to San Francisco. Using Paint.NET, I scaled down the image to a square version that was at least 1152 x 1152. I then cropped the picture further to have a circular outline. I finally saved the image as a PNG:

Mike's cropped original size image

An important aspect to note is that I did not crop my image down to 768 x 768 first, then expand/increase the size to 1152 x 1152. Resizing images multiple times by scaling up, then down, then up again will eventually produce a “grainy image”, which is undesirable. As a result, it’s generally important (especially for photos) to start with a high resolution image and scale down once (I said “generally” above because direct resizing of images is not necessary the best approach, but I’m not ready to get into this further right now – many different people have written about image resizing in the past, so take a look).

Uploading to the NativeScript Image Builder Site

With my base (and highest resolution) image created, I headed over to my NativeScript Image Builder site, selected my image (mike.png), selected the “Static Image – iOS” option, and pressed “Upload App Image”:

NativeScript Image Builder upload app image The site returns a zip file containing the original image resized to the appropriate proportions, as required by iOS:

downloaded zip

zip file contents

Inside the zip file, you’ll find the original image was renamed to [original-name]@3x.png, a 2/3 scaled down version named [original-name]@2x.png, and a 1/3 scaled down version named [original-name].png.

Making Static Images work at Multiple Device Resolutions

To add  static images to the app, I placed the images inside the app/App_Resources/iOS folder (note you’re seeing my wife’s images added and not mine):

images added to App_Resources folder

Once the images are in the App_Resources folder, you can reference them via the res:// syntax within your app. If you recall, this is exactly what I did earlier:

 

When the NativeScript runtime encounters an image loaded via res://, the current mobile platform is detected (Android or iOS), the device screen resolution and pixel density is determined, and the appropriate image is selected for rendering. On iOS, the base image (mike.png) is used for iPad 2 and iPad Mini, the @2x image is used for iPhone 4s, iPhone 5, iPhone 6, and other retina devices, and the @3x image is used for iPhone 6 plus. What’s nice about using the resource approach is that NativeScript handles everything for you.

If you have a change, clone my Git repo over at Github and try out our app. We have had a lot of fun playing with it at home over the past several days. Enjoy!

 

Share

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.