2009-06-02 7 views
7

J'ai une norme UITableViewCell où j'utilise les propriétés du texte et de l'image pour afficher un favicon.ico et une étiquette. Pour la plupart, cela fonctionne très bien puisque UIImage prend en charge le format ICO. Cependant, certains sites (par exemple Amazon.com) ont favicon.ico s qui utilisent la capacité du format ICO pour stocker plusieurs tailles dans le même fichier. Amazon stocke quatre tailles différentes, jusqu'à 48x48. Il en résulte que la plupart des images sont en 16x16 à l'exception de quelques-unes qui arrivent en 32x32 ou 48x48 et qui donnent l'impression que tout est horrible. J'ai cherché ici, le forum officiel, la documentation, et ailleurs sans succès. J'ai essayé tout ce que je pouvais penser pour contraindre la taille de l'image. La seule chose qui a fonctionné était une méthode non documentée, que je ne suis pas sur le point d'utiliser. Ceci est ma première application et ma première expérience avec Cocoa (est venu de C#). Dans le cas où je n'étais pas clair dans ce que je cherchais, idéalement, le conseil se concentrerait sur le réglage des dimensions de la UIImage afin que la version 48x48 atteigne une échelle de 16x16 ou une méthode pour dire UIImage d'utiliser le Version 16x16 présente dans le fichier ICO. Je n'ai pas nécessairement besoin de code: juste une suggestion d'une approche me ferait du bien.Définition des dimensions UIImage sur l'image UITableViewCell

Quelqu'un a-t-il des suggestions? (J'ai demandé dans le forum officiel as well parce que je suis déjà tombé plus d'un jour là-dessus.Si une solution est postée là, je vais le mettre ici aussi.)

Répondre

23

Voici ce que l'utilisateur « bcd » sur les forums officiels posted qui ont fini par résoudre le problème (avec une légère modification par moi-même pour le rendre statique à inclure dans un ensemble de méthodes utilitaires):

+ (UIImage *)scale:(UIImage *)image toSize:(CGSize)size 
{ 
    UIGraphicsBeginImageContext(size); 
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; 
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return scaledImage; 
} 
+0

La version de BCD était une catégorie sur 'UIImage', ce qui est beaucoup plus logique que ce que j'ai fait ici. – bbrown

+0

Merci pour votre réponse, fonctionne parfaitement –

0

Je ne sais pas comment Les fichiers ico fonctionnent, alors il est peut-être possible d'extraire facilement l'image 16x16 et de l'utiliser, mais je n'ai aucune idée de comment. Pour autant que je sache, il n'est pas possible de définir des propriétés utiles sur l'image générique. Le moyen le plus simple (encore en désordre, surtout si vous êtes nouveau) de redimensionner tout en 16x16 serait de sous-classer UITableViewCell, de lui donner un UIImageView, de toujours redimensionner l'image en 16x16, et de définir son contentMode sur UIViewContentModeAspectFit.

+0

J'ai essayé cette approche et cela n'a pas fonctionné, mais je me suis probablement trompé. – bbrown

4

Je fais quelque chose de similaire dans mon application.

UIImage* resizedImage(UIImage *inImage, CGRect thumbRect) 
{ 
    CGImageRef   imageRef = [inImage CGImage]; 
    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef); 

    if (alphaInfo == kCGImageAlphaNone) 
     alphaInfo = kCGImageAlphaNoneSkipLast; 

    CGContextRef bitmap = CGBitmapContextCreate (NULL, thumbRect.size.width, thumbRect.size.height, 8, thumbRect.size.width*3, 
                       CGColorSpaceCreateDeviceRGB(), alphaInfo); 

    CGContextDrawImage(bitmap, thumbRect, imageRef); 

    CGImageRef ref = CGBitmapContextCreateImage(bitmap); 
    UIImage* result = [UIImage imageWithCGImage:ref]; 

    CGContextRelease(bitmap); 
    CGImageRelease(ref); 

    return result; 
} 

Créez ensuite une nouvelle image en limitant les proportions. Remplacer "image" avec le fichier ICO que vous obtenez d'Amazon.

