Soru PHImageManager gelen kare minyatürleri nasıl getirilir?


PHImageManager gelen kare başparmak nasıl getirileceği fikri var mı? PHImageContentModeAspectFill seçeneğinin bir etkisi yoktur.

[[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;
}];

18
2017-09-24 17:52


Menşei


Merhaba Pavel - cevabım sizin için mi çalıştı? Eğer öyleyse, lütfen kabul edildi olarak işaretler misiniz? - Josh Heald
Cevabınız için teşekkürler Josh, ama benim için çalışan gerçek çözüm, 100x100 veya daha fazla boyutta başparmak istemektir. Çözümünüz sadece PHImageManager'daki "akıllı" algoritmalara karşı bir çözümdür, bu yüzden üzgünüm kabul edemem. - Pavel Osipov
Retina ekranları için bir ölçek meselesi değil mi? Hedefin 80 derece kare UIImageView için doğru bir görüntü olduğu varsayılıyordu, kodunuz retina ölçeklerinde çok küçük olan 80 piksellik bir görüntü istiyordu - bu yüzden 100x100'den fazla talepte bulunma sorunu olabilir. Kodum hangi algoritmaları kullanır? Fotoğraf çerçevesiyle doğru bir şekilde çalışacağını düşünüyorum. Uygulamamda var, bu yüzden eğer bir şeye karşı çalışıyorsa, bilmek istediğim şey, çerçeveden en iyi şekilde yararlanmak istiyorum. Daha iyi bir çözümünüz varsa, kendi sorunuzu cevaplamak teşvik edilir :) - Josh Heald
Benim amacım UIImageView değil, UIImage karesine ihtiyacım olmasıdır. - Pavel Osipov
Tamam, yeterince adil, bir görüntü için olduğunu düşündüm, sonuç işleyicinizde yaptığınız gibi. Normalleştirilmiş CropRect yaklaşımını inceledim ve çalışmadığı için ve diğer geliştiriciler Apple geliştirici forumlarında bunu geliştirdiğinden, bir hata oluştu. Eğer kabul edersen sana bir radarı önermeni öneririm. Cevabımı Apple'ın dokümanlarına göre çalışması gereken kodla güncelledim. - Josh Heald


Cevaplar:


Güncelleştirme:

Görüntülerden elde edilen resimlerdeki hatalar PHImageManager iOS 8.3'te düzeltildi, bu yüzden iOS'un bu sürümü ve daha sonra orijinal örneğim şöyle işler: Hatalar hala var ve iOS 8.4 dahil olmak üzere, tam boyutlu bir kare kırpma alarak standart iPhone 6s arka kamera görüntüleri ile onları yeniden üretebilir. İOS 9.0'da, 63 megapiksellik bir panoramadan oluşan büyük ürünlerin bile işe yaradığı şekilde düzgün bir şekilde düzeltildi.

Apple'ın tanımladığı yaklaşım, CGRect görüntünün koordinat alanında, kökenin (0,0) ve azami (1,1) olduğu yer. Bu rect'i PHImageRequestOptions nesne ile birlikte resizeMode arasında PHImageRequestOptionsResizeModeExactve sonra kırpılmış bir görüntüye geri dönmelisiniz.

- (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;
     }];
}

Bu örnek onun yapar cropRect kenar uzunluğunun, varlığın genişliğinin ve yüksekliğinin daha kük olmasına eşittir ve ardından görüntüyü kullanarak resmin koordinat uzayına dönüştürür. CGRectApplyAffineTransform. Kökeni ayarlamak isteyebilirsiniz square (0,0) 'dan başka bir şeye, sık sık kırpma meyvesinin kırpılan resmin ekseni boyunca merkezlenmiş olmasını istersiniz, ancak bunu okuyucu için bir egzersiz olarak bırakacağım. :-)

Orijinal cevap:

John'un cevabı beni oraya yolladı, ama onun kodunu kullanarak gergin ve ezilmiş resimler çekiyordum. İşte benim bir imageView PHImageManager'dan alınan kare küçük resimleri görüntülemek için.

Öncelikle, contentMode sizin için özellik UIImageView ayarlandı ScaleAspectFill. Varsayılan ScaleToFill, kare minik resimleri görüntülemek için düzgün çalışmıyor. PHImageManager, bu yüzden, siz şunu örneklendirmiş olsanız da bunu değiştirdiğinizden emin olun. UIImageView kodda veya film şeridinde.

//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;
}];

belirtme PHImageRequestOptionsResizeModeExact için resizeMode Ayrıca, size bir resim vermediğiniz sürece kırpılmış bir görüntü vermeyeceğinden normalizedCropRectHiçbir yararı olmadığı için burada kullanılmamalı ve kullanıldığında, hızlı bir şekilde geri getirilen önbelleğe alınmış görüntülerin avantajlarını elde edemeyeceğiniz anlamına gelir.

