Giorgio Barchiesi
Giorgio Barchiesi

Reputation: 6177

Fast drawing of UIImage images on a UIView

In my app, I have to draw some images on a view, in real-time, in positions and scaling that frequently change over time. These images are a subset of those contained in a dictionary. Here is the code, a bit summarized:

-(void)drawObjects:(NSArray*)objects withImages:(NSDictionary*)images <etc>
{
    // Get graphic context and save it
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);

    // Display objects in reverse order
    for (int i = [objects count] - 1; i >= 0; i--) {
        MyObject *object = [objects objectAtIndex:i];

        // Check if object shall be visible
        if (<test to check whether the image shall be visible or not>) {

            // Get object image
            UIImage* image = <retrieve image from "images", based on a key stored in "object">;

            // Draw image
            float x = <calculate image destination x>;
            float y = <calculate image destination y>;
            float imageWidth = <calculate image destination width>;
            float imageHeight = <calculate image destination height>;
            CGRect imageRect = CGRectMake(x - imageWidth / 2, y - imageHeight / 2, imageWidth, imageHeight);
            [image drawInRect:imageRect];
        }
    }

    // Restore graphic context
    CGContextRestoreGState(context);
}

My problem is that this code is slow; it takes about 700 to 800 ms to perform the loop, when the number of images is about 15 (iPhone 4, iOS 4.3.5). I have experimented a bit, and it seems that the bottleneck is the drawInRect call, since if I exclude it, everything speeds up drammatically.

Does anyone have suggestions to offer?

Upvotes: 2

Views: 5978

Answers (2)

fzwo
fzwo

Reputation: 9902

The problem is (I think) that you are actually drawing (creating the screen representation) the image in every frame, because drawInRect: has no idea that you want to reuse the image that you displayed in the last frame. But you don't need that. You only want to draw it once, and then transform it afterwards to change its position and size.

UIKit makes this easy for you: Just set the frame for a UIImageView, and the image will be displayed where and how large you want it, without needing to re-render the image data.

You can probably optimize this further by storing the UIImageViews themselves, so that they don't have to be recreated every time they need to be displayed. Istead just set their hidden property accordingly.

Upvotes: 2

David Dunham
David Dunham

Reputation: 8339

Your number one answer: run Instruments and see what part of this is actually taking time. (Yes, chances are it's the drawInRect: but it could be the "get the image" you didn't show).

Upvotes: 0

Related Questions