2009-04-07 3 views
8

Aggiornamento:editing UIImagePickerController serrature ammessi UIImage al formato massimo di 320x320

Con iPhone OS 3.0+, l'intera UIImagePickerController API è cambiato. Questa domanda e risposta dovrebbero essere considerate 2.2. codice legacy.


Quando si utilizza UIImagePickerController e si consente la modifica dell'immagine. L'iPhone consente all'utente di ridimensionare e spostare l'immagine. Tuttavia, la dimensione massima di un'immagine modificata è limitata a 320 x 320.

Ad esempio, ho preso uno screenshot per iPhone e l'ho inserito nella libreria di foto, che è un png 480x320. Quando utilizzo un UIImagePickerController per selezionare quell'immagine, anche se NON ridimensiono o eseguo il panning dell'immagine, questa viene ritagliata a 320x320 prima di essere restituita da UIImagePickerController. Tuttavia, se disattivo la modifica, all'immagine viene restituita la dimensione corretta di 480x320.

La mia teoria: In modo molto sottile, l'iPhone visualizza 2 barre degli strumenti traslucide non standard che si sovrappongono sull'immagine. Queste barre degli strumenti lasciano una innocua "finestra" 320x320 sulla foto. Mi sembra che questa finestra blocchi efficacemente la foto sottostante.

Nota: Il callback restituisce anche un dizionario di modifica con l'immagine originale e il ritaglio di ritaglio, ma ovviamente il rect è anche 320x320 massimo.

Qualche idea su come consentire la ridimensionamento e la panoramica delle immagini più grandi di 320x320?

Alcuni codice:

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

Sto ancora vedendo questo problema su 3.0.1, è corretto in 3.1? – Jasarien

risposta

7

Come ha detto Craig, questo è un problema nei forum dev e le mele di discussione regolare. Tuttavia, ho trovato un modo per aggirarlo. Sto usando un po 'di codice da:

Apple Dev Forums

Questo include la maggior parte di ciò che è necessario, e si prende cura di tutte le questioni di orientamento della fotocamera. Ho aggiunto la seguente che avrà nelle informazioni modificate e utilizzate per ottenere il rect ritaglio originale con questa aggiunta:

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

ho aggiornato il metodo di richiamata dal forum dev inviare al seguente:

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

Invece di fare: CGSize originalSize = CGSizeMake (originalImage.size.width, originalImage.size.height); si può solo fare CGSize originalSize = originalImage.size.width; –

+0

@Frank - Penso che tu intenda che puoi semplicemente creare CGSize originalSize = originalImage.size; – Brian

+0

@ Brian - Sì, è quello che intendevo. Non sono sicuro di come sia stata la larghezza. Dovresti ottenere una sorta di badge per ritirare un errore di 3 anni! –

1

meglio tardi che mai: ecco la sorgente per la funzione 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

devo essere troppo tardi per rispondere a questa domanda, ma ho avuto un modo migliore t o fai questo lavoro.

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

E colture solo l'immagine originale con la relativa CropRect, anche se questa scala metodo dosen't l'immagine, ma è breve e dolce per me. Solo per riferimento :)

2

Con iPhone OS 3.0+, l'intera UIImagePickerController API è cambiato. Questa domanda e risposta dovrebbe essere considerata 2.2. codice legacy.

Nonostante il vostro avvertimento, ci ho messo un prezioso un'ora dev per realizzare iOS 3.0+ ci hanno dato UIImagePickerControllerEditedImage che rende trattare con il ritaglio manualmente per l'utente pinch/zoom e si occupano di orientamento inutili.

Questo è il caso in cui qualcuno stava ancora utilizzando UIImagePickerControllerOriginalImage e sta cercando di capire come applicare il ritaglio tramite UIImagePickerControllerCropRect, ecc. Non è più necessario.

0

Ho scritto un category on UIImage che fornisce un ritaglio a piena risoluzione. Il modo più semplice per installare è con CocoaPods, aggiungendo UIImage-ImagePickerCrop al tuo file pod.

#import <UIImage+ImagePickerCrop.h> 

... 

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

    UIImage *croppedImage = [UIImage croppedImageWithImagePickerInfo:info]; 
    ... 
}