Bug 981318 - expose compressed image quality setting, r=dhylands,khuey
authorMike Habicher <mikeh@mozilla.com>
Mon, 25 Aug 2014 15:12:49 -0400
changeset 223070 10412cc35ca4a8a925c4fbf159c13dd74e0b3d62
parent 223069 f5bd864fdd5dab26c6951872f4c62b78450d2358
child 223071 f22cf1debda460ec1cb404b327d854d12ac0d3fc
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdhylands, khuey
bugs981318
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 981318 - expose compressed image quality setting, r=dhylands,khuey
dom/camera/DOMCameraControl.cpp
dom/camera/DOMCameraControl.h
dom/camera/GonkCameraControl.cpp
dom/camera/GonkCameraParameters.cpp
dom/camera/ICameraControl.h
dom/camera/test/test_camera.html
dom/webidl/CameraControl.webidl
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -393,21 +393,37 @@ nsDOMCameraControl::GetIsoMode(nsString&
 void
 nsDOMCameraControl::SetIsoMode(const nsAString& aIsoMode, ErrorResult& aRv)
 {
   MOZ_ASSERT(mCameraControl);
   aRv = mCameraControl->Set(CAMERA_PARAM_ISOMODE, aIsoMode);
 }
 
 double
+nsDOMCameraControl::GetPictureQuality(ErrorResult& aRv)
+{
+  MOZ_ASSERT(mCameraControl);
+
+  double quality;
+  aRv = mCameraControl->Get(CAMERA_PARAM_PICTURE_QUALITY, quality);
+  return quality;
+}
+void
+nsDOMCameraControl::SetPictureQuality(double aQuality, ErrorResult& aRv)
+{
+  MOZ_ASSERT(mCameraControl);
+  aRv = mCameraControl->Set(CAMERA_PARAM_PICTURE_QUALITY, aQuality);
+}
+
+double
 nsDOMCameraControl::GetZoom(ErrorResult& aRv)
 {
   MOZ_ASSERT(mCameraControl);
 
-  double zoom;
+  double zoom = 1.0;
   aRv = mCameraControl->Get(CAMERA_PARAM_ZOOM, zoom);
   return zoom;
 }
 
 void
 nsDOMCameraControl::SetZoom(double aZoom, ErrorResult& aRv)
 {
   MOZ_ASSERT(mCameraControl);
--- a/dom/camera/DOMCameraControl.h
+++ b/dom/camera/DOMCameraControl.h
@@ -77,16 +77,18 @@ public:
   double GetFocusDistanceOptimum(ErrorResult& aRv);
   double GetFocusDistanceFar(ErrorResult& aRv);
   void SetExposureCompensation(double aCompensation, ErrorResult& aRv);
   double GetExposureCompensation(ErrorResult& aRv);
   int32_t SensorAngle();
   already_AddRefed<dom::CameraCapabilities> Capabilities();
   void GetIsoMode(nsString& aMode, ErrorResult& aRv);
   void SetIsoMode(const nsAString& aMode, ErrorResult& aRv);
+  double GetPictureQuality(ErrorResult& aRv);
+  void SetPictureQuality(double aQuality, ErrorResult& aRv);
 
   // Unsolicited event handlers.
   dom::CameraShutterCallback* GetOnShutter();
   void SetOnShutter(dom::CameraShutterCallback* aCb);
   dom::CameraClosedCallback* GetOnClosed();
   void SetOnClosed(dom::CameraClosedCallback* aCb);
   dom::CameraRecorderStateChange* GetOnRecorderStateChange();
   void SetOnRecorderStateChange(dom::CameraRecorderStateChange* aCb);
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -172,28 +172,32 @@ nsGonkCameraControl::Initialize()
   nsString luminance; // check for support
   mParams.Get(CAMERA_PARAM_LUMINANCE, luminance);
   mLuminanceSupported = !luminance.IsEmpty();
 
   nsString flashMode;
   mParams.Get(CAMERA_PARAM_FLASHMODE, flashMode);
   mFlashSupported = !flashMode.IsEmpty();
 
+  double quality; // informational only
+  mParams.Get(CAMERA_PARAM_PICTURE_QUALITY, quality);
+
   DOM_CAMERA_LOGI(" - maximum metering areas:        %u\n", mCurrentConfiguration.mMaxMeteringAreas);
   DOM_CAMERA_LOGI(" - maximum focus areas:           %u\n", mCurrentConfiguration.mMaxFocusAreas);
   DOM_CAMERA_LOGI(" - default picture size:          %u x %u\n",
     mLastPictureSize.width, mLastPictureSize.height);
+  DOM_CAMERA_LOGI(" - default picture file format:   %s\n",
+    NS_ConvertUTF16toUTF8(mFileFormat).get());
+  DOM_CAMERA_LOGI(" - default picture quality:       %f\n", quality);
   DOM_CAMERA_LOGI(" - default thumbnail size:        %u x %u\n",
     mLastThumbnailSize.width, mLastThumbnailSize.height);
   DOM_CAMERA_LOGI(" - default preview size:          %u x %u\n",
     mCurrentConfiguration.mPreviewSize.width, mCurrentConfiguration.mPreviewSize.height);
   DOM_CAMERA_LOGI(" - default video recorder size:   %u x %u\n",
     mLastRecorderSize.width, mLastRecorderSize.height);
-  DOM_CAMERA_LOGI(" - default picture file format:   %s\n",
-    NS_ConvertUTF16toUTF8(mFileFormat).get());
   DOM_CAMERA_LOGI(" - luminance reporting:           %ssupported\n",
     mLuminanceSupported ? "" : "NOT ");
   if (mFlashSupported) {
     DOM_CAMERA_LOGI(" - flash:                         supported, default mode '%s'\n",
       NS_ConvertUTF16toUTF8(flashMode).get());
   } else {
     DOM_CAMERA_LOGI(" - flash:                         NOT supported\n");
   }
--- a/dom/camera/GonkCameraParameters.cpp
+++ b/dom/camera/GonkCameraParameters.cpp
@@ -110,16 +110,18 @@ GonkCameraParameters::Parameters::GetTex
     case CAMERA_PARAM_LUMINANCE:
       return "luminance-condition";
     case CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE:
       // Not every platform defines KEY_QC_HDR_NEED_1X;
       // for those that don't, we use the raw string key.
       return "hdr-need-1x";
     case CAMERA_PARAM_RECORDINGHINT:
       return KEY_RECORDING_HINT;
+    case CAMERA_PARAM_PICTURE_QUALITY:
+      return KEY_JPEG_QUALITY;
 
     case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
       return KEY_SUPPORTED_PREVIEW_SIZES;
     case CAMERA_PARAM_SUPPORTED_PICTURESIZES:
       return KEY_SUPPORTED_PICTURE_SIZES;
     case CAMERA_PARAM_SUPPORTED_VIDEOSIZES:
       return KEY_SUPPORTED_VIDEO_SIZES;
     case CAMERA_PARAM_SUPPORTED_PICTUREFORMATS:
@@ -656,16 +658,29 @@ GonkCameraParameters::SetTranslated(uint
             } else {
               top = index - 1;
             }
           }
         }
         DOM_CAMERA_LOGI("Zoom = %fx --> index = %d\n", aValue, index);
       }
       return SetImpl(CAMERA_PARAM_ZOOM, index);
