iOS 4 で UIView コンテンツを内部の画像の実際のサイズで保存する (つまり、保存するためにコンテンツを拡大します)
-
26-09-2019 - |
質問
サブビューとして多くの UIImageView を持つ UIView があります。アプリは iOS4 で実行され、Retina ディスプレイ解像度の画像を使用しています (例:画像はスケール = 2 でロードされます)
UIViewの内容を保存したいのですが…しかし ...中に画像の実際のサイズがあります。つまり、ビューのサイズは 200x200 で、内部にスケール = 2 の画像が含まれています。結果として得られる 400x400 の画像とすべての画像を実際のサイズで保存したいと考えています。
さて、最初に思い浮かぶのは、新しい画像コンテキストを作成し、その中にあるすべての画像をscale=1で再度ロードすることです。これで十分ですが、それを行うためのもっとエレガントな方法があるのではないかと考えていました。すでに完了しているため、すべてを再度リロードするには、メモリとプロセッサ時間がかなり消費されているようです...
追記誰かが答えを持っている場合は、コードを含めると良いでしょう
解決
レンダリングのための実装 任意の 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.フレームワーク レイヤーオブジェクトの関数を呼び出しているため、これもプロジェクトに含める必要があります。
UIKit フレームワークで弱いリンクを有効にするには、左側のナビゲーターでプロジェクト項目をクリックし、プロジェクト ターゲットをクリックして、-> ビルド フェーズ -> リンク バイナリをクリックし、UIKit フレームワークで「オプション」(弱い) タイプを選択します。
ここは 図書館 UIColor、UIImage、NSArray、NSDictionary などの同様の拡張機能を備えたもの
他のヒント
MKMapView からピンを PNG ファイルとして保存するためにそのようなことを実行しました(Retina ディスプレイで)。 MKPinAnnotationView:3色以上の色はありますか?
以下は、ファイルの保存を実行する重要な部分の抜粋です。 UIView
(theView
) その Retina 定義を使用します。
-(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; }
キーUIGraphicsBeginImageContextWithOptions第3のパラメータは、画像が最終的に書き出さする方法を決定するスケール、ということです。
あなたは常に実際のピクセル寸法をしたい場合は、使用[[UIScreen mainScreen]スケール]画面の現在の規模を取得します。
を UIGraphicsBeginImageContextWithOptions(viewSizeInPoints, YES, [[UIScreen mainScreen] scale]);
は、のポイントの中の次元で画像を取得し、その結果が真の画素数から縮小されます。手動640x960次元に画像を書き出す場合(例:最初のパラメータとしてのピクセルを渡して)、それは実際にひどいとあなたはそれを見て想像通りについてそのルックスバックにスケールアップされた縮小画像になります。。 P>
あなただけの、それをスケールダウンルートのUIViewのルート層をレンダリングし、元のサイズにコンテキストを復元し、画像をレンダリングするためにCGAffineTransformを使用して、希望のサイズで、新しいグラフィックスコンテキストを作成できませんでしたか?網膜コンテンツのためにこれを試してみましたが、これは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();
インポート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;
}