2009-04-07 8 views
8

UPDATE:UIImagePickerController edycji dozwolony zamki UIImage do max wielkości 320x320

z iPhone OS 3.0+ cały UIImagePickerController API zmieniła. To pytanie i odpowiedź należy rozważyć 2.2. starszy kod.


Podczas korzystania z UIImagePickerController i pozwala na edycję obrazu. IPhone pozwala użytkownikowi na zmianę rozmiaru i panoramowanie obrazu. Jednak maksymalny rozmiar edytowanego obrazu jest ograniczony do 320x320.

Jako przykład wziąłem zrzut ekranu iPhone'a i umieściłem go w bibliotece zdjęć, która ma wymiary 480 x 320 png. Kiedy używam UIImagePickerController, aby wybrać ten obraz, nawet jeśli NIE skaluje ani nie przesunie obrazu, jest przycinany do 320x320, zanim zostanie zwrócony z UIImagePickerController. Jeśli jednak wyłączę edycję, obraz zostanie zwrócony w prawidłowym rozmiarze 480x320.

Moja teoria: Bardzo subtelnie iPhone wyświetla 2 niestandardowe półprzezroczyste paski narzędzi, które nakładają się na obraz. Te paski narzędzi pozostawiają nieszkodliwe "okno" 320x320 nad zdjęciem. Wydaje mi się, że to okno skutecznie przycina podstawowe zdjęcie.

Uwaga: Callback zwraca również słownik do edycji z oryginalnym obrazem i przycinkiem rect, ale oczywiście rect ma również max 320x320.

Jakieś pomysły dotyczące skalowania i panoramowania obrazów większych niż 320x320?

Część kodu:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo { 

     self.myImageView.userInteractionEnabled=YES; 
     CGRect imageFrame = myImageView.frame; 
     CGPoint imageCenter = myImageView.center; 
     imageFrame.size = img.size; 
     myImageView.frame = imageFrame; 
     self.myImageView.image = img; 
     myImageView.center = imageCenter; 

     [self dismissModalViewControllerAnimated:YES]; 
     [self performSelector:@selector(hideToolBars) withObject:nil afterDelay:2.0]; 
    } 
+0

Wciąż widzę ten problem w wersji 3.0.1, czy zostało to naprawione w wersji 3.1? – Jasarien

Odpowiedz

7

Jak powiedział Craig, jest to problem na forach dev i jabłek regularnym forum dyskusyjnym. Jednak znalazłem sposób obejścia tego. Używam kawałek kodu z:

Apple Dev Forums

Obejmuje większość tego, co trzeba, i troszczy się o wszystkich kwestiach orientacji aparatu. Dodałem następujących składników, które odbędzie się w informacji do edycji i używać go dostać oryginalną rect przycinania z tym dodatkowo:

- (UIImage*)scaleImage:(UIImage*)anImage withEditingInfo:(NSDictionary*)editInfo{ 

    UIImage *newImage; 

    UIImage *originalImage = [editInfo valueForKey:@"UIImagePickerControllerOriginalImage"]; 
    CGSize originalSize = CGSizeMake(originalImage.size.width, originalImage.size.height); 
    CGRect originalFrame; 
    originalFrame.origin = CGPointMake(0,0); 
    originalFrame.size = originalSize; 

    CGRect croppingRect = [[editInfo valueForKey:@"UIImagePickerControllerCropRect"] CGRectValue]; 
    CGSize croppingRectSize = CGSizeMake(croppingRect.size.width, croppingRect.size.height); 

    CGSize croppedScaledImageSize = anImage.size; 

    float scaledBarClipHeight = 80; 

    CGSize scaledImageSize; 
    float scale; 

    if(!CGSizeEqualToSize(croppedScaledImageSize, originalSize)){ 

     scale = croppedScaledImageSize.width/croppingRectSize.width; 
     float barClipHeight = scaledBarClipHeight/scale; 

     croppingRect.origin.y -= barClipHeight; 
     croppingRect.size.height += (2*barClipHeight); 

     if(croppingRect.origin.y<=0){ 
      croppingRect.size.height += croppingRect.origin.y; 
      croppingRect.origin.y=0; 
     } 

     if(croppingRect.size.height > (originalSize.height - croppingRect.origin.y)){ 
      croppingRect.size.height = (originalSize.height - croppingRect.origin.y); 
     } 


     scaledImageSize = croppingRect.size; 
     scaledImageSize.width *= scale; 
     scaledImageSize.height *= scale; 

     newImage = [self cropImage:originalImage to:croppingRect andScaleTo:scaledImageSize]; 

    }else{ 

     newImage = originalImage; 

    } 

    return newImage; 
} 

