Редактирование UIImagePickerController позволило заблокировать UIImage до максимального размера 320x320 - PullRequest
8 голосов
/ 07 апреля 2009

Обновление:

В iPhone OS 3.0+ весь API UIImagePickerController изменился. Этот вопрос и ответ следует рассмотреть 2.2. устаревший код.


При использовании UIImagePickerController и вы разрешаете редактирование изображения. IPhone позволяет пользователю изменять размер и панорамировать изображение. Тем не менее, максимальный размер редактируемого изображения ограничен 320x320.

В качестве примера я сделал снимок экрана iPhone и поместил его в библиотеку фотографий размером 480x320 png. Когда я использую UIImagePickerController для выбора этого изображения, даже если я НЕ масштабирую или панорамирую изображение, оно обрезается до 320x320, прежде чем оно будет возвращено из UIImagePickerController. Однако, если я выключу редактирование, изображение вернется к нужному размеру 480x320.

Моя теория: Очень тонко, iPhone отображает 2 нестандартных полупрозрачных панели инструментов, которые накладываются на изображение. Эти панели инструментов оставляют безобидное 320x320 «окно» над фотографией. Мне кажется, что это окно эффективно обрезает основную фотографию.

Примечание: Обратный вызов также возвращает словарь редактирования с исходным изображением и прямоугольником отсечения, но, конечно, прямоугольник также имеет максимальный размер 320x320.

Есть ли идеи о том, как разрешить масштабирование и панорамирование изображений размером более 320x320?

Код:

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

Ответы [ 6 ]

7 голосов
/ 11 апреля 2009

Как сказал Крэйг, это проблема на форумах разработчиков и на форуме для обсуждения яблок. Однако я нашел способ обойти это. Я использую немного кода из:

Форумы разработчиков Apple

Это включает в себя большую часть того, что вам нужно, и заботится обо всех проблемах ориентации камеры. Я добавил следующее, которое будет принимать информацию для редактирования и использовать ее для получения исходного прямоугольника обрезки с этим дополнением:

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

Я обновил метод обратного вызова из сообщения на форуме разработчиков:

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


}
5 голосов
/ 28 февраля 2011

Я должен быть слишком поздно, чтобы ответить на этот вопрос, но у меня есть лучший способ сделать эту работу.

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

Это только обрезает исходное изображение с относительным CropRect, хотя этот метод не масштабирует изображение, но он короткий и приятный для меня. Просто для справки:)

2 голосов
/ 16 марта 2011

С iPhone OS 3.0+, весь UIImagePickerController API имеет изменилось. Этот вопрос и ответ следует учитывать 2.2. устаревший код.

Несмотря на ваше предупреждение, мне потребовался драгоценный час разработки, чтобы понять, что iOS 3.0+ предоставила нам UIImagePickerControllerEditedImage, который избавляет от необходимости вручную обрезать пинч / зум пользователя и управлять ориентацией.

Это в том случае, если кто-то все еще использует UIImagePickerControllerOriginalImage и пытается выяснить, как лучше всего применить обрезку через UIImagePickerControllerCropRect и т. Д. Больше не требуется.

1 голос
/ 18 февраля 2011

Лучше поздно, чем никогда: вот источник 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;
}
1 голос
/ 07 апреля 2009

Похоже, что это мешает SDK, по крайней мере, при установке для allowImageEditing значения TRUE в средстве выбора изображений. На форумах Apple есть небольшая дискуссия на эту тему:

http://discussions.apple.com/message.jspa?messageID=7841993

0 голосов
/ 03 апреля 2014

Я написал категорию на UIImage , которая обеспечивает кадрирование в полном разрешении. Самый простой способ установки - с помощью CocoaPods , добавив UIImage-ImagePickerCrop в ваш подфайл.

#import <UIImage+ImagePickerCrop.h>

...

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

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