2012-05-08 64 views
6

Więc próbuję od razu dowiedzieć się, co robię źle, i nie mogę tego rozgryźć. Co staram się osiągnąć to:Zmiana rozmiaru UII nie działa prawidłowo

  1. Zrób zdjęcie z UIImagePickerController
  2. Take wynikowy fotografię i przyciąć poza górną i dolną tak staje kwadrat (podobny do Instagram)
  3. wyświetlacz, który obraz w UIButton

z jakiegoś powodu, za każdym razem biorę fotografię kończy się zniekształcony w UIButton i wydaje się jakby przycinania nie działa prawidłowo. Oto co robię. W ramach metody didFinishPickingMediaWithInfo Mam następujący kod:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
    //Copy the image to the userImage variable 
    [picker dismissModalViewControllerAnimated:YES]; 
    userImage = nil; 

    //Rotate & resize image 
    userImage = [self resizeAndRotatePhoto:(UIImage *)[info objectForKey:UIImagePickerControllerOriginalImage]]; 
    NSLog(@"Userimage size, width: %f , height: %f", userImage.size.width , userImage.size.height); 

    //Update the image form field with the image and set the image in the controller 
    NSLog(@"Button size is height: %f , width: %f" , userImageAvatarButton.frame.size.height , userImageAvatarButton.frame.size.width); 
    [userImageAvatarButton.layer setMasksToBounds:YES]; 
    [userImageAvatarButton.layer setCornerRadius:3.0]; 
    [userImageAvatarButton setImage:userImage forState:UIControlStateNormal]; 
} 

będę obejmują metodę resizeAndRotatePhoto chwilę, ale wynik jest poniżej. Ponadto w powyższym kodzie @property (strong) (UIImage *)userImage; jest zdefiniowany w pliku nagłówkowym ViewController. Wynik logu powoduje również:

2012-05-07 17:38:07.995 NewApp[10666:707] Userimage size, width: 1936.000000 , height: 1936.000000 
2012-05-07 17:38:08.000 NewApp[10666:707] Button size is height: 60.000000 , width: 60.000000 

Jak widać na poniższym obrazku, zostanie zniekształcony.
form with button

chodzi o metodę resizeAndRotate, tutaj jest:

- (UIImage *)resizeAndRotatePhoto:(UIImage *)source 
{ 
if(source.imageOrientation == UIImageOrientationRight) 
{ 
    source = [self rotateImage:source byDegrees:90]; 
} 
if(userImage.imageOrientation == UIImageOrientationLeft) 
{ 
    source = [self rotateImage:source byDegrees:-90]; 
} 

CGFloat x,y; 
CGFloat size; 
if(source.size.width > source.size.height){ 
    size = source.size.height; 
    x = (source.size.width - source.size.height)/2; 
    y = 0; 
} 
else { 
    size = source.size.width; 
    x = 0; 
    y = (source.size.height - source.size.width)/2; 
} 


CGImageRef imageRef = CGImageCreateWithImageInRect([source CGImage], CGRectMake(x,y,size,size)); 
return [UIImage imageWithCGImage:imageRef]; 
} 

W tym momencie nie mam pojęcia w jaki sposób uzyskać obraz, aby pokazać się niezakłócona. Wygląda na to, że przycina go nieprawidłowo i wyświetla błąd, mimo że system mówi, że obraz jest rzeczywiście kwadratem.

Odpowiedz

9

Porzuciłem to rozwiązanie vocaro.com z innych powodów (takie rozwiązanie zawiesiłoby się w przypadku korzystania z nietypowych formatów obrazu, np. CMYK).

W każdym razie teraz używam metody imageByScalingAspectFillSize następującej kategorii: UIImage, aby tworzyć kwadratowe miniatury.

Nawiasem mówiąc, to automatycznie stosuje skalę ekranu głównego urządzenia (np. Przycisk UIButton, czyli 60x60 punktów na urządzeniu Retina, to zastosuje tę skalę 2x (lub 3x), tj. 120x120 lub Obraz 180x180).

