3

私が開発しているアプリケーションでは、カメラでキャプチャしたいオブジェクトのサイズをユーザーに指定させます (たとえば、30" x 40")。次にやりたいことは、cameraOverlayView を上に置いてカメラ フィードを表示することです。そのオブジェクトをキャプチャするのに適切な比率を持つストロークされた透明な正方形だけを表示します。

だから私はこれを機能させるために2つのことを試みました:

を使用する UIViewController を使用しAVCaptureVideoPreviewLayerて、ライブ ビデオ フィードでビューを表示します。そのフィードの上に、(ユーザーが指定した比率を使用して) 適切な寸法の正方形を描画する透明なビューを表示します。

別の試みで、ポップアップするボタンを含む UIViewController を作成しましたUIImagePickerControllercameraOverlayViewこのコントローラーを使用して、プロパティを使用してピッカーにアタッチするビューも作成しました。

これらの両方の方法で私が抱えている主な問題は、実際にキャプチャされた画像が常に画面に表示されるものよりも大きいことですが、写真を撮った後にその画像の一部を切り取る方法が完全にはわかりません.

例: 私の UIImagePickerController が表示され、その上に 300 x 400px の正方形を示すオーバーレイを置きます。ユーザーはこの正方形を使用してオブジェクトの写真を撮り、オブジェクトをこの正方形の中央に配置します。

写真が撮影されますが、320x480 (または 640x960) の写真ではなく、3500x2400 (またはそのようなもの) の結果が得られます。これは、画面の比率とはまったく異なる比率です (もちろん)。

次に、画像の正しい部分を切り取るにはどうすればよいですか。

表示する必要がある正方形のサイズを実際に計算するコード (また、画像のどの部分を切り取るかを決定するために使用する必要があります):

+ (CGRect) getFrameRect:(CGRect) rect forSize:(CGSize) frameSize {
    if (CGSizeEqualToSize(frameSize, CGSizeZero))
        return CGRectZero;

    float maxWidth = rect.size.width - 20;
    float maxHeight = rect.size.height - 20;

    float ratioX = maxWidth / frameSize.width;
    float ratioY = maxHeight / frameSize.height;
    float ratio = MIN(ratioX, ratioY);

    float newWidth = frameSize.width * ratio;
    float newHeight = frameSize.height * ratio;

    float x = (rect.size.width - newWidth) / 2;
    float y = (rect.size.height - newHeight) / 2;

    return CGRectMake(x, y, newWidth, newHeight);
}

これにより、frameSize パラメーターで指定された比率で作成できる最大の正方形が決まります。正方形が描画される寸法は、rect パラメーターで指定されます。

いくつかの解決策が頭に浮かびますが、それが実行可能かどうかはわかりません。

  • 写真を画面の幅または高さ (どちらか先に来るもの) に縮小し、写真の中心を取り、それは写真を撮るときに表示される中心と同じですか? これがうまくいくかどうかわからないので、少し試してみましたが、失敗しました。
4

1 に答える 1

3

わかりました、解決策を見つけました:

カメラで写真を撮影しているとき、プレビュー画面には撮影中の写真の一部しか表示されません。

iOS デバイスが縦向きモードの場合、写真の高さは画面の高さまで縮小され、中央の 640 ピクセルのみが表示されます。

ここに画像の説明を入力

濃い赤の部分が画面に表示されている部分です。そのため、写真を撮るときは、画像を画面の最大の高さに縮小して、適切な幅にする必要があります。

その後、中央の 640x960 ピクセルを切り取って、写真を撮ったときに表示されたのと同じ画像を実際に取得しました。

その後、長方形のオーバーレイの座標はオーバーレイと同じになります。

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    [picker dismissModalViewControllerAnimated:YES];

    UIImage* artImage = [info objectForKey:UIImagePickerControllerOriginalImage];


    CGFloat imageHeightRatio = artImage.size.height / 960;
    CGFloat imageWidth = artImage.size.width / imageHeightRatio;

    CGSize newImageSize = CGSizeMake(imageWidth, 960);
    artImage = [artImage imageByScalingProportionallyToSize:newImageSize];

    CGRect cutOutRect = CGRectMake((artImage.size.width / 2) - (640 / 2), 0, 640, 960);

    artImage = [self imageByCropping:artImage toRect:cutOutRect];

    CGRect imageCutRect = [FrameSizeCalculations getFrameRect:CGRectMake(0,0, artImage.size.width, artImage.size.height) forSize:self.frameSize];
    artImage = [self imageByCropping:artImage toRect:imageCutRect];

    CGRect imageViewRect = CGRectInset(_containmentView.bounds, 10, 10);

    NSLog(@"ContainmentView: %f x %f x %f x %f",
          _containmentView.frame.origin.x,
          _containmentView.frame.origin.y,
          _containmentView.frame.size.width,
          _containmentView.frame.size.height
          );

    NSLog(@"imageViewRect: %f x %f x %f x %f",
          imageViewRect.origin.x,
          imageViewRect.origin.y,
          imageViewRect.size.width,
          imageViewRect.size.height
          );

    _imageView.frame = [FrameSizeCalculations getFrameRect:imageViewRect forSize:self.frameSize];

    NSLog(@"imageViewRect: %f x %f x %f x %f",
          _imageView.frame.origin.x,
          _imageView.frame.origin.y,
          _imageView.frame.size.width,
          _imageView.frame.size.height
          );

    _imageView.contentMode = UIViewContentModeScaleAspectFill;
    _imageView.image = artImage;
}
于 2013-04-25T06:48:18.223 に答える