如何在不失去图像质量的情况下缩放全屏iPad图像?

3
这是我尝试实现的效果:
在 iPad 上全屏显示动物(基于矢量的艺术,而非照片)。当您点击身体部位(例如耳朵)时,图像会缩放并重新聚焦到耳朵区域,并显示有关耳朵的文本。单击缩小按钮,就回到全身镜头。我知道如何编程缩放和移动,但我不知道处理图像质量的最佳方法。1024x768 图像需要缩放 400% 才能获得所需的裁剪效果。显然,对于新的 iPad,该 1024x768 图像已经开始加倍,需要从那里增加 400%。
最初的想法是使用一个 4096x3072 的图像,并将其缩小到 1/4,然后当你缩放 400% 时,你不会失去图像质量。这张图片几乎使用了 70MB 的内存,这是可以理解的,我也明白为什么会发生这种情况,但显然,当这只是更大应用程序的一部分时,这是无法接受的。更不用说为视网膜屏幕(@2x 版本)做出的影响了。
是否有人对如何在不给设备造成负担的情况下实现此效果有任何建议?看起来 iOS 设备不能使用矢量图像,只能使用光栅化图像。由于我想要实现的细节水平,我无法仅仅缩放并处理质量损失。这是否可行,或者我应该找到不同的方法? 我正在使用 XCode 4.3.1 和 Cocos2d v 1.0.1 进行开发,但如果这可以解决我的问题,我可以尝试使用 v2.0。
我的超级棒的狐猴的全身图像(稍后由平面设计师完成):enter image description here 耳朵的近景:

enter image description here

等我们的设计师完成之后,我想象中会更像这样的东西(来自谷歌图片搜索,并非我们的作品,希望我们的作品不会那么脾气大):enter image description here

2
高清狐猴正是人类所需要的!我终于找到了一个与我有着相同想法的人。 - ajax333221
1
请查看https://dev59.com/c3A75IYBdhLWcg3wW3sZ。此外,还有一个链接到PhotoScroller示例代码,其中包含图像平铺示例。这可能是您正在寻找的内容。 - Rok Jarc
请注意,iPad 1 的最大纹理尺寸为2048x2048。只有最新的iPad(第三代)支持高达4096x4096的纹理尺寸,而iPad 2仅在安装了iOS 5.1后才支持4096x4096,否则也是2048x2048。 - CodeSmile
@LearnCocos2D 是的,我在帖子中忘记提到了。感谢你指出这一点!目前,这是为博物馆内部使用而设计的,我将能够更具体地为iPad 2和“3”设计。这种尺寸限制并不会对我产生影响,但会影响其他人参考本帖子。发现得好。 - BobbyScon
4个回答

3
也许您可以使用多张图片。首先展示一张全屏完全缩小的图像。当用户决定放大某个区域时,显示另一张全屏图像来呈现放大后的部分。您可以为过渡效果添加动画(淡入/淡出),使其足够流畅。
这种方法假设有限的缩放选项。例如,用户可以在动物的n个不同位置进行缩放。

是的,那是我考虑过的一种方法,但理想的最终目标是整个身体都可以缩放。计划B是这样做,并在身体周围闪烁边框,然后缩放该单个图像。 - BobbyScon
我明白了。也许你可以微调动画,使“before”图像(整个身体在缩放时)慢慢淡出+缩放...从而近似于所需的效果。 - SundayMonday
因为我们的设计部门也希望动画化每个身体部位,例如眨眼睛、耳朵抽搐等;我会采取这种方法。创建每个身体部位并将它们拼接在一起是我更加熟悉和能够比马克建议的SVG方法更快地实现的方法。但是,如果您使用大量矢量艺术或具有强大的矢量艺术背景,则绝对值得尝试SVG。 - BobbyScon

3

