10

サブビューとして多くのUIImageViewを持つUIViewがあります。アプリはiOS4で実行され、Retinaディスプレイの解像度の画像を使用しています(つまり、画像はスケール= 2で読み込まれます)

UIViewの内容を保存したいのですが...しかし...内部の画像の実際のサイズがあります。つまり、ビューのサイズは200x200で、内部にscale = 2の画像があります。結果として得られる、400x400の画像と、すべての画像を実際のサイズで保存したいと思います。

ここで最初に頭に浮かぶのは、新しい画像コンテキストを作成し、scale = 1で内部のすべての画像を再度読み込むことです。これで十分ですが、これを行うためのよりエレガントな方法があるかどうか疑問に思いました。すでに完了しているので、すべてを再度リロードするためのメモリとプロセッサ時間の無駄のようです...

誰かが答えを持っているならps-コードを含めるといいでしょう

4

5 に答える 5

26

UIViewを画像にレンダリングするための実装(Retinaディスプレイでも機能します)。

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ファイル(Retinaディスプレイ)として保存するために、このようなことを実行しました。MKPinAnnotationView:3色以上使用できますか?

これは、網膜の定義を使用し て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の3番目のパラメーターがscaleであり、これによって画像が最終的にどのように書き出されるかが決まります。

常に実際のピクセルサイズが必要な場合は、[[UIScreenmainScreen]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新しい2つの画像を呼び出します。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 に答える