来自Retina Display的URL的图像

时间:2011-02-12 02:51:32

标签: objective-c cocoa-touch ios

我有一个应用程序从NSURL中提取图像。是否可以通知应用程序它们是视网膜('@ 2x')版本(图像是视网膜分辨率)?我目前有以下内容,但图像在更高分辨率的显示屏上显示为像素化:

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

7 个答案:

答案 0 :(得分:17)

在将UIImage添加到图像视图之前,需要重新缩放UIImage。

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;

最好避免对比例值进行硬编码,从而调用UIScreen。有关为何需要这些内容的详细信息,请参阅Apple UIImage’s scale property上的文档。

最好避免使用NSData的{​​{1}}方法(除非您的代码在后台线程上运行),因为它使用无法监视或取消的同步网络调用。您可以在this Apple Technical Q&A中阅读有关同步网络的痛苦以及避免它的方法的更多信息。

答案 1 :(得分:11)

尝试使用imageWithData:scale:(iOS 6及更高版本)

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

答案 2 :(得分:5)

您需要在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];
}

文档说要小心以相同的比例构建所有UIImages,否则你可能会遇到奇怪的显示问题,其中显示的是一半大小,双倍大小,半分辨率等等。为避免这一切,请在视网膜分辨率下加载所有UIImages。资源将自动以正确的比例加载。对于根据URL数据构建的UIImages,您需要进行设置。

答案 3 :(得分:1)

只是为了补充一点,我所做的具体如下,在同样的情况下,就像魅力一样。

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];
        }

答案 4 :(得分:0)

@ 2x约定只是从应用程序包加载图像的便捷方式。 如果你不想在视网膜显示器上显示图像,那么你必须使它大2倍:

图片尺寸100x100

查看尺寸:50x50。

编辑:我认为如果您从服务器加载图像,最好的解决方案是添加一些额外的参数(例如缩放)并返回适当大小的图像:

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

您可以使用[[UIScreen主屏幕]比例]

获取比例

答案 5 :(得分: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();
 }];

}

答案 6 :(得分:0)

要以编程方式告诉iPhone特定图片 Retina ,您可以执行以下操作:

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

在我的情况下,TabBarItem图像是动态的,即从服务器下载的图像。然后iOS无法将其识别为视网膜。上面的代码片段对我来说就像一个魅力。