UIImage iade edildi result Kaynakla aynı en boy oranı olacak, ancak UIImageView Bir kare olarak görüntülenecek en boy oranına ayarlanmış, bu yüzden sadece görüntülüyorsanız, işte bu yoldur. Resmi baskı veya ihracat için uygulamanın dışında kırpmanız gerekiyorsa, bu sizin istediğinizi değil - normalizedCropRect bunun için. (düzenleme yapınız- örneğin neyin işe yarayacağı…)

Bunun dışında UIImageView'in içerik modunu ayarladığınızdan emin olun. UIViewContentModeScaleAspectFill ve aşağıdaki 2 satırda clipsToBounds = YES ayarladığınız:

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

NormalizedCropRect kullanım örneği eklemek için düzenle
UYARI - bu işe yaramıyor, ancak Apple'ın belgeleri.

Apple'ın tanımladığı yaklaşım, CGRect görüntünün koordinat alanında, kökenin (0,0) ve azami (1,1) olduğu yer. Bu rect'i PHImageRequestOptions nesne ile birlikte resizeMode arasında PHImageRequestOptionsResizeModeExactve sonra kırpılmış bir görüntüye geri dönmelisiniz. Sorun şu ki, siz orijinal en boy oranı ve tam görüntü olarak geri geliyor.

Kırpma rektinin resmin koordinat alanında doğru şekilde oluşturulduğunu doğruladı ve kullanım talimatını takip ettim. PHImageRequestOptionsResizeModeExactAncak sonuç işleyicisi, orijinal görüntü oranında bir görüntüden geçecektir. Bu çerçeve içinde bir hata gibi görünüyor ve düzeltildiğinde, aşağıdaki kod çalışmalıdır.

- (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;
     }];
}

Tek önerebileceğim, eğer bu problemi yaşıyorsan, bir radarı dosyalamak Apple ile bunu düzeltmek istemek için!


19
2017-09-30 06:50



Bence kullanmalısın [UIScreen mainScreen].scale yerine 2. iPhone 6 Plus, @ 3x ve hepsi bu. - DCMaxxx
Teşekkürler DCMaxxx, iyi nokta. - Josh Heald
Son derece yararlı; Dikkatli olmanız gereken bir şey varsa, bunu koleksiyon görünümü kullanarak yapıyorsanız, UICollectionViewCell uzantısı olan UIImageView. Yaptığım konulardan biri, yaptığım şeydi. cell.contentMode =  yerine cell.imageView.contentMode =  (Bu orijinal cevabı kullanıyor) - mike
Bu çözümle ilgili bir sorunum var .. Ölüm 3.0 (iPhone 6 Plus) ve hedef boyutum 72x72. Ama ben her zaman 216x216 (72x3.0) ile sonuçlanır. Ölçeği değiştirirsem, her zaman 72.0'ın altında olurum (örn. 72/2, 72/3 ..). - Rikco
@Rikco Ölçeği görmezden gelir ve kullanırsanız ne alırsınız? CGSize retinaSquare = CGSizeMake(72.0, 72.0);? 72 olacak hedef büyüklüğüne ihtiyacınız var, çünkü bunu bir dış sisteme aktarıyorsunuz? Çünkü, telefonda görüntülenmek üzere kullanılıyorsa, görüntüyü yükseltmenin neden olduğu bulanıklığı önlemek için, 216x216 olmasını istersiniz. - 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];

    }];

5
2018-04-16 14:45



kullanım result.imageOrientation zorluğu önlemek için kodlanmış yöneltme yerine. - highmaintenance
iyi çalıştı. - Rikco


Tam bir kare elde etmek için, seçenekleri aktararak tam boyutu istediğinizi belirtmeniz gerekir.

    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;
    }];

1
2017-09-25 19:28



Benim için bu, bazı görüntülerde ezilmiş veya gerilmiş olur. - Josh Heald
Küçük görüntüler talep ederseniz bu işe yaramaz. - Pavel Osipov
Tam boyutunu sormanız, içerik modunun göz ardı edildiği anlamına gelmez. Bu durumda, içerik modu hala dolgu niteliğindedir ve bu nedenle kare olmayan görüntüleri geri alacaksınız (orijinalin zaten karesi olmadığı varsayılarak). - EarlyRiser
PHImageContentModeAspectFill'i kullanırsanız, bu hiç mantıklı olmaz mı? - highmaintenance


Bu benim için iyi çalışıyor:

 __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
2018-05-26 11:18