2011-07-20 3 views
3

私は約1.5 MBの大きさのいくつかの大きな画像を持っています。 UIViewContentModeScaleFitを使ってUIImageViewにそれぞれを表示します。 UIImageViewsのiphone - 小さいフレームで大きな画像を表示するUIImageViewはまだ多くのメモリを必要としますか?

フレームサイズはわずか150 * 150

私の質問は、私はフルスクリーンのための大きな画像を表示した場合、メモリは途方もなく上がる理解

です。

しかし、それらが小さいUIImageViewにある場合、それらはまだメモリを消費しますか?

おかげ

答えて

1

それらは、(ディスプレイのピクセルを保持する、すなわちメモリ)フレームバッファメモリの点で同じくらいの費用がかかりませんが、メモリにスケーリングされていない画像を保持することは、依然としてかなりの費用がかかります。 1.5MBが圧縮されたサイズの場合。それはおそらく高い(iOSはおよそ4バイトを使用します*幅*画像ごとの高さは非圧縮UIImageを格納するために使用します)。このような画像は、アプリがバックグラウンドに入ったときにカーネルが実行する自動メモリ管理とうまくやりとりできません。メモリ圧迫が発生したときにバッキングストアが解放されますが、バッキングイメージは解放されません。

VMトラッカーを使用してインストゥルメントを使用してアプリを実行することは、問題がある場合(および自分でサイズを変更し、小さいバージョンを保存し、大きなバージョンをリリースする必要がある場合)には最適な方法です。画像を保存する領域が過度である場合は、それらを診断して、適切な解決策を選択することができます。インストゥルメントを使用して問題を見つけることを含む、イメージメモリの使用方法について詳細に説明する、iOSメモリ管理に関するWWDC 2011セッションをご覧になりたい場合があります。

あなたが最適化する前に、いつものようにプロファイル(あるいはアップルが言うように、Instrument)が!

+0

ありがとうございました。イメージを縮小するためのオープンソースのヘルパーライブラリをお勧めしますか? –

+0

また、VM Trackerはどこにありますか? –

+0

@Jackson:オープンソースのヘルパーライブラリは必要ありません。コアグラフィックスでは約10行です。それが正しく表示されるどこかに置くために、私は急いで私の答えに追加します。 – Tommy

3

UIImagesとUIImageViewは別々のものです。各UIImageViewは、対応するUIImageを表示するサイズを認識しています。 UIImageには、自分自身を表示する方法や表示に使用する方法の概念がないため、UIImageViewのサイズを変更するだけではUIImageには影響しません。したがって、メモリ使用量全体には影響しません。

Core Graphicsを使用してUIImageを取得し、その150x150バージョンを新しいUIImageとして生成し、それをUIImageViewにプッシュすることをお勧めします。

次(I型ほど徹底的にチェックされていない、書かれた)のようなコードの何かが仕事をする必要があり、スケールを実行するには:

#include <math.h> 

- (UIImage *)scaledImageForImage:(UIImage *)srcImage toSize:(CGSize)maxSize 
{ 
    // pick the target dimensions, as though applying 
    // UIViewContentModeScaleAspectFit; seed some values first 
    CGSize sizeOfImage = [srcImage size]; 
    CGSize targetSize; // to store the output size 

    // logic here: we're going to scale so as to apply some multiplier 
    // to both the width and height of the input image. That multiplier 
    // is either going to make the source width fill the output width or 
    // it's going to make the source height fill the output height. Of the 
    // two possibilities, we want the smaller one, since the larger will 
    // make the other axis too large 
    if(maxSize.width/sizeOfImage.width < maxSize.height/sizeOfImage.height) 
    { 
     // we'll letter box then; scaling width to fill width, since 
     // that's the smaller scale of the two possibilities 
     targetSize.width = maxSize.width; 

     // height is the original height adjusted proportionally 
     // to match the proportional adjustment in width 
     targetSize.height = 
         (maxSize.width/sizeOfImage.width) * sizeOfImage.height; 
    } 
    else 
    { 
     // basically the same as the above, except that we pillar box 
     targetSize.height = maxSize.height; 
     targetSize.width = 
        (maxSize.height/sizeOfImage.height) * sizeOfImage.width; 
    } 

    // images can be integral sizes only, so round up 
    // the target size and width, then construct a target 
    // rect that centres the output image within that size; 
    // this all ensures sub-pixel accuracy 
    CGRect targetRect; 

    // store the original target size and round up the original 
    targetRect.size = targetSize; 
    targetSize.width = ceilf(targetSize.width); 
    targetSize.height = ceilf(targetSize.height); 

    // work out how to centre the source image within the integral-sized 
    // output image 
    targetRect.origin.x = (targetSize.width - targetRect.size.height) * 0.5f; 
    targetRect.origin.y = (targetSize.height - targetRect.size.width) * 0.5f; 

    // now create a CGContext to draw to, draw the image to it suitably 
    // scaled and positioned, and turn the thing into a UIImage 

    // get a suitable CoreGraphics context to draw to, in RGBA; 
    // I'm assuming iOS 4 or later here, to save some manual memory 
    // management. 
    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(
      NULL, 
      targetSize.width, targetSize.height, 
      8, targetSize.width * 4, 
      colourSpace, 
      kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast); 
    CGColorSpaceRelease(colourSpace); 

    // clear the context, since it may currently contain anything. 
    CGContextClearRect(context, 
        CGRectMake(0.0f, 0.0f, targetSize.width, targetSize.height)); 

    // draw the given image to the newly created context 
    CGContextDrawImage(context, targetRect, [srcImage CGImage]); 

    // get an image from the CG context, wrapping it as a UIImage 
    CGImageRef cgImage = CGBitmapContextCreateImage(context); 
    UIImage *returnImage = [UIImage imageWithCGImage:cgImage]; 

    // clean up 
    CGContextRelease(context); 
    CGImageRelease(cgImage); 

    return returnImage; 
} 

はもちろん、私は非常に重く、それをコメント化し複雑に見えるよう作りました実際には23行しかありません。

+0

コードをありがとう。私はコードが正しい比率を処理するかどうか疑問に思っていますか? –

+0

いいえ、そうではありません。私はUIViewContentModeScaleAspectFitのヒントを見逃しました。私はコードを一瞬修正します。 – Tommy

+0

2行以下でなければならない 'targetRect.origin.x =(targetSize.width - targetRect.size.height)* 0.5f; targetRect.origin.y =(targetSize.height - targetRect.size.width)* 0.5F; ' ' targetRect.origin.x =(maxSize.width - targetSize.width)である* 0.5F。 targetRect.origin.y =(maxSize.height - targetSize.height)* 0.5f; '?? – NaveenRaghuveer

0

イメージの縮小版を作成し、どこかのディスクにキャッシュし、イメージビューで小さなバージョンを使用し、可能であれば大きなバージョンをアンロードする必要があります。

1
#import <ImageIO/ImageIO.h> 
#import <MobileCoreServices/MobileCoreServices.h> 

+ (UIImage *)resizeImage:(UIImage *)image toResolution:(int)resolution { 
    NSData *imageData = UIImagePNGRepresentation(image); 
    CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); 
    CFDictionaryRef options = (__bridge CFDictionaryRef) @{ 
                (id) kCGImageSourceCreateThumbnailWithTransform : @YES, 
                (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES, 
                (id) kCGImageSourceThumbnailMaxPixelSize : @(resolution) 
                }; 
    CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options); 
    CFRelease(src); 
    UIImage *img = [[UIImage alloc]initWithCGImage:thumbnail]; 
    return img; 
} 
関連する問題