Home > Products > SophiaFramework UNIVERSE > Tutorial > BREW Camera Application > - 4 / 6 -

Simple BREW Camera Application - 4 / 6 -

Implement Camera Class

Objectives of Camera Class

To create a general purpose C++ class for Cameras processing with BREW which will be reusable in other applications more sophiaticated than SimpleCamera.

Header File of Camera Class

- Camera.hpp -

#ifndef __CAMERA_HPP
#define __CAMERA_HPP

#include 


#define PICTURE_WIDTH   240  // Width of image taken with camera
#define PICTURE_HEIGHT  320  // Height of image taken with camera


SFMTYPEDEFCLASS(Camera)
class Camera {
SFMSEALCOPY(Camera)
public:
    enum StatusEnum {   // Status of camera
        STATUS_PREVIEW, // Preview mode
        STATUS_FRAME,   // New frame of the preview was drawn
        STATUS_RECORD,  // Start of snapshot mode
        STATUS_ENCODE   // Completion of photography in snapshot mode
    };

private:
    typedef Void (*NotifySPP)(StatusEnum status, SFCError error, VoidPtr reference);

private:
    SFBCameraSmp _sfbCamera;   // ICamera interface
    StatusEnum _camStatus;     // Camera status
    SFBBitmapSmp _camBitmap;   // Photo image in bitmap
    SFXRectangle _camRect;     // Display area of photo 
                               // image on screen  
    AEEMediaData _mediaData;   // Media data
    ACharPtr _mimeType;        // MIME TYPE
    Bool _camPreviewable;      // Whether it is a possible 
                               // preview now or not?
    Bool _camRecordable;       // Whether photography is 
                               // available in snapshot mode or not? 
    NotifySPP _camSPP;         // Callback function of camera
    VoidPtr _camReference;     // Reference data for the 
                               // above callback function

    Void AfterSnapshot(Void);  // Processing after snapshot 
                               // picture is taken 

public:
    Camera(Void);               // Constructor
    virtual ~Camera(Void);      // Destructor
    SFCError camInitialize(SFXRectangleConstRef rect, 
    NotifySPP spp, VoidPtr reference);  // Initialization of camera
    SFCError camPreview(Void);  // Beginning of Preview mode
    SFCError camRecord(Void);   // Beginning of snapshot mode
    Void camSuspend(Void);      // Suspend camera processing   
    SFCError camResume(Void);   // Resume camera processing
    Void camTerminate(Void);    // Release source
    SFBBitmapSmpRef GetBitmap(Void) {  // Get photo image in bitmap 
        return _camBitmap;
    }
    // Whether it is possible to preview now 
    Bool IsPreviewable(Void) const {  
        return _camPreviewable;
    }
    // Callback handler
    static Void OnCameraSHP(VoidPtr reference, 
    AEECameraNotify* notify);
    // Callback handler (Body)   
    Void OnCamera(AEECameraNotify *notify);
    // Get the current brightness of camera   
    SInt16 GetCamBrightness(Void);
    // Get the range of brightness available for camera 
    Bool GetCamBrightnessRange(SInt16Ptr minimum, 
    SInt16Ptr maximum);
    // Set the brightness of camera   
    Void SetCamBrightness(SInt16 value);
    // Get the current zoom value
    SInt16 GetCamZoom(Void);
    // Get the range of zoom values available for camera
    Bool GetCamZoomRange(SInt16Ptr mininum, SInt16Ptr maximum);
    // Set the zoom value
    Void SetCamZoon(SInt16 value);
    };

#endif

Main functions of Camera class :

  1. camInitialize() : initialize camera
  2. camPreview() : start to preview
  3. camRecord() : take a snapshot
  4. OnCamera() : handle events

Initialize Camera

Camera::camInitialize()

// Intialize Camera class
// rect      : display area for preview
// spp       : pointer to external callback function
// reference : pointer to data for external callback function
SFCError Camera::Initialize(SFXRectangleConstRef rect,
                                     NotifySPP spp, VoidPtr reference)
{

  SFCError error(SFERR_NO_ERROR);
  // Make bitmap for photo image 
  _camBitmap = SFXGraphics::CreateBitmap(rect.GetSize());
  if (_camBitmap != null) {
    error = camResume();  // Preparations for camera processing 
    if (error == SFERR_NO_ERROR) {
      _camRect = rect;
      _camSPP = spp;
      _camReference = reference;
    }
  } else {
    // Bitmap cannot be made because of insufficient memory
    error = SFERR_NO_MEMORY;
  }
  if (error != SFERR_NO_ERROR) {
    camTerminate();
  }
  return error;
}

