Question

Comme beaucoup de gens se plaignent, il semble que dans le SDK d'Apple pour l'écran Retina il y a un bug et imageWithContentsOfFile ne fait charge pas automatiquement les images 2x.

J'ai trébuché dans une belle après comment faire une fonction qui détecte le facteur d'échelle UIScreen et correctement des charges faibles ou des images haute résolution ( http://atastypixel.com/blog/uiimage-resolution-independence-and-the-iphone-4s-retina-display/ ), mais les charges de solution une image 2x et a encore le facteur d'échelle de l'image ensemble à 1,0 et ce résultat à un 2x images redimensionnées 2 fois (donc, 4 fois plus grand que ce qu'il doit ressembler)

imageNamed semble charger avec précision des images basse résolution et haute, mais aucune option pour moi.

Est-ce que quelqu'un a une solution pour les images de chargement de bas / haut res ne pas utiliser le chargement automatique de imageNamed ou imageWithContentsOfFile? (Ou éventuellement solution comment faire le travail de imageWithContentsOfFile correct)

Était-ce utile?

La solution

Ok, solution réelle trouvée par Michael ici: http://atastypixel.com/blog/ UIImage résolution indépendance-et-les-iphone-4-affichage Retina /

Il a compris que UIImage a la méthode « initWithCGImage » qui prend également un facteur d'échelle en entrée (je suppose que la seule méthode où vous pouvez définir vous-même le facteur d'échelle)

[UIImage initWithCGImage:scale:orientation:]

Et cela semble fonctionner très bien, vous pouvez charger vos images sur mesure haute résolution et vient de mettre que le facteur d'échelle est de 2,0

Le problème avec imageWithContentsOfFile est que puisqu'il actuellement ne fonctionne pas correctement, nous ne pouvons pas faire confiance même quand il est fixe (parce que certains utilisateurs auront toujours un iOS sur leurs anciens appareils)

Autres conseils

Je viens de croiser ce ici au travail. Voici mon travail autour qui semble contenir de l'eau:

NSString *imgFile = ...path to your file;
NSData *imgData = [[NSData alloc] initWithContentsOfFile:imgFile];
UIImage *img = [[UIImage alloc] initWithData:imgData];

imageWithContentsOfFile fonctionne correctement (considérant @ 2x images avec la bonne échelle) à partir iOS 4.1 et au-delà.

J'ai développé une goutte en solution pour ce problème. Il utilise la méthode swizzling pour remplacer le comportement du « imageWithContentsOfFile: » méthode de UIImage. Il fonctionne très bien sur les iPhones / iPods pré / post rétine. Vous ne savez pas sur l'iPad.

Espérons que cela est utile.

#import </usr/include/objc/objc-class.h>

@implementation NSString(LoadHighDef)

/** If self is the path to an image, returns the nominal path to the high-res variant of that image */
-(NSString*) stringByInsertingHighResPathModifier {

     NSString *path = [self stringByDeletingPathExtension];

     // We determine whether a device modifier is present, and in case it is, where is 
     // the "split position" at which the "@2x" token is to be added
     NSArray  *deviceModifiers = [NSArray arrayWithObjects:@"~iphone", @"~ipad", nil];
     NSInteger splitIdx = [path length];
     for (NSString *modifier in deviceModifiers) {
          if ([path hasSuffix:modifier]) {
               splitIdx -= [modifier length];
               break;
          }
     }

     // We insert the "@2x" token in the string at the proper position; if no 
     // device modifier is present the token is added at the end of the string
     NSString *highDefPath = [NSString stringWithFormat:@"%@@2x%@",[path substringToIndex:splitIdx], [path substringFromIndex:splitIdx]];

     // We possibly add the extension, if there is any extension at all
     NSString *ext = [self pathExtension];
     return [ext length]>0? [highDefPath stringByAppendingPathExtension:ext] : highDefPath;
}

@end

@implementation UIImage (LoadHighDef)

/* Upon loading this category, the implementation of "imageWithContentsOfFile:" is exchanged with the implementation
 * of our custom "imageWithContentsOfFile_custom:" method, whereby we replace and fix the behavior of the system selector. */
+(void)load {
     Method originalMethod    = class_getClassMethod([UIImage class], @selector(imageWithContentsOfFile:));
     Method replacementMethod = class_getClassMethod([UIImage class], @selector(imageWithContentsOfFile_custom:));
     method_exchangeImplementations(replacementMethod, originalMethod);
}

/** This method works just like the system "imageWithContentsOfFile:", but it loads the high-res version of the image 
 *  instead of the default one in case the device's screen is high-res and the high-res variant of the image is present.
 *
 *  We assume that the original "imageWithContentsOfFile:" implementation properly sets the "scale" factor upon 
 *  loading a "@2x" image . (this is its behavior as of OS 4.0.1).
 *
 *  Note: The "imageWithContentsOfFile_custom:" invocations in this code are not recursive calls by virtue of 
 *  method swizzling. In fact, the original UIImage implementation of "imageWithContentsOfFile:" gets called.
 */

+ (UIImage*) imageWithContentsOfFile_custom:(NSString*)imgName {

     // If high-res is supported by the device...
     UIScreen *screen = [UIScreen mainScreen];
     if ([screen respondsToSelector:@selector(scale)] && [screen scale]>=2.0) {

          // then we look for the high-res version of the image first
          UIImage  *hiDefImg = [UIImage imageWithContentsOfFile_custom:[imgName stringByInsertingHighResPathModifier]];

          // If such high-res version exists, we return it
          // The scale factor will be correctly set because once you give imageWithContentsOfFile:
          // the full hi-res path it properly takes it into account 
          if (hiDefImg!=nil)
               return hiDefImg;
     }

     // If the device does not support high-res of it does but there is
     // no high-res variant of imgName, we return the base version
     return [UIImage imageWithContentsOfFile_custom:imgName];
}

@end

La réponse de Lisa Améliorer Rossellis de garder les images de la rétine à la taille désirée (pas les plus grande échelle):

NSString *imagePath = ...Path to your image
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfFile:imagePath] scale:[UIScreen mainScreen].scale];

[UIImage imageWithContentsOfFile:] ne se charge pas @ 2x graphiques si vous spécifiez un chemin absolu.

Voici une solution:

- (UIImage *)loadRetinaImageIfAvailable:(NSString *)path {

    NSString *retinaPath = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@@2x.%@", [[path lastPathComponent] stringByDeletingPathExtension], [path pathExtension]]];

    if( [UIScreen mainScreen].scale == 2.0 && [[NSFileManager defaultManager] fileExistsAtPath:retinaPath] == YES) 
        return [[[UIImage alloc] initWithCGImage:[[UIImage imageWithData:[NSData dataWithContentsOfFile:retinaPath]] CGImage] scale:2.0 orientation:UIImageOrientationUp] autorelease];
    else
        return [UIImage imageWithContentsOfFile:path];
}

Le crédit va à Christof Dorner sa solution simple (que je modifiée et collé ici).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top