0

Ich habe eine iOS-App mit der Kamera, um Bilder zu machen. Es wird ein Pfad (CGPath) auf dem Bildschirm (z. B. ein Rechteck) verwendet, und es dauert ein Foto in diesem Pfad. Die App unterstützt nur Hochformat.iPhone 6+ (Falsche Skalierung?)

Dafür habe ich geschehen verwenden: AVCaptureSession, AVCaptureStillImageOutput, AVCaptureDevice, AVCaptureVideoPreviewLayer (Ich denke, alle Entwickler vertraut, diese Art von Anwendungen zu machen).

Mein Code verwendet UIScreen.mainScreen().bounds und UIScreen.mainScreen().scale, um verschiedene Geräte anzupassen und ihre Arbeit zu tun.

Alles geht gut (auf iPhone 5, iPhone 6), bis ich die App auf einem iPhone 6+ (mit iOS 9.3.1) versuche und sehe, dass etwas nicht stimmt. Das aufgenommene Bild ist nicht mehr am richtigen Ort.

Ich hatte jemand versuchen auf einem iPhone 6+, und durch eine entsprechende Nachricht konnte ich bestätigen, dass (UIScreen.mainScreen().scale) ist, was es sein sollte: 3.0. Ich habe die richtigen Startbilder (640 × 960, 640 × 1136, 750 × 1334, 1242 × 2208) in das Projekt eingefügt. Also, was könnte das Problem sein?

+1

Wenn du einen git hast, werde ich einen Blick auf 6+ werfen –

Antwort

-1

Falls jemand anderes hat das gleiche Problem. Hier ist, was Dinge für mich schief gelaufen ist:

Ich nannte eine Datei: [email protected]

Wenn UIScreen.mainScreen(). Scale == 3.0 (Fall eines iPhone 6+) muss es benannt werden: [email protected]

+0

Sie müssen nicht die 2x und 3x Erweiterungen für Ihre Bilder verwenden - ich benutze sie nie, es ist so viel Ärger. Greifen Sie einfach das größte Bild und lassen Sie das Gerät für Sie skalieren, z. bigImage.png setze eine UIImageView mit contentMode AspectFill ein. Weniger Kopfschmerzen. –

+0

Ich weiß nicht, ob ich muss. Aber was ich weiß ist, als ich die Datei x. @ 2x.png benannte, gab es in jedem Fall einen Fehler und wenn ich nach dem Wert von UIScreen.mainScreen() benenne, skaliere es. Und das Gerät skalieren zu lassen, ist in allen möglichen Fällen nicht das, was Sie wollen. Dasselbe müssen Sie nicht unbedingt mehrere Bilder haben, um das größte auszuwählen. Wie auch immer, wenn Sie sagen, Sie können vermeiden, mehrere Erweiterungen zu verwenden, das ist das Beste. – Michel

0

Ich benutze den Code unten in einer App, es funktioniert auf 6+.

Der Code startet eine AVCaptureSession und zieht den Videoeingang von der Kamera des Geräts.

Dabei aktualisiert es kontinuierlich die Variable runImage von der captureOutput-Delegatfunktion.

Wenn der Benutzer ein Bild aufnehmen möchte, wird die Methode takePhoto aufgerufen. Diese Methode erstellt eine temporäre UIImageview und füttert die runImage in sie. Diese temporäre UIImageView wird dann verwendet, um eine weitere Variable namens currentImage auf die Skalierung des Geräts zu zeichnen.

Das currentImage, in meinem Fall, ist quadratisch, passend zum previewHolder-Frame, aber ich nehme an, Sie können alles machen, was Sie wollen.

erklären diese:

AVCaptureDevice * device; 
AVCaptureDeviceInput * input; 
AVCaptureVideoDataOutput * output; 
AVCaptureSession * session; 
AVCaptureVideoPreviewLayer * preview; 
AVCaptureConnection * connection; 
UIImage * runImage; 

Last Scanner:

-(void)loadScanner 
{ 

    device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 
    input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; 
    output = [AVCaptureVideoDataOutput new]; 
    session = [AVCaptureSession new]; 

    [session setSessionPreset:AVCaptureSessionPresetPhoto]; 
    [session addInput:input]; 
    [session addOutput:output]; 

    [output setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; 
    [output setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; 

    preview = [AVCaptureVideoPreviewLayer layerWithSession:session]; 
    preview.videoGravity = AVLayerVideoGravityResizeAspectFill; 
    preview.frame = previewHolder.bounds; 

    connection = preview.connection; 
    [connection setVideoOrientation:AVCaptureVideoOrientationPortrait]; 
    [previewHolder.layer insertSublayer:preview atIndex:0]; 

} 

Laufende Bildaufnahme, Updates runImage var.

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 

    runImage = [self imageForBuffer:sampleBuffer]; 

} 

Ähnlich wie oben.

-(UIImage *)imageForBuffer:(CMSampleBufferRef)sampleBuffer 
{ 

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    CGImageRef quartzImage = CGBitmapContextCreateImage(context); 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 
    UIImage *image = [UIImage imageWithCGImage:quartzImage]; 
    CGImageRelease(quartzImage); 

    UIImage * rotated = [[UIImage alloc] initWithCGImage:image.CGImage scale:1.0 orientation:UIImageOrientationRight]; 

    return rotated; 
} 

Auf nehmen Foto:

-(void)takePhoto 
{ 

    UIImageView * temp = [UIImageView new]; 
    temp.frame = previewHolder.frame; 
    temp.image = runImage; 
    temp.contentMode = UIViewContentModeScaleAspectFill; 
    temp.clipsToBounds = true; 
    [self.view addSubview:temp]; 

    UIGraphicsBeginImageContextWithOptions(temp.bounds.size, NO, [UIScreen mainScreen].scale); 
    [temp drawViewHierarchyInRect:temp.bounds afterScreenUpdates:YES]; 
    currentImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    [temp removeFromSuperview]; 

    //further code... 

} 
+0

Warum was macht dein Code? Bitte geben Sie eine Beschreibung zu Ihrem Code und warum er das Problem des Benutzers löst. – Popeye

+0

@Popeye mit weiterer Erklärung aktualisiert; ob es dem Benutzer hilft, weiß ich nicht, dass es wird, aber ich habe keine 6+ Probleme damit gesehen (wenn es sogar ein Problem ist, können wir nicht sicher sagen). –

+0

Ich sehe mir deinen Code an. Versuchen zu sehen, wie es sich von meinen unterscheidet. Anders als meine in Swift, kann ich schon ein paar Variationen sehen. Sie verwenden 'AVCaptureVideoDataOutput', ich verwende' AVCaptureStillImageOutput'; verwenden Sie 'AVCaptureSessionPresetPhoto', verwende ich' AVCaptureSessionPresetHigh' ..etc .. Ich nehme an, es sollte nicht das Problem sein. Auf der anderen Seite können AVLayerVideoGravityResizeAspectFill und AVCaptureVideoOrientationPortrait, die Sie verwenden, und ich kann nicht einen Unterschied machen. Für 'imageForBuffer' verwende ich den Code, den ich hier gefunden habe: developer.apple.com/library/ios/documentation/AudioVideo/ Ich muss noch weiter schauen. – Michel