1

Objective-C、iPhone iOS 6.0

以下のコードは縦方向の向きをうまくサポートしていますが、横向きにしようとすると、ピンチして自動ズームすると、ぎこちない縦向きモードに戻ります (横向きビュー)。

@implementation AVCapture
{
    CGFloat     beginGestureScale;
    CGFloat     effectiveScale;
}


- (id)initWithView:(UIView *)cameraView
{
    ......

    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];

    [self rotateToInterfaceOrientation:(UIInterfaceOrientation)[UIDevice currentDevice].orientation];

    [self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    self.previewLayer.frame = cameraView.frame;
    [self.previewLayer setPosition:CGPointMake(CGRectGetMidX(cameraView.bounds), CGRectGetMidY(cameraView.bounds))];
    [cameraView.layer addSublayer:self.previewLayer];

    effectiveScale = 1.0;

    ......
}


- (void)rotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    CALayer *previewLayer = self.previewLayer;

    switch (toInterfaceOrientation)
    {
        case UIDeviceOrientationLandscapeLeft:
            previewLayer.transform = CATransform3DMakeRotation(M_PI+M_PI_2, 0, 0, 1); // 270 degress
            break;

        case UIDeviceOrientationLandscapeRight:
            previewLayer.transform = CATransform3DMakeRotation(M_PI_2, 0, 0, 1); // 270 degress
            break;

        case UIDeviceOrientationPortraitUpsideDown:
            previewLayer.transform = CATransform3DMakeRotation(M_PI, 0, 0, 1); // 270 degress
            break;

        default:
            previewLayer.transform = CATransform3DMakeRotation(0.0, 0, 0, 1); // 270 degress
            break;
    }

}



// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#pragma mark Pinch to Zoom Gestures
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if ( [gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]] )
        beginGestureScale = effectiveScale;

    return YES;

}



- (void)handlePinchGesture:(UIPinchGestureRecognizer *)recognizer
{
    if ([recognizer numberOfTouches] < 2)
        return;


    BOOL allTouchesAreOnThePreviewLayer = YES;
    NSUInteger numTouches = [recognizer numberOfTouches], i;

    for (i=0; i<numTouches; ++i)
    {
        CGPoint location = [recognizer locationOfTouch:i inView:m_CameraView];
        CGPoint convertedLocation = [self.previewLayer convertPoint:location fromLayer:self.previewLayer.superlayer];

        if (![self.previewLayer containsPoint:convertedLocation])
        {
            allTouchesAreOnThePreviewLayer = NO;
            break;
        }
    }

    if (allTouchesAreOnThePreviewLayer)
    {
        effectiveScale = beginGestureScale * recognizer.scale;

        if (effectiveScale < 1.0)
            effectiveScale = 1.0;

        CGFloat maxScaleAndCropFactor = [[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo] videoMaxScaleAndCropFactor];

        if (effectiveScale > maxScaleAndCropFactor)
            effectiveScale = maxScaleAndCropFactor;

        [CATransaction begin];
        [CATransaction setAnimationDuration:.025];

        // Scale
        [self.previewLayer setAffineTransform:CGAffineTransformMakeScale(effectiveScale, effectiveScale)];

        [CATransaction commit];
    }

}

変換を維持する方法がわかりません。

4

2 に答える 2

0

解決しました!

これを見つけまし:「...プレビューレイヤーの向きを変更しても、画像のキャプチャ方法は変わりません。そのAVCaptureConnection's setVideoOrientation:方法を使用する必要があります。」

..そしてこれ

[captureVideoPreviewLayer.connection setVideoOrientation:self.interfaceOrientation];

だから私はこれを置き換えました:

[self rotateToInterfaceOrientation:(UIInterfaceOrientation)[UIDevice currentDevice].orientation];

これとともに:

[self.previewLayer.connection setVideoOrientation:[UIDevice currentDevice].orientation];

これで、ランドスケープ モード + ピンチしてズームですべて正常に動作するようになりました。:)

于 2013-04-04T00:45:33.487 に答える
0

同様の質問がここで回答されています: CGAffineTransformMakeScale を使用してスケーリング中に UIView が回転する

手動で回転しているpreviewLayerため、スケーリングで変換をオーバーライドしているため、それに応じて認識エンジンを調整する必要があるようです。それが起こるのは、変換が絶対的であるからです。または、少なくとも私は変換についてそう考えています。

CGAffineTransformScale(私がリンクした質問で推奨されていたように) を使用して、 の元の変換と必要なスケールを渡すことはできますpreviewLayerか?

EDITこの問題のドキュメントは次のとおりです : https://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CGAffineTransform/Reference/reference.htmlそれらを変更する必要があります。それが必要だと思います。CGAffineTransformMakeScaleCGAffineTransformScale

EDIT2

[UIView animateWithDuration:.25 animations:^{
   self.previewLayer.transform = CGAffineTransformScale(self.previewLayer.transform, effectiveScale, effectiveScale);
                 }];
于 2013-04-02T07:58:36.543 に答える