views:

2647

answers:

4

I want to be able to an UI object like a UIImageView and tile an image inside of it.

I have been able to use CGContextDrawTiledImage to update the background in the main window, but not an image view. I can do this if I modify the drawRect function inside the MainView class.

I feel I'm close, but still missing something. Can someone point me in the right direction?

- (void)drawRect:(CGRect)rect {

CGImageRef image = CGImageRetain(currentImage.CGImage);

CGRect imageRect;
imageRect.origin = CGPointMake(160, 240);
imageRect.size = CGSizeMake(320.0, 480.0);

CGContextRef uiContext = UIGraphicsGetCurrentContext();

CGContextClipToRect(uiContext, CGRectMake(0.0, 0.0, rect.size.width, rect.size.height));

CGContextDrawTiledImage(uiContext, imageRect, image);

}

+2  A: 

Rather than trying to modify a UIImageView, consider subclassing UIView instead. UIImageView is specifically designed for one non-tiled image and some of the internals may be messing you up. It's not really intended to be modified in the way you describe.

In a subclass of UIView (UITiledImageView?) you can use the drawRect: method to do what you want. You can even create ivars for the image, its size and tiling properties for greater flexibility and extensibility.

Updated with sample project: http://github.com/kailoa/6tringle-tiledimageview/tree/master

The relevant drawing code:

- (void)drawRect:(CGRect)rect 
{
    if (TiledImage) {

        //Since we are retaining the image, we append with ret_ref.  this reminds us to release at a later date.
        CGImageRef image_to_tile_ret_ref = CGImageRetain(TiledImage.CGImage); 

        CGRect image_rect;
        image_rect.size = TiledImage.size;  //This sets the tile to the native size of the image.  Change this value to adjust the size of an indivitual "tile."

        CGContextRef context = UIGraphicsGetCurrentContext();

        CGContextDrawTiledImage(context, image_rect, image_to_tile_ret_ref);

        CGImageRelease(image_to_tile_ret_ref);
    }
}
Kailoa Kadano
A: 

I recently did this by creating a custom UIView.

@interface TiledImageView : UIView {
@private
    UIImage *image_;
}

@property (nonatomic, retain) UIImage *image;
@end

and for the .m file:

@implementation TiledImageView
@synthesize image = image_;

- (void)dealloc {
    [image_ release];
    [super dealloc];
}

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Initialization code
     self.image = [UIImage imageNamed:@"BGTile.png"];

    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    // Drawing code
    CGImageRef image = CGImageRetain(image_.CGImage);

    CGRect imageRect;
    imageRect.origin = CGPointMake(0.0, 0.0);
    imageRect.size = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));

    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextClipToRect(context, CGRectMake(0.0, 0.0, rect.size.width, rect.size.height)); 
    CGContextDrawTiledImage(context, imageRect, image);
    CGImageRelease(image);
}

@end
keremk
A: 

Let's say you've got a CGImageRef for the image you want to tile called tileImage and a UIImageView called imageView. What you need to do is create a UIImage to assign to the image property of imageView. You can do that like this:

CGSize imageViewSize = imageView.bounds.size;
UIGraphicsBeginImageContext(imageViewSize);
CGContextRef imageContext = UIGraphicsGetCurrentContext();
CGContextDrawTiledImage(imageContext, (CGRect){ CGPointZero, imageViewSize }, tileImage);
UIImage *finishedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

imageView.image = finishedImage;

This will create a bitmap image context of the desired size, tile the image into that context, get a UIImage out of the context, then assign it to the UIImageView. You can really put this code anywhere so long as the image view and tile image are loaded and ready to go.

Alex
+3  A: 

If you just want to tile an image in the view, change it to a normal UIView and tile the background with UIColor initWithPatternImage:

backgroundView.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageWithContentsOfFile:[self bundlePath:@"some_tile_image.png" inDirectory:@"tiles"]]];
Chris Blackwell
I would use -[UIImage imageNamed:] here, but yeah same idea. I think it's possible to change the offset as well, but don't recall exactly.
Andrew Pouliot
This one is perfect. It's pretty weird that iOS allows an image to be a UIColor, but whatever.
jboxer