2010-11-18 5 views
10

UIView uygulamasında birçok UIImageViews altyazı var. Uygulama iOS4'te çalışıyor ve görüntüleri retina ekran çözünürlüğü ile kullanıyoruz (örn. Ölçek = 2 ile görüntü yükü)İçindeki görüntülerin gerçek boyutuyla IOS 4'teki UIView içeriğinin kaydedilmesi (yani, kayıt için biriktirilecek içerikler)

UIView'in içeriğini kaydetmek istiyorum ... BUT ... resimlerin gerçek boyutuna sahip içeride. Yani Görünümün boyutu 200x200 ve içinde ölçek = 2 olan görüntüler var, 400x400'lük bir görüntüyü ve tüm görüntüleri gerçek boyutlarıyla kaydetmek istiyorum.

Akla ilk gelen şey, yeni bir resim bağlamı oluşturmak ve ölçek = 1 ile içindeki tüm görüntüleri tekrar yüklemek ve bunu yapmaktır, ancak bunu yapmak için daha şık bir yol olup olmadığını merak ediyordum? Zaten bittiği için her şeyi yeniden yüklemek için bellek ve işlemci zamanı gibi bir bel gibi görünüyor ...

p.s. Herhangi bir cevap varsa - kod güzel olurdu

cevap

25

Görüntüyü herhangi bir UIView 10 görüntü için işleme (retina görüntüleme için de çalışıyor).

helper.h dosyası:

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

ve helper.m dosyasında uygulama ait:

#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 ölçek faktörü. Bitmap'e uygulanacak ölçek faktörü. 0,0 değerini belirtirseniz, ölçek faktörü cihazın ana ekranının ölçek faktörüne ayarlanır. Ayrıca, katman nesnesinde işlev çağırdığımız için projeye de dahil edilmelidir.

UIKit çerçevesi üzerindeki zayıf bağlantıyı etkinleştirmek için, sol gezginde proje öğesine tıklayın, proje hedefi -> yapı aşamaları -> ikili bağlantıya tıklayın ve UIKit çerçevesinde "isteğe bağlı" (zayıf) türünü seçin. İşte

+0

UIGraphicsBeginImageContextWithOptions işlevini kullanıp kullanamayacağınızı denetleme amacı nedir? Geriye dönük uyumluluk için mi? – pixelfreak

+0

Bu çözüm ayrıca renderInContext yöntemi için QuartzCore çerçevesini gerektirir. – arlomedia

+0

@pixelfreak Bunun nedeni, UIGraphicsBeginImageContextWithOptions yalnızca iOS 4 + 'da kullanılabilir. – shannoga

0

İstenilen boyutta yeni bir grafik bağlamı oluşturamazsınız, bir CGAffineTransform kullanarak aşağı ölçeklendirebilir, kökünü UIView'in kök katmanına dönüştürür, içeriği geri yükler. orijinal boyut ve görüntüyü oluşturuyor musunuz? Ben kurtarmaya böyle birşey gerçekleştirdiğiniz

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

Merhaba Steven iki görüntülerde renderInContext çağrı (yani piksel 1/4 kullanılarak ölçeklenmiş veya çekirdekten daha büyük olan görüntü verileri) grafikler farklı şekilde çalışır? –

+0

Burada yanlış olabilir, çünkü bu bölümün özellikleri konusunda biraz tereddüt ediyorum, ancak yukarıda test edilmek, bunun küçültülmüş bir işlem olmadığını gösterdi. Öncelikle, özellikle ölçeklenmiş bir bitmap bağlamı oluşturdum, bitmap bağlamını kullanarak yeniden boyutlandırdım ve sonuçlandı, ancak sonuç (beklediğiniz gibi) oldu. Bununla birlikte, yukarıdaki yöntem, orijinal kaynaklar makul büyüklükte/kalitede olduğu sürece net bir görüntü sağlar. –

+0

Bir kod sözcüğü olarak, yukarıdaki kod, myOriginalImage'ın UIView nokta boyutundan daha büyük olduğunu varsayar (retina veya başka bir şekilde) –

4

:

gibi bir şey ... retina içerik bu çalıştı, ancak bu UIImageViews içinde küçültülmüş olan büyük resimler için iyi iş gibi görünüyor mı (retina ekranda) bir PNG dosyası olarak MKMapView gelen pimleri:

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

: MKPinAnnotationView: Are there more than three colors available?

İşte retina tanımını kullanarak bir UIView (theView) kaydedilmesini gerçekleştirir önemli kısmının özü bulunuyor

+0

Hey +1, UIGraphicsBeginImageContextWithOptions'dan bahsetmek için ... her küçük iOS güncellemesiyle ortaya çıkan bir dizi yeni rastgele fonksiyon var ... Yorgunum var :) –

+0

UIGraphicsBeginImageContextWithOptions da benim için yeni. Güncellemeleri daha dikkatli gözden geçirmelisiniz ... –

+0

ipucu için teşekkürler! –

2

anahtar UIGraphicsBeginImageContextWithOptions üçüncü parametre görüntü sonuçta yazılacak nasıl belirler ölçekli, olmasıdır ... UIColor, UIImage, NSArray, NSDictionary, benzer uzantıları ile library olduğunu dışarı.olacak,

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

ölçeğini kullanırsanız = iPhone4 üzerinde 1.0: Her zaman gerçek piksel boyutlarını istiyorsanız

, [[UIScreen mainScreen] ölçek] Ekranın şimdiki ölçek almak için kullanmak boyutu punto ile bir görüntü elde edin ve sonuç gerçek piksel sayısından aşağı ölçeklenir. Görüntüyü 640x960 boyutuna manuel olarak yazarsanız (örneğin: ilk parametre olarak pikselleri geçirme), aslında görüntünün göründüğü kadar korkunç görünmesini sağlayan ölçeklendirilmiş görüntü olacaktır.

+1

Dokümanlara göre, ölçek argümanını 0,0 olarak ayarlamak, [[UIScreen mainScreen] ölçeğine] ayarlamakla aynı şeydir. – arlomedia

0

İthalat QuartzCore (ithalat, Aşama kurmak, ana projeyi tıklayın) ve gereken yerler ekleyin:

#import <QuartzCore/QuartzCore.h> 

Benim imageViews özellikleri vardır senin değilse, .self görmezden ve fonksiyon içine imageViews geçmesi parametre olarak, o zaman yanılıyorumdur ancak bunun da bir hale küçültülmüş sahip değilse düzeltin, yeni 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; 
} 
İlgili konular