+
+    case CAMERA_PARAM_PICTURE_QUALITY:
+      {
+        // Convert aValue [0.0..1.0] to nearest index in the range [1..100].
+        index = (aValue + 0.005) * 99.0 + 1.0;
+        if (aValue < 0.0) {
+          index = 1;
+        } else if (aValue > 1.0) {
+          index = 100;
+        }
+        DOM_CAMERA_LOGI("Picture quality = %f --> index = %d\n", aValue, index);
+      }
+      return SetImpl(CAMERA_PARAM_PICTURE_QUALITY, index);
   }
 
   return SetImpl(aKey, aValue);
 }
 
 nsresult
 GonkCameraParameters::GetTranslated(uint32_t aKey, double& aValue)
 {
@@ -720,16 +735,29 @@ GonkCameraParameters::GetTranslated(uint
       }
       rv = GetImpl(aKey, index);
       if (NS_SUCCEEDED(rv)) {
         val = index * mExposureCompensationStep;
         DOM_CAMERA_LOGI("exposure compensation (aKey=%d): index=%d --> EV=%f\n", aKey, index, val);
       }
       break;
 
+    case CAMERA_PARAM_PICTURE_QUALITY:
+      // Convert index [1..100] to a quality value [0.0..1.0].
+      rv = GetImpl(aKey, index);
+      if (index < 2) {
+        val = 0.0;
+      } else if (index > 99) {
+        val = 1.0;
+      } else {
+        val = static_cast<double>(index - 1) / 99.0;
+      }
+      DOM_CAMERA_LOGI("index = %d --> picture quality = %f\n", index, val);
+      break;
+
     default:
       rv = GetImpl(aKey, val);
       break;
   }
 
   if (NS_SUCCEEDED(rv)) {
     aValue = val;
   }
