在iPhone中使用JPG图像和2x图像

22

我正在开发一个iPhone应用,目标是iOS 4.0或更高版本。我想向UIImageView添加一张JPEG格式的图片。目前我已经完成了以下步骤...

UIImageView *bgImageView            =   [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 246.0)];
bgImageView.image                   =   [UIImage imageNamed:@"background"];
[self.view addSubview:bgImageView];
[bgImageView release];

我添加了两个图片,

  1. background.jpg(普通1x图像)
  2. background@2x.jpg(适用于2x / retina显示的图像)。

但是当我构建和运行时,一切都正常运行,除了没有背景。我的所有其他小部件都在那里,但有一个白色背景,并且图像没有显示。

接下来,我为我的背景创建了两个png图像,将其添加到项目中并运行。这次我的背景被显示出来了。我感到困惑,因为根据文档,jpg图像可以在iPhone上使用UIImage。

我再次尝试使用我的jpg图像,并将上面的代码更改为:

UIImageView *bgImageView            =   [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 246.0)];
bgImageView.image                   =   [UIImage imageNamed:@"background.jpg"]; //added extension
[self.view addSubview:bgImageView];
[bgImageView release];

当我运行上面的代码时,背景图片显示出来了,但是2x图片没有加载。这说明我的jpg图片没问题,不是罪魁祸首。所以当我只给出图片名称而不带扩展名时,在相应的设备上会加载png文件(1x和2x),而根本不会加载jpg文件。 看起来像是一个bug(无论是sdk还是文档)。iOS 4已经好几年了,为什么没有人注意到呢?除了将所有图片转换为png之外,我还有其他选择吗?
编辑:
好吧,问题已经过去两天了,没有答案。我已经将所有的图片都转换成了png,我的项目也完成了(因为我的项目不能等待...)。不过,为了自己和未来遇到这个问题的人,我想更多地了解这个问题。至少有人可以确认这确实是苹果的一个bug。我开始设置赏金,以便更多的人可以看到这个线程。
再次编辑:
离这个赏金结束还有2天。感谢所有回答的人。但是让我澄清一件事情。我已经说过我已经将所有的图片都转换成了png,并且继续前进。我只想确认imageNamed是否以相同的方式处理jpg和png文件。文档肯定会这样说(除非苹果在UIImage文档之外的其他地方写了),如果文档是正确的,那么我的代码失败了,有两个可能的原因。
  1. imageNamed中存在一个错误。如果这是原因,那么我除了提交错误报告、将我的图片更改为png或编写一个包装器(就像Chandan在他的答案中所说的那样)并继续前进之外,没有太多的选择。
  2. 我使用的jpeg图像存在一些问题。好吧,我不是一个photoshop专家。但我使用了RGBA jpg图像。如果图像确实有问题,我准备询问我的设计师朋友并提供更多信息。

还有一件事。这篇文章只是讲述了这个问题。但他不知道背后的原因。所以我不是孤单的。

编辑:结束

嗯,这与图像本身有关。我谷歌搜索并下载了一些示例jpeg图像并进行了测试。其中一些显示正确,而另一些则没有。由于时间限制已到,我将把边界交给PengOne,他尝试重现了这个错误并成功加载了没有扩展名的jpg图像,从而让我使用更多的图像。感谢每个试图帮助我的人。


1
我认为在移动设备上显示图像时,PNG格式更好 - 它们体积小,支持alpha通道且不需要压缩。而且也没有@2x的问题。 :) - akashivskyy
1
为什么你想要使用jpg格式呢?在iOS上,尽可能使用png格式更好。编辑:Kashiv更快一步了。 :) 我会选择批量转换器... - Eiko
1
此外,对于iOS推荐使用png格式的图片,因为在编译时,苹果会进行一些“优化”处理,使得png图片在设备加载时更高效。但这些优化处理也会导致该png图片在其他设备上无法查看。Jeff Lamarche在这里讨论了这个问题:http://iphonedevelopment.blogspot.com/2008/10/iphone-optimized-pngs.html - Paul.s
1
你是如何生成你的@2x jpg图像的?似乎微小的像素变化会影响到事情...这里有一个关于这个主题的好文章http://globalmoxie.com/blog/designing-for-iphone4-retina-display.shtml。始终缩小,取@2x图像,将其调整为50%并将其用作1x图像,对我总是有效。 - Santthosh
1
我也遇到过将2x文件和1x文件存储在不同文件夹中时出现问题。使用相同的图像,分开的文件夹会导致2x的使用效果不佳,而放在同一个文件夹中则完美运行...真是匪夷所思。 - Steven Veltema
显示剩余5条评论
5个回答

