diff --git a/dom/camera/DOMCameraControl.cpp b/dom/camera/DOMCameraControl.cpp index fc09eb70e7b1..2f9f29b98ec5 100644 --- a/dom/camera/DOMCameraControl.cpp +++ b/dom/camera/DOMCameraControl.cpp @@ -397,12 +397,28 @@ nsDOMCameraControl::SetIsoMode(const nsAString& aIsoMode, ErrorResult& aRv) 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; } diff --git a/dom/camera/DOMCameraControl.h b/dom/camera/DOMCameraControl.h index 3dbb944ad61f..00e577972fc8 100644 --- a/dom/camera/DOMCameraControl.h +++ b/dom/camera/DOMCameraControl.h @@ -82,6 +82,8 @@ public: already_AddRefed 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(); diff --git a/dom/camera/GonkCameraControl.cpp b/dom/camera/GonkCameraControl.cpp index 15a3190e018e..b846e3a49734 100644 --- a/dom/camera/GonkCameraControl.cpp +++ b/dom/camera/GonkCameraControl.cpp @@ -177,18 +177,22 @@ nsGonkCameraControl::Initialize() 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) { diff --git a/dom/camera/GonkCameraParameters.cpp b/dom/camera/GonkCameraParameters.cpp index 3307f3c0b290..6e5581ebf3f1 100644 --- a/dom/camera/GonkCameraParameters.cpp +++ b/dom/camera/GonkCameraParameters.cpp @@ -115,6 +115,8 @@ GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey) 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; @@ -661,6 +663,19 @@ GonkCameraParameters::SetTranslated(uint32_t aKey, const double& aValue) 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); @@ -725,6 +740,19 @@ GonkCameraParameters::GetTranslated(uint32_t aKey, double& aValue) } 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(index - 1) / 99.0; + } + DOM_CAMERA_LOGI("index = %d --> picture quality = %f\n", index, val); + break; + default: rv = GetImpl(aKey, val); break; diff --git a/dom/camera/ICameraControl.h b/dom/camera/ICameraControl.h index 115bf924a043..3d33f831c21e 100644 --- a/dom/camera/ICameraControl.h +++ b/dom/camera/ICameraControl.h @@ -33,6 +33,7 @@ enum { 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, diff --git a/dom/camera/test/test_camera.html b/dom/camera/test/test_camera.html index 4d861cfab35b..2d20b1618564 100644 --- a/dom/camera/test/test_camera.html +++ b/dom/camera/test/test_camera.html @@ -159,9 +159,23 @@ var Camera = { 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) { diff --git a/dom/webidl/CameraControl.webidl b/dom/webidl/CameraControl.webidl index e88b5ff9cdae..3a88471db89e 100644 --- a/dom/webidl/CameraControl.webidl +++ b/dom/webidl/CameraControl.webidl @@ -257,6 +257,16 @@ interface CameraControl : MediaStream [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