--- a/dom/camera/ICameraControl.h
+++ b/dom/camera/ICameraControl.h
@@ -28,16 +28,17 @@ enum {
   CAMERA_PARAM_PREVIEWFORMAT,
   CAMERA_PARAM_PREVIEWFRAMERATE,
   CAMERA_PARAM_VIDEOSIZE,
   CAMERA_PARAM_PICTURE_SIZE,
   CAMERA_PARAM_PICTURE_FILEFORMAT,
   CAMERA_PARAM_PICTURE_ROTATION,
   CAMERA_PARAM_PICTURE_LOCATION,
   CAMERA_PARAM_PICTURE_DATETIME,
+  CAMERA_PARAM_PICTURE_QUALITY,
   CAMERA_PARAM_EFFECT,
   CAMERA_PARAM_WHITEBALANCE,
   CAMERA_PARAM_SCENEMODE,
   CAMERA_PARAM_FLASHMODE,
   CAMERA_PARAM_FOCUSMODE,
   CAMERA_PARAM_ZOOM,
   CAMERA_PARAM_METERINGAREAS,
   CAMERA_PARAM_FOCUSAREAS,
--- a/dom/camera/test/test_camera.html
+++ b/dom/camera/test/test_camera.html
@@ -154,19 +154,33 @@ var Camera = {
     ok(camcap.isoModes.length == 0, "ISO modes length = " + camcap.isoModes.length);
 
     // The emulator doesn't support zoom, so these parameters will be very constrained
     // For more ambitious tests, see test_camera_fake_parameters.html
     ok(Camera._zoomRatios.length == 1, "zoom ratios length = " + Camera._zoomRatios.length);
     ok(Camera.cameraObj.zoom == 1.0, "zoom = " + Camera.cameraObj.zoom);
     // Test snapping to supported values
     Camera.cameraObj.zoom = 0.9;
-    ok(Camera.cameraObj.zoom == 1.0, "zoom = " + Camera.cameraObj.zoom);
+    ok(Camera.cameraObj.zoom == 1.0, "zoom (lower limit) = " + Camera.cameraObj.zoom);
     Camera.cameraObj.zoom = 1.1;
-    ok(Camera.cameraObj.zoom == 1.0, "zoom = " + Camera.cameraObj.zoom);
+    ok(Camera.cameraObj.zoom == 1.0, "zoom (upper limit) = " + Camera.cameraObj.zoom);
+
+    // Check image quality handling
+    Camera.cameraObj.pictureQuality = 0.0;
+    ok(Camera.cameraObj.pictureQuality == 0.0, "picture quality = " + Camera.cameraObj.pictureQuality);
+    Camera.cameraObj.pictureQuality = -0.1;
+    ok(Camera.cameraObj.pictureQuality == 0.0, "picture quality (minimum limit) = " + Camera.cameraObj.pictureQuality);
+    Camera.cameraObj.pictureQuality = -Math.pow(2, 80);
+    ok(Camera.cameraObj.pictureQuality == 0.0, "picture quality (BIG negative) = " + Camera.cameraObj.pictureQuality);
+    Camera.cameraObj.pictureQuality = 1.0;
+    ok(Camera.cameraObj.pictureQuality == 1.0, "picture quality = " + Camera.cameraObj.pictureQuality);
+    Camera.cameraObj.pictureQuality = 1.1;
+    ok(Camera.cameraObj.pictureQuality == 1.0, "picture quality (maximum limit) = " + Camera.cameraObj.pictureQuality);
+    Camera.cameraObj.pictureQuality = Math.pow(2, 80);
+    ok(Camera.cameraObj.pictureQuality == 1.0, "picture quality (BIG positive) = " + Camera.cameraObj.pictureQuality);
 
     Camera._tests = new Array();
     for (var i in Camera._pictureSizes) {
       for (var l in Camera._fileFormats) {
         var config = {
           pictureSize: Camera._pictureSizes[i],
           fileFormat: Camera._fileFormats[l]
         };
--- a/dom/webidl/CameraControl.webidl
+++ b/dom/webidl/CameraControl.webidl
@@ -252,16 +252,26 @@ interface CameraControl : MediaStream
   /* the size of the picture to be returned by a call to takePicture();
      an object with 'height' and 'width' properties that corresponds to
      one of the options returned by capabilities.pictureSizes. */
   [Throws]
   CameraSize getPictureSize();
   [Throws]
   void setPictureSize(optional CameraSize size);
 
+  /* if the image blob to be returned by takePicture() supports lossy
+     compression, this setting controls the quality-size trade-off;
+     valid values range from 0.0 for smallest size/worst quality to 1.0
+     for largest size/best quality. Note that depending on the range of
+     values supported by the underlying platform, this attribute may not
+     'get' the exact value that was previously 'set'. If this setting is
+     not supported, it is ignored. */
+  [Throws]
+  attribute double           pictureQuality;
+
   /* the size of the thumbnail to be included in the picture returned
      by a call to takePicture(), assuming the chosen fileFormat supports
      one; an object with 'height' and 'width' properties that corresponds
      to one of the options returned by capabilities.pictureSizes.
 
      this setting should be considered a hint: the implementation will
      respect it when possible, and override it if necessary. */
   [Throws]