Category Archives: UIKit

iOS Graphics – Adding Images

In my last post, we learned how to use the UIKit framework for drawing simple shapes on the iPhone/iPad screen. In this post, we find out how to load and display external image files in the same view, using the UIImage class.

Quoting again from the relevant portion of the Apple developer website:

UIImage object is a high-level way to display image data. You can create images from files, from Quartz image objects, or from raw image data you receive. The UIImage class also offers several options for drawing images to the current graphics context using different blend modes and opacity values.

This is what the application will look like after we’re done loading and displaying all the images:

Screen Shot 2014-04-24 at 12.44.56 AM

For the purpose of this app, I used the exact same set of images I used for my HTML5 cartoon. Each individual image was created using GIMP and was 400 pixels by 400 pixels. In this case, each individual image  (except the background) is on a transparent layer. Thus, the individual images can be assembled (in the right order) to create the final picture shown in the center.

Here is a step-by-step guide about how to create the view seen in the screenshot above:

STEP 1: Create a Single View Application

Like the previous post, we create a single view application for iOS in Xcode and then create a subclass of UIView called drawShapes. Make sure that the DrawShapes class is associated with the Main Storyboard.

STEP 2: Copy image files to your project

In the “Project Navigator”, click on the “Supporting Files” folder and then click on

Files —-> Add Files to “Your Project Name”

Select the image files and make sure your tick the box below.

Screen Shot 2014-04-24 at 12.56.10 AM

On a retina display, we can automatically display each image in a screen size of 200 pixels by 200 pixels, provided we append the “@2x” qualifier to the image name . However, in this application, we explicitly specify the location and size of the bounding rectangle inside which we want to place each image, so whether or not you use the “@2x” qualifier is irrelevant.

STEP 3: Customize the drawRect method

The APIs to load and draw images will be inside the drawRect method, like before. The complete implementation file for loading and displaying the images is provided below.

@implementation drawShapes

- (void)drawRect:(CGRect)rect
{
    CGRect quad;
    UIBezierPath *path;
    UIColor* strokeColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
    [strokeColor setStroke];
    [path stroke];

    // draw individual images in these squares
    quad = CGRectMake(10, 30, 90, 90);
    path = [UIBezierPath bezierPathWithRect:quad];
    [path stroke];
    
    quad = CGRectMake(110, 30, 90, 90);
    path = [UIBezierPath bezierPathWithRect:quad];
    [path stroke];
    
    quad = CGRectMake(210, 30, 90, 90);
    path = [UIBezierPath bezierPathWithRect:quad];
    [path stroke];
    
    quad = CGRectMake(65, 340, 90, 90);
    path = [UIBezierPath bezierPathWithRect:quad];
    [path stroke];
    
    quad = CGRectMake(165, 340, 90, 90);
    path = [UIBezierPath bezierPathWithRect:quad];
    [path stroke];
    
    // load external image files
    UIImage* background   = [UIImage imageNamed:@"background@2x.png"];
    UIImage* baseline     = [UIImage imageNamed:@"baseline@2x.png"];
    UIImage* readThePaper = [UIImage imageNamed:@"readThePaper@2x.png"];
    UIImage* hat          = [UIImage imageNamed:@"hat@2x.png"];
    UIImage* legs         = [UIImage imageNamed:@"legs@2x.png"];

    // drawing individual images
    [background   drawInRect:CGRectMake(10, 30, 90, 90)];
    [baseline     drawInRect:CGRectMake(110, 30, 90, 90)];
    [readThePaper drawInRect:CGRectMake(210, 30, 90, 90)];
    [hat          drawInRect:CGRectMake(65, 340, 90, 90)];
    [legs         drawInRect:CGRectMake(165, 340, 90, 90)];
    
    // drawing them together (in the right order)
    [background   drawInRect:CGRectMake(60, 130, 200, 200)];
    [baseline     drawInRect:CGRectMake(60, 130, 200, 200)];
    [readThePaper drawInRect:CGRectMake(60, 130, 200, 200)];
    [hat          drawInRect:CGRectMake(60, 130, 200, 200)];
    [legs         drawInRect:CGRectMake(60, 130, 200, 200)];
    
    CGSize imageSize = [baseline size];
    NSLog(@"Image height = %f width = %f",imageSize.height, imageSize.width);
}

@end

You can query the size of the images using the size method. In this case, the NSLog at the end prints out values of 400 each for the height and width.

STEP 3: Think about what you can do with images in your app

That’s all there is to the basic task of loading and displaying images in the current graphics context using the UIKit framework. In future posts, I’ll explore additional things we can do with image objects, including coordinate transformations and animation.

iOS Graphics – Introduction

In this post, we will learn how to create an iPhone application that creates the graphic shown below, using the UIKit framework.

Quoting from the Apple Developer website:

The UIKit framework provides the classes needed to construct and manage an application’s user interface for iOS. It provides an application object, event handling, drawing model, windows, views, and controls specifically designed for a touch screen interface.

Example of UIView Graphics

It is assumed that you have some degree of familiarity with the Xcode IDE. In particular, you should know how to create and run projects, add files to existing projects and use the Attribute Inspector and the Identity Inspector (located in the right hand-side panel).

