在iOS 4中保存UIView内容,其内部图像的实际大小(即缩放比例用于保存)

时间:2010-11-18 09:54:50

标签: iphone uiview ios4 calayer retina-display

我有一个UIView,其中包含许多UIImageViews作为子视图。该应用程序在iOS4上运行,我使用具有视网膜显示分辨率的图像(即图像加载比例= 2)

我想要保存UIView的内容...但是...内部有真实的图像大小。即视图的大小为200x200,内部有scale = 2的图像,我想保存400x400的结果图像以及所有图像的真实大小。

现在首先想到的是创建一个新的图像上下文并再次加载scale = 1的内部所有图像,这应该做,但我想知道是否有更优雅的方法来做到这一点?看起来像是内存的腰部和处理器时间再次重新加载所有东西,因为它已经完成......

P.S。如果有人有答案 - 包括代码会很好

5 个答案:

答案 0 :(得分:25)

任何UIView 呈现为图像的实现(也适用于视网膜显示)。

helper.h文件:

@interface UIView (Ext) 
- (UIImage*) renderToImage;
@end

和helper.m文件中的所属实现:

#import <QuartzCore/QuartzCore.h>

@implementation UIView (Ext)
- (UIImage*) renderToImage
{
  // IMPORTANT: using weak link on UIKit
  if(UIGraphicsBeginImageContextWithOptions != NULL)
  {
    UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0);
  } else {
    UIGraphicsBeginImageContext(self.frame.size);
  }

  [self.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();  
  return image;
}

0.0是比例因子。要应用于位图的比例因子。如果指定值0.0,则比例因子将设置为设备主屏幕的比例因子。

QuartzCore.framework 也应放入项目中,因为我们在图层对象上调用函数。

要在UIKit框架上启用弱链接,请单击左侧导航器中的项目项,单击项目目标 - &gt;构建阶段 - &gt;链接二进制文件并在UIKit框架上选择“可选”(弱)类型。

以下是library,其中包含类似UIColor,UIImage,NSArray,NSDictionary,...的扩展名。

答案 1 :(得分:4)

我已经执行了将MKMapView中的引脚保存为PNG文件(在视网膜显示中):MKPinAnnotationView: Are there more than three colors available?

以下是使用其视网膜定义执行UIViewtheView)保存的关键部分的摘录:


-(void) saveMyView:(UIView*)theView {
    //The image where the view content is going to be saved.
    UIImage* image = nil;
    UIGraphicsBeginImageContextWithOptions(theView.frame.size, NO, 2.0);
    [theView.layer renderInContext: UIGraphicsGetCurrentContext()];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    NSData* imgData = UIImagePNGRepresentation(image);
    NSString* targetPath = [NSString stringWithFormat:@"%@/%@", [self writablePath], @"thisismyview.png" ];
    [imgData writeToFile:targetPath atomically:YES]; 
}

-(NSString*) writablePath { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; return documentsDirectory; }

答案 2 :(得分:2)

关键是UIGraphicsBeginImageContextWithOptions的第三个参数是 scale ,它确定最终如何写出图像。

如果您一直想要实际像素尺寸,请使用[[UIScreen主屏幕]比例]获取屏幕的当前比例:

UIGraphicsBeginImageContextWithOptions(viewSizeInPoints, YES, [[UIScreen mainScreen] scale]);

如果您在iPhone4上使用scale = 1.0,您将获得一个尺寸为 points 的图像,结果将从真实的像素数量缩小。如果您手动将图像写入640x960尺寸(例如:将像素作为第一个参数传递),它实际上将是按比例缩小的缩小图像,看起来像您想象的那样糟糕。

答案 3 :(得分:0)

难道你不能只创建一个所需大小的新图形上下文,使用CGAffineTransform缩小它,渲染根UIView的根层,将上下文恢复到原始大小并渲染图像?没有试过这个视网膜内容,但这似乎适用于在UIImageViews中缩小的大图像...

类似的东西:

CGSize originalSize = myOriginalImage.size; //or whatever

//create context
UIGraphicsBeginImageContext(originalSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context); //1 original context

// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, originalSize.height);
CGContextScaleCTM(context, 1.0, -1.0);

//original image
CGContextDrawImage(context, CGRectMake(0,0,originalSize.width,originalSize.height), myOriginalImage.CGImage);

CGContextRestoreGState(context);//1 restore to original for UIView render;

//scaling
CGFloat wratio = originalSize.width/self.view.frame.size.width;
CGFloat hratio = originalSize.height/self.view.frame.size.height;

//scale context to match view size
CGContextSaveGState(context); //1 pre-scaled size
CGContextScaleCTM(context, wratio, hratio);

//render 
[self.view.layer renderInContext:context];

CGContextRestoreGState(context);//1  restore to pre-scaled size;

UIImage *exportImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

答案 4 :(得分:0)

导入QuartzCore(单击主项目,构建阶段,导入)以及您需要的位置添加:

#import <QuartzCore/QuartzCore.h>

我的imageViews是属性,如果不是,请忽略.self并将imageViews作为参数传递给函数,然后在新renderInContext <中的两个图像上调用UIGraphicsCurrentContext / p>

- (UIImage *)saveImage
{
    UIGraphicsBeginImageContextWithOptions(self.mainImage.bounds.size, NO, 0.0);

    [self.backgroundImage.layer renderInContext:UIGraphicsGetCurrentContext()];
    [self.mainImage.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage *savedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return savedImage;
}