2017-04-24 3 views
1

カメラで撮影した2448x3264のUIImageを回転しようとしました。私がすると、メモリはおよそ3分の1秒で約120Mbスパイクし、その後通常の状態に戻ります。問題は、メモリが少ないデバイス(iPod touchなど)では、アプリがクラッシュすることです。たとえそれがないとしても、私はそれが1つのイメージのためにそれほど多くの記憶を使うべきではないと思う。これが起こると、Iphone 5も遅れます。CGラスタデータが1つの画像に対して大きすぎます

this回答にコメントによれば、UIGraphicsGetCurrentContextを(使用した後解凍メモリのバイト単位のサイズ)の幅であるべきである*高さ* CGImageGetBitsPerComponent(image.CGImage)/ 8バイトなので、画像は8Mバイトを占めるべきではなく、120

これがなぜ起こり、どのように修正するのか、ここ

は、回転した画像を返すようにUIImageのcaterogy方法は次のとおり

- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees { 
    CGFloat radian = (CGFloat) (degrees * (M_PI/ 180.0f)); 
    CGSize rotatedSize = [self rotatedImageSize:degrees]; 

    // Create the bitmap context 
    UIGraphicsBeginImageContextWithOptions(rotatedSize, NO, 0); 
    CGContextRef bitmap = UIGraphicsGetCurrentContext(); 

    CGPoint contextCenter = CGPointMake(rotatedSize.width/2.0f, 
rotatedSize.height/2.0f); 
    CGContextTranslateCTM(bitmap, contextCenter.x, contextCenter.y); 

    // // Rotate the image context 
    CGContextRotateCTM(bitmap, radian); 
    // Now, draw the rotated/scaled image into the context 
    [self drawInRect:CGRectMake(-self.size.width/2.0f, - 
self.size.height/2.0f, self.size.width, self.size.height)]; 

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return newImage; 
} 

ここ回転メソッドが実行されるだけラスタデータをメモリにピークを引き起こしているものであること機器からの証明、です​​

答えて

0

いくつかの発言:

  • 2448x3264x(たとえば、4バイト/ピクセル)は約30メガバイトです。
  • 回転させないでください。それが画面に表示されている場合は、ビューのtransformプロパティを使用できます。ファイルに変換され、ローテーションが8つのexifの向きのいずれかである場合は、どちらの方法が上がっているかを示すメタデータを書きます。同様に、ファイルから来ている場合は、Image I/Oを使用し、CGImageSourceRefに画面上に配置するのに必要なサイズの方向付けされたサムネイルを生成するように頼みます。 (ヒントはkCGImageSourceThumbnailMaxPixelSizeとkCGImageSourceCreateThumbnailWithTransformを使用してください。)任意の角度に対して、イメージを回転させるCoreImageフィルターを使用して、画面(GPU上)に必要なサイズにダウンサンプルします。同様に、vImageを使って同じことをCPU上で行うことができます(ヒントvImageAffineWarpCG_ARGB8888)。 vImageは非常に高速で、コアグラフィックよりもはるかに優れたリサンプリングが可能です。そんなこと...痛い場合はやめてください。
  • 角度から回転行列に変換する時間を過ごす前に、一時停止する必要があります。たとえば、角度が90度の場合、必要な行列は[0 1 -1 0 0 0]と正確になり、計算結果の近似値よりもリサンプリングのコードが楽になります。回転行列は[cos(t)sin(t)-sin(t)cos(t)0 0]である。クライアントは既にコサインとサインを直接渡すことができます。
関連する問題