2009-03-25 21 views
8

Quiero ser capaz de un objeto UI como un UIImageView y colorear una imagen dentro de él.¿Cómo puedo usar CGContextDrawTiledImage para colocar una imagen en mosaico?

He podido usar CGContextDrawTiledImage para actualizar el fondo en la ventana principal, pero no en una vista de imagen. Puedo hacer esto si modifico la función drawRect dentro de la clase MainView.

Siento que estoy cerca, pero aún me falta algo. ¿Alguien me puede apuntar en la dirección correcta?

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

}

+1

Esta es una pregunta muy antigua, lo sé: en caso de que alguien tropiece aquí: no debe anular drawRect de UIImageView: creo que es la única subclase de UIView en UIKit con esta restricción ... –

Respuesta

17

Digamos que tienes un CGImageRef para la imagen que desea baldosas llamada tileImage y una llamada UIImageViewimageView. Lo que necesita hacer es crear un UIImage para asignar a la propiedad image de imageView. Puede hacerlo de esta manera:

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

imageView.image = finishedImage; 

Esto creará un contexto mapa de bits del tamaño deseado, colocar la imagen en ese contexto, obtener una UIImage fuera del contexto, a continuación, asignar a la UIImageView. Realmente puede colocar este código en cualquier lugar siempre que la vista de la imagen y la imagen del mosaico estén cargadas y listas para funcionar.

2

lugar de tratar de modificar un UIImageView, consideran como subclase UIView lugar. UIImageView está diseñado específicamente para una imagen sin mosaico y algunas de las partes internas pueden estar ensuciándolo. En realidad, no tiene la intención de ser modificado de la manera que describes.

En una subclase de UIView (UITiledImageView?) Puede utilizar el método drawRect: para hacer lo que desee. Incluso puede crear ivars para la imagen, su tamaño y propiedades de mosaico para una mayor flexibilidad y extensibilidad.

Actualizado con proyecto de ejemplo: http://github.com/kailoa/6tringle-tiledimageview/tree/master

El código de disposición correspondiente:

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

poco hice esto creando una UIView personalizado.

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

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

y para el archivo .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 
26

Si lo que desea es baldosas de una imagen en la vista, cambiarlo a un UIView normal y baldosas del fondo con UIColor initWithPatternImage:

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

Usaría - [UIImage imageNamed:] aquí, pero sí la misma idea. Creo que es posible cambiar el desplazamiento también, pero no recuerdo exactamente. –

+1

Este es perfecto. Es bastante extraño que iOS permita que una imagen sea un UIColor, pero lo que sea. – jakeboxer

+16

Eso se filtraría. Use esto 'backgroundView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: @" some_tile_image.png "]];' –

1

Lo siento por no saber cómo añadir comentarios a las respuestas de otros por lo que, Creé una nueva respuesta aquí:

Solo quiero señalar que la respuesta proporcionada por Kailoa Kadano tiene un error, el image_rect.origin no se inicializó correctamente.

Hace alrededor de 3 semanas, copié su código en mi proyecto, y parece funcionar. Sin embargo, ayer, traté de ejecutar el código en el simulador ios (iphone 4.3), simplemente cuelgo en CGContextDrawTiledImage. Después de añadir la siguiente línea como demostró en la respuesta de keremk:

image_rect.origin = CGPointMake(0.0, 0.0); 

funciona de nuevo!

Es bastante complicado, en realidad al principio probé con el simulador de iPhone 4.3, luego probé con el simulador de iPhone 4.0, ayer cuando cambié de nuevo a 4.3 simulador o 4.2 simulador, el problema ocurre. Es decir, image_rect.origin no está definido, a veces son datos cero, a veces puede tener algunos datos aleatorios.

Cuestiones relacionadas