Quá trình chụp ảnh đòi hỏi phải truyền ảnh hiện tại từ camera đến ứng dụng khách. Trước khi chụp ảnh tĩnh, ta nên truy vấn các khả năng của camera đang sử
dụng. Có hai tham số cần phải thiết lập dựa trên các khả năng là: định dạng ảnh và kích thước ảnh.
vChọn định dạng ảnh
Các định dạng được hỗ trợ được xác định bởi biến thành viên TCamera- Info::iImageFormatsSupported của kiểu liệt kê CCamera::TFormat. Khi sử dụng camera có hỗ trợ nhiều định dạng, ta cần phải chọn định dạng nào phù hợp với ứng dụng nhất.
CCamera::TFormat iFormat; TInt iSizeIndex;
// Khởi tạo truy vấn camera để lấy kích cỡ được hỗ trợ
void CCameraDemoAppUi::SelectCaptureModeL(CCamera::TFormat aFormat) {
iFormat = aFormat;
//iSizeArray là mảng RArray<TSize> đã được khai báo
for (TInt i=0; i<iInfo.iNumImageSizesSupported; ++i) {
TSize size;
iCamera->EnumerateCaptureSizes(size, i, iFormat); iSizeArray.AppendL(size);
}
// SelectBestSize() xem qua danh sách các kích cỡ được hỗ trợ để tìm
// kích cỡ phù hợp với ứng dụng iSizeIndex = SelectBestSize(iSizeArray); iCamera->PrepareImageCaptureL(iFormat, iSizeIndex); } // Hàm dùng để chụp ảnh void CCameraDemoAppUi::CaptureImage() { iCamera->CaptureImage(); }
Sau đây là những định dạng ảnh có thểđược hỗ trợ:
• EFormatJpeg và EFormatExif: đây là những định dạng được mã hóa, cần phải giải mã trước khi hiển thị chúng lên màn hình. Dữ liệu được mã hóa trong một chuỗi dữ liệu và ta phải dùng thư viện ICL (Image Conversion Library) để giải mã dữ liệu.
• EFormatFbsBitmapColorXxx: đây là những định dạng không nén, trong đó ảnh chụp được biểu diễn bằng một đối tượng CFbsBitmap.
• EFormatXxBitRGBXxx và EFormatYUVXxx: đây là những định dạng dữ liệu thô, các đặc tính của chúng được xác định bởi định dạng chính xác, dữ liệu được lưu trong một chuỗi dữ liệu.
Các định dạng được hỗ trợ bởi camera có thể bị ảnh hưởng bởi độ phân giải của camera đó. Những camera có độ phân giải cao có khả năng biểu diễn dữ liệu
ảnh dưới định dạng nén vì bộ nhớ cần để lưu trữ ảnh dưới dạng không nén là rất lớn. Một khi đã lựa chọn xong định dạng sẽ được sử dụng, ta có thể liệt kê các kích thước chụp được hỗ trợ bởi định dạng đó. Số lượng kích thước được lưu trong biến
TCameraInfo::iNumImageSizesSupported. Các kích thước là kết quả trả
về của hàm CCamera::EnumerateCaptureSizes().
vChuẩn bị chụp ảnh
Trước khi chụp ảnh, ta cần phải chuẩn bị đối tượng CCamera bằng cách sử
dụng phương thức PrepareImageCaptureL(). Việc này cho phép hệ thống con camera cấp phát đủ bộ nhớ cần thiết và thực hiện các thiết lập khác để chụp
ảnh; phương thức này phải được gọi ít nhất một lần trước khi yêu cầu chụp ảnh.
iCamera->PrepareImageCaptureL(aFormat, aSizeIndex);
Tham số aSizeIndex là chỉ mục của kích thước ảnh mà ta muốn chụp; nó tương ứng với tham số aSizeIndex của phương thức EnumerateCapture- Sizes().
Camera đã sẵn sàng để chụp ảnh sau khi ta đã gọi phương thức
PrepareImageCaptureL()thành công. Chú ý rằng:
• Những thiết lập ảnh trên chỉ dùng để chụp ảnh.
• Phải chuẩn bị camera trước khi chụp ảnh.
vChụp ảnh
Chụp ảnh là một thao tác không đồng bộ. Nó được thực hiện bằng cách gọi phương thức CaptureImage():
iCamera->CaptureImage();
Sau khi gọi phương thức trên, ta sẽ nhận được một callback đến phương thức
MCameraObserver2::ImageBufferReady():
void CCameraAppUi::ImageBufferReady(MCameraBuffer& aCameraBuffer, TInt aError) { if (aError == KErrNone) { // Sử dụng ảnh } else { // quản lý lỗi } } Chú ý rằng kính ngắm sẽ không tựđộng ngừng khi chụp ảnh. Ứng dụng khách phải có trách nhiệm ngừng kính ngắm và hiển thịảnh đã được chụp.
Trong trường hợp muốn chụp nhiều hơn một ảnh, ta có thể gọi lại phương thức
CaptureImage(), tuy nhiên ta không được gọi lại CaptureImage() trước khi:
• Nhận được callback từImageBufferReady().
• Hủy quá trình chụp ảnh hiện hành bằng cách gọi CancelImage- Capture().
Ảnh sẽ được đóng gói bởi lớp MCameraBuffer, lớp này cũng được dùng khi nhận ảnh từ kính ngắm. Lớp MCameraBuffer có thể lưu trữ dữ liệu ảnh theo nhiều cách và có thể lữu trữ nhiều khung ảnh. Khi chụp ảnh tĩnh, lớp này lưu trữ
Nhưđã đề cập ở trên, ta có thể chọn định dạng ảnh chụp. Nếu ta yêu cầu định dạng EFormatFbsBitmapColorXxx, phương thức McameraBuffer ::BitmapL() sẽ trả về quyền điều khiển thực thể CFbsBitmap đang chứa dữ
liệu ảnh. Nếu ta yêu cầu định dạng EFormatJpeg hay EFormatExif, chuỗi dữ
liệu có thể được giải mã thành thực thể CFbsBitmap bằng cách sử dụng lớp
CImageDecoder hoặc ghi trực tiếp dữ liệu ảnh vào tập tin JPEG. Đối với những
định dạng khác, dữ liệu được biểu diễn dưới dạng chuỗi, dữ liệu có thể được truy xuất bằng phương thức MCameraBuffer::DataL(). Sự thể hiện của dữ liệu phụ thuộc vào định dạng mà ta đã yêu cầu.
Luận văn này chọn định dạng ảnh là EFormatExif để có thể lưu ảnh chụp vào tập tin JPEG. Phương pháp này vừa nhanh vừa tiết kiệm được bộ nhớ dùng để
lưu trữ tập tin ảnh đã được chụp.
Chú ý rằng, sau khi đã hoàn thành việc xử lý đối tượng MCameraBuffer, ta phải gọi phương thức Release() để tránh bị rò rỉ bộ nhớ. Phương thức này giải phóng tất cả bộ nhớđã được sử dụng và cho phép hệ thống con camera được tái sử
dụng bộ nhớ khi cần.
Nếu ta đang làm việc với những điện thoại chỉ hỗ trợ McameraObserver
chứ không hỗ trợMcameraObserver2, callback tương đương là:
MCameraObserver::ImageReady(CFbsBitmap* aBmp, HBufC8* aData, TInt aError)
CFbsBitmap và con trỏ HBufC8 có thể được xem như là các đối tượng
được trả về từ phương thức MCameraBuffer::BitmapL() và phương thức
MCameraBuffer::DataL(). Chỉ một trong hai tham số này là hợp lệ và được xác định bởi định dạng ảnh đang được sử dụng. Trong trường hợp dùng con trỏ, ta phải xóa nó sau khi đã sử dụng để tránh rò rỉ bộ nhớ.
vLưu trữảnh
Sau khi đã chụp ảnh, ta phải thực hiện lưu trữảnh để làm đầu vào cho các khối khác trong ứng dụng:
void StorePicture( TDesC8* aData ) {
RFile file;
TInt err = file.Create(iEikonEnv -> FsSession(), aSavingFile, EFileWrite); if (!err) { file.Write(*aData); file.Close(); } else {
SetError(_L("File saving error %d"),err); }
}
Chuỗi aSavingFile chứa tên tập tin ảnh được lưu với đường dẫn đầy đủ.