Merge "DngCreator: Add thumbnail TIFF tags in subIFD1"

This commit is contained in:
TreeHugger Robot
2021-09-14 19:56:03 +00:00
committed by Android (Google) Code Review

View File

@@ -920,26 +920,6 @@ static bool validateDngHeader(JNIEnv* env, sp<TiffWriter> writer,
return true;
}
static status_t moveEntries(sp<TiffWriter> writer, uint32_t ifdFrom, uint32_t ifdTo,
const Vector<uint16_t>& entries) {
for (size_t i = 0; i < entries.size(); ++i) {
uint16_t tagId = entries[i];
sp<TiffEntry> entry = writer->getEntry(tagId, ifdFrom);
if (entry.get() == nullptr) {
ALOGE("%s: moveEntries failed, entry %u not found in IFD %u", __FUNCTION__, tagId,
ifdFrom);
return BAD_VALUE;
}
if (writer->addEntry(entry, ifdTo) != OK) {
ALOGE("%s: moveEntries failed, could not add entry %u to IFD %u", __FUNCTION__, tagId,
ifdFrom);
return BAD_VALUE;
}
writer->removeEntry(tagId, ifdFrom);
}
return OK;
}
/**
* Write CFA pattern for given CFA enum into cfaOut. cfaOut must have length >= 4.
* Returns OK on success, or a negative error code if the CFA enum was invalid.
@@ -2255,66 +2235,27 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
}
}
Vector<uint16_t> tagsToMove;
tagsToMove.add(TAG_NEWSUBFILETYPE);
tagsToMove.add(TAG_ACTIVEAREA);
tagsToMove.add(TAG_BITSPERSAMPLE);
tagsToMove.add(TAG_COMPRESSION);
tagsToMove.add(TAG_IMAGEWIDTH);
tagsToMove.add(TAG_IMAGELENGTH);
tagsToMove.add(TAG_PHOTOMETRICINTERPRETATION);
tagsToMove.add(TAG_BLACKLEVEL);
tagsToMove.add(TAG_BLACKLEVELREPEATDIM);
tagsToMove.add(TAG_SAMPLESPERPIXEL);
tagsToMove.add(TAG_PLANARCONFIGURATION);
if (isBayer) {
tagsToMove.add(TAG_CFAREPEATPATTERNDIM);
tagsToMove.add(TAG_CFAPATTERN);
tagsToMove.add(TAG_CFAPLANECOLOR);
tagsToMove.add(TAG_CFALAYOUT);
}
tagsToMove.add(TAG_XRESOLUTION);
tagsToMove.add(TAG_YRESOLUTION);
tagsToMove.add(TAG_RESOLUTIONUNIT);
tagsToMove.add(TAG_WHITELEVEL);
tagsToMove.add(TAG_DEFAULTSCALE);
tagsToMove.add(TAG_DEFAULTCROPORIGIN);
tagsToMove.add(TAG_DEFAULTCROPSIZE);
if (nullptr != writer->getEntry(TAG_OPCODELIST2, TIFF_IFD_0).get()) {
tagsToMove.add(TAG_OPCODELIST2);
}
if (nullptr != writer->getEntry(TAG_OPCODELIST3, TIFF_IFD_0).get()) {
tagsToMove.add(TAG_OPCODELIST3);
}
if (moveEntries(writer, TIFF_IFD_0, TIFF_IFD_SUB1, tagsToMove) != OK) {
jniThrowException(env, "java/lang/IllegalStateException", "Failed to move entries");
return nullptr;
}
// Setup thumbnail tags
{
// Set photometric interpretation
uint16_t interpretation = 2; // RGB
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_PHOTOMETRICINTERPRETATION, 1,
&interpretation, TIFF_IFD_0), env, TAG_PHOTOMETRICINTERPRETATION, writer);
&interpretation, TIFF_IFD_SUB1), env, TAG_PHOTOMETRICINTERPRETATION, writer);
}
{
// Set planar configuration
uint16_t config = 1; // Chunky
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_PLANARCONFIGURATION, 1, &config,
TIFF_IFD_0), env, TAG_PLANARCONFIGURATION, writer);
TIFF_IFD_SUB1), env, TAG_PLANARCONFIGURATION, writer);
}
{
// Set samples per pixel
uint16_t samples = SAMPLES_PER_RGB_PIXEL;
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_SAMPLESPERPIXEL, 1, &samples,
TIFF_IFD_0), env, TAG_SAMPLESPERPIXEL, writer);
TIFF_IFD_SUB1), env, TAG_SAMPLESPERPIXEL, writer);
}
{
@@ -2322,7 +2263,7 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
uint16_t bits[SAMPLES_PER_RGB_PIXEL];
for (int i = 0; i < SAMPLES_PER_RGB_PIXEL; i++) bits[i] = BITS_PER_RGB_SAMPLE;
BAIL_IF_INVALID_RET_NULL_SP(
writer->addEntry(TAG_BITSPERSAMPLE, SAMPLES_PER_RGB_PIXEL, bits, TIFF_IFD_0),
writer->addEntry(TAG_BITSPERSAMPLE, SAMPLES_PER_RGB_PIXEL, bits, TIFF_IFD_SUB1),
env, TAG_BITSPERSAMPLE, writer);
}
@@ -2330,55 +2271,55 @@ static sp<TiffWriter> DngCreator_setup(JNIEnv* env, jobject thiz, uint32_t image
// Set subfiletype
uint32_t subfileType = 1; // Thumbnail image
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_NEWSUBFILETYPE, 1, &subfileType,
TIFF_IFD_0), env, TAG_NEWSUBFILETYPE, writer);
TIFF_IFD_SUB1), env, TAG_NEWSUBFILETYPE, writer);
}
{
// Set compression
uint16_t compression = 1; // None
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_COMPRESSION, 1, &compression,
TIFF_IFD_0), env, TAG_COMPRESSION, writer);
TIFF_IFD_SUB1), env, TAG_COMPRESSION, writer);
}
{
// Set dimensions
uint32_t uWidth = nativeContext->getThumbnailWidth();
uint32_t uHeight = nativeContext->getThumbnailHeight();
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_IMAGEWIDTH, 1, &uWidth, TIFF_IFD_0),
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_IMAGEWIDTH, 1, &uWidth, TIFF_IFD_SUB1),
env, TAG_IMAGEWIDTH, writer);
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_IMAGELENGTH, 1, &uHeight, TIFF_IFD_0),
env, TAG_IMAGELENGTH, writer);
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_IMAGELENGTH, 1, &uHeight,
TIFF_IFD_SUB1), env, TAG_IMAGELENGTH, writer);
}
{
// x resolution
uint32_t xres[] = { 72, 1 }; // default 72 ppi
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_XRESOLUTION, 1, xres, TIFF_IFD_0),
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_XRESOLUTION, 1, xres, TIFF_IFD_SUB1),
env, TAG_XRESOLUTION, writer);
// y resolution
uint32_t yres[] = { 72, 1 }; // default 72 ppi
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_YRESOLUTION, 1, yres, TIFF_IFD_0),
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_YRESOLUTION, 1, yres, TIFF_IFD_SUB1),
env, TAG_YRESOLUTION, writer);
uint16_t unit = 2; // inches
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_RESOLUTIONUNIT, 1, &unit, TIFF_IFD_0),
env, TAG_RESOLUTIONUNIT, writer);
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_RESOLUTIONUNIT, 1, &unit,
TIFF_IFD_SUB1), env, TAG_RESOLUTIONUNIT, writer);
}
}
if (writer->addStrip(TIFF_IFD_0) != OK) {
ALOGE("%s: Could not setup thumbnail strip tags.", __FUNCTION__);
ALOGE("%s: Could not setup main image strip tags.", __FUNCTION__);
jniThrowException(env, "java/lang/IllegalStateException",
"Failed to setup thumbnail strip tags.");
"Failed to setup main image strip tags.");
return nullptr;
}
if (writer->hasIfd(TIFF_IFD_SUB1)) {
if (writer->addStrip(TIFF_IFD_SUB1) != OK) {
ALOGE("%s: Could not main image strip tags.", __FUNCTION__);
ALOGE("%s: Could not thumbnail image strip tags.", __FUNCTION__);
jniThrowException(env, "java/lang/IllegalStateException",
"Failed to setup main image strip tags.");
"Failed to setup thumbnail image strip tags.");
return nullptr;
}
}
@@ -2548,19 +2489,15 @@ static void DngCreator_nativeWriteImage(JNIEnv* env, jobject thiz, jobject outSt
Vector<StripSource*> sources;
sp<DirectStripSource> thumbnailSource;
uint32_t targetIfd = TIFF_IFD_0;
bool hasThumbnail = writer->hasIfd(TIFF_IFD_SUB1);
if (hasThumbnail) {
ALOGV("%s: Adding thumbnail strip sources.", __FUNCTION__);
uint32_t bytesPerPixel = SAMPLES_PER_RGB_PIXEL * BYTES_PER_RGB_SAMPLE;
uint32_t thumbWidth = context->getThumbnailWidth();
thumbnailSource = new DirectStripSource(env, context->getThumbnail(), TIFF_IFD_0,
thumbnailSource = new DirectStripSource(env, context->getThumbnail(), TIFF_IFD_SUB1,
thumbWidth, context->getThumbnailHeight(), bytesPerPixel,
bytesPerPixel * thumbWidth, /*offset*/0, BYTES_PER_RGB_SAMPLE,
SAMPLES_PER_RGB_PIXEL);
sources.add(thumbnailSource.get());
targetIfd = TIFF_IFD_SUB1;
}
if (isDirect) {
@@ -2584,6 +2521,9 @@ static void DngCreator_nativeWriteImage(JNIEnv* env, jobject thiz, jobject outSt
DirectStripSource stripSource(env, pixelBytes, targetIfd, uWidth, uHeight, pStride,
rStride, uOffset, BYTES_PER_SAMPLE, SAMPLES_PER_RAW_PIXEL);
sources.add(&stripSource);
if (thumbnailSource.get() != nullptr) {
sources.add(thumbnailSource.get());
}
status_t ret = OK;
if ((ret = writer->write(out.get(), sources.editArray(), sources.size())) != OK) {
@@ -2601,6 +2541,9 @@ static void DngCreator_nativeWriteImage(JNIEnv* env, jobject thiz, jobject outSt
InputStripSource stripSource(env, *inBuf, targetIfd, uWidth, uHeight, pStride,
rStride, uOffset, BYTES_PER_SAMPLE, SAMPLES_PER_RAW_PIXEL);
sources.add(&stripSource);
if (thumbnailSource.get() != nullptr) {
sources.add(thumbnailSource.get());
}
status_t ret = OK;
if ((ret = writer->write(out.get(), sources.editArray(), sources.size())) != OK) {
@@ -2612,6 +2555,7 @@ static void DngCreator_nativeWriteImage(JNIEnv* env, jobject thiz, jobject outSt
return;
}
}
}
static void DngCreator_nativeWriteInputStream(JNIEnv* env, jobject thiz, jobject outStream,
@@ -2654,20 +2598,8 @@ static void DngCreator_nativeWriteInputStream(JNIEnv* env, jobject thiz, jobject
sp<DirectStripSource> thumbnailSource;
uint32_t targetIfd = TIFF_IFD_0;
bool hasThumbnail = writer->hasIfd(TIFF_IFD_SUB1);
Vector<StripSource*> sources;
if (hasThumbnail) {
ALOGV("%s: Adding thumbnail strip sources.", __FUNCTION__);
uint32_t bytesPerPixel = SAMPLES_PER_RGB_PIXEL * BYTES_PER_RGB_SAMPLE;
uint32_t width = context->getThumbnailWidth();
thumbnailSource = new DirectStripSource(env, context->getThumbnail(), TIFF_IFD_0,
width, context->getThumbnailHeight(), bytesPerPixel,
bytesPerPixel * width, /*offset*/0, BYTES_PER_RGB_SAMPLE,
SAMPLES_PER_RGB_PIXEL);
sources.add(thumbnailSource.get());
targetIfd = TIFF_IFD_SUB1;
}
sp<JniInputStream> in = new JniInputStream(env, inStream);
@@ -2676,6 +2608,18 @@ static void DngCreator_nativeWriteInputStream(JNIEnv* env, jobject thiz, jobject
rowStride, uOffset, BYTES_PER_SAMPLE, SAMPLES_PER_RAW_PIXEL);
sources.add(&stripSource);
bool hasThumbnail = writer->hasIfd(TIFF_IFD_SUB1);
if (hasThumbnail) {
ALOGV("%s: Adding thumbnail strip sources.", __FUNCTION__);
uint32_t bytesPerPixel = SAMPLES_PER_RGB_PIXEL * BYTES_PER_RGB_SAMPLE;
uint32_t width = context->getThumbnailWidth();
thumbnailSource = new DirectStripSource(env, context->getThumbnail(), TIFF_IFD_SUB1,
width, context->getThumbnailHeight(), bytesPerPixel,
bytesPerPixel * width, /*offset*/0, BYTES_PER_RGB_SAMPLE,
SAMPLES_PER_RGB_PIXEL);
sources.add(thumbnailSource.get());
}
status_t ret = OK;
if ((ret = writer->write(out.get(), sources.editArray(), sources.size())) != OK) {
ALOGE("%s: write failed with error %d.", __FUNCTION__, ret);