Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Capturing Photos without the iOS screen
-
I want to remove the iOS screens when I am taking photos.
You know, when you runphotos.capture_image()
and it pulls up the default iOS screen and returns the photo? I don't want it to do that. I just want to press a button in my homemade ui.View(already done) and I want it to take a photo without waiting for the user to click a second button on the iOS photo screen. Can anybody help? -
While this isn't possible with the
photos
module, here's an (unfortunately somewhat complicated) example of how to do it with the Objective-C bridge:from objc_util import * import time import threading C = ObjCClass def take_photo_now(filename='photo.jpg'): session = C('AVCaptureSession').new().autorelease() session.sessionPreset = 'AVCaptureSessionPresetPhoto' device = C('AVCaptureDevice').defaultDeviceWithMediaType_('vide') device_input = C('AVCaptureDeviceInput').deviceInputWithDevice_error_(device, None) session.addInput_(device_input) image_output = C('AVCaptureStillImageOutput').new().autorelease() session.addOutput_(image_output) session.startRunning() # NOTE: You may need to adjust this to wait for the camera to be ready (use a higher number if you see black photos): time.sleep(0.1) def handler_func(_block, _buffer, _err): buffer = ObjCInstance(_buffer) img_data = C('AVCaptureStillImageOutput').jpegStillImageNSDataRepresentation_(buffer) img_data.writeToFile_atomically_(filename, True) e.set() video_connection = None for connection in image_output.connections(): for port in connection.inputPorts(): if str(port.mediaType()) == 'vide': video_connection = connection break if video_connection: break e = threading.Event() handler = ObjCBlock(handler_func, restype=None, argtypes=[c_void_p, c_void_p, c_void_p]) retain_global(handler) image_output.captureStillImageAsynchronouslyFromConnection_completionHandler_(video_connection, handler) e.wait() take_photo_now('photo.jpg') import console console.quicklook('photo.jpg')
-
Thank you so much! Is there any way to get rid of that awful "photo-taken" noise without muting my device?
-
@NoBetterName That's not easily possible, unless you're okay with a lower-quality image (with a maximum resolution of 1920x1080, i.e. HD video).
-
I wonder if you could mute the device through the objc util module and then unmute it after the picture is taken...
I think I remember how to set volume, but it I don't think this is volume related. I think it is the ringer that needs to be muted.
-
I would be OK with that low quality, this isn't for storing to the camera roll. How do you accomplish that? @omz
-
@NoBetterName This is not possible but capturing photo with low resolutions.
-
@azad1875 @omz I am fine with the lower-quality, as long as I don't get the sound. This program uses I method that I invented, and if it makes the sound, it will be obvious how it uses the camera.I don't want this to be copied. Can anybody show me how to do this? Since the ringer slider is a physical button, I have ruled out muting that. I tried, but nothing exists, even in objc_util. Can anyone help?
-
Anybody?
-
@omz I'm attempting to use your example to make a qr code reader. I'm hung up on how to make the dispatch queue work with the AVCaptureMetadataOutputObjectsDelegate. Any help would be greatly appreciated.
-
@wrenoud Have you seen this sample code I posted a while ago? https://forum.omz-software.com/topic/2779/barcode-qr-code-camera-scanner-demo-objc_util
-
@omz I hadn't! Exactly what I was looking for. I'm interested in trying to use QR codes for indoor navigation and I thought pythonista would be a great platform for demonstrating this. I'll come back and share when I have some results.
-
@omz This code is very helpful for me. From the apple developer website (https://developer.apple.com/documentation/avfoundation/avcapturestillimageoutput), the AVCaptureStillImageOutput class is going to be instead with AVCapturePhotoOutput class. Could you give a similar example with the new AVCapturePhotoOutput class? Thank you very much!
-
Is there any way to return the image directly rather than save to a file?
-
Could you give a similar example with the new AVCapturePhotoOutput class?
I made an example script. You can check the script via following URL. Explanation is written in Japanese, but you can get a code example.
http://www.hirax.net/diaryweb/2018/04/22.html#11012 -
@hirax i tried running your script but i am getting a syntax error on line 13.
-
@ihf remove the line break at begin of line 14,
Then idem at new line 19
Then idem at new line 27
Etc...The code seems to be splitted in long lines
-
# coding: utf-8 from objc_util import * import time AVCaptureSession = ObjCClass('AVCaptureSession') AVCaptureDevice = ObjCClass('AVCaptureDevice') AVCaptureDeviceInput = ObjCClass('AVCaptureDeviceInput') AVCapturePhotoOutput = ObjCClass('AVCapturePhotoOutput') def manualCapture(device, output, focusDistance, fileName): def captureOutput_didFinishProcessingPhotoSampleBuffer_previewPhotoSampleBuffer_resolvedSettings_bracketSettings_error_( _self, _cmd, _output, _photoBuffer, _previewBuffer, _resolveSettings, bracketSettings, _error ): photoBuffer = ObjCInstance(_photoBuffer) jpegPhotoData = ObjCClass('AVCapturePhotoOutput' ).JPEGPhotoDataRepresentationForJPEGSampleBuffer_previewPhotoSampleBuffer_( photoBuffer, _previewBuffer) jpegPhotoData.writeToFile_atomically_(fileName, True ) # delegate CameraManualPhotoCaptureDelegate = create_objc_class( 'CameraManualPhotoCaptureDelegate', methods=[ captureOutput_didFinishProcessingPhotoSampleBuffer_previewPhotoSampleBuffer_resolvedSettings_bracketSettings_error_ ], protocols=[ 'AVCapturePhotoCaptureDelegate' ]) device.lockForConfiguration_(None) device.setFocusModeLockedWithLensPosition_completionHandler_( focusDistance, None) device.unlockForConfiguration() time.sleep(1) delegate = CameraManualPhotoCaptureDelegate.new() settings = ObjCClass('AVCapturePhotoSettings' ).photoSettings() settings.AVCaptureFocusMode = 0 output.capturePhotoWithSettings_delegate_( settings, delegate ) time.sleep(1) delegate.release() @on_main_thread def main(): session = AVCaptureSession.alloc().init() device =AVCaptureDevice.defaultDeviceWithMediaType_('vide') _input =AVCaptureDeviceInput.deviceInputWithDevice_error_( device, None) if _input: session.addInput_(_input) else: return session.startRunning() output = AVCapturePhotoOutput.alloc().init() session.addOutput_(output) time.sleep(1) manualCapture(device, output, 0.0, 'sample.jpg') time.sleep(1) session.stopRunning() session.release() output.release() if __name__ == '__main__': main()
-
@cvp said:
The code seems to be splitted in long lines
Yes. In the example in the URL, we have aditttional lines.
I noticed that the above example doesn't work when manualCapture is called more than one times. In the cases, we will get only one image(saved) file.
-
To make it work in multiple-calls, we need to call "manualCapture" from threading. If we modify the above code in the way, then, it works even in multiple shots.