web-dev-qa-db-ja.com

PHImageManagerから2乗サムネイルをフェッチする方法は?

PHImageManagerから2乗された親指をフェッチする方法を誰かが考えていますか? PHImageContentModeAspectFillオプションは無効です。

[[PHImageManager defaultManager]
  requestImageForAsset:(PHAsset *)_asset
            targetSize:CGSizeMake(80, 80)
           contentMode:PHImageContentModeAspectFill
               options:nil
         resultHandler:^(UIImage *result, NSDictionary *info) {
    // sadly result is not a squared image
    imageView.image = result;
}];
19
Pavel Osipov

更新:

PHImageManagerから取得した画像のトリミングのバグはiOS 8.3で修正されたため、そのバージョンのiOS以降では、私の元の例は次のように動作します。 バグはまだiOS 8.4までであり、標準のiPhone 6sバックカメラ画像でフルサイズの正方形の切り抜きを使って再現できます。これらはiOS 9.0で適切に修正されており、63メガピクセルのパノラマの大きなクロップでも問題なく機能します。

Apple定義のアプローチは、画像の座標空間でCGRectを渡すことです。ここで、原点は(0,0)で、最大は(1,1 )このrectをPHImageRequestOptionsオブジェクトでresizeModePHImageRequestOptionsResizeModeExactとともに渡すと、トリミングされた画像が返されます。

- (void)showSquareImageForAsset:(PHAsset *)asset
{
    NSInteger retinaScale = [UIScreen mainScreen].scale;
    CGSize retinaSquare = CGSizeMake(100*retinaScale, 100*retinaScale);

    PHImageRequestOptions *cropToSquare = [[PHImageRequestOptions alloc] init];
    cropToSquare.resizeMode = PHImageRequestOptionsResizeModeExact;

    CGFloat cropSideLength = MIN(asset.pixelWidth, asset.pixelHeight);
    CGRect square = CGRectMake(0, 0, cropSideLength, cropSideLength);
    CGRect cropRect = CGRectApplyAffineTransform(square,
                                                 CGAffineTransformMakeScale(1.0 / asset.pixelWidth,
                                                                            1.0 / asset.pixelHeight));

    cropToSquare.normalizedCropRect = cropRect;

    [[PHImageManager defaultManager]
     requestImageForAsset:(PHAsset *)asset
     targetSize:retinaSquare
     contentMode:PHImageContentModeAspectFit
     options:cropToSquare
     resultHandler:^(UIImage *result, NSDictionary *info) {
         self.imageView.image = result;
     }];
}

この例では、辺の長さのcropRectをアセットの幅と高さの小さい方に等しくしてから、CGRectApplyAffineTransformを使用して画像の座標空間に変換します。 squareの原点を(0,0)以外に設定すると、トリミングされる画像の軸に沿って中央にトリミングされた正方形が必要になることがよくありますが、それはそのままにしておきます読者のための演習。 :-)

元の回答:

ジョンの答えは、ほとんどの方法で私に届きましたが、彼のコードを使用して、画像を引き伸ばし、押しつぶしていました。これが、PHImageManagerから取得した正方形のサムネイルを表示するimageViewを取得する方法です。

まず、contentModeUIImageViewプロパティがScaleAspectFillに設定されていることを確認します。デフォルトはScaleToFillです。これはPHImageManagerからの正方形のサムネイルを表示するために正しく機能しないため、コードでUIImageViewをインスタンス化したかどうかにかかわらず、これを必ず変更してくださいストーリーボードで。

//view dimensions are based on points, but we're requesting pixels from PHImageManager
NSInteger retinaMultiplier = [UIScreen mainScreen].scale;
CGSize retinaSquare = CGSizeMake(imageView.bounds.size.width * retinaMultiplier, imageView.bounds.size.height * retinaMultiplier);

[[PHImageManager defaultManager]
     requestImageForAsset:(PHAsset *)_asset
               targetSize:retinaSquare
              contentMode:PHImageContentModeAspectFill
                  options:nil
            resultHandler:^(UIImage *result, NSDictionary *info) {

    // The result is not square, but correctly displays as a square using AspectFill
    imageView.image = result;
}];

PHImageRequestOptionsResizeModeExactを指定しない限り、resizeModenormalizedCropRectを指定する必要はありません。 、それを使用すると、キャッシュされた画像がすぐに返されるという利点が得られません。