zaktualizowałem oddzwaniania metodę z forów dev odpowiedzieć na następujące kwestie:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo { 

    [self dismissModalViewControllerAnimated:YES]; 
    self.myImageView.userInteractionEnabled=YES; 
    CGRect imageFrame = myImageView.frame; 
    CGPoint imageCenter = myImageView.center; 
    UIImage *croppedImage; 


    NSMutableDictionary *imageDescriptor = [editInfo mutableCopy]; 

    // CGFloat scaleSize = 400.0f; 
    CGFloat scaleSize = 640.0f; 
    switch ([picker sourceType]) { 
      //done 
     case UIImagePickerControllerSourceTypePhotoLibrary: 
      croppedImage = [self scaleImage:img withEditingInfo:editInfo]; 
      [imageDescriptor setObject:croppedImage forKey:@"croppedImage"]; 
      break; 


     case UIImagePickerControllerSourceTypeCamera: { 
      UIImageOrientation originalOrientation = [[editInfo objectForKey:UIImagePickerControllerOriginalImage] imageOrientation]; 
      if (originalOrientation != UIImageOrientationUp) { 
       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
       CGRect origRect; 
       [[editInfo objectForKey:UIImagePickerControllerCropRect] getValue:&origRect]; 
       UIImage *rotatedImage = straightenAndScaleImage([editInfo objectForKey:UIImagePickerControllerOriginalImage], scaleSize); 
       CGFloat scale = scaleSize/1600.0f; 
       origRect.origin.x *= scale; 
       origRect.origin.y *= scale; 
       origRect.size.width *= scale; 
       origRect.size.height *= scale; 
       croppedImage = [self cropImage:rotatedImage to:origRect andScaleTo:CGSizeMake(320, 480)]; 
       [imageDescriptor setObject:croppedImage forKey:@"croppedImage"]; 
       [pool drain]; 
      } 
      else { 
       croppedImage = [self scaleImage:img withEditingInfo:editInfo]; 
       [imageDescriptor setObject:croppedImage forKey:@"croppedImage"]; 
      } 
     } 
      break; 

     case UIImagePickerControllerSourceTypeSavedPhotosAlbum: { 
      UIImageOrientation originalOrientation = [[editInfo objectForKey:UIImagePickerControllerOriginalImage] imageOrientation]; 
      if (originalOrientation != UIImageOrientationUp) { 
       NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
       CGRect origRect; 
       [[editInfo objectForKey:UIImagePickerControllerCropRect] getValue:&origRect]; 
       UIImage *rotatedImage = straightenAndScaleImage([editInfo objectForKey:UIImagePickerControllerOriginalImage], scaleSize); 
       CGFloat scale = scaleSize/640.0f; 
       origRect.origin.x *= scale; 
       origRect.origin.y *= scale; 
       origRect.size.width *= scale; 
       origRect.size.height *= scale; 
       croppedImage = [self cropImage:rotatedImage to:origRect andScaleTo:CGSizeMake(320, 480)]; 
       [imageDescriptor setObject:croppedImage forKey:@"croppedImage"]; 
       [pool drain]; 
      } 
      else { 
       croppedImage = [self scaleImage:img withEditingInfo:editInfo]; 
       [imageDescriptor setObject:croppedImage forKey:@"croppedImage"]; 
      } 
     } 
      break; 
     default: 
      break; 
    } 

    imageFrame.size = croppedImage.size; 
    myImageView.frame = imageFrame; 
    myImageView.image = [imageDescriptor objectForKey:@"croppedImage"]; 
    myImageView.center = imageCenter; 


} 
+0

Zamiast wykonywać: CGSize originalSize = CGSizeMake (originalImage.size.width, originalImage.size.height); można po prostu wykonać: CGSize originalSize = originalImage.size.width; –

+0

@Frank - Myślę, że masz na myśli, że możesz po prostu zrobić CGSize originalSize = originalImage.size; – Brian

+0

@Brian - Tak, to właśnie miałem na myśli. Nie mam pewności, w jaki sposób .width się tam dostał. Powinieneś dostać odznakę za odebranie 3-letniego błędu! –

1

lepiej późno niż wcale: oto źródło dla funkcji orientationTransformForImage

 

