Update:
Der Bug beim Beschneiden Bilder, wie sie von
PHImageManager
abgerufen wurden, wurde in iOS 8.3 behoben, so dass für diese Version von iOS und später, mein ursprüngliches Beispiel, wie folgt funktioniert:
Es scheint die Fehler sind immer noch da und bis iOS 8.4, kann ich sie mit Standard-iPhone 6s zurück Kamerabilder reproduzieren, wobei eine volle Größe Platz Ernte. Sie sind in iOS 9.0 richtig behoben, wo selbst große Bilder eines 63-Megapixel-Panoramas gut funktionieren.
Der von Apple definierte Ansatz besteht darin, eine CGRect
im Koordinatenraum des Bildes zu übergeben, wobei der Ursprung (0,0) und das Maximum (1,1) ist. Sie übergeben diese Rect im PHImageRequestOptions
Objekt, zusammen mit einem resizeMode
von PHImageRequestOptionsResizeModeExact
, und dann sollten Sie ein beschnittenes Bild zurück erhalten.
- (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;
}];
}
Dieses Beispiel macht seine cropRect
der Seitenlänge gleich dem kleineren von der Breite und Höhe des Vermögenswerts, und dann in dem Koordinatenraum des Bildes wandelt sie unter Verwendung von CGRectApplyAffineTransform
. Vielleicht möchten Sie den Ursprung von square
auf etwas anderes als (0,0) setzen, so oft Sie möchten, dass das Crop-Quadrat entlang der Achse des Bildes, das abgeschnitten wird, zentriert ist, aber ich lasse das als Übung für den Leser . :-)
Ursprüngliche Antwort:
John Antwort hat mich da die meisten die Art und Weise, aber seinen Code Ich war gespannt zu werden und zerquetscht Bilder. Hier ist, wie ich eine imageView
bekommen habe, um quadratische Thumbnails aus dem PHImageManager anzuzeigen.
Stellen Sie zunächst sicher, dass die Eigenschaft contentMode
für Ihre UIImageView
auf ScaleAspectFill
festgelegt ist. Der Standardwert ist ScaleToFill
, der nicht korrekt funktioniert, um quadratische Miniaturbilder aus PHImageManager
anzuzeigen, also stellen Sie sicher, dass Sie dies ändern, ob Sie die UIImageView
in Code oder im Storyboard instanziiert haben.
//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;
}];
Angabe PHImageRequestOptionsResizeModeExact
für die resizeMode
nicht erforderlich ist, da es Sie nicht eine beschnittene Bild geben, wenn Sie auch eine normalizedCropRect
liefern, und hier nicht verwendet werden sollte, da es keinen Nutzen ist, und dessen Verwendung bedeutet, dass Sie don‘ t die Vorteile von schnell zurückgespeicherten Bildern nutzen.
Die UIImage
in result
zurückgegeben wird das gleiche Seitenverhältnis wie die Quelle sein, aber richtig zur Verwendung in einem UIImageView
skaliert, dem Aspekts gesetzt füllen als ein Quadrat angezeigt werden, also, wenn Sie es gerade angezeigt wird, ist dies der Weg, den man gehen sollte. Wenn Sie das Bild für den Druck oder Export außerhalb der App zuschneiden müssen, ist dies nicht das, was Sie wollen - schauen Sie sich die Verwendung von normalizedCropRect
dafür an. (Bearbeiten- siehe unten zum Beispiel, was funktionieren soll ...
)
Außer dies auch sicherstellen, dass der Sie den Inhalt Modus des UIImageView UIViewContentModeScaleAspectFill gesetzt und dass Sie setzen clipsToBounds = YES durch die folgenden zwei Zeilen:
imageView.contentMode=UIViewContentModeScaleAspectFill;
imageView.clipsToBounds=YES;
bearbeiten zu Fügen Sie normalizedCropRect Verwendungsbeispiel hinzu
WARNUNG - das funktioniert nicht, sollte aber gemäß Apple's documentation.
Der von Apple definierte Ansatz besteht darin, eine CGRect
im Koordinatenraum des Bildes zu übergeben, wobei der Ursprung (0,0) und das Maximum (1,1) ist. Sie übergeben diese Rect im PHImageRequestOptions
Objekt, zusammen mit einem resizeMode
von PHImageRequestOptionsResizeModeExact
, und dann sollten Sie ein beschnittenes Bild zurück erhalten. Das Problem ist, dass Sie es nicht tun, es kommt zurück wie das ursprüngliche Seitenverhältnis und das vollständige Bild.
Ich habe überprüft, dass das Crop-Rect korrekt im Koordinatenraum des Bildes erstellt wurde, und folgte der Anweisung PHImageRequestOptionsResizeModeExact
zu verwenden, aber dem Ergebnishandler wird immer noch ein Bild im ursprünglichen Seitenverhältnis übergeben. Dies scheint ein Fehler im Framework zu sein, und wenn es behoben ist, sollte der folgende Code funktionieren.
- (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;
}];
}
Alles, was ich vorschlagen kann, ist, dass, wenn Sie dieses Problem haben, Sie file a radar mit Apple zu verlangen, dass sie es zu beheben!
Hallo Pavel - hat für Sie meine Antwort Arbeit? Wenn ja, würden Sie es bitte als akzeptiert markieren? –
Danke für die Antwort Josh, aber die wirkliche Lösung, die für mich funktioniert, ist es, Daumen mit der Größe 100x100 oder mehr anzufordern. Ihre Lösung ist nur ein Workaround gegen "intelligente" Algorithmen in PHImageManager, also entschuldige, dass ich sie nicht akzeptieren kann. –
Ist das nicht ein Maßstab für Retina-Bildschirme? Ich ging davon aus, dass das Ziel ein Bild war, das für ein UiMageView mit 80 Punkten genau richtig ist, wo Ihr Code ein 80-Pixel-Bild verlangte, das bei Retina-Skalierungen zu klein ist - das könnte der Grund sein, mehr als 100x100 zu verbessern. Mit welchen Algorithmen arbeitet mein Code? Ich denke, es funktioniert korrekt mit dem Photos-Framework, und ich habe es in meiner App, wenn es gegen etwas arbeitet, würde ich gerne wissen, da ich das Framework optimal nutzen möchte. Wenn Sie eine bessere Lösung haben, wird die Beantwortung Ihrer eigenen Frage empfohlen :) –