CGRect sz = CGRectMake(0.0f, 0.0f, 16, 16); 
UIImage *resized = resizedImage(image, sz); 
+0

Pour une raison ou une autre, votre code générait beaucoup d'erreurs CoreGraphics pour moi. Cela pourrait être un problème avec le format ICO. C'est une bonne réponse cependant. – bbrown

+1

Ont-ils compilé/lié des erreurs? Je ne pense pas que Xcode soit lié par défaut à l'infrastructure CoreGraphics pour les nouveaux projets, vous devrez donc ajouter cela et l'instruction @import correspondante. –

+1

Oui, vous devez créer un lien vers le framework CoreGraphics. Si ce n'était pas le cas, vous auriez ces erreurs. –

1

Je n'ai pas encore assez de karma pour commenter les réponses, mais j'ai eu un bon succès avec le code bbrandons ci-dessus. J'ai reçu un bon nombre d'avertissements sur la console mais en considérant que le nombre d'octets par ligne n'était pas assez élevé - après avoir lu les réponses post j'ai fini par le mettre à 0, ce qui permet au système de déterminer la bonne valeur.

par exemple:

CGContextRef bitmap = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, CGColorSpaceCreateDeviceRGB(), alphaInfo); 
+0

Si vous avez réclamé 8 bits par composant, c'est 1 octet par composant. La réponse de brandon empêche 'kCGImageAlphaNone', donc, pour un espace colorimétrique RVB, il y a toujours quatre composants (trois couleurs, plus alpha). C'est 1 × 4 = 4 octets par pixel. Ainsi, lui et vous devez multiplier la largeur (pixels par ligne) par 4, pas 3. Passer 0 n'est pas documenté pour fonctionner, donc vous ne devriez probablement pas compter dessus et ne pas utiliser cette astuce ou fichier bogue de documentation demandant qu'il soit documenté: https://bugreport.apple.com –

+0

Merci pour votre description des calculs Peter, a du sens - Je vais aussi déposer un bug de documentation pour le calcul automatique aussi. – crafterm

1

Voilà comment je l'ai fait.Cette technique prend soin de déplacer le texte et les étiquettes texte de détail de manière appropriée à la gauche:

@interface SizableImageCell : UITableViewCell {} 
@end 
@implementation SizableImageCell 
- (void)layoutSubviews { 
    [super layoutSubviews]; 

    float desiredWidth = 80; 
    float w=self.imageView.frame.size.width; 
    if (w>desiredWidth) { 
     float widthSub = w - desiredWidth; 
     self.imageView.frame = CGRectMake(self.imageView.frame.origin.x,self.imageView.frame.origin.y,desiredWidth,self.imageView.frame.size.height); 
     self.textLabel.frame = CGRectMake(self.textLabel.frame.origin.x-widthSub,self.textLabel.frame.origin.y,self.textLabel.frame.size.width+widthSub,self.textLabel.frame.size.height); 
     self.detailTextLabel.frame = CGRectMake(self.detailTextLabel.frame.origin.x-widthSub,self.detailTextLabel.frame.origin.y,self.detailTextLabel.frame.size.width+widthSub,self.detailTextLabel.frame.size.height); 
     self.imageView.contentMode = UIViewContentModeScaleAspectFit; 
    } 
} 
@end 

... 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[SizableImageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; 
     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
    } 

    cell.textLabel.text = ... 
    cell.detailTextLabel.text = ... 
    cell.imageView.image = ... 
    return cell; 
} 
0

J'ai modifié la catégorie des gens d'autres, afin de rendre toutes les images occupent la même largeur (largeur visible), SANS ECHELLE:

-(UIImage*) centerImage:(UIImage *)inImage inRect:(CGRect) thumbRect 
{ 

    CGSize size= thumbRect.size; 
    UIGraphicsBeginImageContext(size); 
    //calculation 
    [inImage drawInRect:CGRectMake((size.width-inImage.size.width)/2, (size.height-inImage.size.height)/2, inImage.size.width, inImage.size.height)]; 
    UIImage *newThumbnail = UIGraphicsGetImageFromCurrentImageContext();   
    // pop the context 
    UIGraphicsEndImageContext(); 
    return newThumbnail; 
} 
Questions connexes