UIImage + SimpleResize.h:

/* UIImage+SimpleResize.h 
* 
* Modified by Robert Ryan on 5/19/11. 
*/ 

@import UIKit; 

/** Image resizing category. 
* 
* Modified by Robert Ryan on 5/19/11. 
* 
* Inspired by http://ofcodeandmen.poltras.com/2008/10/30/undocumented-uiimage-resizing/ 
* but adjusted to support AspectFill and AspectFit modes. 
*/ 

@interface UIImage (SimpleResize) 

/** Resize the image to be the required size, stretching it as needed. 
* 
* @param size   The new size of the image. 
* @param contentMode The `UIViewContentMode` to be applied when resizing image. 
*      Either `UIViewContentModeScaleToFill`, `UIViewContentModeScaleAspectFill`, or 
*      `UIViewContentModeScaleAspectFit`. 
* 
* @return    Return `UIImage` of resized image. 
*/ 

- (UIImage * _Nullable)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode; 

/** Resize the image to be the required size, stretching it as needed. 
* 
* @param size   The new size of the image. 
* @param contentMode The `UIViewContentMode` to be applied when resizing image. 
*      Either `UIViewContentModeScaleToFill`, `UIViewContentModeScaleAspectFill`, or 
*      `UIViewContentModeScaleAspectFit`. 
* @param scale  The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen. 
* 
* @return    Return `UIImage` of resized image. 
*/ 

- (UIImage * _Nullable)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode scale:(CGFloat)scale; 

/** Crop the image to be the required size. 
* 
* @param bounds  The bounds to which the new image should be cropped. 
* 
* @return    Cropped `UIImage`. 
*/ 

- (UIImage * _Nullable)imageByCroppingToBounds:(CGRect)bounds; 

/** Crop the image to be the required size. 
* 
* @param bounds  The bounds to which the new image should be cropped. 
* @param scale  The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen. 
* 
* @return    Cropped `UIImage`. 
*/ 

- (UIImage * _Nullable)imageByCroppingToBounds:(CGRect)bounds scale:(CGFloat)scale; 

/** Resize the image to fill the rectange of the specified size, preserving the aspect ratio, trimming if needed. 
* 
* @param size The new size of the image. 
* 
* @return  Return `UIImage` of resized image. 
*/ 

- (UIImage * _Nullable)imageByScalingAspectFillSize:(CGSize)size; 

/** Resize the image to fill the rectange of the specified size, preserving the aspect ratio, trimming if needed. 
* 
* @param size The new size of the image. 
* @param scale The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen. 
* 
* @return  Return `UIImage` of resized image. 
*/ 

- (UIImage * _Nullable)imageByScalingAspectFillSize:(CGSize)size scale:(CGFloat)scale; 

/** Resize the image to be the required size, stretching it as needed. 
* 
* @param size The new size of the image. 
* 
* @return  Resized `UIImage` of resized image. 
*/ 

- (UIImage * _Nullable)imageByScalingToFillSize:(CGSize)size; 

/** Resize the image to be the required size, stretching it as needed. 
* 
* @param size The new size of the image. 
* @param scale The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen. 
* 
* @return  Resized `UIImage` of resized image. 
*/ 

- (UIImage * _Nullable)imageByScalingToFillSize:(CGSize)size scale:(CGFloat)scale; 

/** Resize the image to fit within the required size, preserving the aspect ratio, with no trimming taking place. 
* 
* @param size The new size of the image. 
* 
* @return  Return `UIImage` of resized image. 
*/ 

- (UIImage * _Nullable)imageByScalingAspectFitSize:(CGSize)size; 

/** Resize the image to fit within the required size, preserving the aspect ratio, with no trimming taking place. 
* 
* @param size The new size of the image. 
* @param scale The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen. 
* 
* @return  Return `UIImage` of resized image. 
*/ 

- (UIImage * _Nullable)imageByScalingAspectFitSize:(CGSize)size scale:(CGFloat)scale; 

@end 

UIImage + SimpleResize.m:

