2009-03-25 4 views
8

Je veux être en mesure d'un objet UI comme un UIImageView et carreler une image à l'intérieur de celui-ci.Comment puis-je utiliser CGContextDrawTiledImage pour mettre en mosaïque une image?

J'ai été capable d'utiliser CGContextDrawTiledImage pour mettre à jour l'arrière-plan dans la fenêtre principale, mais pas une vue d'image. Je peux le faire si je modifie la fonction drawRect dans la classe MainView. Je sens que je suis proche, mais il manque toujours quelque chose. Quelqu'un peut me diriger dans la bonne 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); 

}

+1

Ceci est une question très ancienne, je sais: au cas où quelqu'un trébuche ici: vous ne devez pas surcharger drawRect de UIImageView - je pense que c'est la seule sous-classe UIView dans UIKit avec cette restriction ... –

Répondre

17

Disons que vous avez un CGImageRef pour l'image que vous voulez tuile appelé tileImage et un UIImageView appelé imageView. Ce que vous devez faire est de créer un UIImage à attribuer à la propriété image de imageView. Vous pouvez le faire comme ceci:

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

imageView.image = finishedImage; 

Cela va créer un contexte d'image bitmap de la taille désirée, la tuile l'image dans ce contexte, obtenir un UIImage hors du contexte, puis attribuez-lui au UIImageView. Vous pouvez vraiment mettre ce code n'importe où tant que la vue de l'image et l'image de la mosaïque sont chargées et prêtes à l'emploi.

2

Plutôt que d'essayer de modifier un UIImageView, considérer le sous-classement UIView à la place. UIImageView est spécialement conçu pour une image non carrelée et certains de ses composants internes peuvent vous embêter. Ce n'est pas vraiment destiné à être modifié de la manière que vous décrivez.

Dans une sous-classe de UIView (UITiledImageView?), Vous pouvez utiliser la méthode drawRect: pour faire ce que vous voulez. Vous pouvez même créer des ivars pour l'image, sa taille et ses propriétés de pavage pour plus de flexibilité et d'extensibilité.

Mise à jour avec exemple de projet: http://github.com/kailoa/6tringle-tiledimageview/tree/master

Le code de dessin concerné:

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

J'ai fait récemment en créant un UIView personnalisé.

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

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

et pour le fichier .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 vous voulez juste tuile une image dans la vue, changer à un UIView normal et paver le fond avec UIColor initWithPatternImage:

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

Je voudrais utiliser - [UIImage imageNamed:] ici, mais ouais même idée. Je pense qu'il est également possible de changer le décalage, mais je ne me souviens pas exactement. –

+1

Celui-ci est parfait. C'est assez bizarre que iOS permette à une image d'être un UIColor, mais peu importe. – jakeboxer

+16

Cela aurait une fuite. Utilisez ce 'backgroundView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: @" some_tile_image.png "]];' –

1

Désolé de ne pas savoir comment ajouter un commentaire aux réponses des autres, donc J'ai créé une nouvelle réponse ici:

Je veux juste souligner la réponse fournie par Kailoa Kadano a un bug, l'image_rect.origin n'est pas initialisé correctement.

Il y a environ 3 semaines, j'ai copié son code dans mon projet, et cela semble fonctionner. Cependant, hier, j'ai essayé d'exécuter le code dans le simulateur ios (iphone 4.3), il suffit de se bloquer dans CGContextDrawTiledImage. Après avoir ajouté la ligne suivante comme montré dans la réponse de keremk:

image_rect.origin = CGPointMake(0.0, 0.0); 

cela fonctionne à nouveau! C'est plutôt compliqué, en fait d'abord j'ai testé sous simulateur iphone 4.3, puis récemment testé sous simulateur iphone 4.0, puis hier quand je suis revenu à 4.3 simulateur ou 4.2 simulateur, le problème se produit. C'est à dire que image_rect.origin est indéfini, parfois c'est zéro donnée, parfois il y a des données aléatoires.

Questions connexes