Merge "DngCreator : Add support for maximum resolution mode captures for ultra high resolution sensors." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0c9840906a
@@ -83,6 +83,22 @@ using android::base::GetProperty;
|
|||||||
return nullptr; \
|
return nullptr; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BAIL_IF_EMPTY_RET_BOOL(entry, jnienv, tagId, writer) \
|
||||||
|
if ((entry).count == 0) { \
|
||||||
|
jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
|
||||||
|
"Missing metadata fields for tag %s (%x)", \
|
||||||
|
(writer)->getTagName(tagId), (tagId)); \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BAIL_IF_EMPTY_RET_STATUS(entry, jnienv, tagId, writer) \
|
||||||
|
if ((entry).count == 0) { \
|
||||||
|
jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
|
||||||
|
"Missing metadata fields for tag %s (%x)", \
|
||||||
|
(writer)->getTagName(tagId), (tagId)); \
|
||||||
|
return BAD_VALUE; \
|
||||||
|
}
|
||||||
|
|
||||||
#define BAIL_IF_EXPR_RET_NULL_SP(expr, jnienv, tagId, writer) \
|
#define BAIL_IF_EXPR_RET_NULL_SP(expr, jnienv, tagId, writer) \
|
||||||
if (expr) { \
|
if (expr) { \
|
||||||
jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
|
jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
|
||||||
@@ -764,15 +780,76 @@ uint32_t DirectStripSource::getIfd() const {
|
|||||||
// End of DirectStripSource
|
// End of DirectStripSource
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Get the appropriate tag corresponding to default / maximum resolution mode.
|
||||||
|
static int32_t getAppropriateModeTag(int32_t tag, bool maximumResolution) {
|
||||||
|
if (!maximumResolution) {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
switch (tag) {
|
||||||
|
case ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE:
|
||||||
|
return ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION;
|
||||||
|
case ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE:
|
||||||
|
return ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION;
|
||||||
|
case ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE:
|
||||||
|
return ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION;
|
||||||
|
default:
|
||||||
|
ALOGE("%s: Tag %d doesn't have sensor info related maximum resolution counterpart",
|
||||||
|
__FUNCTION__, tag);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isMaximumResolutionModeImage(const CameraMetadata& characteristics, uint32_t imageWidth,
|
||||||
|
uint32_t imageHeight, const sp<TiffWriter> writer,
|
||||||
|
JNIEnv* env) {
|
||||||
|
// If this isn't an ultra-high resolution sensor, return false;
|
||||||
|
camera_metadata_ro_entry capabilitiesEntry =
|
||||||
|
characteristics.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
|
||||||
|
size_t capsCount = capabilitiesEntry.count;
|
||||||
|
const uint8_t* caps = capabilitiesEntry.data.u8;
|
||||||
|
if (std::find(caps, caps + capsCount,
|
||||||
|
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR) ==
|
||||||
|
caps + capsCount) {
|
||||||
|
// not an ultra-high resolution sensor, cannot have a maximum resolution
|
||||||
|
// mode image.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the image width and height are either the maximum resolution
|
||||||
|
// pre-correction active array size or the maximum resolution pixel array
|
||||||
|
// size, this image is a maximum resolution RAW_SENSOR image.
|
||||||
|
|
||||||
|
// Check dimensions
|
||||||
|
camera_metadata_ro_entry entry = characteristics.find(
|
||||||
|
ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION);
|
||||||
|
|
||||||
|
BAIL_IF_EMPTY_RET_BOOL(entry, env, TAG_IMAGEWIDTH, writer);
|
||||||
|
|
||||||
|
uint32_t preWidth = static_cast<uint32_t>(entry.data.i32[2]);
|
||||||
|
uint32_t preHeight = static_cast<uint32_t>(entry.data.i32[3]);
|
||||||
|
|
||||||
|
camera_metadata_ro_entry pixelArrayEntry =
|
||||||
|
characteristics.find(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION);
|
||||||
|
|
||||||
|
BAIL_IF_EMPTY_RET_BOOL(pixelArrayEntry, env, TAG_IMAGEWIDTH, writer);
|
||||||
|
|
||||||
|
uint32_t pixWidth = static_cast<uint32_t>(pixelArrayEntry.data.i32[0]);
|
||||||
|
uint32_t pixHeight = static_cast<uint32_t>(pixelArrayEntry.data.i32[1]);
|
||||||
|
|
||||||
|
return (imageWidth == preWidth && imageHeight == preHeight) ||
|
||||||
|
(imageWidth == pixWidth && imageHeight == pixHeight);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the default crop relative to the "active area" of the image sensor (this active area
|
* Calculate the default crop relative to the "active area" of the image sensor (this active area
|
||||||
* will always be the pre-correction active area rectangle), and set this.
|
* will always be the pre-correction active area rectangle), and set this.
|
||||||
*/
|
*/
|
||||||
static status_t calculateAndSetCrop(JNIEnv* env, const CameraMetadata& characteristics,
|
static status_t calculateAndSetCrop(JNIEnv* env, const CameraMetadata& characteristics,
|
||||||
sp<TiffWriter> writer) {
|
sp<TiffWriter> writer, bool maximumResolutionMode) {
|
||||||
|
camera_metadata_ro_entry entry = characteristics.find(
|
||||||
camera_metadata_ro_entry entry =
|
getAppropriateModeTag(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
|
||||||
characteristics.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
|
maximumResolutionMode));
|
||||||
|
BAIL_IF_EMPTY_RET_STATUS(entry, env, TAG_IMAGEWIDTH, writer);
|
||||||
uint32_t width = static_cast<uint32_t>(entry.data.i32[2]);
|
uint32_t width = static_cast<uint32_t>(entry.data.i32[2]);
|
||||||
uint32_t height = static_cast<uint32_t>(entry.data.i32[3]);
|
uint32_t height = static_cast<uint32_t>(entry.data.i32[3]);
|
||||||
|
|
||||||
@@ -811,11 +888,18 @@ static bool validateDngHeader(JNIEnv* env, sp<TiffWriter> writer,
|
|||||||
"Image height %d is invalid", height);
|
"Image height %d is invalid", height);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool isMaximumResolutionMode =
|
||||||
|
isMaximumResolutionModeImage(characteristics, static_cast<uint32_t>(width),
|
||||||
|
static_cast<uint32_t>(height), writer, env);
|
||||||
|
|
||||||
camera_metadata_ro_entry preCorrectionEntry =
|
camera_metadata_ro_entry preCorrectionEntry = characteristics.find(
|
||||||
characteristics.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
|
getAppropriateModeTag(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
|
||||||
camera_metadata_ro_entry pixelArrayEntry =
|
isMaximumResolutionMode));
|
||||||
characteristics.find(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE);
|
BAIL_IF_EMPTY_RET_BOOL(preCorrectionEntry, env, TAG_IMAGEWIDTH, writer);
|
||||||
|
|
||||||
|
camera_metadata_ro_entry pixelArrayEntry = characteristics.find(
|
||||||
|
getAppropriateModeTag(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, isMaximumResolutionMode));
|
||||||
|
BAIL_IF_EMPTY_RET_BOOL(pixelArrayEntry, env, TAG_IMAGEWIDTH, writer);
|
||||||
|
|
||||||
int pWidth = static_cast<int>(pixelArrayEntry.data.i32[0]);
|
int pWidth = static_cast<int>(pixelArrayEntry.data.i32[0]);
|
||||||
int pHeight = static_cast<int>(pixelArrayEntry.data.i32[1]);
|
int pHeight = static_cast<int>(pixelArrayEntry.data.i32[1]);
|
||||||
@@ -1236,10 +1320,13 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
|
|||||||
uint32_t preHeight = 0;
|
uint32_t preHeight = 0;
|
||||||
uint8_t colorFilter = 0;
|
uint8_t colorFilter = 0;
|
||||||
bool isBayer = true;
|
bool isBayer = true;
|
||||||
|
bool isMaximumResolutionMode =
|
||||||
|
isMaximumResolutionModeImage(characteristics, imageWidth, imageHeight, writer, env);
|
||||||
{
|
{
|
||||||
// Check dimensions
|
// Check dimensions
|
||||||
camera_metadata_entry entry =
|
camera_metadata_entry entry = characteristics.find(
|
||||||
characteristics.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
|
getAppropriateModeTag(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
|
||||||
|
isMaximumResolutionMode));
|
||||||
BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_IMAGEWIDTH, writer);
|
BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_IMAGEWIDTH, writer);
|
||||||
preXMin = static_cast<uint32_t>(entry.data.i32[0]);
|
preXMin = static_cast<uint32_t>(entry.data.i32[0]);
|
||||||
preYMin = static_cast<uint32_t>(entry.data.i32[1]);
|
preYMin = static_cast<uint32_t>(entry.data.i32[1]);
|
||||||
@@ -1247,15 +1334,18 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
|
|||||||
preHeight = static_cast<uint32_t>(entry.data.i32[3]);
|
preHeight = static_cast<uint32_t>(entry.data.i32[3]);
|
||||||
|
|
||||||
camera_metadata_entry pixelArrayEntry =
|
camera_metadata_entry pixelArrayEntry =
|
||||||
characteristics.find(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE);
|
characteristics.find(getAppropriateModeTag(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
|
||||||
|
isMaximumResolutionMode));
|
||||||
|
|
||||||
|
BAIL_IF_EMPTY_RET_NULL_SP(pixelArrayEntry, env, TAG_IMAGEWIDTH, writer);
|
||||||
uint32_t pixWidth = static_cast<uint32_t>(pixelArrayEntry.data.i32[0]);
|
uint32_t pixWidth = static_cast<uint32_t>(pixelArrayEntry.data.i32[0]);
|
||||||
uint32_t pixHeight = static_cast<uint32_t>(pixelArrayEntry.data.i32[1]);
|
uint32_t pixHeight = static_cast<uint32_t>(pixelArrayEntry.data.i32[1]);
|
||||||
|
|
||||||
if (!((imageWidth == preWidth && imageHeight == preHeight) ||
|
if (!((imageWidth == preWidth && imageHeight == preHeight) ||
|
||||||
(imageWidth == pixWidth && imageHeight == pixHeight))) {
|
(imageWidth == pixWidth && imageHeight == pixHeight))) {
|
||||||
jniThrowException(env, "java/lang/AssertionError",
|
jniThrowException(env, "java/lang/AssertionError",
|
||||||
"Height and width of image buffer did not match height and width of"
|
"Height and width of image buffer did not match height and width of"
|
||||||
"either the preCorrectionActiveArraySize or the pixelArraySize.");
|
" either the preCorrectionActiveArraySize or the pixelArraySize.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1773,11 +1863,12 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
|
|||||||
|
|
||||||
{
|
{
|
||||||
// Set dimensions
|
// Set dimensions
|
||||||
if (calculateAndSetCrop(env, characteristics, writer) != OK) {
|
if (calculateAndSetCrop(env, characteristics, writer, isMaximumResolutionMode) != OK) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
camera_metadata_entry entry =
|
camera_metadata_entry entry = characteristics.find(
|
||||||
characteristics.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
|
getAppropriateModeTag(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
|
||||||
|
isMaximumResolutionMode));
|
||||||
BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_ACTIVEAREA, writer);
|
BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_ACTIVEAREA, writer);
|
||||||
uint32_t xmin = static_cast<uint32_t>(entry.data.i32[0]);
|
uint32_t xmin = static_cast<uint32_t>(entry.data.i32[0]);
|
||||||
uint32_t ymin = static_cast<uint32_t>(entry.data.i32[1]);
|
uint32_t ymin = static_cast<uint32_t>(entry.data.i32[1]);
|
||||||
@@ -1872,8 +1963,9 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
|
|||||||
|
|
||||||
camera_metadata_entry entry2 = results.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
|
camera_metadata_entry entry2 = results.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
|
||||||
|
|
||||||
camera_metadata_entry entry =
|
camera_metadata_entry entry = characteristics.find(
|
||||||
characteristics.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
|
getAppropriateModeTag(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
|
||||||
|
isMaximumResolutionMode));
|
||||||
BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_IMAGEWIDTH, writer);
|
BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_IMAGEWIDTH, writer);
|
||||||
uint32_t xmin = static_cast<uint32_t>(entry.data.i32[0]);
|
uint32_t xmin = static_cast<uint32_t>(entry.data.i32[0]);
|
||||||
uint32_t ymin = static_cast<uint32_t>(entry.data.i32[1]);
|
uint32_t ymin = static_cast<uint32_t>(entry.data.i32[1]);
|
||||||
@@ -1899,7 +1991,12 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
|
|||||||
// Hot pixel map is specific to bayer camera per DNG spec.
|
// Hot pixel map is specific to bayer camera per DNG spec.
|
||||||
if (isBayer) {
|
if (isBayer) {
|
||||||
// Set up bad pixel correction list
|
// Set up bad pixel correction list
|
||||||
camera_metadata_entry entry3 = characteristics.find(ANDROID_STATISTICS_HOT_PIXEL_MAP);
|
// We first check the capture result. If the hot pixel map is not
|
||||||
|
// available, as a fallback, try the static characteristics.
|
||||||
|
camera_metadata_entry entry3 = results.find(ANDROID_STATISTICS_HOT_PIXEL_MAP);
|
||||||
|
if (entry3.count == 0) {
|
||||||
|
entry3 = characteristics.find(ANDROID_STATISTICS_HOT_PIXEL_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
if ((entry3.count % 2) != 0) {
|
if ((entry3.count % 2) != 0) {
|
||||||
ALOGE("%s: Hot pixel map contains odd number of values, cannot map to pairs!",
|
ALOGE("%s: Hot pixel map contains odd number of values, cannot map to pairs!",
|
||||||
@@ -1908,7 +2005,8 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust the bad pixel coordinates to be relative to the origin of the active area DNG tag
|
// Adjust the bad pixel coordinates to be relative to the origin of the active area
|
||||||
|
// DNG tag
|
||||||
std::vector<uint32_t> v;
|
std::vector<uint32_t> v;
|
||||||
for (size_t i = 0; i < entry3.count; i += 2) {
|
for (size_t i = 0; i < entry3.count; i += 2) {
|
||||||
int32_t x = entry3.data.i32[i];
|
int32_t x = entry3.data.i32[i];
|
||||||
@@ -1962,6 +2060,8 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
|
|||||||
std::array<float, 6> distortion = {1.f, 0.f, 0.f, 0.f, 0.f, 0.f};
|
std::array<float, 6> distortion = {1.f, 0.f, 0.f, 0.f, 0.f, 0.f};
|
||||||
bool gotDistortion = false;
|
bool gotDistortion = false;
|
||||||
|
|
||||||
|
// The capture result would have the correct intrinsic calibration
|
||||||
|
// regardless of the sensor pixel mode.
|
||||||
camera_metadata_entry entry4 =
|
camera_metadata_entry entry4 =
|
||||||
results.find(ANDROID_LENS_INTRINSIC_CALIBRATION);
|
results.find(ANDROID_LENS_INTRINSIC_CALIBRATION);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user