UIImageで返されるresultは、ソースと同じアスペクト比になりますが、正方形として表示するようにアスペクトフィルに設定されているUIImageViewで使用するために正しくスケーリングされます。表示しているだけなら、これが方法です。アプリの外で印刷またはエクスポートするために画像をトリミングする必要がある場合、これは望ましくありません。そのためのnormalizedCropRectの使用を検討してください。 (編集-何が機能するかの例については、以下を参照してください...)

これを除いて、UIImageViewのコンテンツモードをUIViewContentModeScaleAspectFillに設定し、次の2行でclipsToBounds = YESを設定していることも確認してください。

imageView.contentMode=UIViewContentModeScaleAspectFill;
imageView.clipsToBounds=YES;

normalizedCropRectの使用例を追加するための編集
警告-これは機能しませんが、 Appleのドキュメントに従っているはずです。

Apple定義のアプローチは、画像の座標空間でCGRectを渡すことです。ここで、原点は(0,0)で、最大は(1,1このrectをPHImageRequestOptionsオブジェクトでresizeModePHImageRequestOptionsResizeModeExactとともに渡すと、トリミングされた画像が返されます。問題は、 t、元のアスペクト比とフル画像として戻ってきます。

トリミング四角形が画像の座標空間に正しく作成されていることを確認し、PHImageRequestOptionsResizeModeExactを使用するための指示に従いましたが、結果ハンドラーには元のアスペクト比で画像が渡されます。これはフレームワークのバグのようです。修正すると、次のコードが機能するはずです。

- (void)showSquareImageForAsset:(PHAsset *)asset
{
    NSInteger retinaScale = [UIScreen mainScreen].scale;
    CGSize retinaSquare = CGSizeMake(100*retinaScale, 100*retinaScale);

    PHImageRequestOptions *cropToSquare = [[PHImageRequestOptions alloc] init];
    cropToSquare.resizeMode = PHImageRequestOptionsResizeModeExact;

    CGFloat cropSideLength = MIN(asset.pixelWidth, asset.pixelHeight);
    CGRect square = CGRectMake(0, 0, cropSideLength, cropSideLength);
    CGRect cropRect = CGRectApplyAffineTransform(square,
                                                 CGAffineTransformMakeScale(1.0 / asset.pixelWidth,
                                                                            1.0 / asset.pixelHeight));

    cropToSquare.normalizedCropRect = cropRect;

    [[PHImageManager defaultManager]
     requestImageForAsset:(PHAsset *)asset
     targetSize:retinaSquare
     contentMode:PHImageContentModeAspectFit
     options:cropToSquare
     resultHandler:^(UIImage *result, NSDictionary *info) {
         self.imageView.image = result;
     }];
}

私が提案できることは、あなたがこの問題を抱えているなら、あなたは レーダーを提出する Appleを使って彼らにそれを修正するよう要求することです!

20
Josh Heald
  PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; 
    options.resizeMode = PHImageRequestOptionsResizeModeExact;

  NSInteger retinaMultiplier = [UIScreen mainScreen].scale;
  CGSize retinaSquare = CGSizeMake(imageView.bounds.size.width * retinaMultiplier, imageView.bounds.size.height * retinaMultiplier);

    [[PHImageManager defaultManager]
             requestImageForAsset:(PHAsset *)_asset
                       targetSize:retinaSquare
                      contentMode:PHImageContentModeAspectFill
                          options:options
                    resultHandler:^(UIImage *result, NSDictionary *info) {

                    imageView.image =[UIImage imageWithCGImage:result.CGImage scale:retinaMultiplier orientation:result.imageOrientation];

    }];
6
Max Gribov

正確な正方形を取得するには、次のようにオプションを渡して、正確なサイズが必要であることを示す必要があります。

    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];

    // No, really, we want this exact size    
    options.resizeMode = PHImageRequestOptionsResizeModeExact

    [[PHImageManager defaultManager]
             requestImageForAsset:(PHAsset *)_asset
                       targetSize:CGSizeMake(160, 160)
                      contentMode:PHImageContentModeAspectFill
                          options:options
                    resultHandler:^(UIImage *result, NSDictionary *info) {

    // Happily, result is now a squared image
    imageView.image = result;
    }];
2
John Fox

これは私にとってはうまくいきます:

 __block UIImage* imgThumb;

CGSize size=CGSizeMake(45, 45);// Size for Square image

[self.imageManager requestImageForAsset:<your_current_phAsset>
                             targetSize:size
                            contentMode:PHImageContentModeAspectFill
                                options:nil
                          resultHandler:^(UIImage *result, NSDictionary *info) {

                              imgThumb = result;

  }];
0
Shahul Hasan