4

iOSの背面カメラから画像をキャプチャすることができます。私の範囲内で写真を撮ってほしいことを除いて、すべてが完璧に機能していUIViewます。

私のコードは以下の通りです:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    session = [[AVCaptureSession alloc] init];

    session.sessionPreset = AVCaptureSessionPresetMedium;

    captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
    captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    captureVideoPreviewLayer.frame = vImagePreview.bounds;
    [vImagePreview.layer addSublayer:captureVideoPreviewLayer];

    AVCaptureDevice *device = [self backFacingCameraIfAvailable];
    NSError *error = nil;
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if (!input) {
        // Handle the error appropriately.
        NSLog(@"ERROR: trying to open camera: %@", error);
    }
    [session addInput:input];

    stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
    [stillImageOutput setOutputSettings:outputSettings];
    AVCaptureConnection *videoConnection = nil;
    for (AVCaptureConnection *connection in stillImageOutput.connections) {
        for (AVCaptureInputPort *port in [connection inputPorts]) {
            if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
                videoConnection = connection;
                break;
            }
        }
        if (videoConnection) {
            break;
        }
    }

    [session startRunning];

    [session addOutput:stillImageOutput];
}

-(AVCaptureDevice *)backFacingCameraIfAvailable{

    NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    AVCaptureDevice *captureDevice = nil;
    for (AVCaptureDevice *device in videoDevices){
        if (device.position == AVCaptureDevicePositionBack){
            captureDevice = device;
            break;
        }
    }

    //  couldn't find one on the back, so just get the default video device.
    if (!captureDevice){
        captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    }
    return captureDevice;
}

そして、以下は画像をキャプチャするためのコードです:

- (IBAction)captureTask {
    AVCaptureConnection *videoConnection = nil;
    for (AVCaptureConnection *connection in stillImageOutput.connections){
        for (AVCaptureInputPort *port in [connection inputPorts]){

            if ([[port mediaType] isEqual:AVMediaTypeVideo]){

                videoConnection = connection;
                break;
            }
        }
        if (videoConnection) {
            break;
        }
    }

    NSLog(@"about to request a capture from: %@", stillImageOutput);
    [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
     {
         CFDictionaryRef exifAttachments = CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL);
         if (exifAttachments) {
             // Do something with the attachments.
             NSLog(@"attachements: %@", exifAttachments);
         } else {
             NSLog(@"no attachments");
         }

         NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
         UIImage *image = [[UIImage alloc] initWithData:imageData];
         stillImage = image;

     }];
}

私が直面している問題は、写真を撮って保存することstillImageですが、画像は私が知る限り、iPhone画面全体のものです。UIView *vImagePreviewそれは私が作成した範囲ではありません。キャプチャした画像の境界をクリップする方法はありますか?

[編集]

ドキュメントを読んだ後、私はここにあるように、画像が適切な解像度であることに気づきました:session.sessionPreset = AVCaptureSessionPresetMedium;。画像を正方形のようにする方法はありますか?Instagramがどのように画像を作成するのか?ドキュメントによると、すべてのセッションプリセットはすべての四角ではありません:(

私は以下で試しました:

captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResize;

ただし、現在のビューに合わせて画像のサイズを変更するだけで、正方形の画像は作成されません。

4

2 に答える 2

6

私はあなたの不満を理解しています.プリセットはカスタマイズ可能であるか、より多くのオプションがあるべきです! 私が自分の画像で行うことは、次のコードを書いた中心についてそれらをトリミングすることです:

- (UIImage *)crop:(UIImage *)image from:(CGSize)src to:(CGSize)dst
{
    CGPoint cropCenter = CGPointMake((src.width/2), (src.height/2));
    CGPoint cropStart = CGPointMake((cropCenter.x - (dst.width/2)), (cropCenter.y - (dst.height/2)));
    CGRect cropRect = CGRectMake(cropStart.x, cropStart.y, dst.width, dst.height);
    CGImageRef cropRef = CGImageCreateWithImageInRect(image.CGImage, cropRect);
    UIImage* cropImage = [UIImage imageWithCGImage:cropRef];
    CGImageRelease(cropRef);

    return cropImage;
}

src元の寸法をdst表し、トリミングされた寸法を表します。もちろん、imageトリミングしたい画像です。

于 2013-01-01T00:20:45.003 に答える
0

デバイスが Retina ディスプレイの場合、このスクリーンショットは以下のように機能します。

if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES && [[UIScreen mainScreen] scale] == 2.00)
{
    CGPoint cropCenter = CGPointMake((src.width), (src.height));
    CGPoint cropStart = CGPointMake((cropCenter.x - (dst.width)), (cropCenter.y - (dst.height)));
    CGRect cropRect = CGRectMake(cropStart.x, cropStart.y, dst.width*2, dst.height*2);
    CGImageRef cropRef = CGImageCreateWithImageInRect(image.CGImage, cropRect);
    UIImage* cropImage = [UIImage imageWithCGImage:cropRef];
    CGImageRelease(cropRef);
    return cropImage;
}
else
{
    CGPoint cropCenter = CGPointMake((src.width/2), (src.height/2));
    CGPoint cropStart = CGPointMake((cropCenter.x - (dst.width/2)), (cropCenter.y - (dst.height/2)));
    CGRect cropRect = CGRectMake(cropStart.x, cropStart.y, dst.width, dst.height);
    CGImageRef cropRef = CGImageCreateWithImageInRect(image.CGImage, cropRect);
    UIImage* cropImage = [UIImage imageWithCGImage:cropRef];
    CGImageRelease(cropRef);

    return cropImage;
}
于 2013-07-23T07:47:33.533 に答える