1st argument: clipped size of photo image as SFXRectangle type

2nd argument: external callback function after handling events

The signature of this function is as follows.

  Void foo(Camera::StatusEnum status, SFCError error, VoidPtr reference);
  // foo is function name

3rd argument: pointer to the data for the function that is the 2nd argument

Camera::camResume()

// Initialize camera 
SFCError Camera::camResume(Void)
{
  SFCError error(SFERR_NO_ERROR);
  // Get instance of camera
  if ((_sfbCamera = SFBCamera::NewInstance()) != null) {
    _camPreviewable = true;
    _camRecordable = false;
    // Register internal callback 
    error = _sfbCamera->RegisterNotify(OnCameraSHP, this);
    if (error == SFERR_NO_ERROR) {
      AEESize size;
      size.cx = PICTURE_WIDTH;
      size.cy = PICTURE_HEIGHT;
      error = _sfbCamera->SetSize(&size);
      if (error == SFERR_NO_ERROR) {
        // Set the size of photo image
        error = _sfbCamera->SetDisplaySize(&size);
      }
    }
  } else {
    // instance of camera cannot be gotten 
    // because of insufficient memory
    error = SFERR_NO_MEMORY;
  }
  if (error != SFERR_NO_ERROR) {
    camSuspend();
  }
  return error;
}

When the Camera needs to suspend its usage, all phone resources (memory) that were being used should be released. And when it resumes, it should be instantiated and initialized again.

The camResume() function is for getting an instance of camera by using SFBCamera::NewInstance() and registering the internal callback functions for camera events by using SFBCamera::RegisterNotify().

The signature of RegisterNotify() is as follows.

  SFCError RegisterNotify(PFNCAMERANOTIFY notify, VoidPtr data);

The variable notify is a pointer to the callback function and data is a pointer to the data of the callback function.

In the above example, OnCameraSHP() of Camera is registered.

The callback function is the static function with the following signature.

  Void foo(VoidPtr reference, AEECameraNotify *notify);

* The status of camera is saved in nStatus of AEECameraNotify structure.

The size of the photo image AEESize, must be always set by calling SFBCamera::SetDisplaySize() before moving into Preview Mode.

In the example of the Camera class, the size of photo image for both Preview and Snapshot is fixed.

* By using SFBCamera::GetDisplaySizeList() or SFBCamera::GetSizeList(), the size of the photo image can modified to fit a mobile handset.

Start the Preview Mode

Camera::camPreview()

// Start to preview
SFCError Camera::camPreview(Void)
{
  SFCError error(SFERR_NO_ERROR);
  if (_sfbCamera != null) {
    _camStatus = STATUS_PREVIEW;
    _camPreviewable = false;
    _camRecordable = false;
    error = _sfbCamera->Preview(); // Boot up the camera for previewing
  } else {
    error = SFERR_FAILED;
  }
  return error;
}

The status of camera is saved in nCmd or nSubCmd included in the 2nd argument AEECameraNotify of the callback function foo.

The status of camera may be known by the value of 3 member variable: nStatus, nCmd and nSubCmd, but here it is found only by the value of the _camStatus member variable of the Camera class.

Take Photo in Snapshot Mode

Camera::camRecord()

// take photo in snapshot mode
SFCError Camera::camRecord(Void)
{
  SFCError error(SFERR_NO_ERROR);
  if (_sfbCamera != null) {
    _camPreviewable = false;
    _camRecordable = false;

    _camStatus = STATUS_RECORD;
    error = _sfbCamera->Stop();  // end of preview
    // event handler is called at the end of preview
    // photo in snapshot mode is taken in this handler
  } else {
    error = SFERR_FAILED;
  }
  return error;
}

Preview Mode cannot directly change into Snapshot Mode, and it is necessary to stop the Preview mode by calling SFBCamera::Stop().

At this point, the event CAM_STATUS_DONE will occur.

And STATUS_RECORD should be set on the _camStatus member variable just before the Preview Mode ends.