CGAffineTransform orientationTransformForImage(UIImage *image, CGSize *newSize) { 
    CGImageRef img = [image CGImage]; 
    CGFloat width = CGImageGetWidth(img); 
    CGFloat height = CGImageGetHeight(img); 
    CGSize size = CGSizeMake(width, height); 
    CGAffineTransform transform = CGAffineTransformIdentity; 
    CGFloat origHeight = size.height; 
    UIImageOrientation orient = image.imageOrientation; 
    switch(orient) { /* EXIF 1 to 8 */ 
     case UIImageOrientationUp: 
      break; 
     case UIImageOrientationUpMirrored: 
      transform = CGAffineTransformMakeTranslation(width, 0.0f); 
      transform = CGAffineTransformScale(transform, -1.0f, 1.0f); 
      break; 
     case UIImageOrientationDown: 
      transform = CGAffineTransformMakeTranslation(width, height); 
      transform = CGAffineTransformRotate(transform, M_PI); 
      break; 
     case UIImageOrientationDownMirrored: 
      transform = CGAffineTransformMakeTranslation(0.0f, height); 
      transform = CGAffineTransformScale(transform, 1.0f, -1.0f); 
      break; 
     case UIImageOrientationLeftMirrored: 
      size.height = size.width; 
      size.width = origHeight; 
      transform = CGAffineTransformMakeTranslation(height, width); 
      transform = CGAffineTransformScale(transform, -1.0f, 1.0f); 
      transform = CGAffineTransformRotate(transform, 3.0f * M_PI/2.0f); 
      break; 
     case UIImageOrientationLeft: 
      size.height = size.width; 
      size.width = origHeight; 
      transform = CGAffineTransformMakeTranslation(0.0f, width); 
      transform = CGAffineTransformRotate(transform, 3.0f * M_PI/2.0f); 
      break; 
     case UIImageOrientationRightMirrored: 
      size.height = size.width; 
      size.width = origHeight; 
      transform = CGAffineTransformMakeScale(-1.0f, 1.0f); 
      transform = CGAffineTransformRotate(transform, M_PI/2.0f); 
      break; 
     case UIImageOrientationRight: 
      size.height = size.width; 
      size.width = origHeight; 
      transform = CGAffineTransformMakeTranslation(height, 0.0f); 
      transform = CGAffineTransformRotate(transform, M_PI/2.0f); 
      break; 
     default: 
      ; 
    } 
    *newSize = size; 
    return transform; 
} 
5

muszę być za późno, aby odpowiedzieć na to pytanie, ale mam lepszy sposób t o załatw to zadanie.

static inline double radians (double degrees) {return degrees * M_PI/180;} 

+(UIImage*)editedImageFromMediaWithInfo:(NSDictionary*)info{ 
    if(![info objectForKey:UIImagePickerControllerCropRect])return nil; 
    if(![info objectForKey:UIImagePickerControllerOriginalImage])return nil; 

    UIImage *originalImage=[info objectForKey:UIImagePickerControllerOriginalImage]; 
    CGRect rect=[[info objectForKey:UIImagePickerControllerCropRect] CGRectValue]; 

    CGImageRef imageRef = CGImageCreateWithImageInRect([originalImage CGImage], rect); 

    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef); 
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef); 
    CGContextRef bitmap = CGBitmapContextCreate(NULL, rect.size.width, rect.size.height, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo); 

    if (originalImage.imageOrientation == UIImageOrientationLeft) { 
     CGContextRotateCTM (bitmap, radians(90)); 
     CGContextTranslateCTM (bitmap, 0, -rect.size.height); 

    } else if (originalImage.imageOrientation == UIImageOrientationRight) { 
     CGContextRotateCTM (bitmap, radians(-90)); 
     CGContextTranslateCTM (bitmap, -rect.size.width, 0); 

    } else if (originalImage.imageOrientation == UIImageOrientationUp) { 
     // NOTHING 
    } else if (originalImage.imageOrientation == UIImageOrientationDown) { 
     CGContextTranslateCTM (bitmap, rect.size.width, rect.size.height); 
     CGContextRotateCTM (bitmap, radians(-180.)); 
    } 

    CGContextDrawImage(bitmap, CGRectMake(0, 0, rect.size.width, rect.size.height), imageRef); 
    CGImageRef ref = CGBitmapContextCreateImage(bitmap); 

    UIImage *resultImage=[UIImage imageWithCGImage:ref]; 
    CGImageRelease(imageRef); 
    CGContextRelease(bitmap); 
    CGImageRelease(ref); 

    return resultImage; 
} 

To crops tylko oryginalny obraz ze względną CropRect, chociaż ta metoda nie robi skali obrazu, ale jest krótki i słodki dla mnie. Tylko dla odniesienia :)

2

z iPhone OS 3.0+, cała UIImagePickerController API zmieniło. To pytanie i odpowiedź: należy uznać za 2.2. starszy kod.

Pomimo swojej ostrzeżenia, zajęło mi godzinę cennego dev zrealizować iOS 3.0+ dał nam UIImagePickerControllerEditedImage co sprawia, że ​​do czynienia z ręcznie przycinania do użytkownika pinch zoom/i radzenia sobie z orientacją niepotrzebne.

Jest tak na wypadek, gdyby ktoś nadal używał UIImagePickerControllerOriginalImage i próbował dowiedzieć się, jak najlepiej zastosować przycinanie za pomocą UIImagePickerControllerCropRect itp. Nie jest już potrzebny.

0

Napisałem category on UIImage, który zapewnia uprawę w pełnej rozdzielczości. Najłatwiejszy sposób instalacji to CocoaPods, dodając UIImage-ImagePickerCrop do swojego podfile.

#import <UIImage+ImagePickerCrop.h> 

... 

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info { 
    [self dismissViewControllerAnimated:YES completion:nil]; 

    UIImage *croppedImage = [UIImage croppedImageWithImagePickerInfo:info]; 
    ... 
} 
Powiązane problemy