
सभी हाबरा समुदाय को बधाई!
आज मैं आपको एक नए उत्पाद -
QCamplr के उदाहरण का उपयोग करके iOS डिवाइस के कैमरे के साथ काम करने के तरीके के बारे में बताना
चाहूंगा ।
इस पोस्ट में, मैं कैमरा स्थापित करने और इसके साथ आगे के काम के लिए एक छवि प्राप्त करने के बुनियादी पहलुओं पर चर्चा करूंगा।
चरण 1: चौखटे आयात करें
मैंने पहले से ही Xcode 5 में Objective-C के नए सिंटैक्स फीचर्स का उपयोग करना शुरू कर दिया है, यही कारण है कि
#import
द्वारा प्रतिस्थापित किया गया है
@import
IOS कैमरा के साथ काम करने के लिए, हमें निश्चित रूप से
AVFoundation.framework की आवश्यकता है
, और
हमें CoreMedia , CoreVideo और
ImageIO से सुविधाओं की भी आवश्यकता हो सकती है। मैं आपको इन सभी रूपरेखाओं को अभी आयात करने की सलाह देता हूं, ताकि बाद में कोई त्रुटि न हो।
@import AVFoundation; @import CoreMedia; @import CoreVideo; @import ImageIO;
चरण 2: गुणों और विधियों की घोषणा करें
@property (nonatomic, strong, readonly) AVCaptureSession *captureSession; @property (nonatomic, strong, readonly) AVCaptureDevice *captureDevice; @property (nonatomic, strong, readonly) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer; @property (nonatomic, strong, readonly) AVCaptureDeviceInput *captureDeviceInput; @property (nonatomic, strong, readonly) AVCaptureStillImageOutput *captureStillImageOutput; + (QCCameraManager *)sharedManager; - (void)setupCaptureSessionWithSessionPreset:(NSString *)sessionPreset captureDevice:(AVCaptureDevice *)captureDevice captureViewLayer:(CALayer *)captureViewLayer; - (void)captureStillImageWithCompletionHandler:(void (^)(UIImage *capturedStillImage))completionHandler; - (BOOL)toggleCaptureDevice; - (AVCaptureDevice *)captureDeviceWithPosition:(AVCaptureDevicePosition)captureDevicePosition; - (BOOL)configureFocusModeOnDevice:(AVCaptureDevice *)captureDevice withFocusMode:(AVCaptureFocusMode)focusMode focusPointOfInterest:(CGPoint)focusPointOfInterest; - (BOOL)configureExposureModeOnDevice:(AVCaptureDevice *)captureDevice withExposureMode:(AVCaptureExposureMode)exposureMode exposurePointOfInterest:(CGPoint)exposurePointOfInterest; - (BOOL)configureWhiteBalanceModeOnDevice:(AVCaptureDevice *)captureDevice withWhiteBalanceMode:(AVCaptureWhiteBalanceMode)whiteBalanceMode; - (BOOL)configureFlashModeOnDevice:(AVCaptureDevice *)captureDevice withFlashMode:(AVCaptureFlashMode)flashMode; - (BOOL)configureTorchModeOnDevice:(AVCaptureDevice *)captureDevice withTorchMode:(AVCaptureTorchMode)torchMode torchLevel:(CGFloat)torchLevel; - (BOOL)configureLowLightBoostOnDevice:(AVCaptureDevice *)captureDevice withLowLightBoostEnabled:(BOOL)lowLightBoostEnabled;
हमारे सभी गुणों में आसानी से
कीवर्ड हैं । चूंकि हम किसी को भी उन्हें सीधे संशोधित करने के लिए नहीं चाहते हैं, लेकिन ऐसी परिस्थितियां हैं जब हमें मुख्य
एवीफ़ाउंडेशन स्टैक से एक सक्रिय सत्र या किसी अन्य संपत्ति को जल्दी से एक्सेस करने की आवश्यकता होती है, जिसे आईओएस डिवाइस के कैमरे से तस्वीरें लेने की आवश्यकता होती है।
इसके बाद, हमने 11 विधियों की घोषणा की, जिनके बारे में मैं अगले चरणों में अधिक विस्तार से चर्चा करूंगा।अब आप सुरक्षित रूप से .m फ़ाइल खोल सकते हैं और हमारे कैमरे के कार्यान्वयन को लिखना शुरू कर सकते हैं।चरण 3: सिंगलटन
तथ्य यह है कि iOS डिवाइस केवल एक सक्रिय
AVCaptureSession का समर्थन करता है। यदि आप एक ही समय में कई सत्र बनाने और चलाने का प्रयास करते हैं, तो आपको
कंसोल में एक त्रुटि दिखाई देगी। ऐसे कई क्षण भी आते हैं जब हमें अपने आवेदन के किसी भी वर्ग से कैमरा गुणों को एक्सेस करने की आवश्यकता होती है, यही कारण है कि हम
सिंगलटन बनाएंगे। हम ARC का समर्थन करते हैं, इसलिए
हम इस तरह से
सिंगलटन बनाते हैं:
+ (QCCameraManager *)sharedManager { static dispatch_once_t dispatchOncePredicate; __strong static QCCameraManager *cameraManager = nil; dispatch_once(&dispatchOncePredicate, ^{ cameraManager = [[QCCameraManager alloc] init]; }); return cameraManager; }
चरण 4: हमारे AVFoundation Stack को बनाएं और कस्टमाइज़ करें
- (void)setupCaptureSessionWithSessionPreset:(NSString *)sessionPreset captureDevice:(AVCaptureDevice *)captureDevice captureViewLayer:(CALayer *)captureViewLayer { [self setCaptureSession:[[AVCaptureSession alloc] init]]; if([[self captureSession] canSetSessionPreset:sessionPreset]) { [[self captureSession] setSessionPreset:sessionPreset]; } else { [[self captureSession] setSessionPreset:AVCaptureSessionPresetHigh]; } [self setCaptureDevice:captureDevice]; [self setCaptureDeviceInput:[[AVCaptureDeviceInput alloc] initWithDevice:[self captureDevice] error:nil]]; if(![[[self captureSession] inputs] count]) { if([[self captureSession] canAddInput:[self captureDeviceInput]]) { [[self captureSession] addInput:[self captureDeviceInput]]; } } [self setCaptureStillImageOutput:[[AVCaptureStillImageOutput alloc] init]]; [[self captureStillImageOutput] setOutputSettings:[[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG, AVVideoCodecKey, nil]]; if ([[self captureSession] canAddOutput:[self captureStillImageOutput]]) { [[self captureSession] addOutput:[self captureStillImageOutput]]; } [self configureWhiteBalanceModeOnDevice:[self captureDevice] withWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]; [self configureLowLightBoostOnDevice:[self captureDevice] withLowLightBoostEnabled:YES]; [self setCaptureVideoPreviewLayer:[[AVCaptureVideoPreviewLayer alloc] initWithSession:[self captureSession]]]; [[self captureVideoPreviewLayer] setVideoGravity:AVLayerVideoGravityResizeAspectFill]; [[self captureVideoPreviewLayer] setBounds:[captureViewLayer bounds]]; [[self captureVideoPreviewLayer] setFrame:[captureViewLayer bounds]]; [captureViewLayer setMasksToBounds:YES]; [captureViewLayer insertSublayer:[self captureVideoPreviewLayer] atIndex:0]; }
यहाँ सब कुछ बहुत सरल है:
- हम एक सत्र बनाते हैं, और इसके लिए एक पूर्व निर्धारित करते हैं, यह तस्वीर की गुणवत्ता और संकल्प को प्रभावित करता है, जो आपको तब प्राप्त होगा जब चित्र स्क्रीन पर प्रदर्शित होता है और सीधे शॉट होता है।
- हम उस डिवाइस का चयन करते हैं जिसका उपयोग शूटिंग के लिए किया जाएगा, हमारे मामले में डिफ़ॉल्ट रूप से यह हमेशा रियर कैमरा होता है
- अगला, हमें अपने सत्र के लिए इनपुट संलग्न करना होगा। वास्तविक समय में स्क्रीन पर कैमरे से छवि प्रदर्शित करने के लिए हमें इसकी आवश्यकता होगी। एक सत्र केवल एक इनपुट का समर्थन करता है, और आउटपुट की संख्या एक तक सीमित नहीं है। चेक की तरह "क्या मैं इस इनपुट को सत्र में संलग्न कर सकता हूं?" हमेशा करने की आवश्यकता है!
- हम उसी चीज के बारे में करते हैं, केवल अब हम आउटपुट कनेक्ट करते हैं , हमें कैमरे से शूट करने और वास्तविक छवि प्राप्त करने के लिए इसकी आवश्यकता होगी। चेक की तरह "क्या मैं इस आउटपुट को सत्र में संलग्न कर सकता हूं?" करने की आवश्यकता है, हमेशा!
- इसके अलावा, हम उन कैमरा विकल्पों का एक छोटा विन्यास करते हैं, जिनके लिए हम उपयोगकर्ता को एक्सेस नहीं देते हैं। मैं आपको उनके बारे में थोड़ी देर बाद बताऊंगा।
- अंत में, हम एक परत बनाते हैं, जिस पर वास्तविक समय में चित्र हमारे इनपुट डिवाइस से प्रदर्शित होगा। परत को परत के उप- परत के रूप में जोड़ें, जिसे हमने इस पद्धति के तर्क के रूप में पारित किया।
सत्र बनाया! इसे शुरू करने के लिए, आपको
कैप्चर सत्र संपत्ति पर
स्टार्टरिंग विधि को कॉल करने की आवश्यकता है, सत्र को बाधित करने के लिए, आपको
स्टॉपरिंग विधि को कॉल करने की आवश्यकता है।
यह आपके नियंत्रक में इस पद्धति के लिए कॉल की तरह लग सकता है:
[[QCCameraManager sharedManager] setupCaptureSessionWithSessionPreset:AVCaptureSessionPresetPhoto captureDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] captureViewLayer:[[self view] layer]]; [[[[QCCameraManager sharedManager] captureSession] startRunning];
चरण 5: कैमरा सेट करें
- (BOOL)configureTorchModeOnDevice:(AVCaptureDevice *)captureDevice withTorchMode:(AVCaptureTorchMode)torchMode torchLevel:(CGFloat)torchLevel { if([captureDevice hasTorch] && [captureDevice isTorchAvailable]) { if([captureDevice torchMode] != torchMode) { if([captureDevice isTorchModeSupported:torchMode]) { if(!(([captureDevice isTorchActive]) && (torchMode == AVCaptureTorchModeOn))) { if([captureDevice lockForConfiguration:nil]) { if((torchMode == AVCaptureTorchModeOn) && (torchLevel >= 0.0f)) { [captureDevice setTorchModeOnWithLevel:torchLevel error:nil]; } else { [captureDevice setTorchMode:torchMode]; } [captureDevice unlockForConfiguration]; } else { return NO; } } } else { return NO; } } return YES; } else { return NO; } } - (BOOL)configureFlashModeOnDevice:(AVCaptureDevice *)captureDevice withFlashMode:(AVCaptureFlashMode)flashMode { if([captureDevice isFlashAvailable] && [captureDevice isFlashModeSupported:flashMode]) { if([captureDevice flashMode] != flashMode) { if([captureDevice lockForConfiguration:nil]) { [captureDevice setFlashMode:flashMode]; [captureDevice unlockForConfiguration]; } else { return NO; } } return YES; } else { return NO; } } - (BOOL)configureWhiteBalanceModeOnDevice:(AVCaptureDevice *)captureDevice withWhiteBalanceMode:(AVCaptureWhiteBalanceMode)whiteBalanceMode { if([captureDevice isWhiteBalanceModeSupported:whiteBalanceMode]) { if([captureDevice whiteBalanceMode] != whiteBalanceMode) { if([captureDevice lockForConfiguration:nil]) { [captureDevice setWhiteBalanceMode:whiteBalanceMode]; [captureDevice unlockForConfiguration]; } else { return NO; } } return YES; } else { return NO; } } - (BOOL)configureFocusModeOnDevice:(AVCaptureDevice *)captureDevice withFocusMode:(AVCaptureFocusMode)focusMode focusPointOfInterest:(CGPoint)focusPointOfInterest { if([captureDevice isFocusModeSupported:focusMode] && [captureDevice isFocusPointOfInterestSupported]) { if([captureDevice focusMode] == focusMode) { if([captureDevice lockForConfiguration:nil]) { [captureDevice setFocusPointOfInterest:focusPointOfInterest]; [captureDevice setFocusMode:focusMode]; [captureDevice unlockForConfiguration]; } else { return NO; } } return YES; } else { return NO; } } - (BOOL)configureExposureModeOnDevice:(AVCaptureDevice *)captureDevice withExposureMode:(AVCaptureExposureMode)exposureMode exposurePointOfInterest:(CGPoint)exposurePointOfInterest { if ([captureDevice isExposureModeSupported:exposureMode] && [captureDevice isExposurePointOfInterestSupported]) { if([captureDevice exposureMode] == exposureMode) { if([captureDevice lockForConfiguration:nil]) { [captureDevice setExposurePointOfInterest:exposurePointOfInterest]; [captureDevice setExposureMode:exposureMode]; [captureDevice unlockForConfiguration]; } else { return NO; } } return YES; } else { return NO; } } - (BOOL)configureLowLightBoostOnDevice:(AVCaptureDevice *)captureDevice withLowLightBoostEnabled:(BOOL)lowLightBoostEnabled { if([captureDevice isLowLightBoostSupported]) { if([captureDevice isLowLightBoostEnabled] != lowLightBoostEnabled) { if([captureDevice lockForConfiguration:nil]) { [captureDevice setAutomaticallyEnablesLowLightBoostWhenAvailable:lowLightBoostEnabled]; [captureDevice unlockForConfiguration]; } else { return NO; } } return YES; } else { return NO; } }
सभी संभव कैमरा सेटिंग्स हमारे अपने तरीकों से किए जाते हैं, वे सभी एक ही सिद्धांत पर काम करते हैं। आपको केवल यह जानना चाहिए कि पैरामीटर बदलने से पहले हमें
लॉकफोरकॉन्फ़िगरेशन कॉल करने की आवश्यकता है
: विधि, कॉन्फ़िगरेशन प्रक्रिया को पूरा करने के बाद हमें
अनलॉकफ़ोरकॉन्फ़िगरेशन विधि को कॉल करने की आवश्यकता है।
QCamplr में, हम उपयोगकर्ता को 4 विकल्प कॉन्फ़िगर करने में सक्षम करते हैं: फ्लैश, टॉर्चलाइट (रात का दृश्य), फोकस और एक्सपोज़र।

चरण 5: एक तस्वीर लें
- (void)captureStillImageWithCompletionHandler:(void (^)(UIImage *capturedStillImage))completionHandler { if(![[self captureStillImageOutput] isCapturingStillImage]) { [[NSNotificationCenter defaultCenter] postNotificationName:@"QCCameraManagedWillCaptureStillImageNotification" object:nil userInfo:nil]; [[self captureStillImageOutput] captureStillImageAsynchronouslyFromConnection:[[self captureStillImageOutput] connectionWithMediaType:AVMediaTypeVideo] completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { if (imageDataSampleBuffer) { UIImage *capturedStillImage = [[UIImage alloc] initWithData:[AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]]; completionHandler([capturedStillImage croppedImageFromCaptureDevice:[self captureDevice]]); } }]; } }
जब आप QCamplr में बड़े लाल "टॉगलर" पर क्लिक करते हैं तो यह विधि कहलाती है। पूरा होने में हैन्डलर में एक jpeg इमेज आती है जो क्लास UIImage के ऑब्जेक्ट में लिपटी होती है।

अब आपके कैमरे की मदद करने के लिए कुछ सहायक विधियाँ हैं।
विधि # 1
आप इस विधि का उपयोग करके फ्रंट या रियर कैमरे तक पहुँच सकते हैं:
- (AVCaptureDevice *)captureDeviceWithPosition:(AVCaptureDevicePosition)captureDevicePosition { NSArray *captureDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; for(AVCaptureDevice *captureDevice in captureDevices) { if([captureDevice position] == captureDevicePosition) { return captureDevice; } } return nil; }
विधि # 2
आप इस विधि का उपयोग कर फ्रंट कैमरे से पीछे और इसके विपरीत स्विच कर सकते हैं:
- (BOOL)toggleCaptureDevice { if ([[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count] > 1) { AVCaptureDeviceInput *captureDeviceInput = [self captureDeviceInput]; if([[[self captureDeviceInput] device] position] == AVCaptureDevicePositionBack) { [self setCaptureDeviceInput:[[AVCaptureDeviceInput alloc] initWithDevice:[self captureDeviceWithPosition:AVCaptureDevicePositionFront] error:nil]]; } else if([[[self captureDeviceInput] device] position] == AVCaptureDevicePositionFront) { [self setCaptureDeviceInput:[[AVCaptureDeviceInput alloc] initWithDevice:[self captureDeviceWithPosition:AVCaptureDevicePositionBack] error:nil]]; } else if([[[self captureDeviceInput] device] position] == AVCaptureDevicePositionUnspecified) { return NO; } [self setCaptureDevice:[[self captureDeviceInput] device]]; [[self captureSession] beginConfiguration]; [[self captureSession] removeInput:captureDeviceInput]; if([[self captureSession] canAddInput:[self captureDeviceInput]]) { [[self captureSession] addInput:[self captureDeviceInput]]; } else { [[self captureSession] addInput:captureDeviceInput]; } [[self captureSession] commitConfiguration]; return YES; } else { return NO; } }
उपयोगी लिंक
AVFoundation प्रलेखनआधिकारिक साइट QCamplrPS मुझे उम्मीद है कि यह लेख उन सभी के लिए उपयोगी था जो डिवाइस के कैमरों के साथ काम करने में अधिक स्वतंत्रता और लचीलापन प्राप्त करना चाहते थे, लेकिन यह नहीं जानते थे कि कहां से शुरू करें। मैं सभी को और अधिक गुणवत्ता कोड, और हमारी कड़ी मेहनत के लिए शुभकामनाएं देता हूं!