如何使用CGContextDrawTiledImage平铺图像?

时间:2009-03-25 01:42:14

标签: iphone cocoa-touch

我希望能够像UIImageView这样的UI对象并在其中平铺图像。

我已经能够使用CGContextDrawTiledImage更新主窗口中的背景,但不能更新图像视图。如果我修改MainView类中的drawRect函数,我可以这样做。

我觉得我很亲密,但仍然缺少一些东西。有人能指出我正确的方向吗?

- (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);

}

5 个答案:

答案 0 :(得分:26)

如果您只想在视图中平铺图像,请将其更改为普通UIView并使用UIColor initWithPatternImage平铺背景:

backgroundView.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageWithContentsOfFile:[self bundlePath:@"some_tile_image.png" inDirectory:@"tiles"]]];

答案 1 :(得分:17)

假设您想要平铺的图片CGImageReftileImageUIImageViewimageView。您需要做的是创建UIImage以分配给image的{​​{1}}属性。你可以这样做:

imageView

这将创建所需大小的位图图像上下文,将图像平铺到该上下文中,从上下文中获取CGSize imageViewSize = imageView.bounds.size; UIGraphicsBeginImageContext(imageViewSize); CGContextRef imageContext = UIGraphicsGetCurrentContext(); CGContextDrawTiledImage(imageContext, (CGRect){ CGPointZero, imageViewSize }, tileImage); UIImage *finishedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); imageView.image = finishedImage; ,然后将其分配给UIImage。只要图像视图和平铺图像已加载并准备就绪,您就可以将此代码放在任何位置。

答案 2 :(得分:2)

不要试图修改UIImageView,而是考虑子类化UIView。 UIImageView专为一个非平铺图像而设计,一些内部可能会让你烦恼。它并不打算以你描述的方式进行修改。

在UIView(UITiledImageView?)的子类中,您可以使用drawRect:方法来执行您想要的操作。您甚至可以为图像,大小和平铺属性创建ivars,以获得更大的灵活性和可扩展性。

更新了示例项目:http://github.com/kailoa/6tringle-tiledimageview/tree/master

相关图纸代码:

- (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);
    }
}

答案 3 :(得分:1)

很抱歉不知道如何在其他人的答案中添加评论,所以我在这里创建了一个新答案:

我只想指出Kailoa Kadano提供的答案有错误,image_rect.origin没有正确初始化。

大约3个星期前,我在我的项目中复制了他的代码,看起来很有效。但是,昨天,我试图在ios模拟器(iphone 4.3)中运行代码,它只是挂在CGContextDrawTiledImage中。 添加以下行后,如keremk的回答所示:

image_rect.origin = CGPointMake(0.0, 0.0);

再次有效!

这是相当棘手的,实际上起初我在iphone 4.3模拟器下测试过,最近我在iphone 4.0模拟器下测试过,然后昨天当我切换回4.3模拟器或4.2模拟器时,问题就出现了。那就是image_rect.origin是未定义的,有时它是零数据,有时它可能有一些随机数据。

答案 4 :(得分:0)

我最近通过创建自定义UIView来做到这一点。

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

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

和.m文件:

@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