10

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

我想保存 UIView 的内容......但是......里面有图像的真实大小。即视图的大小为 200x200 和内部比例为 2 的图像,我想保存 400x400 的结果图像和所有图像的真实大小。

现在首先想到的是创建一个新的图像上下文并再次加载其中 scale=1 的所有图像,这应该可以,但我想知道是否有更优雅的方法可以做到这一点?似乎需要大量的内存和处理器时间来重新加载所有内容,因为它已经完成了......

ps如果有人有答案 - 包括代码会很好

4

5 回答 5

26

将任何 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 框架上启用弱链接,请单击左侧导航器中的项目项,单击项目目标 -> 构建阶段 -> 链接二进制并在 UIKit 框架上选择“可选”(弱)类型。

这是具有类似 UIColor、UIImage、NSArray、NSDictionary 扩展名的...

于 2010-11-25T15:03:45.243 回答
4

我已经执行了这样的操作,将 MKMapView 中的图钉保存为 PNG 文件(在视网膜显示中):MKPinAnnotationView:是否有超过三种颜色可用?

这是使用其视网膜定义 执行UIView( )保存的关键部分的摘录:theView


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

于 2010-11-24T10:04:21.293 回答
2

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

如果您总是想要真实的像素尺寸,请使用 [[UIScreen mainScreen] scale] 获取屏幕的当前比例:

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

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

于 2011-04-23T17:08:00.153 回答
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();
于 2010-11-24T04:18:52.093 回答
0

导入 QuartzCore(点击主项目,构建阶段,导入)并在需要的地方添加:

#import <QuartzCore/QuartzCore.h>

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

- (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;
}
于 2013-05-16T18:07:55.293 回答