11
根据UIImage类的参考文档:

讨论

此方法在系统缓存中查找指定名称的图像对象,并返回该对象(如果存在)。如果匹配的图像对象尚未在缓存中,则此方法从指定文件加载图像数据,缓存它,然后返回生成的对象。

在运行iOS 4或更高版本的设备上,如果设备的屏幕比例为1.0,则行为相同。 如果屏幕比例为2.0,则此方法首先搜索具有相同文件名且附加了@2x后缀的图像文件。例如,如果文件名为button,则首先搜索button@2x。 如果找到2x,则加载该图像并将返回的UIImage对象的比例属性设置为2.0。否则,它会加载未修改的文件名并将比例属性设置为1.0。有关支持具有不同比例因素的图像的详细信息,请参见iOS应用程序编程指南。特殊

注意事项

在iOS 4及更高版本中,文件名不需要指定文件名扩展名。在iOS 4之前,必须指定文件名扩展名。

由于您的目标是iOS 4.0及更高版本,因此不需要文件名扩展名。 我尝试重现此潜在的错误,但在没有文件名扩展名的情况下,它按预期工作。

以下是可能导致应用程序出现此效果的原因:

  1. 如果您在某个时候更改了图像,则可能问题来自缓存。

  2. 如果您选择不使用文件名扩展名,并且同时有"background.jpg"和"background.png"作为选项,则似乎优先使用".png"文件。

  • 如果您在首次运行应用后将目标设置为iOS 4.0及更高版本,则需要使用文件名扩展名,图像可能会被缓存为空白,这将导致回到理论1。


  • 我尝试重现这个潜在的错误,但是对我来说,没有文件名扩展名的情况下它按预期工作。你的意思是说你成功地使用了jpg图像而没有文件名扩展名?那么这一定是我的图像出了问题。 - Krishnabhadra
    如果在首次运行应用后将目标设置为iOS 4.0及更高版本,则需要文件名扩展名并且图像可能会被缓存为空白。从项目开始,针对iOS 4.0及更高版本进行了定位。此外,我所有其他的图像(都是PNG格式)一开始就没有加扩展名,并且它们工作得很好。(但要注意我以前从未构建过针对4.0以下版本的应用程序)。 - Krishnabhadra
    @krishnabhadra...是的,我开始使用没有扩展名的jpg文件,它们能够正常加载。我没有使用png文件和任何复杂的内容(只是为了测试而创建的虚拟应用)。非常奇怪。 - PengOne

    7
    编写一个包装器来获取图像,如下所示:
    -(UIImage*) getImage:(NSString*)imageName{
    
        UIImage *image;
    
        if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES && [[UIScreen mainScreen] scale] == 2.00) {
    
            // RETINA DISPLAY
            NSString *jpegFile = [imageName stringByAppendingString:@"@2x.jpg"];
            image = [UIImage imageNamed:jpegFile];
        }
        else{
    
            NSString *jpegFile = [imageName stringByAppendingString:@".jpg"];
            image = [UIImage imageNamed:jpegFile];
        }
    
        return image;
    }
    

    从你的代码中调用

    bgImageView.image                   =   getImage(@"background");
    

    很好的想法@Chandan..我已经写了一个类似的包装器,它运行得非常好..但是我仍然将我的图像更改为png格式,以使用苹果的本地imageNamed并减少工作量(因为我在项目中有很多图像)..但是你的代码非常有用.. - Krishnabhadra
    1
    将 .jpg 文件更改为 .png 将增加图像大小,从而增加捆绑包大小... 如果没有问题,那就好。 - Chandan Shetty SP
    将 .jpg 文件更改为 .png 将增加图像大小,从而增加捆绑包大小。你确定吗?我认为 png 更轻量级。 - Krishnabhadra
    .png 图像包含 alpha 通道,因此大小会更大。只需检查单个 .jpg 的大小,并通过将相同文件转换为 .png 来验证它。 - Chandan Shetty SP
    但是在移动设备上显示图像时,PNG格式更好,详见http://mobile.tutsplus.com/tutorials/mobile-design-tutorials/mobile-design_png-or-jpg/和http://iphonedevelopment.blogspot.com/2008/10/iphone-optimized-pngs.html。 - Krishnabhadra
    我知道苹果公司推荐使用 .png 图像格式... 既然你要将 .jpg 转换为 .png,我只是提醒你图像大小会增加这个事实。 - Chandan Shetty SP

    5
    随着Xcode 6的推出,我发现在某些iOS7设备上JPG图像可能根本无法渲染(它们可能在某些设备上工作,但在其他设备上不起作用,或者它们可能在任何设备上都不起作用,并且您可能会在另一台开发人员的机器上看到不同的结果,似乎没有任何一致性)。这与是否仅在XIB中引用UIImageView或使用[UIImage imageNamed:](返回nil)以编程方式引用图像无关。

    在长时间的思考后,解决方案是将*.jpg文件扩展名重命名为*.png(同时显然保留文件内容为JPG数据)。

    希望对你有所帮助。


    1
    我正在使用资源目录,这解决了我的问题! - João Nunes
    @JoaoNunes 注意,我已经在使用资产目录。起初我没有使用,但是在使用启动屏幕XIB时,使用JPG文件仍然存在更多的iOS8 / Xcode 6.0错误。请参见此处... http://stackoverflow.com/questions/26139254/3x-images-incorrectly-used-on-iphone-6-or-5s-or-5-in-xibs-with-the-use-as-lau/26140455#26140455 - Oliver Pearmain
    今天我可能会向苹果发送一个关于JPG和storyboard图像以及UIImage命名的错误报告。 - João Nunes
    1
    我刚刚提交了一个 bug 报告:18631644。 - João Nunes
    干得好,伙计。我考虑过创建一个工单,但我无法可靠地复现。你能否将详细信息复制到http://openradar.appspot.com,以便它们公开可见? - Oliver Pearmain

    1

    您只需要提供图像的完整名称。

    bgImageView.image = [UIImage imageNamed:@"background.jpg"]; 
    

    不要忘记扩展名。

    至于 @2x,没有必要在代码中任何地方调用它。如果您编码正确,就无需像这里的一些人建议的那样测试视网膜显示。


    我已经按照你的建议尝试过了。我的意思是,我使用了与你在答案中提供的完全相同的代码行。我在我的3GS手机上成功显示了图片。但是我的iPhone 4也显示了我的1x图片,而且看起来被拉伸并且不清晰。 - Krishnabhadra
    我猜这不是一个编程问题。你检查过将background@2x.png文件正确链接到XCode项目了吗?在iOS Retina模拟器上是否有相同的问题? - Florian Mielke
    抱歉 @Florian..我没看到你的评论..是的,我在 iPhone 模拟器中也遇到了同样的问题。 - Krishnabhadra

    -1

    你可以使用jpg格式,我自己试过了,可以工作。唯一的建议是关于实例化的方式。 尝试这样做:

    stockImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Morbo.jpg"]];
    
    stockImage.frame = CGRectMake(0,0, self.view.bounds.size.width, self.view.bounds.size.height)  ;
    
    [self.view addSubview:stockImage];
    

    这是我使用的图片:

    http://futurama.wikia.com/wiki/File:Morbo.jpg


    1
    是的@elmo,当我给出带有扩展名jpg的图像名称时,图像显示正常。但是当我给出**[UIImage imageNamed:@"Morbo"]**时,jpg图像不显示...但是当我给出扩展名2x时,在iphone 4中无法加载图像...我认为您没有正确阅读我的问题... - Krishnabhadra
    1
    对不起,你是正确的,对于程序员来说,失读症有点像诅咒;)我以为一般的暗示是jpg不能使用。我只记得第一次尝试使用图像时它们无法工作,所以我就像在Web编程中一样添加了扩展名。 - Elmo
    我相信可以使用jpg格式的图片..我已经使它工作了..唯一的问题是**UIImage imageNamed:**是否以与png相同的方式处理jpg图像...对于png,它们可以理解1x和2x的图像而不需要给出扩展名..但是对于jpg,它们简单地没有扩展名。 - Krishnabhadra

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接