2011-02-12 24 views
15

Tengo una aplicación que extrae imágenes de NSURL. ¿Es posible informar a la aplicación que son versiones retina ('@ 2x') (las imágenes son de resolución retina)? Actualmente tengo el siguiente, pero las imágenes aparecen pixelated en las pantallas de mayor resolución:Imagen de URL para Retina Display

NSURL *url = [NSURL URLWithString:self.imageURL]; 
NSData *data = [NSData dataWithContentsOfURL:url]; 
UIImage *image = [UIImage imageWithData:data]; 
self.pictureImageView.image = image; 

Respuesta

11

Intente utilizar imageWithData:scale: (iOS 6 y versiones posteriores)

NSData *imageData = [NSData dataWithContentsOfURL:url]; 
UIImage *image = [UIImage imageWithData:imageData scale:[[UIScreen mainScreen] scale]]; 
+0

También funciona para 3x imágenes? (Supongo que sí debido a la escala '[UIScreen mainScreen]]] – androniennn

0

@ 2x convención es sólo forma conveniente para cargar las imágenes de paquete de aplicaciones. Si quieres probar para ver la imagen en la pantalla de la retina entonces usted tiene que hacerlo 2 veces más grande:

Tamaño de imagen 100x100

Ver tamaño: 50x50.

Editar: Creo que si va a cargar imágenes desde un servidor la mejor solución sería añadir un poco de parámetro adicional (por ejemplo escala) y las imágenes del tamaño adecuado retorno:

www.myserver.com/get_image.php?image_name=img.png&scale=2 

Puede obtener escala utilizando [ [Escala UIScreen mainScreen]]

17

Debe volver a escalar el UIImage antes de agregarlo a la vista de imagen.

NSURL *url = [NSURL URLWithString:self.imageURL]; 
NSData *data = [NSData dataWithContentsOfURL:url]; 
UIImage *image = [UIImage imageWithData:data]; 
CGFloat screenScale = [UIScreen mainScreen].scale; 
if (image.scale != screenScale) 
    image = [UIImage imageWithCGImage:image.CGImage scale:screenScale orientation:image.imageOrientation]; 
self.pictureImageView.image = image; 

Es mejor evitar la codificación forzada del valor de escala, por lo tanto, la llamada UIScreen. Consulte la documentación de Apple en UIImage’s scale property para obtener más información acerca de por qué es necesario.

También es mejor evitar el método NSData-dataWithContentsOfURL: (a menos que su código se esté ejecutando en una cadena de fondo), ya que utiliza una llamada de red síncrona que no puede monitorearse o cancelarse. Puede leer más sobre los problemas de las redes sincrónicas y las formas de evitarlo en this Apple Technical Q&A.

+0

Gracias! ¡Parece justo lo que estaba buscando! –

+0

Esto ya no funciona en iOS7. Ver la respuesta de n13 a continuación, que funciona. Además, consulte la respuesta aceptada aquí: http://stackoverflow.com/questions/5518790/downloading-normal-image-vs-retina-device-image-2x – RajV

1

Solo para agregar a esto, lo que hice específicamente fue lo siguiente, en la misma situación, funciona como un encanto.

double scaleFactor = [UIScreen mainScreen].scale; 
     NSLog(@"Scale Factor is %f", scaleFactor); 
     if (scaleFactor==1.0) { 
      [cell.videoImageView setImageWithURL:[NSURL URLWithString:regularThumbnailURLString]; 
     }else if (scaleFactor==2.0){ 
      [cell.videoImageView setImageWithURL:[NSURL URLWithString:retinaThumbnailURLString]; 
     } 
5

Debe configurar la escala en el UIImage.

UIImage* img = [[UIImage alloc] initWithData:data]; 
CGFloat screenScale = [UIScreen mainScreen].scale; 
if (screenScale != img.scale) { 
    img = [UIImage imageWithCGImage:img.CGImage scale:screenScale orientation:img.imageOrientation]; 
} 

La documentación dice que tener cuidado para construir todas sus UIImages a la misma escala, de lo contrario podría obtener problemas de visualización extraños donde las cosas se muestran en la talla media, de dos plazas, la mitad de resolución, etcétera. Para evitar todo eso, carga todos los UIImages a la resolución de la retina. Los recursos se cargarán automáticamente en la escala correcta. Para UIImages construidos a partir de datos de URL, debe configurarlo.

0
+ (void)deviceScaledImageForView:(UIImageView*)v 
     withParameterizedUrl:(NSString*)url 
       iPadSupport:(BOOL)iPadSupport 
         after:(UITask)after 
{ 

// ...Declare Retina and Retina Plus versions of the the URL string... 
NSString* url2x = @""; 
NSString* url3x = @""; 

// ...And if I'm on an iPad with my caller allowing iPad-specific images... 
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && iPadSupport) { 
    // ...Generate the iPad non-retina and retina versions of the URL... 
    /* Note 3x is not applicable to iPad */ 
    url = [url stringByReplacingOccurrencesOfString:@".png" withString:@"~ipad.png"]; 
    url2x = [url stringByReplacingOccurrencesOfString:@"~ipad.png" withString:@"@2x~ipad.png"]; 
} 
// ...Or, for iPhone... 
else { 
    // ...Generate the iPhone non-Retina, Retina and Retina Plus versions of the URL... 
    url2x = [url stringByReplacingOccurrencesOfString:@".png" withString:@"@2x.png"]; 
    url3x = [url stringByReplacingOccurrencesOfString:@".png" withString:@"@3x.png"]; 
} 

// ...If I'm running on iOS 7.1 or newer... 
CGFloat scale = .0f; 
UIScreen* screen = [UIScreen mainScreen]; 
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) 
    // ...Choose a scale based on the iOS 8 API. 

    //currently the scale for the 6 plus ranges from 2.6 to 2.8 to 3.0 depending on zoomed mode or running on the sim 
    // since our images are at 2x or at 3x we want whole numbers. 
    scale = ceilf(screen.nativeScale); 
else 
    // ...Choose a device scale on the iOS 7 API. 
    scale = screen.scale; 

// ...If I've chosen a Retina Plus scale... 
if (scale > 2.0f){ 
    // ...Select the 3x Retina Plus version of the image. 
    url = url3x; 
} 

// ...Otherwise for retina displays... 
else if (scale == 2.0f) 
    // ...Select the Retina version of the image. 
    url = url2x; 

// ...And finally, request the image data with SDWebImage (for cache support)... 
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:url] 
                 options:SDWebImageDownloaderUseNSURLCache 
                progress:nil 
                completed:^(UIImage* i, 
                   NSData* d, 
                   NSError* e, 
                   BOOL finished) 
{ 
    // ...And after the image is obtained... 
    // ...Apply it to the image view with the correct device scale... 
    v.image = [UIImage imageWithData:d scale:scale]; 

    // ...And if I have an after-action... 
    if (after) 
     // ...Run it. 
     after(); 
}]; 

} 
0

A decir iPhone mediante programación esa imagen en particular es Retina, se puede hacer algo como esto:

UIImage *img = [self getImageFromDocumentDirectory]; 
img = [UIImage imageWithCGImage:img.CGImage scale:2 orientation:img.imageOrientation]; 

En mi caso, la imagen TabBarItem era dinámica, es decir, que se estaba descargando del servidor. Entonces el iOS no puede identificarlo como retina. El fragmento de código anterior funcionó para mí como un amuleto.

Cuestiones relacionadas