Sunday, August 16, 2009

Making Tiles


Creating hexagonal tiles from the image involves applying a tile mask and cutting up the image into smaller UIImageView objects. A layer of shading is also applied to add a little depth to the tiles.

I created a class called Puzzle that is derived from the UIImageView class. The makeTileAtPoint method creates a Tile object (another UIImageView class) at that location, and adds it to an array of tiles.

- (void)makeTileAtPoint:(CGPoint)point {

CGImageRef maskRef = [UIImage imageNamed:@"shading.png"].CGImage;

CGImageRef flatMaskRef = [UIImage imageNamed:@"mask.png"].CGImage;

int width = CGImageGetWidth(maskRef);

int height = CGImageGetHeight(maskRef);

UIImage* tileRectImage = [self imageFromImage:self.image inRect:CGRectMake(point.x, point.y, width, height)];

// Clip the tile (the mask is not clipping the image properly)

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

// create a bitmap graphics context the size of the image

CGContextRef mainViewContentContext = CGBitmapContextCreate (NULL, width, height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);

// free the rgb colorspace

CGColorSpaceRelease(colorSpace);

if (mainViewContentContext==NULL)

return;

// Define the mask for the tile

CGContextClipToMask(mainViewContentContext, CGRectMake(0, 0, width, height), flatMaskRef);

// Draw the tile image

CGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, width, height), tileRectImage.CGImage);

// Draw the shine and shadow for the tile

CGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, width, height), maskRef);

// Create CGImageRef of the main view bitmap content, and then

// release that bitmap context

CGImageRef mainViewContentBitmapContext = CGBitmapContextCreateImage(mainViewContentContext);

CGContextRelease(mainViewContentContext);

UIImage* tileImage = [UIImage imageWithCGImage:mainViewContentBitmapContext];

CGImageRelease(mainViewContentBitmapContext);

Tile* tile = [[Tile alloc] initWithImage:tileImage];

tile.frame = CGRectMake(point.x, point.y, width, height);

[tiles addObject:tile];

}


- (UIImage *)imageFromImage:(UIImage *)srcImage inRect:(CGRect)rect {

CGImageRef sourceImageRef = [srcImage CGImage];

CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect);

UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

CGImageRelease(newImageRef);

return newImage;

}

3 comments:

  1. This is great. Great job. Will there be a chance you might put this all together in a generic tutorial of a complete puzzle project? Possibly explaining steps on the different iphone UIimage functions you used and why?

    Thanks and great job,

    ReplyDelete
  2. Thanks. I certainly plan to have more sample code and perhaps tutorials up here, as time permits. UIImage is easy to use, but I'm running into some speed issues when I do heavy image processing (e.g. having a blur effect in the scope). I may have to do some of the heavy lifting in OpenGL ES. There's a great sample code I found on the Apple site on how to do image processing with OpenGL. (http://developer.apple.com/iphone/library/samplecode/GLImageProcessing)

    ReplyDelete
  3. Thanks. Could you give any pointer to programmatically creating the type of shading instead of using preexisting images?

    ReplyDelete