从UIImagePickerViewController图像的方形缩略图

在我的应用程序中,用户select一个图像或使用UIImagePickerViewController拍摄图片。 一旦图像被选中,我想在正方形的UIImageView(90×90)上显示它的缩略图。

我正在使用Apple的代码来创build一个缩略图。 问题是缩略图不是平方的,函数设置kCGImageSourceThumbnailMaxPixelSize键到90后,似乎只能调整图像的高度,而据我所知,kCGImageSourceThumbnailMaxPixelSize键应该负责设置缩略图的高度和宽度。

这里是我的代码的一瞥:

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

这是我的图像视图如何实例化:

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

如果我没有设置imageView.contentMode = UIViewContentModeScaleAspectFit; 缩略图将被扭曲,因为它只是我的原始图像的一个版本,高度为90像素。

那么,为什么我的缩略图不是平方?

最简单的事情就是将contentMode上的contentMode设置为UIViewContentModeScaleAspectFill 。 然而,这可能并不理想,因为它会把整个图像保存在记忆中。

这里是我用来调整图像的一些代码。

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

如果尺寸与图像的宽高比不一样,此版本将保持图像不被扭曲。

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

通常你只需要一个图像的顶部平方 (而不是中心)。 而且你希望最终的图像具有一定的尺寸,比如128×128,就像下面的例子。

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

以下是您可以参考的链接:

1) UIImage +resize

2) UIImage + ProportionalFill

在这里,您可以调整视图的大小,并添加比例填充,以便按比例填充纵横比和其他function,如裁剪,比例等。

您可以使用-(UIImage*)resizedImageToSize:(CGSize*)size方法在参考链接UIImage +resize以上只是为了重新形象的图像。

希望这可以帮助你。

让我知道你是否需要更多的帮助。

上面的聪明错误的Swift 2.x版本的答案:

  // 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() 

另一种方法 – 前几天遇到问题,而其他人在使用最适合大图像的苹果示例代码时可能会遇到同样的问题。

正如在接受的答案中提到的那样,这有把整个图像加载到内存中的问题,如果它太大,iOS可能会杀死你的应用程序。 苹果示例代码中的CGImageSourceCreateThumbnailAtIndex效率更高,但是该示例中存在一个错误。 CFDictionaryCreate中的第三个参数是要复制的“numValues”。 需要3个而不是2个。

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