When the internal callback function recognizes that the value of _camStatus is STATUS_RECORD, the mode will be changed to Snapshot Mode.

Internal Callback Function

Camera::OnCameraSHP() registered by using SFBCamera::RegisterNotify() is a internal callback function. This is because callback functions must be static functions.

OnCamera() is called from OnCameraSHP(). This means that the real body of the internal callback function is OnCamera().

// Internal Callback Handler
Void OnCameraSHP(VoidPtr reference, AEECameraNotify *notify)
{
  // call the body of Internal Callback Handler
  static_cast<CameraPtr>(reference)->OnCamera(notify);
  return;
}
// Internal Callback Handler ( body )
Void Camera::OnCamera(AEECameraNotify* notify)
{
  switch (notify->nStatus) {
    case CAM_STATUS_START:  // completion of camera bootup
      if (_camStatus == STATUS_PREVIEW) {
        _camRecordable = true;
        // call external callback function
        _camSPP(_camStatus, SFERR_NO_ERROR, _camReference);
      }
      break;
    case CAM_STATUS_FRAME:  // new frame has been gotten
      if (_camStatus == STATUS_PREVIEW) {
        SFBBitmapSmp bitmap;
        // The photo image of the camera is obtained as a bitmap.
        if (_sfbCamera->GetFrame(&bitmap) == SFERR_NO_ERROR) {
          // Clip displayed area from photo image
          _camBitmap->BltIn(SFXRectangle(0, 0, _camRect.GetSize()),
                                        bitmap, _camRect.GetOrigin());
        }
        // Call external callback function
        _camSPP(STATUS_FRAME, SFERR_NO_ERROR, _camReference);

        SFXGraphicsPtr pg = SFXGraphics::GetInstance();
        // The obtained image is displayed on the screen. 
        pg->BitBlt(_camRect, _camBitmap, SFXGrid(0, 0));
        pg->Update();  // update screen
      }
      break;
    case CAM_STATUS_DONE:  // Completion of processing
      if (_camStatus == STATUS_RECORD) {
        _camStatus = STATUS_ENCODE;
        _sfbCamera->DeferEncode(true);  // Set delay encode mode 
        _sfbCamera->SetMediaData(&_mediaData, _mimeType);
        // Take a picture in the snapshot mode.  
        _sfbCamera->RecordSnapshot();
      } else if (_camStatus == STATUS_ENCODE) {
        AfterSnapshot();
      }
      break;
    case CAM_STATUS_FAIL:
    case CAM_STATUS_ABORT:
      // call external callback function
      _camSPP(_camStatus, EFAILED, _camReference);
      break;
  }
  return;
}

The external callback function registered by using Camera::camInitialize() is called with camera status and error code as argument.

The first case statement is for handling the CAM_STATUS_START event that will occur when the camera is booted up.

The second case statement is for handling the CAM_STATUS_FRAME event that will occur when a new image is taken every fixed period in Preview Mode ( this period can be changed by using SFBCamera::SetFramesPerSecond() ).

The code for displaying the photo image only is as follows.

  // _sfbCamera is the instance of camera. 
  SFBBitmapSmp bitmap;
  // The photo image of the camera is obtained as a bitmap. 
  if (_sfbCamera->GetFrame(&bitmap) == SFERR_NO_ERROR) {
  // Clip displayed area from photo image 
  _camBitmap->BltIn(SFXRectangle(0, 0, _camRect.GetSize()), 
                             bitmap, _camRect.GetOrigin()); 
  }
  // call external callback function
  _camSPP(STATUS_FRAME, SFERR_NO_ERROR, _camReference);
  // get instance of screen
  SFXGraphicsPtr pg = SFXGraphics::GetInstance();
  // transfer image to screen
  pg->BitBlt(_camRect, _camBitmap, SFXGrid(0, 0));
  // update screen
  pg->Update();               

*1. When using BREW API, it is necessary to explicitly release the bitmap gotten by using ICAMERA_GetFrame(). But SophiaFramework UNIVERSE automatically releases an image when the control is out of its scope.

*2. As noise canceling functions will not work in Preview Mode, images taken in this mode should not be used for processing.

