Miniature carrée de l'image UIImagePickerViewController

Dans mon application, l'user sélectionne une image ou prend une photo en utilisant UIImagePickerViewController. Une fois l'image sélectionnée, je veux afficher sa vignette sur un carré UIImageView (90×90).

J'utilise le code d' Apple pour créer une vignette. Le problème est que la vignette n'est pas au carré, la fonction, après avoir réglé la key kCGImageSourceThumbnailMaxPixelSize à 90, semble seulement resize la hauteur de l'image, et autant que je sache la key kCGImageSourceThumbnailMaxPixelSize devrait être responsable de la définition de la hauteur et de la largeur de la vignette.

Voici un aperçu de mon code:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; NSData *imageData = UIImageJPEGRepresentation (image, 0.5); // My image view is 90x90 UIImage *thumbImage = MyCreateThumbnailImageFromData(imageData, 90); [myImageView setImage:thumbImage]; if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); } [picker dismissViewControllerAnimated:YES completion:nil]; } UIImage* MyCreateThumbnailImageFromData (NSData * data, int imageSize) { CGImageRef myThumbnailImage = NULL; CGImageSourceRef myImageSource; CFDictionaryRef myOptions = NULL; CFSsortingngRef myKeys[3]; CFTypeRef myValues[3]; CFNumberRef thumbnailSize; // Create an image source from NSData; no options. myImageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); // Make sure the image source exists before continuing. if (myImageSource == NULL){ fprintf(stderr, "Image source is NULL."); return NULL; } // Package the integer as a CFNumber object. Using CFTypes allows you // to more easily create the options dictionary later. thumbnailSize = CFNumberCreate(NULL, kCFNumberIntType, &imageSize); // Set up the thumbnail options. myKeys[0] = kCGImageSourceCreateThumbnailWithTransform; myValues[0] = (CFTypeRef)kCFBooleanTrue; myKeys[1] = kCGImageSourceCreateThumbnailFromImageIfAbsent; myValues[1] = (CFTypeRef)kCFBooleanTrue; myKeys[2] = kCGImageSourceThumbnailMaxPixelSize; myValues[2] = thumbnailSize; myOptions = CFDictionaryCreate(NULL, (const void **) myKeys, (const void **) myValues, 2, &kCFTypeDictionaryKeyCallBacks, & kCFTypeDictionaryValueCallBacks); // Create the thumbnail image using the specified options. myThumbnailImage = CGImageSourceCreateThumbnailAtIndex(myImageSource, 0, myOptions); UIImage* scaled = [UIImage imageWithCGImage:myThumbnailImage]; // Release the options dictionary and the image source // when you no longer need them. CFRelease(thumbnailSize); CFRelease(myOptions); CFRelease(myImageSource); // Make sure the thumbnail image exists before continuing. if (myThumbnailImage == NULL) { fprintf(stderr, "Thumbnail image not created from image source."); return NULL; } return scaled; } 

Et voici comment mon image est instanciée:

 myImageView = [[UIImageView alloc] init]; imageView.contentMode = UIViewContentModeScaleAspectFit; CGRect rect = imageView.frame; rect.size.height = 90; rect.size.width = 90; imageView.frame = rect; [imageView setUserInteractionEnabled:YES]; 

Si je ne définis pas imageView.contentMode = UIViewContentModeScaleAspectFit; la vignette sera déformée, car il s'agit juste d'une version de mon image originale avec une hauteur de 90 pixels.

Alors, pourquoi ma vignette n'est pas au carré?

La solution la plus simple consiste à définir le paramètre contentMode de votre imageView comme étant UIViewContentModeScaleAspectFill place. Cependant, cela peut ne pas être idéal car cela garderait toute l'image en memory.

Voici un code que j'utilise pour resize les images.

 + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)size { UIGraphicsBeginImageContextWithOptions(size, NO, 0); [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

Cette version empêchera l'image d'être déformée si la taille n'a pas le même format d'image que l'image.

 + (UIImage *)imageWithImage:(UIImage *)image scaledToFillSize:(CGSize)size { CGFloat scale = MAX(size.width/image.size.width, size.height/image.size.height); CGFloat width = image.size.width * scale; CGFloat height = image.size.height * scale; CGRect imageRect = CGRectMake((size.width - width)/2.0f, (size.height - height)/2.0f, width, height); UIGraphicsBeginImageContextWithOptions(size, NO, 0); [image drawInRect:imageRect]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

Souvent, vous voulez seulement le carré supérieur d'une image (plutôt que le centre). Et vous voulez que l'image finale soit d'une certaine taille, disons 128×128, comme dans l'exemple ci-dessous.

 - (UIImage *)squareAndSmall // as a category (so, 'self' is the input image) { // fromCleverError's original // http://stackoverflow.com/questions/17884555 CGSize finalsize = CGSizeMake(128,128); CGFloat scale = MAX( finalsize.width/self.size.width, finalsize.height/self.size.height); CGFloat width = self.size.width * scale; CGFloat height = self.size.height * scale; CGRect rr = CGRectMake( 0, 0, width, height); UIGraphicsBeginImageContextWithOptions(finalsize, NO, 0); [self drawInRect:rr]; UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 

Voici un lien auquel vous pouvez vous référer:

1) UIImage + Redimensionner

2) UIImage + ProportionalFill

Ici, vous pouvez resize la vue et également append un remplissage proportionnel afin que proportionnellement le rapport d'aspect et d'autres fonctions comme la culture, l'échelle, etc.

Vous pouvez utiliser -(UIImage*)resizedImageToSize:(CGSize*)size méthode de -(UIImage*)resizedImageToSize:(CGSize*)size sous lien de reference UIImage + Redimensionner ci-dessus juste pour resize l'image.

J'espère que cela vous aide.

Faites-moi savoir si vous voulez plus d'aide.

Version Swift 2.x de la réponse de Clever Error ci-dessus:

  // Define thumbnail size let size = CGSize(width: 100, height: 100) // Define rect for thumbnail let scale = max(size.width/image.size.width, size.height/image.size.height) let width = image.size.width * scale let height = image.size.height * scale let x = (size.width - width) / CGFloat(2) let y = (size.height - height) / CGFloat(2) let thumbnailRect = CGRectMake(x, y, width, height) // Generate thumbnail from image UIGraphicsBeginImageContextWithOptions(size, false, 0) image.drawInRect(thumbnailRect) let thumbnail = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() 

Une autre façon de le faire – a rencontré un problème l'autre jour et d'autres personnes pourraient avoir le même problème lors de l'utilisation de l' exemple de code pomme qui est le mieux pour les grandes images.

Comme mentionné dans la réponse acceptée, cela a le problème de charger l'intégralité de l'image dans la memory et iOS peut tuer votre application si elle est trop grande. CGImageSourceCreateThumbnailAtIndex dans le code d'exemple d'Apple est plus efficace, mais il y a un bug dans l'exemple. Le troisième paramètre de CFDictionaryCreate est le "numValues" à copyr. Doit être 3 pas 2.

 myOptions = CFDictionaryCreate(NULL, (const void **) myKeys, (const void **) myValues, 3, //Changed to 3 &kCFTypeDictionaryKeyCallBacks, & kCFTypeDictionaryValueCallBacks);