এই পাঠে, আমরা আলোচনা করব কীভাবে ফ্রেমওয়ার্ক API ব্যবহার করে সরাসরি ক্যামেরা হার্ডওয়্যার নিয়ন্ত্রণ করা যায়।
মনে রাখবেন: এই পৃষ্ঠাটি
ক্যামেরা ক্লাসকে রেফার করে, যা বন্ধ হয়ে গেছে। আমরা
CameraX অথবা নির্দিষ্ট ব্যবহারের ক্ষেত্রে,
Camera2 ব্যবহার করার সাজেশন দিই। CameraX এবং Camera2, দুটিই Android 5.0
(API লেভেল ২১) এবং তার পরবর্তী ভার্সনে কাজ করে।
Camera1 থেকে CameraX-এ কীভাবে মাইগ্রেট করবেন তা জানতে,
Camera1 থেকে CameraX-এ মাইগ্রেট করুন দেখুন।
বিকল্প হিসেবে, আপনি
Camera1 থেকে CameraX-এ মাইগ্রেট করার জন্য এজেন্টিক স্কিল ব্যবহার করতে পারেন।
ডিভাইসের ক্যামেরা সরাসরি কন্ট্রোল করার জন্য, আগে থেকে থাকা ক্যামেরা অ্যাপ্লিকেশন থেকে ছবি বা ভিডিওর অনুরোধ করার চেয়ে অনেক বেশি কোডের প্রয়োজন হয়। তবে, আপনি যদি কোনও বিশেষ ক্যামেরা অ্যাপ্লিকেশন তৈরি করতে চান অথবা আপনার অ্যাপ UI-তে সম্পূর্ণভাবে ইন্টিগ্রেট করা কিছু তৈরি করতে চান, তাহলে এই টিউটোরিয়াল আপনাকে দেখাবে যে কীভাবে তা করতে হয়।
নিম্নলিখিত সম্পর্কিত রিসোর্স দেখুন:
ক্যামেরা অবজেক্ট খুলুন
ক্যামেরা সরাসরি কন্ট্রোল করার প্রসেসের প্রথম ধাপ হল Camera অবজেক্টের ইনস্ট্যান্স
পাওয়া। Android-এর নিজস্ব ক্যামেরা অ্যাপ্লিকেশনের মতো, ক্যামেরা অ্যাক্সেস করার জন্য
সাজেস্ট করা পদ্ধতি হল onCreate() থেকে লঞ্চ করা একটি পৃথক থ্রেডে
Camera খোলা। এই পদ্ধতিটি একটি ভাল ধারণা
কারণ এটি কিছু সময় নিতে পারে এবং UI থ্রেডকে ধীর করে দিতে পারে। আরও বেসিক ইমপ্লিমেন্টেশনে,
কোড আবার ব্যবহার করার সুবিধা দিতে এবং কন্ট্রোলের ফ্লো সহজ রাখতে,
ক্যামেরা খোলার কাজটি onResume() পদ্ধতিতে পিছিয়ে দেওয়া যেতে পারে।
ক্যামেরা অন্য কোনও অ্যাপ্লিকেশন আগে থেকেই ব্যবহার করলে, Camera.open() কল করলে
ব্যতিক্রম দেখায়, তাই আমরা এটিকে
try ব্লকে র্যাপ করি।
Kotlin
private fun safeCameraOpen(id: Int): Boolean { return try { releaseCameraAndPreview() mCamera = Camera.open(id) true } catch (e: Exception) { Log.e(getString(R.string.app_name), "failed to open Camera") e.printStackTrace() false } } private fun releaseCameraAndPreview() { preview?.setCamera(null) mCamera?.also { camera -> camera.release() mCamera = null } }
জাভা
private boolean safeCameraOpen(int id) { boolean qOpened = false; try { releaseCameraAndPreview(); camera = Camera.open(id); qOpened = (camera != null); } catch (Exception e) { Log.e(getString(R.string.app_name), "failed to open Camera"); e.printStackTrace(); } return qOpened; } private void releaseCameraAndPreview() { preview.setCamera(null); if (camera != null) { camera.release(); camera = null; } }
API লেভেল ৯ থেকে, ক্যামেরা ফ্রেমওয়ার্ক একাধিক ক্যামেরায় কাজ করে। আপনি যদি
পুরনো API ব্যবহার করেন এবং কোনও আর্গুমেন্ট ছাড়াই open() কল করেন, তাহলে আপনি প্রথম রিয়ার-ফেসিং ক্যামেরা পাবেন।
ক্যামেরা প্রিভিউ তৈরি করুন
ছবি তোলার জন্য সাধারণত ব্যবহারকারীকে শাটার ক্লিক করার আগে সাবজেক্টের প্রিভিউ দেখতে হয়। এটি করতে, ক্যামেরা সেন্সর যা ক্যাপচার করছে তার প্রিভিউ আঁকার জন্য আপনি SurfaceView ব্যবহার করতে পারেন।
প্রিভিউ ক্লাস
প্রিভিউ দেখানো শুরু করতে, আপনার প্রিভিউ ক্লাস প্রয়োজন। প্রিভিউয়ের
জন্য android.view.SurfaceHolder.Callback ইন্টারফেসের প্রয়োগ প্রয়োজন, যা ক্যামেরা হার্ডওয়্যার থেকে অ্যাপ্লিকেশনে ইমেজ ডেটা
পাঠাতে ব্যবহার করা হয়।
Kotlin
class Preview( context: Context, val surfaceView: SurfaceView = SurfaceView(context) ) : ViewGroup(context), SurfaceHolder.Callback { var mHolder: SurfaceHolder = surfaceView.holder.apply { addCallback(this@Preview) setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) } ... }
জাভা
class Preview extends ViewGroup implements SurfaceHolder.Callback { SurfaceView surfaceView; SurfaceHolder holder; Preview(Context context) { super(context); surfaceView = new SurfaceView(context); addView(surfaceView); // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. holder = surfaceView.getHolder(); holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } ... }
পরবর্তী বিভাগে যেমন দেখানো হয়েছে, লাইভ ইমেজ প্রিভিউ শুরু করার আগে প্রিভিউ ক্লাসকে Camera অবজেক্টে পাস করতে হবে।
প্রিভিউ সেট ও শুরু করুন
ক্যামেরা ইনস্ট্যান্স এবং এর সাথে সম্পর্কিত প্রিভিউ অবশ্যই একটি নির্দিষ্ট ক্রমে তৈরি করতে হবে, যেখানে ক্যামেরা অবজেক্টটি প্রথমে থাকবে। নিম্নলিখিত স্নিপেটে, ক্যামেরা শুরু করার প্রসেস এনক্যাপসুলেট করা হয়েছে যাতে ব্যবহারকারী ক্যামেরা পরিবর্তন করার জন্য কিছু করলে, setCamera() পদ্ধতির মাধ্যমে Camera.startPreview() কল করা হয়। প্রিভিউ ক্লাস surfaceChanged() কলব্যাক পদ্ধতিতে প্রিভিউ অবশ্যই রিস্টার্ট করতে হবে।
Kotlin
fun setCamera(camera: Camera?) { if (mCamera == camera) { return } stopPreviewAndFreeCamera() mCamera = camera mCamera?.apply { mSupportedPreviewSizes = parameters.supportedPreviewSizes requestLayout() try { setPreviewDisplay(holder) } catch (e: IOException) { e.printStackTrace() } // Important: Call startPreview() to start updating the preview // surface. Preview must be started before you can take a picture. startPreview() } }
জাভা
public void setCamera(Camera camera) { if (mCamera == camera) { return; } stopPreviewAndFreeCamera(); mCamera = camera; if (mCamera != null) { List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes(); supportedPreviewSizes = localSizes; requestLayout(); try { mCamera.setPreviewDisplay(holder); } catch (IOException e) { e.printStackTrace(); } // Important: Call startPreview() to start updating the preview // surface. Preview must be started before you can take a picture. mCamera.startPreview(); } }
ক্যামেরা সেটিংস পরিবর্তন করুন
ক্যামেরা সেটিংস, ক্যামেরা যেভাবে ছবি তোলে তা পরিবর্তন করে, জুম লেভেল থেকে এক্সপোজার নিয়ন্ত্রণ পর্যন্ত। এই উদাহরণে শুধু প্রিভিউ সাইজ পরিবর্তন করা হয়; আরও অনেক কিছুর জন্য ক্যামেরা অ্যাপ্লিকেশনের সোর্স কোড দেখুন।
Kotlin
override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) { mCamera?.apply { // Now that the size is known, set up the camera parameters and begin // the preview. parameters?.also { params -> params.setPreviewSize(previewSize.width, previewSize.height) requestLayout() parameters = params } // Important: Call startPreview() to start updating the preview surface. // Preview must be started before you can take a picture. startPreview() } }
জাভা
@Override public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // Now that the size is known, set up the camera parameters and begin // the preview. Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewSize(previewSize.width, previewSize.height); requestLayout(); mCamera.setParameters(parameters); // Important: Call startPreview() to start updating the preview surface. // Preview must be started before you can take a picture. mCamera.startPreview(); }
প্রিভিউ ওরিয়েন্টেশন সেট করুন
বেশিরভাগ ক্যামেরা অ্যাপ্লিকেশন ডিসপ্লেকে ল্যান্ডস্কেপ মোডে লক করে দেয় কারণ এটি ক্যামেরা সেন্সরের স্বাভাবিক
ওরিয়েন্টেশন। এই সেটিং আপনাকে পোর্ট্রেট-মোডে ফটো তুলতে বাধা দেয় না, কারণ ডিভাইসের ওরিয়েন্টেশন EXIF হেডারে রেকর্ড করা হয়। setCameraDisplayOrientation() পদ্ধতি আপনাকে পরিবর্তন করতে দেয়
ছবি কীভাবে রেকর্ড করা হয় তা প্রভাবিত না করে প্রিভিউ কীভাবে দেখানো হয়। তবে, API লেভেল ১৪-এর আগের Android ভার্সনে, ওরিয়েন্টেশন পরিবর্তন করার আগে আপনাকে প্রিভিউ বন্ধ করতে হবে এবং তারপর এটি আবার চালু করতে হবে।
ছবি তুলুন
প্রিভিউ শুরু হয়ে গেলে ছবি তোলার জন্য Camera.takePicture()
পদ্ধতি ব্যবহার করুন। আপনি Camera.PictureCallback এবং Camera.ShutterCallback অবজেক্ট তৈরি করে Camera.takePicture()-এ পাস করতে পারবেন।
আপনি যদি ক্রমাগত ছবি তুলতে চান, তাহলে আপনি একটি Camera.PreviewCallback তৈরি করতে পারেন যা onPreviewFrame() প্রয়োগ করে। এর মাঝামাঝি কিছু করতে চাইলে, আপনি শুধু বেছে নেওয়া প্রিভিউ ফ্রেম ক্যাপচার করতে পারেন অথবা takePicture() কল করার জন্য
দেরিতে অ্যাকশন সেট-আপ করতে পারেন।
প্রিভিউ রিস্টার্ট করুন
ছবি তোলার পরে, ব্যবহারকারী অন্য ছবি তোলার আগে আপনাকে অবশ্যই প্রিভিউ রিস্টার্ট করতে হবে। এই উদাহরণে, শাটার বোতাম ওভারলোড করে রিস্টার্ট করা হয়েছে।
Kotlin
fun onClick(v: View) { previewState = if (previewState == K_STATE_FROZEN) { camera?.startPreview() K_STATE_PREVIEW } else { camera?.takePicture(null, rawCallback, null) K_STATE_BUSY } shutterBtnConfig() }
জাভা
@Override public void onClick(View v) { switch(previewState) { case K_STATE_FROZEN: camera.startPreview(); previewState = K_STATE_PREVIEW; break; default: camera.takePicture( null, rawCallback, null); previewState = K_STATE_BUSY; } // switch shutterBtnConfig(); }
প্রিভিউ বন্ধ করে ক্যামেরা রিলিজ করুন
আপনার অ্যাপ্লিকেশন ক্যামেরা ব্যবহার করা শেষ করলে, এটি ক্লিন-আপ করার সময়। বিশেষ করে,
আপনাকে অবশ্যই Camera অবজেক্ট রিলিজ করতে হবে, অন্যথায় আপনার নিজের অ্যাপ্লিকেশনের নতুন ইনস্ট্যান্স সহ অন্যান্য
অ্যাপ্লিকেশন ক্র্যাশ করার ঝুঁকি থাকে।
কখন আপনার প্রিভিউ বন্ধ করে ক্যামেরা রিলিজ করা উচিত? আপনার প্রিভিউ সারফেস নষ্ট হয়ে যাওয়া থেকে
বোঝা যায় যে প্রিভিউ বন্ধ করে ক্যামেরা রিলিজ করার সময় হয়ে গেছে,
যেমন Preview ক্লাস থেকে এই পদ্ধতিতে দেখানো হয়েছে।
Kotlin
override fun surfaceDestroyed(holder: SurfaceHolder) { // Surface will be destroyed when we return, so stop the preview. // Call stopPreview() to stop updating the preview surface. mCamera?.stopPreview() } /** * When this function returns, mCamera will be null. */ private fun stopPreviewAndFreeCamera() { mCamera?.apply { // Call stopPreview() to stop updating the preview surface. stopPreview() // Important: Call release() to release the camera for use by other // applications. Applications should release the camera immediately // during onPause() and re-open() it during onResume()). release() mCamera = null } }
জাভা
@Override public void surfaceDestroyed(SurfaceHolder holder) { // Surface will be destroyed when we return, so stop the preview. if (mCamera != null) { // Call stopPreview() to stop updating the preview surface. mCamera.stopPreview(); } } /** * When this function returns, mCamera will be null. */ private void stopPreviewAndFreeCamera() { if (mCamera != null) { // Call stopPreview() to stop updating the preview surface. mCamera.stopPreview(); // Important: Call release() to release the camera for use by other // applications. Applications should release the camera immediately // during onPause() and re-open() it during onResume()). mCamera.release(); mCamera = null; } }
টিউটোরিয়ালের আগের অংশে, এই পদ্ধতিটি setCamera() পদ্ধতিরও অংশ ছিল, তাই ক্যামেরা শুরু করার সময় সবসময় প্রিভিউ বন্ধ করার মাধ্যমে শুরু হয়।