2010-11-18 30 views
10

我有一個UIView與許多UIImageViews作爲子視圖。該應用程序運行在iOS4上,並使用具有視網膜顯示分辨率的圖像(即圖像以scale = 2加載)保存iOS 4中的UIView內容與真正的圖像大小(即規模競爭力保存)

我想保存UIView的內容...但...有圖像的實際大小內。即該視圖的大小爲200x200,圖像的scale = 2,我想將結果圖像保存爲400x400,並將所有圖像保存爲實際大小。

現在首先想到的是創建一個新的圖像上下文,並再次加載所有圖像scale = 1,應該這樣做,但我想知道是否有更好的方法來做到這一點?看起來像內存和處理器的時間來重新裝入所有東西,因爲它已經完成...

p.s.如果任何人有答案 - 包括代碼將是不錯的

回答

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框架上啓用弱鏈接,請單擊左側導航器中的項目項目,單擊項目目標 - >構建階段 - >鏈接二進制,然後在UIKit框架上選擇「可選」(弱)類型。

這裏是library與的UIColor,UIImage的,NSArray中,NSDictionary中,類似的擴展...

+0

檢查是否可以使用'UIGraphicsBeginImageContextWithOptions'有什麼意義?它是否向後兼容? – pixelfreak 2012-01-11 19:27:08

+0

該解決方案還需要QuartzCore框架,用於renderInContext方法。 – arlomedia 2012-04-16 19:51:19

+0

@pixelfreak這是因爲UIGraphicsBeginImageContextWithOptions僅適用於iOS 4 +。 – shannoga 2012-07-02 19:37:27

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(); 
+0

嗨史蒂芬,糾正我,如果我錯了,但不實際有縮小渲染(即使用像素的1/4圖像數據),這是比例放大或核心圖形以不同的方式工作? – 2010-11-24 13:09:44

+0

我可能在這裏錯了,因爲我對這部分Quartz的細節有些模糊,但是通過上面的測試表明它不是縮小的渲染。起初,我專門創建了一個按比例縮小的位圖上下文,進行了重新縮放,並使用位圖上下文進行了渲染,但結果卻是廢話(正如您所期望的)。然而,只要原始來源具有合理的尺寸/質量,上述方法提供了清晰的圖像。 – 2010-11-25 02:05:58

+0

以上代碼假設myOriginalImage大於UIView點大小(視網膜或其他) – 2010-11-25 02:12:54

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

+0

嗨+1提及UIGraphicsBeginImageContextWithOptions ... gosh有一個新的隨機函數,就像每一個小的iOS更新出來...我越來越累了:) – 2010-11-24 10:58:09

+0

UIGraphicsBeginImageContextWithOptions對我來說也是一個新的。應該仔細查看更新... – 2010-11-25 02:13:24

+0

感謝您的提示! – 2012-04-01 15:38:35

2

的關鍵在於向UIGraphicsBeginImageContextWithOptions的第三個參數是規模,它決定如何圖像將最終被寫入出。

如果你總是希望真正的像素尺寸,使用[[UIScreen mainScreen]規模]得到屏幕的當前規模:

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

如果使用規模= 1.0 iPhone4上,你會在中獲得一個尺寸爲012的圖像,結果從真實像素數減小。如果您手動將圖像寫入640x960尺寸(例如:將像素作爲第一個參數傳遞),則它實際上是縮小的圖像,縮小後的圖像看起來像您想象的那麼可怕。

+1

根據文檔,將scale參數設置爲0.0與將其設置爲[[UIScreen mainScreen]比例]相同。 – arlomedia 2012-04-16 19:53:19

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