包含UIView的UIImage / UIImageView重绘是否已缩放

时间:2012-01-12 15:17:03

标签: objective-c ios uiimageview uiimage

我的iPad应用程序有一个导航,我在其中显示不同页面的屏幕截图,因为我想一次显示多个屏幕截图,我将容器缩放到原始屏幕截图的大约24%(1024x768)。

- (void) loadView
{
    // get landscape screen frame
    CGRect screenFrame = [UIScreen mainScreen].bounds;
    CGRect landscapeFrame = CGRectMake(0, 0, screenFrame.size.height, screenFrame.size.width);

    UIView *view = [[UIView alloc] initWithFrame:landscapeFrame];
    view.backgroundColor = [UIColor grayColor];

    self.view = view;

    // add container view for 2 images
    CGRect startFrame = CGRectMake(-landscapeFrame.size.width/2, 0, landscapeFrame.size.width*2, landscapeFrame.size.height);
    container = [[UIView alloc] initWithFrame:startFrame];
    container.backgroundColor = [UIColor whiteColor];

    // add image 1 (1024x768)
    UIImage *img1 = [UIImage imageNamed:@"01.jpeg"];
    UIImageView *img1View = [[UIImageView alloc] initWithImage:img1];
    [container addSubview:img1View];

    // add image 2 (1024x768)
    UIImage *img2 = [UIImage imageNamed:@"02.jpeg"];
    UIImageView *img2View = [[UIImageView alloc] initWithImage:img2];

    // move img2 to the right of img1
    CGRect newFrame = img2View.frame;
    newFrame.origin.x = 1024.0;
    img2View.frame = newFrame;

    [container addSubview:img2View];

    // scale to 24%
    container.transform = CGAffineTransformMakeScale(0.24, 0.24);

    [self.view addSubview:container];
}

但是当我使用“小”文本缩放图像时,它看起来像这样:

我必须使用大截图,因为如果用户点击图像,它应该缩放到100%并且清脆。

有没有办法在不破坏性能的情况下“平稳地”(动态地)缩放图像? 它有两个版本就足够了:全px和24%版本的另一个版本。

2 个答案:

答案 0 :(得分:3)

缩小图像看起来很糟糕的原因是它在OpenGL中进行缩放,OpenGL使用快速但低质量的线性插值。您可能知道,UIView构建在CALayer之上,而CALayer又是OpenGL纹理的一种包装器。由于该层的内容位于视频卡中,因此CALayer可以在GPU上完成所有的魔术,无论CPU是忙于加载网站,还是阻止磁盘访问,或者其他什么。我之所以提到这一点,只是因为注意层内纹理中的实际内容是有用的。在你的情况下,UIImageView的图层在其纹理上有完整的1024x768位图图像,并且不受容器变换的影响:UIImageView中的CALayer看不到它(让我们看到..)246x185 on - 屏幕并重新缩放其位图,它只是让OpenGL做它的事情,并在每次更新显示时缩小位图。

为了获得更好的缩放比例,我们需要在CoreGraphics而不是OpenGL中进行扩展。这是一种方法:

- (UIImage*)scaleImage:(UIImage*)image by:(float)scale
{
    CGSize size = CGSizeMake(image.size.width * scale, image.size.height * scale);
    UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

- (void)loadView
{
    // get landscape screen frame
    CGRect screenFrame = [UIScreen mainScreen].bounds;
    CGRect landscapeFrame = CGRectMake(0, 0, screenFrame.size.height, screenFrame.size.width);

    UIView *view = [[UIView alloc] initWithFrame:landscapeFrame];
    view.backgroundColor = [UIColor grayColor];

    self.view = view;

    // add container view for 2 images
    CGRect startFrame = CGRectMake(-landscapeFrame.size.width/2, 0, landscapeFrame.size.width*2, landscapeFrame.size.height);
    container = [[UIView alloc] initWithFrame:startFrame];
    container.backgroundColor = [UIColor whiteColor];

    // add image 1 (1024x768)
    UIImage *img1 = [UIImage imageNamed:@"01.png"];
    img1View = [[TapImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
    img1View.userInteractionEnabled = YES; // important!
    img1View.image = [self scaleImage:img1 by:0.24];
    [container addSubview:img1View];

    // add image 2 (1024x768)
    UIImage *img2 = [UIImage imageNamed:@"02.png"];
    img2View = [[TapImageView alloc] initWithFrame:CGRectMake(1024, 0, 1024, 768)];
    img2View.userInteractionEnabled = YES;
    img2View.image = [self scaleImage:img2 by:0.24];
    [container addSubview:img2View];

    // scale to 24% and layout subviews
    zoomed = YES;
    container.transform = CGAffineTransformMakeScale(0.24, 0.24);

    [self.view addSubview:container];
}

- (void)viewTapped:(id)sender
{
    zoomed = !zoomed;

    [UIView animateWithDuration:0.5 animations:^
    {
        if ( zoomed )
        {
            container.transform = CGAffineTransformMakeScale(0.24, 0.24);
        }
        else
        {
            img1View.image = [UIImage imageNamed:@"01.png"];
            img2View.image = [UIImage imageNamed:@"02.png"];
            container.transform = CGAffineTransformMakeScale(1.0, 1.0);
        }
    }
    completion:^(BOOL finished)
    {
        if ( zoomed )
        {
            UIImage *img1 = [UIImage imageNamed:@"01.png"];
            img1View.image = [self scaleImage:img1 by:0.24];
            UIImage *img2 = [UIImage imageNamed:@"02.png"];
            img2View.image = [self scaleImage:img2 by:0.24];
        }
    }];
}

这里是TapImageView,一个UIImageView子类,告诉我们何时通过向响应者链发送动作来点击它:

@interface TapImageView : UIImageView
@end

@implementation TapImageView

- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    [[UIApplication sharedApplication] sendAction:@selector(viewTapped:) to:nil from:self forEvent:event];
}

@end

答案 1 :(得分:1)

而不是缩放容器及其所有子视图。从容器的内容创建UIImageView并将其框架大小调整为原始的24%。

UIGraphicsBeginImageContext(container.bounds.size);
[container renderInContext:UIGraphicsGetCurrentContext()];
UIImage *containerImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

UIImageView *containerImageView = [[UIImageView alloc] initWithImage:containerImage];
CGRectFrame containerFrame = startFrame;
containerFrame.size.with *= 0.24;
containerFrame.size.height *= 0.24;
containerImageView.frame = containerFrame;

[self.view addSubView:containerImageView];