Now simply follow these steps.

STEP 1

Open a new project in Xcode (iOS application – Single View Application).In the Deployment Info, select iPhone in the Devices menu and portrait in the Device Orientation.

STEP 2

Create a new file (Cocoa Touch — Objective-C class) called drawShapes. Xcode will create the header and implementation files automatically:

  • drawShapes.h
  • drawShapes.m

Copy the contents below in these files:

#import <UIKit/UIKit.h>

@interface drawShapes : UIView
@end

All we have done above is to declare our own little class called “drawShapes” and specified that this class inherits from the UIView class. All of the graphics commands used in this example are part of the drawRect method. The drawRect method is defined in the UIView class and overridden here by our custom graphics commands, as detailed below in the implementation file for our class.

#import "drawShapes.h"

@implementation drawShapes

- (void)drawRect:(CGRect)rect
{
    CGRect quad;
    UIBezierPath *path;
    UIColor* fillColor;
    UIColor* strokeColor;
    
    // rectangular tiling of the iPhone screen
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            float x = 64*i;
            float y = 96*j;
            float width = 64;
            float height = 96;

            quad = CGRectMake(x, y, width, height);
            path = [UIBezierPath bezierPathWithRect:quad];
        
            float R = (arc4random() % 255)/255.;
            float G = (arc4random() % 255)/255.;
            float B = (arc4random() % 255)/255.;
        
            fillColor = [UIColor colorWithRed:R green:G blue:B alpha:1.0];
            [fillColor setFill];
            [path fill];

            strokeColor = [UIColor colorWithRed:R green:G blue:B alpha:1.0];
            [strokeColor setStroke];
            [path stroke];
        }
    }
    
    // draw a red circle with a black perimeter
    quad = CGRectMake(100, 100, 120, 120);
    path = [UIBezierPath bezierPathWithOvalInRect:quad];

    fillColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0];
    [fillColor setFill];
    [path fill];
    
    strokeColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
    [strokeColor setStroke];
    [path stroke];
    
    // custom drawing: a white arrow with a black outline
    {
        UIBezierPath* arrowPath = [UIBezierPath bezierPath];
        
        // define the path
        [arrowPath moveToPoint:CGPointMake(0.0, 0.0)];
        [arrowPath addLineToPoint:CGPointMake(30.0, 0.0)];
        [arrowPath addLineToPoint:CGPointMake(30.0, -5.0)];
        [arrowPath addLineToPoint:CGPointMake(40.0, 5.0)];
        [arrowPath addLineToPoint:CGPointMake(30.0, 15.0)];
        [arrowPath addLineToPoint:CGPointMake(30.0, 10.0)];
        [arrowPath addLineToPoint:CGPointMake(0.0, 10.0)];
        [arrowPath closePath];
        
        // coordinate transformation using the current context
        {
            CGContextRef context =  UIGraphicsGetCurrentContext ();
            float PI = 3.1415;
            CGContextTranslateCTM(context, 170, 125);
            CGContextScaleCTM(context, 2, 2);
            CGContextRotateCTM(context, PI/2.0);
        }
        
        // set the fill color to white
        fillColor = [UIColor whiteColor];
        [fillColor setFill];
        [arrowPath fill];
        
        // set the outline to black
        strokeColor = [UIColor blackColor];
        [strokeColor setStroke];
        [arrowPath stroke];
    }
}

@end

Most of the code is self-explanatory and you can see that we specify a random color for filling and stroking (drawing the border on) each rectangle .

For drawing the circle, we specify the bounding box inside which it is inscribed.

Finally, we define a custom shape (the arrow) using the following coordinates for the individual points (the seven points are traversed in clock-wise order starting from the origin).

Screen Shot 2014-04-22 at 5.55.06 AM

To move the arrow to the location shown in the iPhone screenshot above, coordinate transformations are applied, in the following order:

  • rotate clockwise by 90 degrees (π/2 radians) about the origin
  • scale by a factor of 2 along X and Y
  • translate by 170px along X and 125px along Y

Note that these transformations need to be listed in reverse order in the code:

CGContextTranslateCTM(context, 170, 125);
CGContextScaleCTM(context, 2, 2);
CGContextRotateCTM(context, PI/2.0);

As an aside, the “CG” stands for Core Graphics and “CTM” stands for current transformation matrix. Unlike C++, Objective-C does not have namespaces. Thus, one needs to be careful to avoid name collisions between different functions. Hence the ubiquitous prefixes all over the place like CG, NS (NextStep legacy) and UI (user interface).

STEP 3

Click on “Main_iPhone.storyboard”. If you wish, you can change the background color by using the appropriate selections in the Attribute Inspector panel. But more importantly, open the Identity Inspector and select the class you just created (drawShapes) in the very first drop-down menu.

STEP 4

That’s it! Build and run your application and you should see the iPhone screen fill up with the graphic shown in the screenshot above.

As you can see, it does not take much to create and display simple graphics for iOS. In later posts, we will explore other graphics frameworks in detail, including Core Graphics and OpenGL-ES. In my next post, I will show you how to add images to your view.