The 3rd case statement is for handling the CAM_STATUS_DONE event. The CAM_STATUS_DONE event will occur when calling SFBCamera::Stop() which ends the Preview Mode or SFBCamera::RecordSnapshot() which is for taking a picture in the Snapshot Mode

By utilizing this feature, changing into the Snapshot Mode is implemented in the callback function; not by calling SFBCamera::Stop() found in camRecord() of the Camera class.

Mode Transition Flow

As Delay Encode is being used, SFBCamera::DeferEncode() is called with an initial value of true. Then SFBCamera::SetMediaData(), SetMediaData(), SFBCamera::RecordSnapshot() are all respectively called sequentially.

* With Regard to calling SetMediaData(), arbitrary values can be set because the photo image is not saved as file.

After SFBCamera::RecordSnapshot() is called, a CAM_STATUS_DONE event will occur when a photo is taken. The photo image can be retrieved by using SFBCamera::GetFrame() function.

At this time, the mode of camera is changed into a waiting staus that is neither Preview Mode nor the Snapshot Mode. To change into Preview Mode, SFBCamera::Preview() needs to be called ( In the Camera class, camPreview() needs to be called ).

In Camera class, the photo image is clipped with the appropriate size in AfterSnapshot(), saved in the _camBitmap member variable and retrieved by using Camera::GetBitmap().

The other case statements are for handling errors.

Contol the Brightness and Zoom

// Get current brightness
SInt16 Camera::GetCamBrightness(Void)
{
  SInt16 result(0);
  if (_sfbCamera != null) {
    SInt32 value;
    AEEParmInfo info;
    // Get brightness
    if (_sfbCamera->GetParm(CAM_PARM_BRIGHTNESS,
                        &value, (SInt32Ptr)&info) == SFERR_NO_ERROR) {
      result = (SInt16)value;
    }
  }
  return result;
}

// Get range of brightness
Bool Camera::GetCamBrightnessRange(SInt16Ptr minimum, SInt16Ptr maximum)
{
  Bool result(false);
  *minimum = *maximum = 0;
  if (_sfbCamera != null) {
    Bool support;
    if (_sfbCamera->IsBrightness(&support) == SFERR_NO_ERROR) {
      if (support) {
        SInt32 value;
        AEEParmInfo info;
        // Get range
    	if (_sfbCamera->GetParm(CAM_PARM_BRIGHTNESS,
                        &value, (SInt32Ptr)&info) == SFERR_NO_ERROR) {
          	*minimum = (SInt16)info.nMin;
          	*maximum = (SInt16)info.nMax;
          	result = true;
        }
      }
    }
  }
  return result;
}

// Set brightness
Void Camera::SetCamBrightness(SInt16 value)
{
  if (_sfbCamera != null) {
    if (_camRecordable) {
    // Set brightness
      _sfbCamera->SetBrightness(value);
    }
  }
}

// Get current zoom value
SInt16 Camera::GetCamZoom(Void)
{
  SInt16 result(0);
  if (_sfbCamera != null) {
    SInt32 value;
    AEEParmInfo info;
    // Get zoom value
    if (_sfbCamera->GetParm(CAM_PARM_ZOOM,
                        &value, (SInt32Ptr)&info) == SFERR_NO_ERROR) {
            result = (SInt16)value;
    }
  }
  return result;
}

// Get range of zoom value 
Bool Camera::GetCamZoomRange(SInt16Ptr minimum, SInt16Ptr maximum)
{
  Bool result(false);
  *minimum = *maximum = 0;
  if (_sfbCamera != null) {
    Bool support;
    if (_sfbCamera->IsZoom(&support) == SFERR_NO_ERROR) {
      if (support) {
        SInt32 value;
        AEEParmInfo info;
        // Get range
        if (_sfbCamera->GetParm(CAM_PARM_ZOOM,
                        &value, (SInt32Ptr)&info) == SFERR_NO_ERROR) {
          *minimum = (SInt16)info.nMin;
          *maximum = (SInt16)info.nMax;
          result = true;
        }
      }
    }
  }
  return result;
}

// Set zoom value
Void Camera::SetCamZoom(SInt16 value)
{
  if (_sfbCamera != null) {
    if (_camRecordable) {
    // Setting zoom value
      _sfbCamera->SetZoom(value); 
    }
  }
}

Go back  1   2   3   4   5   Apdx   Next page