// UIImage+SimpleResize.m 
// 
// Created by Robert Ryan on 5/19/11. 

#import "UIImage+SimpleResize.h" 

@implementation UIImage (SimpleResize) 

- (UIImage *)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode { 
    return [self imageByScalingToSize:size contentMode:contentMode scale:0]; 
} 

- (UIImage *)imageByScalingToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode scale:(CGFloat)scale { 
    if (contentMode == UIViewContentModeScaleToFill) { 
     return [self imageByScalingToFillSize:size]; 
    } 
    else if ((contentMode == UIViewContentModeScaleAspectFill) || 
      (contentMode == UIViewContentModeScaleAspectFit)) { 
     CGFloat horizontalRatio = self.size.width/size.width; 
     CGFloat verticalRatio  = self.size.height/size.height; 
     CGFloat ratio; 

     if (contentMode == UIViewContentModeScaleAspectFill) 
      ratio = MIN(horizontalRatio, verticalRatio); 
     else 
      ratio = MAX(horizontalRatio, verticalRatio); 

     CGSize sizeForAspectScale = CGSizeMake(self.size.width/ratio, self.size.height/ratio); 

     UIImage *image = [self imageByScalingToFillSize:sizeForAspectScale scale:scale]; 

     // if we're doing aspect fill, then the image still needs to be cropped 

     if (contentMode == UIViewContentModeScaleAspectFill) { 
      CGRect subRect = CGRectMake(floor((sizeForAspectScale.width - size.width)/2.0), 
             floor((sizeForAspectScale.height - size.height)/2.0), 
             size.width, 
             size.height); 
      image = [image imageByCroppingToBounds:subRect]; 
     } 

     return image; 
    } 

    return nil; 
} 

- (UIImage *)imageByCroppingToBounds:(CGRect)bounds { 
    return [self imageByCroppingToBounds:bounds scale:0]; 
} 

- (UIImage *)imageByCroppingToBounds:(CGRect)bounds scale:(CGFloat)scale { 
    if (scale == 0) { 
     scale = [[UIScreen mainScreen] scale]; 
    } 
    CGRect rect = CGRectMake(bounds.origin.x * scale, bounds.origin.y * scale, bounds.size.width * scale, bounds.size.height * scale); 
    CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], rect); 
    UIImage *croppedImage = [UIImage imageWithCGImage:imageRef scale:scale orientation:self.imageOrientation]; 
    CGImageRelease(imageRef); 
    return croppedImage; 
} 

- (UIImage *)imageByScalingToFillSize:(CGSize)size { 
    return [self imageByScalingToFillSize:size scale:0]; 
} 

- (UIImage *)imageByScalingToFillSize:(CGSize)size scale:(CGFloat)scale { 
    UIGraphicsBeginImageContextWithOptions(size, false, scale); 
    [self drawInRect:CGRectMake(0, 0, size.width, size.height)]; 
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return image; 
} 

- (UIImage *)imageByScalingAspectFillSize:(CGSize)size { 
    return [self imageByScalingAspectFillSize:size scale:0]; 
} 

- (UIImage *)imageByScalingAspectFillSize:(CGSize)size scale:(CGFloat)scale { 
    return [self imageByScalingToSize:size contentMode:UIViewContentModeScaleAspectFill scale:scale]; 
} 

- (UIImage *)imageByScalingAspectFitSize:(CGSize)size { 
    return [self imageByScalingAspectFitSize:size scale:0]; 
} 

- (UIImage *)imageByScalingAspectFitSize:(CGSize)size scale:(CGFloat)scale { 
    return [self imageByScalingToSize:size contentMode:UIViewContentModeScaleAspectFit scale:scale]; 
} 

@end 
+2

dziękuję. Po wielu godzinach frustracji i szukania w sieci próbując blisko 20 zaproponowanych rozwiązań, jest to jedyne rozwiązanie, które zadziałało. Wielkie dzięki. – thephatp

+1

tak. zaoszczędził mi również godzin pracy. Doceniam kategorię! – kevinl