2013-07-26 24 views
14

私のアプリでは、ユーザーが画像を選択するか、UIImagePickerViewControllerを使って画像を撮ります。画像を選択したら、そのサムネイルを正方形のUIImageView(90x90)に表示したいと思います。UIImagePickerViewControllerの四角いサムネイル画像

私はApple's codeを使用してサムネイルを作成しています。問題は、サムネイルが二乗されていないことです。関数は、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ピクセルのちょうどバージョンです。

なぜ、サムネイルが二乗されないのですか?ここで

+0

注 - のiOSの知識を持つメタユーザーは、いくつかの超便利なコードを離れて編集しました以下のCleverの答えから。実際にプログラミングして実際に役に立つ答えが得られ、実際にClever(壮大な)アイデアを使用したい場合は、以下の「編集」ボタンをクリックするだけで履歴が表示され、切り取り、貼り付け、アプリストアに送信できます: ) – Fattie

+0

@JoeBlow Clever Errorの回答の[編集履歴](http://stackoverflow.com/posts/17884863/revisions)に削除されたコードはありません。 – cpburnz

+0

http://stackoverflow.com/posts/17884863/revisions rev "5" – Fattie

答えて

52

あなたのimageViewの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; 
} 

は、多くの場合、あなたは(というよりも中央)画像のちょうどトップ平方をしたいです。下の例のように、最終イメージのサイズが128x128となるようにします。

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

このアプローチはイメージを歪めます。私はすでにこれを試しました。 – douglasd3

+2

イメージを歪ませてはならないバージョンを追加しました。 –

+0

これは歪んでいませんが、サムネイル画像は二乗されません。つまり、90x90ですが、画像は四角形を塗りつぶすように拡大されませんでした。 – douglasd3

6

あなたが参照できるリンクです:ここでは

1)UIImage+Resize

2)UIImage+ProportionalFill

あなたは、ビューのサイズを変更しても、そのため比例​​アスペクト比と他のを比例塗りつぶしを追加することができますクロップ、スケールなどの機能

上記の参照リンクUIImage + Resizeの下で-(UIImage*)resizedImageToSize:(CGSize*)sizeメソッドを使用すると、イメージを拡大することができます。

希望すると、これが役立ちます。

さらなるヘルプが必要な場合はお知らせください。

+0

2番目のリンクは本当に役に立ちました。私はまだ問題が何だったのか分かっていないが、今働いていると、それは私に多くの時間を節約するだろう。ありがとう! – douglasd3

+1

@ douglasd3:2番目のリンクは、トリミングやスケーリングのような多くの機能に本当に役立ちます。 –

0

これを行うための別の方法は - 先日の問題に遭遇し、大規模なイメージのために最善であるapple sample codeを使用したときに、他の人が同じ問題がある可能性があります。

受け入れられた回答に記載されているとおり、これは画像全体をメモリに読み込む問題があり、大きすぎるとiOSによってアプリが強制終了する可能性があります。AppleのサンプルコードのCGImageSourceCreateThumbnailAtIndexはより効率的ですが、この例ではバグがあります。 CFDictionaryCreateの3番目のパラメータは、コピーするnumValuesです。 にする必要がない2.

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

OKですが、私はこのメソッドをQuartzを使って受け入れる答えに対してテストしました。受け入れられた答えは 'UIImage'を持っていれば15倍高速です。' CGImageSourceCreateThumbnailAtIndex'を使用できるように 'CFData'に変換する必要があるためです。 。このプロセス全体が15倍遅くなります。 – SpaceDog

3

上記かしこいエラーの答えのスウィフト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() 
+1

Swift 3の場合、let thumbnailRectの割り当てをCGRect(x:x、y:y、width:width、height:height)に変更します。 –

関連する問題