我已经了解到一些人使用SVG,但它似乎非常复杂。这是一篇写得很好的文章,当我回到工作电脑时,我会查看这个过程。我已经在原始问题中添加了一个新图像,它更接近艺术风格。在您的意见中,像这样更复杂的艺术品是否适用于SVG方法?从我浏览的内容中,我了解到SVG方法适用于单个对象,而不一定适用于由数十个对象组成的字符。但也许他的例子只是概念的基本介绍。感谢您的建议! - BobbyScon
是的,我认为这种技术可能会起作用,这取决于您需要多频繁重新渲染SVG。您可以使用缓存技术来保留任何已呈现的图像,并在内存不足时将它们删除。这可能比仅加载预渲染纹理要复杂一些,但您正在交换设备上的空间和计算时间。如果您正在使用OpenGL,另一种由Apple推荐的技术是使用PVRTC纹理,如此处所述http://j.mp/AiYgNP(抱歉使用URL缩短服务)。这样,纹理将以压缩形式存储在视频卡上。但是,PVRTC纹理需要预先渲染。 - Mark
PVRTC似乎是一个有效的方案,但即使是苹果也表示这可能无法在未来的设备上工作,并鼓励使用未压缩格式作为备用。与PVRTC相比,SVG看起来是解决此问题的更好方法,但考虑到正确完成这一点需要多少时间,我认为回报率不够高。我肯定会记住这一点,以备将来绘画时使用。如果有人对SVG方法感兴趣,请尝试此项目,其中包含可用于动画的工作示例,但缩放效果不如我所希望的那样好:https://github.com/reklis/SVGKit/ - BobbyScon

0

@BobbyScon:实际上,我按照我的建议解决了你的任务——这是我当前项目的一个副作用。从PDF加载的全屏精灵在iPad 2上需要25毫秒,并占用120kb的磁盘空间。导出为PNG格式的同一张图片需要77毫秒才能加载。从PDF中提取的精灵可以轻松缩放到任何大小而不会出现任何问题。我将很快创建一个完全可工作的Cocos2d扩展,请在此处查看:http://www.cocos2d-iphone.org/forum/topic/30152。 - Kidstamatic Apps

0

您可以在Quartz 2D框架中使用CGContextScaleCTM函数来平滑缩放高分辨率图像。

您可以在下面提到的url中找到一款由苹果开发的不错的样例应用程序。 MoveMe_APLMoveMeView_m

TiledImageView.h

#import <UIKit/UIKit.h>

@interface TiledImageView : UIView {
    CGFloat imageScale;
    UIImage* image;
    CGRect imageRect;
}
@property (retain) UIImage* image;

-(id)initWithFrame:(CGRect)_frame image:(UIImage*)_image scale:(CGFloat)_scale;

@end

TiledImageView.m

#import "TiledImageView.h"
#import <QuartzCore/QuartzCore.h>

@implementation TiledImageView

@synthesize image;

// Set the layer's class to be CATiledLayer.
+ (Class)layerClass {
    Return [CATiledLayer class];
}

- (void)dealloc {
    [image release];
    //--
    [super dealloc];
}

// Create a new TiledImageView with the desired frame and scale.
-(id)initWithFrame:(CGRect)_frame image:(UIImage*)_image scale:(CGFloat)_scale {
    if ((self = [super initWithFrame:_frame])) {
        self.image = _image;
        imageRect = CGRectMake(0.0f, 0.0f, CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage));
        imageScale = _scale;
        CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
        // levelsOfDetail and levelsOfDetailBias determine how
        // the layer is rendered at different zoom levels.  This
        // only matters while the view is zooming, since once the 
        // the view is done zooming a new TiledImageView is created
        // at the correct size and scale.
        tiledLayer.levelsOfDetail = 4;
        tiledLayer.levelsOfDetailBias = 4;
        tiledLayer.tileSize = CGSizeMake(512.0, 512.0); 
    }
    return self;
}

-(void)drawRect:(CGRect)_rect {
    CGContextRef context = UIGraphicsGetCurrentContext();    
    CGContextSaveGState(context);
    // Scale the context so that the image is rendered 
    // at the correct size for the zoom level.
    CGContextScaleCTM(context, imageScale,imageScale);  
    CGContextDrawImage(context, imageRect, image.CGImage);
    CGContextRestoreGState(context);    
}
@end

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