0

高レベルの要約:低解像度のALAssetグループ画像[グループposterImage]をより高品質のバージョンに置き換えて、画面上でより大きく表示できるようにします。通常、インターフェイスで必要に応じてロードしますが、[ALAssetsGroupenumerateAssetsAtIndexes]は非常に低速です。(私はxの量だけ目に見えるよりも広いプリロードを行うことができ、それでもそれを行うことができますが、それは価値があるよりも面倒であるように見え、特にiOS5では応答が遅いという問題があります)

私ができると思ったのは、各グループの最初のアセットをリクエストし、それをスケーリングして結果を保存することでした。ただし、画像のサイズが大きいことを考慮しても、メモリの割り当てが行われていることに驚いています。VM Trackerを使用すると、多数のCGImage割り当てと、作成している「マップされたファイル」のサムネイルが表示されます。私はARCを使用しているので、元の大きな画像がドロップアウトすることを期待していましたが、VMトラッカーの結果はそれをむき出しにしません。

デフォルトのposterImage実装を使用する場合、Resident Mem〜= 30mb、Dirty Mem〜= 80mb、Virtual tops〜240mb(それ自体が大きい)。「ライブ」<割り当てプロファイラーごとに10MB。

代わりに次のコードを使用すると、150から80番目の画像の読み込みがクラッシュします。その時点で、Resident Mem> 480mb、Dirty Mem> 420mb、Virtualはなんと750mbでした。明らかにこれは受け入れられません。

これは、NSOperationQueue内で使用しているコードで、各グループの最初の画像を取得して高解像度のポスター画像として使用しています。

NSIndexSet* i = [NSIndexSet indexSetWithIndex:0];
ALAssetsGroupEnumerationResultsBlock assetsEnumerationBlock = ^(ALAsset *result, NSUInteger i, BOOL *stop) {

  if (result) {
     // pull the full resolution image and then scale it to fit our desired area
     ALAssetRepresentation *assetRepresentation = [result defaultRepresentation];
     CGImageRef ref = [assetRepresentation fullScreenImage];
     CGFloat imgWidth = CGImageGetWidth(ref);
     CGFloat imgHeight = CGImageGetHeight(ref);
     CGFloat minDimension = MIN(imgWidth,imgHeight);

     // grab a square subset of the image, centered, to use
     CGRect subRect = CGRectMake(0, 0, minDimension, minDimension);
     subRect.origin = CGPointMake(imgWidth / 2 - minDimension / 2, imgHeight / 2 - minDimension / 2);
     CGImageRef squareRef = CGImageCreateWithImageInRect(ref,subRect);
     // now scale it down to fit
     CGFloat heightScale = dimension / minDimension;
     UIImage* coverImage = [UIImage imageWithCGImage:squareRef scale:1/heightScale orientation:UIImageOrientationUp];

     if (coverImage) {
        [mainViewController performSelectorOnMainThread:@selector(imageDidLoad:) 
                                             withObject:[NSArray arrayWithObjects:coverImage, [NSNumber numberWithInt:photoIndex], nil] 
                                          waitUntilDone:NO];
     }      
     CGImageRelease(squareRef);
     // DO NOT RELEASE 'ref' it will be 'zombied' as it is already handled by the system
     //CGImageRelease(ref);

     *stop = YES;
   }
   else {
      // default image grab....
   }
};
[group enumerateAssetsAtIndexes:i options:NSEnumerationConcurrent usingBlock:assetsEnumerationBlock];

上記で何か問題が発生しているのでしょうか、それともすべての画像を読み込んで賢くないのでしょうか。考えれば考えるほど、目に見える画像のウィンドウとその周りのバッファをロードするのが道だと思いますが、上記のコードで何が間違っていたのかについてもっと知りたいと思います。ありがとう!

4

1 に答える 1

0

私はあなたとまったく同じことをしましたが、この答えのおかげで: iPhoneカメラでキャプチャされた最後の画像をフェッチすることで、メモリをそれほど消費せずにはるかに高速にすることができました。

fullScreenImage とそのサムネイルだけをフェッチしないため、もちろんこれにより画像が大幅に小さくなります。

私の最終的なコード:

   ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

// Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {

    // Within the group enumeration block, filter to enumerate just photos.
    [group setAssetsFilter:[ALAssetsFilter allPhotos]];
    int nrOfPhotos = 200;
    [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, nrOfPhotos)]
                            options:0
                         usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {

                             // The end of the enumeration is signaled by asset == nil.
                             if (alAsset) {
                                 NSLog(@"Index: %i", index);

                                 CGImageRef imageRef = [alAsset thumbnail];
                                 UIImage *latestPhoto = [UIImage imageWithCGImage:imageRef scale:1.f orientation:UIImageOrientationUp];

                                 //Do something with images

                         }
                         }];
}
                     failureBlock: ^(NSError *error) {
                         // Typically you should handle an error more gracefully than this.
                         NSLog(@"No groups");
                     }];
于 2012-12-06T14:56:14.887 に答える