8

アップデート:

iPhone OS 3.0 以降では、UIImagePickerController API 全体が変更されました。この質問と回答は 2.2 と見なす必要があります。レガシーコード。


UIImagePickerController を使用し、画像の編集を許可する場合。iPhone では、ユーザーは画像のサイズ変更とパンを行うことができます。ただし、編集した画像の最大サイズは 320x320 に制限されています。

例として、iPhone のスクリーンショットを撮り、480x320 の png であるフォト ライブラリに配置しました。UIImagePickerController を使用してその画像を選択すると、画像を拡大縮小またはパンしなくても、UIImagePickerController から返される前に 320x320 にトリミングされます。ただし、編集をオフにすると、画像は適切な 480x320 サイズで返されます。

私の理論: 非常に微妙に、iPhone は画像の上に重なる 2 つの非標準の半透明のツールバーを表示します。これらのツールバーは、写真の上に無害な 320x320 の「ウィンドウ」を残します。このウィンドウは、下にある写真を効果的に切り取っているように見えます。

注: コールバックは元の画像とクリッピング rect を含む編集辞書も返しますが、もちろん rect も最大 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];
    }
4

6 に答える 6

7

craig が言ったように、これは開発者フォーラムとリンゴの通常のディスカッション ボードの問題です。しかし、私はそれを回避する方法を見つけました。私は次のコードを少し使用しています:

Apple Dev フォーラム

これには、必要なもののほとんどが含まれており、カメラの向きに関するすべての問題が処理されます。編集情報を取り込み、それを使用して、この追加で元のトリミング四角形を取得する次のものを追加しました。

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


}
于 2009-04-11T17:59:16.910 に答える
5

この質問に答えるには遅すぎるに違いありませんが、この仕事を成し遂げるためのより良い方法があります。

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 を使用して元の画像をトリミングするだけですが、私にとっては短くて便利です。参考までに:)

于 2011-02-28T16:32:36.940 に答える
2

遅刻するよりはましです。orientationTransformForImage関数のソースは次のとおりです。

CGAffineTransform orientationTransformForImage(UIImage *image, CGSize *newSize) {
    CGImageRef img = [画像 CGImage];
    CGFloat 幅 = CGImageGetWidth(img);
    CGFloat の高さ = CGImageGetHeight(img);
    CGSize size = CGSizeMake(幅, 高さ);
    CGAffineTransform 変換 = CGAffineTransformIdentity;
    CGFloat origHeight = size.height;
    UIImageOrientation orient = image.imageOrientation;
    switch(orient) { /* EXIF 1 ~ 8 */
        ケース UIImageOrientationUp:
            壊す;
        ケース UIImageOrientationUpMirrored:
            変換 = CGAffineTransformMakeTranslation(幅, 0.0f);
            変換 = CGAffineTransformScale(変換、-1.0f、1.0f);
            壊す;
        ケース UIImageOrientationDown:
            変換 = CGAffineTransformMakeTranslation(幅、高さ);
            変換 = CGAffineTransformRotate(変換、M_PI);
            壊す;
        ケース UIImageOrientationDownMirrored:
            変換 = CGAffineTransformMakeTranslation(0.0f, 高さ);
            変換 = CGAffineTransformScale(変換、1.0f、-1.0f);
            壊す;
        ケース UIImageOrientationLeftMirrored:
            size.height = size.width;
            size.width = origHeight;
            変換 = CGAffineTransformMakeTranslation(高さ、幅);
            変換 = CGAffineTransformScale(変換、-1.0f、1.0f);
            変換 = CGAffineTransformRotate(変換、3.0f * M_PI / 2.0f);
            壊す;
        ケース UIImageOrientationLeft:
            size.height = size.width;
            size.width = origHeight;
            変換 = CGAffineTransformMakeTranslation(0.0f, 幅);
            変換 = CGAffineTransformRotate(変換、3.0f * M_PI / 2.0f);
            壊す;
        ケース UIImageOrientationRightMirrored:
            size.height = size.width;
            size.width = origHeight;
            変換 = CGAffineTransformMakeScale(-1.0f, 1.0f);
            変換 = CGAffineTransformRotate(変換、M_PI / 2.0f);
            壊す;
        ケース UIImageOrientationRight:
            size.height = size.width;
            size.width = origHeight;
            変換 = CGAffineTransformMakeTranslation(高さ、0.0f);
            変換 = CGAffineTransformRotate(変換、M_PI / 2.0f);
            壊す;
        デフォルト:
            ;
    }
    *newSize = サイズ;
    変換を返します。
}
于 2011-02-18T03:28:00.483 に答える
2

iPhone OS 3.0 以降では、UIImagePickerController API 全体が変更されました。この質問と回答は 2.2 と見なす必要があります。レガシーコード。

あなたの警告にもかかわらず、iOS 3.0+ が UIImagePickerControllerEditedImage を提供し、ユーザーのピンチ/ズームに合わせて手動でトリミングしたり、向きを処理したりする必要がなくなったことに気付くのに貴重な開発時間を要しました。

これは、誰かがまだ UIImagePickerControllerOriginalImage を使用していて、UIImagePickerControllerCropRect などを介してクロッピングを適用する最善の方法を見つけようとしている場合に備えています。不要になりました。

于 2011-03-16T07:57:16.223 に答える
1

これは、少なくともイメージ ピッカーで allowImageEditing を TRUE に設定する場合、SDK の妨げになるようです。このトピックについては、次の Apple フォーラムで少し議論されています。

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

于 2009-04-07T18:35:36.880 に答える