android_hardware_camera2_DngCreator.cpp revision 46d8444631b4b1253a76bfcc78a29d26014d022f
1f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk/* 2f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * Copyright 2014 The Android Open Source Project 3f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * 4f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * you may not use this file except in compliance with the License. 6f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * You may obtain a copy of the License at 7f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * 8f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * 10f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * Unless required by applicable law or agreed to in writing, software 11f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * See the License for the specific language governing permissions and 14f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk * limitations under the License. 15f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk */ 16f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 17f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk//#define LOG_NDEBUG 0 18f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#define LOG_TAG "DngCreator_JNI" 1946d8444631b4b1253a76bfcc78a29d26014d022fDan Albert#include <inttypes.h> 2046d8444631b4b1253a76bfcc78a29d26014d022fDan Albert#include <string.h> 2146d8444631b4b1253a76bfcc78a29d26014d022fDan Albert 2246d8444631b4b1253a76bfcc78a29d26014d022fDan Albert#include <utils/Log.h> 2346d8444631b4b1253a76bfcc78a29d26014d022fDan Albert#include <utils/Errors.h> 2446d8444631b4b1253a76bfcc78a29d26014d022fDan Albert#include <utils/StrongPointer.h> 2546d8444631b4b1253a76bfcc78a29d26014d022fDan Albert#include <utils/RefBase.h> 2646d8444631b4b1253a76bfcc78a29d26014d022fDan Albert#include <utils/Vector.h> 2746d8444631b4b1253a76bfcc78a29d26014d022fDan Albert#include <cutils/properties.h> 28f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 29f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include <system/camera_metadata.h> 30f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include <camera/CameraMetadata.h> 31f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include <img_utils/DngUtils.h> 32f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include <img_utils/TagDefinitions.h> 33f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include <img_utils/TiffIfd.h> 34f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include <img_utils/TiffWriter.h> 35f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include <img_utils/Output.h> 3647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk#include <img_utils/Input.h> 3747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk#include <img_utils/StripSource.h> 38f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 39f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include "android_runtime/AndroidRuntime.h" 40f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include "android_runtime/android_hardware_camera2_CameraMetadata.h" 41f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 42f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include <jni.h> 43f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include <JNIHelp.h> 44f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 45f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkusing namespace android; 46f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkusing namespace img_utils; 47f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 4847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk#define BAIL_IF_INVALID(expr, jnienv, tagId, writer) \ 49f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if ((expr) != OK) { \ 50f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \ 5147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Invalid metadata for tag %s (%x)", (writer)->getTagName(tagId), (tagId)); \ 52f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; \ 53f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 54f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 5547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk#define BAIL_IF_EMPTY(entry, jnienv, tagId, writer) \ 56f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (entry.count == 0) { \ 57f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \ 5847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Missing metadata fields for tag %s (%x)", (writer)->getTagName(tagId), (tagId)); \ 59f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; \ 60f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 61f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 62b6079005ed0631c3972ff427f56e12523ec214a7Ruben Brunk#define ANDROID_DNGCREATOR_CTX_JNI_ID "mNativeContext" 63f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 64f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatic struct { 65f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jfieldID mNativeContext; 66f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} gDngCreatorClassInfo; 67f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 68f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatic struct { 69f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jmethodID mWriteMethod; 70f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} gOutputStreamClassInfo; 71f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 7247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic struct { 7347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jmethodID mReadMethod; 7447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jmethodID mSkipMethod; 7547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} gInputStreamClassInfo; 7647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 7747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic struct { 7847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jmethodID mGetMethod; 7947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} gInputByteBufferClassInfo; 8047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 81f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkenum { 82f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BITS_PER_SAMPLE = 16, 83f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BYTES_PER_SAMPLE = 2, 8447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BYTES_PER_RGB_PIXEL = 3, 8547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BITS_PER_RGB_SAMPLE = 8, 8647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BYTES_PER_RGB_SAMPLE = 1, 8747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk SAMPLES_PER_RGB_PIXEL = 3, 8847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk SAMPLES_PER_RAW_PIXEL = 1, 8947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0 = 0, 9047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_SUB1 = 1, 9147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_GPSINFO = 2, 92f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk}; 93f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 94f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk// ---------------------------------------------------------------------------- 95f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 9647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk/** 9747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * Container class for the persistent native context. 9847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk */ 9947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 10047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkclass NativeContext : public LightRefBase<NativeContext> { 10147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 10247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkpublic: 10347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk NativeContext(); 10447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk virtual ~NativeContext(); 10547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 10647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TiffWriter* getWriter(); 10747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 10847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t getThumbnailWidth(); 10947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t getThumbnailHeight(); 11047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk const uint8_t* getThumbnail(); 11147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 11247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk bool setThumbnail(const uint8_t* buffer, uint32_t width, uint32_t height); 11347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 11447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkprivate: 11547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk Vector<uint8_t> mCurrentThumbnail; 11647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TiffWriter mWriter; 11747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mThumbnailWidth; 11847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mThumbnailHeight; 11947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk}; 12047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 12147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkNativeContext::NativeContext() : mThumbnailWidth(0), mThumbnailHeight(0) {} 12247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 12347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkNativeContext::~NativeContext() {} 12447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 12547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkTiffWriter* NativeContext::getWriter() { 12647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return &mWriter; 12747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 12847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 12947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkuint32_t NativeContext::getThumbnailWidth() { 13047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return mThumbnailWidth; 13147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 13247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 13347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkuint32_t NativeContext::getThumbnailHeight() { 13447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return mThumbnailHeight; 13547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 13647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 13747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkconst uint8_t* NativeContext::getThumbnail() { 13847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return mCurrentThumbnail.array(); 13947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 14047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 14147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkbool NativeContext::setThumbnail(const uint8_t* buffer, uint32_t width, uint32_t height) { 14247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mThumbnailWidth = width; 14347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mThumbnailHeight = height; 14447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 14547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk size_t size = BYTES_PER_RGB_PIXEL * width * height; 14647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (mCurrentThumbnail.resize(size) < 0) { 14747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Could not resize thumbnail buffer.", __FUNCTION__); 14847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return false; 14947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 15047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 15147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint8_t* thumb = mCurrentThumbnail.editArray(); 15247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk memcpy(thumb, buffer, size); 15347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return true; 15447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 15547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 15647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// End of NativeContext 15747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// ---------------------------------------------------------------------------- 15847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 15947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk/** 16047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * Wrapper class for a Java OutputStream. 16147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * 16247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * This class is not intended to be used across JNI calls. 16347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk */ 164f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkclass JniOutputStream : public Output, public LightRefBase<JniOutputStream> { 165f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkpublic: 166f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk JniOutputStream(JNIEnv* env, jobject outStream); 167f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 168f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk virtual ~JniOutputStream(); 169f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 170f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk status_t open(); 17147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 172f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk status_t write(const uint8_t* buf, size_t offset, size_t count); 17347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 174f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk status_t close(); 175f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkprivate: 176f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk enum { 17747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BYTE_ARRAY_LENGTH = 4096 178f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk }; 179f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jobject mOutputStream; 180f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk JNIEnv* mEnv; 181f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jbyteArray mByteArray; 182f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk}; 183f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 184f967a5486a78db244624fde4c105aa5e6fa914b9Ruben BrunkJniOutputStream::JniOutputStream(JNIEnv* env, jobject outStream) : mOutputStream(outStream), 185f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk mEnv(env) { 186f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk mByteArray = env->NewByteArray(BYTE_ARRAY_LENGTH); 187f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (mByteArray == NULL) { 188f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jniThrowException(env, "java/lang/OutOfMemoryError", "Could not allocate byte array."); 189f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 190f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 191f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 192f967a5486a78db244624fde4c105aa5e6fa914b9Ruben BrunkJniOutputStream::~JniOutputStream() { 193f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk mEnv->DeleteLocalRef(mByteArray); 194f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 195f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 196f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatus_t JniOutputStream::open() { 197f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Do nothing 198f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return OK; 199f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 200f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 201f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatus_t JniOutputStream::write(const uint8_t* buf, size_t offset, size_t count) { 202f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk while(count > 0) { 203f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk size_t len = BYTE_ARRAY_LENGTH; 204f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk len = (count > len) ? len : count; 205f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk mEnv->SetByteArrayRegion(mByteArray, 0, len, reinterpret_cast<const jbyte*>(buf + offset)); 206f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 207f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (mEnv->ExceptionCheck()) { 208f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return BAD_VALUE; 209f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 210f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 211f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk mEnv->CallVoidMethod(mOutputStream, gOutputStreamClassInfo.mWriteMethod, mByteArray, 212f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 0, len); 213f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 214f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (mEnv->ExceptionCheck()) { 215f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return BAD_VALUE; 216f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 217f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 218f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk count -= len; 219f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk offset += len; 220f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 221f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return OK; 222f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 223f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 224f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatus_t JniOutputStream::close() { 225f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Do nothing 226f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return OK; 227f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 228f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 22947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// End of JniOutputStream 230f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk// ---------------------------------------------------------------------------- 231f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 23247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk/** 23347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * Wrapper class for a Java InputStream. 23447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * 23547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * This class is not intended to be used across JNI calls. 23647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk */ 23747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkclass JniInputStream : public Input, public LightRefBase<JniInputStream> { 23847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkpublic: 23947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk JniInputStream(JNIEnv* env, jobject inStream); 24047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 24147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk status_t open(); 24247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 24347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk status_t close(); 24447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 24547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ssize_t read(uint8_t* buf, size_t offset, size_t count); 24647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 24747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ssize_t skip(size_t count); 24847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 24947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk virtual ~JniInputStream(); 25047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkprivate: 25147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk enum { 25247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BYTE_ARRAY_LENGTH = 4096 25347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk }; 25447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jobject mInStream; 25547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk JNIEnv* mEnv; 25647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jbyteArray mByteArray; 25747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 25847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk}; 25947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 26047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkJniInputStream::JniInputStream(JNIEnv* env, jobject inStream) : mInStream(inStream), mEnv(env) { 26147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mByteArray = env->NewByteArray(BYTE_ARRAY_LENGTH); 26247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (mByteArray == NULL) { 26347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/OutOfMemoryError", "Could not allocate byte array."); 26447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 26547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 26647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 26747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkJniInputStream::~JniInputStream() { 26847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mEnv->DeleteLocalRef(mByteArray); 26947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 27047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 27147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkssize_t JniInputStream::read(uint8_t* buf, size_t offset, size_t count) { 27247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 27347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jint realCount = BYTE_ARRAY_LENGTH; 27447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (count < BYTE_ARRAY_LENGTH) { 27547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk realCount = count; 27647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 27747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jint actual = mEnv->CallIntMethod(mInStream, gInputStreamClassInfo.mReadMethod, mByteArray, 0, 27847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk realCount); 27947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 28047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (actual < 0) { 28147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return NOT_ENOUGH_DATA; 28247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 28347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 28447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (mEnv->ExceptionCheck()) { 28547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 28647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 28747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 28847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mEnv->GetByteArrayRegion(mByteArray, 0, actual, reinterpret_cast<jbyte*>(buf + offset)); 28947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (mEnv->ExceptionCheck()) { 29047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 29147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 29247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return actual; 29347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 29447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 29547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkssize_t JniInputStream::skip(size_t count) { 29647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jlong actual = mEnv->CallLongMethod(mInStream, gInputStreamClassInfo.mSkipMethod, 29747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk static_cast<jlong>(count)); 29847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 29947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (mEnv->ExceptionCheck()) { 30047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 30147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 30247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (actual < 0) { 30347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return NOT_ENOUGH_DATA; 30447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 30547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return actual; 30647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 30747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 30847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatus_t JniInputStream::open() { 30947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Do nothing 31047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return OK; 31147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 31247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 31347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatus_t JniInputStream::close() { 31447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Do nothing 31547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return OK; 31647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 31747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 31847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// End of JniInputStream 31947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// ---------------------------------------------------------------------------- 32047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 32147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk/** 32247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * Wrapper class for a non-direct Java ByteBuffer. 32347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * 32447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * This class is not intended to be used across JNI calls. 32547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk */ 32647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkclass JniInputByteBuffer : public Input, public LightRefBase<JniInputByteBuffer> { 32747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkpublic: 32847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk JniInputByteBuffer(JNIEnv* env, jobject inBuf); 32947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 33047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk status_t open(); 33147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 33247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk status_t close(); 33347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 33447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ssize_t read(uint8_t* buf, size_t offset, size_t count); 33547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 33647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk virtual ~JniInputByteBuffer(); 33747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkprivate: 33847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk enum { 33947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BYTE_ARRAY_LENGTH = 4096 34047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk }; 34147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jobject mInBuf; 34247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk JNIEnv* mEnv; 34347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jbyteArray mByteArray; 34447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk}; 34547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 34647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkJniInputByteBuffer::JniInputByteBuffer(JNIEnv* env, jobject inBuf) : mInBuf(inBuf), mEnv(env) { 34747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mByteArray = env->NewByteArray(BYTE_ARRAY_LENGTH); 34847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (mByteArray == NULL) { 34947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/OutOfMemoryError", "Could not allocate byte array."); 35047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 35147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 35247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 35347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkJniInputByteBuffer::~JniInputByteBuffer() { 35447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mEnv->DeleteLocalRef(mByteArray); 35547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 35647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 35747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkssize_t JniInputByteBuffer::read(uint8_t* buf, size_t offset, size_t count) { 35847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jint realCount = BYTE_ARRAY_LENGTH; 35947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (count < BYTE_ARRAY_LENGTH) { 36047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk realCount = count; 36147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 36247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 36347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mEnv->CallObjectMethod(mInBuf, gInputByteBufferClassInfo.mGetMethod, mByteArray, 0, 36447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk realCount); 36547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 36647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (mEnv->ExceptionCheck()) { 36747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 36847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 36947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 37047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mEnv->GetByteArrayRegion(mByteArray, 0, realCount, reinterpret_cast<jbyte*>(buf + offset)); 37147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (mEnv->ExceptionCheck()) { 37247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 37347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 37447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return realCount; 37547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 37647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 37747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatus_t JniInputByteBuffer::open() { 37847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Do nothing 37947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return OK; 38047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 38147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 38247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatus_t JniInputByteBuffer::close() { 38347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Do nothing 38447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return OK; 38547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 38647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 38747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// End of JniInputByteBuffer 38847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// ---------------------------------------------------------------------------- 38947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 39047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk/** 39147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * StripSource subclass for Input types. 39247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * 39347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * This class is not intended to be used across JNI calls. 39447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk */ 39547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 39647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkclass InputStripSource : public StripSource, public LightRefBase<InputStripSource> { 39747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkpublic: 39847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk InputStripSource(JNIEnv* env, Input& input, uint32_t ifd, uint32_t width, uint32_t height, 39947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t pixStride, uint32_t rowStride, uint64_t offset, uint32_t bytesPerSample, 40047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t samplesPerPixel); 40147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 40247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk virtual ~InputStripSource(); 40347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 40447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk virtual status_t writeToStream(Output& stream, uint32_t count); 40547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 40647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk virtual uint32_t getIfd() const; 40747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkprotected: 40847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mIfd; 40947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk Input* mInput; 41047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mWidth; 41147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mHeight; 41247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mPixStride; 41347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mRowStride; 41447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint64_t mOffset; 41547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk JNIEnv* mEnv; 41647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mBytesPerSample; 41747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mSamplesPerPixel; 41847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk}; 41947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 42047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkInputStripSource::InputStripSource(JNIEnv* env, Input& input, uint32_t ifd, uint32_t width, 42147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t height, uint32_t pixStride, uint32_t rowStride, uint64_t offset, 42247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t bytesPerSample, uint32_t samplesPerPixel) : mIfd(ifd), mInput(&input), 42347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mWidth(width), mHeight(height), mPixStride(pixStride), mRowStride(rowStride), 42447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mOffset(offset), mEnv(env), mBytesPerSample(bytesPerSample), 42547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mSamplesPerPixel(samplesPerPixel) {} 42647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 42747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkInputStripSource::~InputStripSource() {} 42847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 42947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatus_t InputStripSource::writeToStream(Output& stream, uint32_t count) { 4303e1902504979b9b456a14dffa6507ee2d9ea3d6aRuben Brunk uint32_t fullSize = mWidth * mHeight * mBytesPerSample * mSamplesPerPixel; 43147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jlong offset = mOffset; 43247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 43347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (fullSize != count) { 43447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Amount to write %u doesn't match image size %u", __FUNCTION__, count, 43547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk fullSize); 43647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(mEnv, "java/lang/IllegalStateException", "Not enough data to write"); 43747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 43847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 43947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 44047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Skip offset 44147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk while (offset > 0) { 44247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ssize_t skipped = mInput->skip(offset); 44347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (skipped <= 0) { 44447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (skipped == NOT_ENOUGH_DATA || skipped == 0) { 44547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(mEnv, "java/io/IOException", 44647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Early EOF encountered in skip, not enough pixel data for image of size %u", 44747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk fullSize); 44847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk skipped = NOT_ENOUGH_DATA; 44947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } else { 45047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!mEnv->ExceptionCheck()) { 45147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(mEnv, "java/io/IOException", 45247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Error encountered while skip bytes in input stream."); 45347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 45447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 45547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 45647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return skipped; 45747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 45847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk offset -= skipped; 45947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 46047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 46147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk Vector<uint8_t> row; 46247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (row.resize(mRowStride) < 0) { 46347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(mEnv, "java/lang/OutOfMemoryError", "Could not allocate row vector."); 46447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 46547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 46647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 46747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint8_t* rowBytes = row.editArray(); 46847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 46947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk for (uint32_t i = 0; i < mHeight; ++i) { 47047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk size_t rowFillAmt = 0; 47147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk size_t rowSize = mPixStride; 47247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 47347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk while (rowFillAmt < mRowStride) { 47447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ssize_t bytesRead = mInput->read(rowBytes, rowFillAmt, rowSize); 47547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (bytesRead <= 0) { 47647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (bytesRead == NOT_ENOUGH_DATA || bytesRead == 0) { 47747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(mEnv, "java/io/IOException", 47847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Early EOF encountered, not enough pixel data for image of size %u", 47947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk fullSize); 48047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk bytesRead = NOT_ENOUGH_DATA; 48147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } else { 48247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!mEnv->ExceptionCheck()) { 48347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(mEnv, "java/io/IOException", 48447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Error encountered while reading"); 48547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 48647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 48747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return bytesRead; 48847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 48947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk rowFillAmt += bytesRead; 49047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk rowSize -= bytesRead; 49147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 49247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 49347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (mPixStride == mBytesPerSample * mSamplesPerPixel) { 49447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s: Using stream per-row write for strip.", __FUNCTION__); 49547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 49647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (stream.write(rowBytes, 0, mBytesPerSample * mSamplesPerPixel * mWidth) != OK || 49747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mEnv->ExceptionCheck()) { 49847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!mEnv->ExceptionCheck()) { 49947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(mEnv, "java/io/IOException", "Failed to write pixel data"); 50047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 50147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 50247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 50347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } else { 50447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s: Using stream per-pixel write for strip.", __FUNCTION__); 50547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(mEnv, "java/lang/IllegalStateException", 50647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Per-pixel strides are not supported for RAW16 -- pixels must be contiguous"); 50747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 50847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 50947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // TODO: Add support for non-contiguous pixels if needed. 51047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 51147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 51247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return OK; 51347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 51447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 51547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkuint32_t InputStripSource::getIfd() const { 51647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return mIfd; 51747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 51847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 51947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// End of InputStripSource 52047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// ---------------------------------------------------------------------------- 52147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 52247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk/** 52347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * StripSource subclass for direct buffer types. 52447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * 52547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk * This class is not intended to be used across JNI calls. 52647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk */ 52747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 52847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkclass DirectStripSource : public StripSource, public LightRefBase<DirectStripSource> { 52947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkpublic: 53047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk DirectStripSource(JNIEnv* env, const uint8_t* pixelBytes, uint32_t ifd, uint32_t width, 53147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t height, uint32_t pixStride, uint32_t rowStride, uint64_t offset, 53247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t bytesPerSample, uint32_t samplesPerPixel); 53347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 53447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk virtual ~DirectStripSource(); 53547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 53647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk virtual status_t writeToStream(Output& stream, uint32_t count); 53747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 53847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk virtual uint32_t getIfd() const; 53947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkprotected: 54047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mIfd; 54147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk const uint8_t* mPixelBytes; 54247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mWidth; 54347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mHeight; 54447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mPixStride; 54547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mRowStride; 54647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint16_t mOffset; 54747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk JNIEnv* mEnv; 54847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mBytesPerSample; 54947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t mSamplesPerPixel; 55047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk}; 55147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 55247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkDirectStripSource::DirectStripSource(JNIEnv* env, const uint8_t* pixelBytes, uint32_t ifd, 55347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t width, uint32_t height, uint32_t pixStride, uint32_t rowStride, 55447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint64_t offset, uint32_t bytesPerSample, uint32_t samplesPerPixel) : mIfd(ifd), 55547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mPixelBytes(pixelBytes), mWidth(width), mHeight(height), mPixStride(pixStride), 55647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mRowStride(rowStride), mOffset(offset), mEnv(env), mBytesPerSample(bytesPerSample), 55747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mSamplesPerPixel(samplesPerPixel) {} 55847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 55947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben BrunkDirectStripSource::~DirectStripSource() {} 56047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 56147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatus_t DirectStripSource::writeToStream(Output& stream, uint32_t count) { 5623e1902504979b9b456a14dffa6507ee2d9ea3d6aRuben Brunk uint32_t fullSize = mWidth * mHeight * mBytesPerSample * mSamplesPerPixel; 56347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 56447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (fullSize != count) { 56547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Amount to write %u doesn't match image size %u", __FUNCTION__, count, 56647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk fullSize); 56747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(mEnv, "java/lang/IllegalStateException", "Not enough data to write"); 56847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 56947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 57047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 57147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (mPixStride == mBytesPerSample * mSamplesPerPixel 57247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk && mRowStride == mWidth * mBytesPerSample * mSamplesPerPixel) { 57347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s: Using direct single-pass write for strip.", __FUNCTION__); 57447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 57547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (stream.write(mPixelBytes, mOffset, fullSize) != OK || mEnv->ExceptionCheck()) { 57647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!mEnv->ExceptionCheck()) { 57747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(mEnv, "java/io/IOException", "Failed to write pixel data"); 57847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 57947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 58047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 58147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } else if (mPixStride == mBytesPerSample * mSamplesPerPixel) { 58247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s: Using direct per-row write for strip.", __FUNCTION__); 58347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 58447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk for (size_t i = 0; i < mHeight; ++i) { 58547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (stream.write(mPixelBytes, mOffset + i * mRowStride, mPixStride * mWidth) != OK || 58647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk mEnv->ExceptionCheck()) { 58747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!mEnv->ExceptionCheck()) { 58847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(mEnv, "java/io/IOException", "Failed to write pixel data"); 58947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 59047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 59147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 59247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 59347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } else { 59447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s: Using direct per-pixel write for strip.", __FUNCTION__); 59547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 59647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(mEnv, "java/lang/IllegalStateException", 59747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Per-pixel strides are not supported for RAW16 -- pixels must be contiguous"); 59847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 59947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 60047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // TODO: Add support for non-contiguous pixels if needed. 60147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 60247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return OK; 60347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 60447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 60547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 60647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkuint32_t DirectStripSource::getIfd() const { 60747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return mIfd; 60847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 60947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 61047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// End of DirectStripSource 61147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// ---------------------------------------------------------------------------- 61247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 61347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic bool validateDngHeader(JNIEnv* env, TiffWriter* writer, jint width, jint height) { 61447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk bool hasThumbnail = writer->hasIfd(TIFF_IFD_SUB1); 61547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 61647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // TODO: handle lens shading map, etc. conversions for other raw buffer sizes. 61747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, (hasThumbnail) ? TIFF_IFD_SUB1 : TIFF_IFD_0)->getData<uint32_t>()); 61847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, (hasThumbnail) ? TIFF_IFD_SUB1 : TIFF_IFD_0)->getData<uint32_t>()); 61947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 62047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (width < 0 || metadataWidth != static_cast<uint32_t>(width)) { 62147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \ 62247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Metadata width %d doesn't match image width %d", metadataWidth, width); 62347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return false; 62447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 62547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 62647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (height < 0 || metadataHeight != static_cast<uint32_t>(height)) { 62747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \ 62847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Metadata height %d doesn't match image height %d", metadataHeight, height); 62947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return false; 63047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 63147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 63247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return true; 63347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 63447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 63547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic status_t moveEntries(TiffWriter* writer, uint32_t ifdFrom, uint32_t ifdTo, 63647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk const Vector<uint16_t>& entries) { 63747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk for (size_t i = 0; i < entries.size(); ++i) { 63847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint16_t tagId = entries[i]; 63947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sp<TiffEntry> entry = writer->getEntry(tagId, ifdFrom); 64047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (entry == NULL) { 64147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: moveEntries failed, entry %u not found in IFD %u", __FUNCTION__, tagId, 64247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ifdFrom); 64347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 64447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 64547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer->addEntry(entry, ifdTo) != OK) { 64647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: moveEntries failed, could not add entry %u to IFD %u", __FUNCTION__, tagId, 64747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ifdFrom); 64847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return BAD_VALUE; 64947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 65047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk writer->removeEntry(tagId, ifdFrom); 65147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 65247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return OK; 65347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 65447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 655d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk/** 656d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * Write CFA pattern for given CFA enum into cfaOut. cfaOut must have length >= 4. 657d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * Returns OK on success, or a negative error code if the CFA enum was invalid. 658d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk */ 659d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunkstatic status_t convertCFA(uint8_t cfaEnum, /*out*/uint8_t* cfaOut) { 660d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa = 661d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>( 662d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaEnum); 663d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk switch(cfa) { 664d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: { 665d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[0] = 0; 666d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[1] = 1; 667d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[2] = 1; 668d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[3] = 2; 669d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk break; 670d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 671d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: { 672d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[0] = 1; 673d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[1] = 0; 674d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[2] = 2; 675d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[3] = 1; 676d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk break; 677d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 678d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: { 679d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[0] = 1; 680d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[1] = 2; 681d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[2] = 0; 682d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[3] = 1; 683d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk break; 684d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 685d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: { 686d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[0] = 2; 687d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[1] = 1; 688d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[2] = 1; 689d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaOut[3] = 0; 690d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk break; 691d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 692d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk default: { 693d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk return BAD_VALUE; 694d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 695d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 696d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk return OK; 697d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk} 698d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 699d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk/** 700d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * Convert the CFA layout enum to an OpcodeListBuilder::CfaLayout enum, defaults to 701d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * RGGB for an unknown enum. 702d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk */ 703d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunkstatic OpcodeListBuilder::CfaLayout convertCFAEnumToOpcodeLayout(uint8_t cfaEnum) { 704d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa = 705d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>( 706d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaEnum); 707d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk switch(cfa) { 708d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: { 709d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk return OpcodeListBuilder::CFA_RGGB; 710d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 711d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: { 712d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk return OpcodeListBuilder::CFA_GRBG; 713d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 714d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: { 715d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk return OpcodeListBuilder::CFA_GBRG; 716d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 717d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: { 718d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk return OpcodeListBuilder::CFA_BGGR; 719d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 720d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk default: { 721d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk return OpcodeListBuilder::CFA_RGGB; 722d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 723d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 724d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk} 725d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 726d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk/** 727d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * For each color plane, find the corresponding noise profile coefficients given in the 728d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * per-channel noise profile. If multiple channels in the CFA correspond to a color in the color 729d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * plane, this method takes the pair of noise profile coefficients with the higher S coefficient. 730d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * 731d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * perChannelNoiseProfile - numChannels * 2 noise profile coefficients. 732d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * cfa - numChannels color channels corresponding to each of the per-channel noise profile 733d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * coefficients. 734d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * numChannels - the number of noise profile coefficient pairs and color channels given in 735d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * the perChannelNoiseProfile and cfa arguments, respectively. 736d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * planeColors - the color planes in the noise profile output. 737d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * numPlanes - the number of planes in planeColors and pairs of coefficients in noiseProfile. 738d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * noiseProfile - 2 * numPlanes doubles containing numPlanes pairs of noise profile coefficients. 739d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * 740d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk * returns OK, or a negative error code on failure. 741d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk */ 742d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunkstatic status_t generateNoiseProfile(const double* perChannelNoiseProfile, uint8_t* cfa, 743d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk size_t numChannels, const uint8_t* planeColors, size_t numPlanes, 744d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk /*out*/double* noiseProfile) { 745d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 746d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk for (size_t p = 0; p < numPlanes; ++p) { 747d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk size_t S = p * 2; 748d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk size_t O = p * 2 + 1; 749d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 750d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk noiseProfile[S] = 0; 751d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk noiseProfile[O] = 0; 752d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk bool uninitialized = true; 753d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk for (size_t c = 0; c < numChannels; ++c) { 754d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk if (cfa[c] == planeColors[p] && perChannelNoiseProfile[c * 2] > noiseProfile[S]) { 755d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk noiseProfile[S] = perChannelNoiseProfile[c * 2]; 756d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk noiseProfile[O] = perChannelNoiseProfile[c * 2 + 1]; 757d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk uninitialized = false; 758d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 759d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 760d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk if (uninitialized) { 76146d8444631b4b1253a76bfcc78a29d26014d022fDan Albert ALOGE("%s: No valid NoiseProfile coefficients for color plane %zu", 76246d8444631b4b1253a76bfcc78a29d26014d022fDan Albert __FUNCTION__, p); 763d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk return BAD_VALUE; 764d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 765d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 766d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk return OK; 767d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk} 768d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 76947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// ---------------------------------------------------------------------------- 770f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkextern "C" { 771f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 77247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic NativeContext* DngCreator_getNativeContext(JNIEnv* env, jobject thiz) { 773f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGV("%s:", __FUNCTION__); 77447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return reinterpret_cast<NativeContext*>(env->GetLongField(thiz, 775f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk gDngCreatorClassInfo.mNativeContext)); 776f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 777f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 77847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic void DngCreator_setNativeContext(JNIEnv* env, jobject thiz, sp<NativeContext> context) { 779f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGV("%s:", __FUNCTION__); 78047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk NativeContext* current = DngCreator_getNativeContext(env, thiz); 78147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 78247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (context != NULL) { 78347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk context->incStrong((void*) DngCreator_setNativeContext); 784f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 78547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 786f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (current) { 78747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk current->decStrong((void*) DngCreator_setNativeContext); 788f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 78947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 790f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk env->SetLongField(thiz, gDngCreatorClassInfo.mNativeContext, 79147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk reinterpret_cast<jlong>(context.get())); 79247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 79347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 79447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic TiffWriter* DngCreator_getCreator(JNIEnv* env, jobject thiz) { 79547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s:", __FUNCTION__); 79647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk NativeContext* current = DngCreator_getNativeContext(env, thiz); 79747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (current) { 79847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return current->getWriter(); 79947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 80047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return NULL; 801f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 802f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 803f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatic void DngCreator_nativeClassInit(JNIEnv* env, jclass clazz) { 804f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGV("%s:", __FUNCTION__); 805f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 806f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk gDngCreatorClassInfo.mNativeContext = env->GetFieldID(clazz, 807b6079005ed0631c3972ff427f56e12523ec214a7Ruben Brunk ANDROID_DNGCREATOR_CTX_JNI_ID, "J"); 808f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk LOG_ALWAYS_FATAL_IF(gDngCreatorClassInfo.mNativeContext == NULL, 809b6079005ed0631c3972ff427f56e12523ec214a7Ruben Brunk "can't find android/hardware/camera2/DngCreator.%s", 810b6079005ed0631c3972ff427f56e12523ec214a7Ruben Brunk ANDROID_DNGCREATOR_CTX_JNI_ID); 811f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 812f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jclass outputStreamClazz = env->FindClass("java/io/OutputStream"); 813f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk LOG_ALWAYS_FATAL_IF(outputStreamClazz == NULL, "Can't find java/io/OutputStream class"); 814f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk gOutputStreamClassInfo.mWriteMethod = env->GetMethodID(outputStreamClazz, "write", "([BII)V"); 815f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk LOG_ALWAYS_FATAL_IF(gOutputStreamClassInfo.mWriteMethod == NULL, "Can't find write method"); 81647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 81747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jclass inputStreamClazz = env->FindClass("java/io/InputStream"); 81847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk LOG_ALWAYS_FATAL_IF(inputStreamClazz == NULL, "Can't find java/io/InputStream class"); 81947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk gInputStreamClassInfo.mReadMethod = env->GetMethodID(inputStreamClazz, "read", "([BII)I"); 82047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk LOG_ALWAYS_FATAL_IF(gInputStreamClassInfo.mReadMethod == NULL, "Can't find read method"); 82147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk gInputStreamClassInfo.mSkipMethod = env->GetMethodID(inputStreamClazz, "skip", "(J)J"); 82247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk LOG_ALWAYS_FATAL_IF(gInputStreamClassInfo.mSkipMethod == NULL, "Can't find skip method"); 82347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 82447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jclass inputBufferClazz = env->FindClass("java/nio/ByteBuffer"); 82547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk LOG_ALWAYS_FATAL_IF(inputBufferClazz == NULL, "Can't find java/nio/ByteBuffer class"); 82647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk gInputByteBufferClassInfo.mGetMethod = env->GetMethodID(inputBufferClazz, "get", 82747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "([BII)Ljava/nio/ByteBuffer;"); 82847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk LOG_ALWAYS_FATAL_IF(gInputByteBufferClassInfo.mGetMethod == NULL, "Can't find get method"); 829f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 830f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 831f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatic void DngCreator_init(JNIEnv* env, jobject thiz, jobject characteristicsPtr, 832b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk jobject resultsPtr, jstring formattedCaptureTime) { 833f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGV("%s:", __FUNCTION__); 834f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk CameraMetadata characteristics; 835f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk CameraMetadata results; 836f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (CameraMetadata_getNativeMetadata(env, characteristicsPtr, &characteristics) != OK) { 837f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jniThrowException(env, "java/lang/AssertionError", 838f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk "No native metadata defined for camera characteristics."); 839f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; 840f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 841f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (CameraMetadata_getNativeMetadata(env, resultsPtr, &results) != OK) { 842f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jniThrowException(env, "java/lang/AssertionError", 843f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk "No native metadata defined for capture results."); 844f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; 845f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 846f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 84747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sp<NativeContext> nativeContext = new NativeContext(); 84847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TiffWriter* writer = nativeContext->getWriter(); 849f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 850f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk writer->addIfd(TIFF_IFD_0); 851f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 852f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk status_t err = OK; 853f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 854f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk const uint32_t samplesPerPixel = 1; 855f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk const uint32_t bitsPerSample = BITS_PER_SAMPLE; 856f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t imageWidth = 0; 857f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t imageHeight = 0; 858f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 859f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB; 860d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk uint8_t cfaPlaneColor[3] = {0, 1, 2}; 861d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk uint8_t cfaEnum = -1; 862f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 863f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // TODO: Greensplit. 864f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // TODO: Add remaining non-essential tags 86547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 86647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Setup main image tags 86747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 868f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 869f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set orientation 870f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint16_t orientation = 1; // Normal 871f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_0), env, 87247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_ORIENTATION, writer); 873f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 874f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 875f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 876f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set subfiletype 877f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t subfileType = 0; // Main image 878f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_NEWSUBFILETYPE, 1, &subfileType, TIFF_IFD_0), env, 87947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_NEWSUBFILETYPE, writer); 880f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 881f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 882f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 883f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set bits per sample 884f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint16_t bits = static_cast<uint16_t>(bitsPerSample); 885f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_BITSPERSAMPLE, 1, &bits, TIFF_IFD_0), env, 88647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_BITSPERSAMPLE, writer); 887f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 888f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 889f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 890f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set compression 891f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint16_t compression = 1; // None 892f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_COMPRESSION, 1, &compression, TIFF_IFD_0), env, 89347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_COMPRESSION, writer); 894f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 895f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 896f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 897f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set dimensions 898f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry = 899f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE); 90047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry, env, TAG_IMAGEWIDTH, writer); 901f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t width = static_cast<uint32_t>(entry.data.i32[2]); 902f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t height = static_cast<uint32_t>(entry.data.i32[3]); 903f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_IMAGEWIDTH, 1, &width, TIFF_IFD_0), env, 90447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_IMAGEWIDTH, writer); 905f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_IMAGELENGTH, 1, &height, TIFF_IFD_0), env, 90647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_IMAGELENGTH, writer); 907f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk imageWidth = width; 908f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk imageHeight = height; 909f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 910f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 911f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 912f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set photometric interpretation 91347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint16_t interpretation = 32803; // CFA 914f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_PHOTOMETRICINTERPRETATION, 1, &interpretation, 91547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_PHOTOMETRICINTERPRETATION, writer); 916f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 917f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 918f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 919f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set blacklevel tags 920f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry = 921f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_BLACK_LEVEL_PATTERN); 92247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry, env, TAG_BLACKLEVEL, writer); 923f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk const uint32_t* blackLevel = reinterpret_cast<const uint32_t*>(entry.data.i32); 924f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_BLACKLEVEL, entry.count, blackLevel, TIFF_IFD_0), env, 92547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_BLACKLEVEL, writer); 926f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 927f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint16_t repeatDim[2] = {2, 2}; 928f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_BLACKLEVELREPEATDIM, 2, repeatDim, TIFF_IFD_0), env, 92947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_BLACKLEVELREPEATDIM, writer); 930f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 931f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 932f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 933f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set samples per pixel 934f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint16_t samples = static_cast<uint16_t>(samplesPerPixel); 935f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_SAMPLESPERPIXEL, 1, &samples, TIFF_IFD_0), 93647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_SAMPLESPERPIXEL, writer); 937f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 938f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 939f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 940f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set planar configuration 941f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint16_t config = 1; // Chunky 942f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_PLANARCONFIGURATION, 1, &config, TIFF_IFD_0), 94347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_PLANARCONFIGURATION, writer); 944f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 945f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 946f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 947f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set CFA pattern dimensions 948f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint16_t repeatDim[2] = {2, 2}; 949f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_CFAREPEATPATTERNDIM, 2, repeatDim, TIFF_IFD_0), 95047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_CFAREPEATPATTERNDIM, writer); 951f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 952f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 953f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 954f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set CFA pattern 955f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry = 956f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT); 95747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry, env, TAG_CFAPATTERN, writer); 958d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 959d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk const int cfaLength = 4; 960d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaEnum = entry.data.u8[0]; 961d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk uint8_t cfa[cfaLength]; 962d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk if ((err = convertCFA(cfaEnum, /*out*/cfa)) != OK) { 963d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk jniThrowExceptionFmt(env, "java/lang/IllegalStateException", 964d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk "Invalid metadata for tag %d", TAG_CFAPATTERN); 965f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 966d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 967d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, cfaLength, cfa, TIFF_IFD_0), env, 968d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk TAG_CFAPATTERN, writer); 969d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 970d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk opcodeCfaLayout = convertCFAEnumToOpcodeLayout(cfaEnum); 971f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 972f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 973f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 974f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set CFA plane color 975f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_CFAPLANECOLOR, 3, cfaPlaneColor, TIFF_IFD_0), 97647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_CFAPLANECOLOR, writer); 977f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 978f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 979f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 980f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set CFA layout 981f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint16_t cfaLayout = 1; 982f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_CFALAYOUT, 1, &cfaLayout, TIFF_IFD_0), 98347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_CFALAYOUT, writer); 984f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 985f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 986f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 987b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // image description 988b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint8_t imageDescription = '\0'; // empty 989b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_IMAGEDESCRIPTION, 1, &imageDescription, TIFF_IFD_0), 99047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_IMAGEDESCRIPTION, writer); 991b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 992b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 993b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 994b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // make 995b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk char manufacturer[PROPERTY_VALUE_MAX]; 996b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 997b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // Use "" to represent unknown make as suggested in TIFF/EP spec. 998b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk property_get("ro.product.manufacturer", manufacturer, ""); 999b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint32_t count = static_cast<uint32_t>(strlen(manufacturer)) + 1; 1000b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1001b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_MAKE, count, reinterpret_cast<uint8_t*>(manufacturer), 100247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_MAKE, writer); 1003b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1004b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1005b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1006b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // model 1007b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk char model[PROPERTY_VALUE_MAX]; 1008b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1009b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // Use "" to represent unknown model as suggested in TIFF/EP spec. 1010b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk property_get("ro.product.model", model, ""); 1011b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint32_t count = static_cast<uint32_t>(strlen(model)) + 1; 1012b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1013b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_MODEL, count, reinterpret_cast<uint8_t*>(model), 101447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_MODEL, writer); 1015b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1016b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1017b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1018b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // x resolution 1019b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint32_t xres[] = { 72, 1 }; // default 72 ppi 1020b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_XRESOLUTION, 1, xres, TIFF_IFD_0), 102147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_XRESOLUTION, writer); 1022b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1023b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // y resolution 1024b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint32_t yres[] = { 72, 1 }; // default 72 ppi 1025b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_YRESOLUTION, 1, yres, TIFF_IFD_0), 102647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_YRESOLUTION, writer); 1027b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1028b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint16_t unit = 2; // inches 1029b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_RESOLUTIONUNIT, 1, &unit, TIFF_IFD_0), 103047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_RESOLUTIONUNIT, writer); 1031b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1032b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1033b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1034b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // software 1035b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk char software[PROPERTY_VALUE_MAX]; 1036b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk property_get("ro.build.fingerprint", software, ""); 1037b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint32_t count = static_cast<uint32_t>(strlen(software)) + 1; 1038b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_SOFTWARE, count, reinterpret_cast<uint8_t*>(software), 103947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_SOFTWARE, writer); 1040b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1041b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1042b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1043b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // datetime 1044b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk const size_t DATETIME_COUNT = 20; 1045b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk const char* captureTime = env->GetStringUTFChars(formattedCaptureTime, NULL); 1046b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1047b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk size_t len = strlen(captureTime) + 1; 1048b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk if (len != DATETIME_COUNT) { 1049b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk jniThrowException(env, "java/lang/IllegalArgumentException", 1050b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk "Timestamp string length is not required 20 characters"); 1051b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk return; 1052b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1053b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 105447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer->addEntry(TAG_DATETIME, DATETIME_COUNT, 105547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk reinterpret_cast<const uint8_t*>(captureTime), TIFF_IFD_0) != OK) { 105647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env->ReleaseStringUTFChars(formattedCaptureTime, captureTime); 105747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 105847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Invalid metadata for tag %x", TAG_DATETIME); 105947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 106047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 1061b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1062b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // datetime original 106347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer->addEntry(TAG_DATETIMEORIGINAL, DATETIME_COUNT, 106447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk reinterpret_cast<const uint8_t*>(captureTime), TIFF_IFD_0) != OK) { 106547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env->ReleaseStringUTFChars(formattedCaptureTime, captureTime); 106647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 106747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Invalid metadata for tag %x", TAG_DATETIMEORIGINAL); 106847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 106947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 1070b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk env->ReleaseStringUTFChars(formattedCaptureTime, captureTime); 1071b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1072b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1073b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1074b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // TIFF/EP standard id 1075b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint8_t standardId[] = { 1, 0, 0, 0 }; 1076b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_TIFFEPSTANDARDID, 4, standardId, 107747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_TIFFEPSTANDARDID, writer); 1078b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1079b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1080b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1081b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // copyright 1082b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint8_t copyright = '\0'; // empty 1083b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_COPYRIGHT, 1, ©right, 108447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_COPYRIGHT, writer); 1085b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1086b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1087b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1088b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // exposure time 1089b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk camera_metadata_entry entry = 1090b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk results.find(ANDROID_SENSOR_EXPOSURE_TIME); 109147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry, env, TAG_EXPOSURETIME, writer); 1092b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1093b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk int64_t exposureTime = *(entry.data.i64); 1094b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1095b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk if (exposureTime < 0) { 1096b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // Should be unreachable 1097b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk jniThrowException(env, "java/lang/IllegalArgumentException", 1098b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk "Negative exposure time in metadata"); 1099b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk return; 1100b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1101b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1102b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // Ensure exposure time doesn't overflow (for exposures > 4s) 1103b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint32_t denominator = 1000000000; 1104b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk while (exposureTime > UINT32_MAX) { 1105b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk exposureTime >>= 1; 1106b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk denominator >>= 1; 1107b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk if (denominator == 0) { 1108b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // Should be unreachable 1109b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk jniThrowException(env, "java/lang/IllegalArgumentException", 1110b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk "Exposure time too long"); 1111b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk return; 1112b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1113b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1114b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1115b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint32_t exposure[] = { static_cast<uint32_t>(exposureTime), denominator }; 1116b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_EXPOSURETIME, 1, exposure, 111747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_EXPOSURETIME, writer); 1118b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1119b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1120b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1121b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1122b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // ISO speed ratings 1123b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk camera_metadata_entry entry = 1124b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk results.find(ANDROID_SENSOR_SENSITIVITY); 112547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry, env, TAG_ISOSPEEDRATINGS, writer); 1126b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1127b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk int32_t tempIso = *(entry.data.i32); 1128b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk if (tempIso < 0) { 1129b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk jniThrowException(env, "java/lang/IllegalArgumentException", 1130b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk "Negative ISO value"); 1131b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk return; 1132b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1133b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1134b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk if (tempIso > UINT16_MAX) { 1135b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk ALOGW("%s: ISO value overflows UINT16_MAX, clamping to max", __FUNCTION__); 1136b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk tempIso = UINT16_MAX; 1137b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1138b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1139b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint16_t iso = static_cast<uint16_t>(tempIso); 1140b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_ISOSPEEDRATINGS, 1, &iso, 114147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_ISOSPEEDRATINGS, writer); 1142b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1143b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1144b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1145b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // focal length 1146b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk camera_metadata_entry entry = 1147b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk results.find(ANDROID_LENS_FOCAL_LENGTH); 114847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry, env, TAG_FOCALLENGTH, writer); 1149b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1150b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint32_t focalLength[] = { static_cast<uint32_t>(*(entry.data.f) * 100), 100 }; 1151b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_FOCALLENGTH, 1, focalLength, 115247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_FOCALLENGTH, writer); 1153b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1154b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1155b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1156b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk // f number 1157b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk camera_metadata_entry entry = 1158b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk results.find(ANDROID_LENS_APERTURE); 115947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry, env, TAG_FNUMBER, writer); 1160b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1161b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk uint32_t fnum[] = { static_cast<uint32_t>(*(entry.data.f) * 100), 100 }; 1162b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_FNUMBER, 1, fnum, 116347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_FNUMBER, writer); 1164b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk } 1165b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk 1166b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk { 1167f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set DNG version information 1168f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint8_t version[4] = {1, 4, 0, 0}; 1169f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_DNGVERSION, 4, version, TIFF_IFD_0), 117047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_DNGVERSION, writer); 1171f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1172f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint8_t backwardVersion[4] = {1, 1, 0, 0}; 1173f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_DNGBACKWARDVERSION, 4, backwardVersion, TIFF_IFD_0), 117447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_DNGBACKWARDVERSION, writer); 1175f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1176f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1177f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1178f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set whitelevel 1179f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry = 1180f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_INFO_WHITE_LEVEL); 118147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry, env, TAG_WHITELEVEL, writer); 1182f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t whiteLevel = static_cast<uint32_t>(entry.data.i32[0]); 1183f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_WHITELEVEL, 1, &whiteLevel, TIFF_IFD_0), env, 118447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_WHITELEVEL, writer); 1185f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1186f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1187f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1188f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set default scale 1189f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t defaultScale[4] = {1, 1, 1, 1}; 1190f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTSCALE, 2, defaultScale, TIFF_IFD_0), 119147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_DEFAULTSCALE, writer); 1192f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1193f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1194f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk bool singleIlluminant = false; 1195f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1196f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set calibration illuminants 1197f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry1 = 1198f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT1); 119947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry1, env, TAG_CALIBRATIONILLUMINANT1, writer); 1200f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry2 = 1201f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT2); 1202f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (entry2.count == 0) { 1203f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk singleIlluminant = true; 1204f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1205f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint16_t ref1 = entry1.data.u8[0]; 1206f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1207f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_CALIBRATIONILLUMINANT1, 1, &ref1, 120847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_CALIBRATIONILLUMINANT1, writer); 1209f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1210f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (!singleIlluminant) { 1211f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint16_t ref2 = entry2.data.u8[0]; 1212f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_CALIBRATIONILLUMINANT2, 1, &ref2, 121347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_CALIBRATIONILLUMINANT2, writer); 1214f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1215f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1216f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1217f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1218f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set color transforms 1219f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry1 = 1220f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM1); 122147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry1, env, TAG_COLORMATRIX1, writer); 1222f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1223f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk int32_t colorTransform1[entry1.count * 2]; 1224f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1225f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk size_t ctr = 0; 1226f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk for(size_t i = 0; i < entry1.count; ++i) { 1227f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk colorTransform1[ctr++] = entry1.data.r[i].numerator; 1228f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk colorTransform1[ctr++] = entry1.data.r[i].denominator; 1229f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1230f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 123147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_COLORMATRIX1, entry1.count, colorTransform1, 123247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_COLORMATRIX1, writer); 1233f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1234f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (!singleIlluminant) { 1235f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry2 = characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM2); 123647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry2, env, TAG_COLORMATRIX2, writer); 1237f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk int32_t colorTransform2[entry2.count * 2]; 1238f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1239f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ctr = 0; 1240f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk for(size_t i = 0; i < entry2.count; ++i) { 1241f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk colorTransform2[ctr++] = entry2.data.r[i].numerator; 1242f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk colorTransform2[ctr++] = entry2.data.r[i].denominator; 1243f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1244f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 124547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_COLORMATRIX2, entry2.count, colorTransform2, 124647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_COLORMATRIX2, writer); 1247f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1248f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1249f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1250f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1251f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set calibration transforms 1252f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry1 = 1253f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM1); 125447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry1, env, TAG_CAMERACALIBRATION1, writer); 1255f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1256f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk int32_t calibrationTransform1[entry1.count * 2]; 1257f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1258f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk size_t ctr = 0; 1259f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk for(size_t i = 0; i < entry1.count; ++i) { 1260f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk calibrationTransform1[ctr++] = entry1.data.r[i].numerator; 1261f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk calibrationTransform1[ctr++] = entry1.data.r[i].denominator; 1262f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1263f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1264b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_CAMERACALIBRATION1, entry1.count, 1265b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk calibrationTransform1, TIFF_IFD_0), env, TAG_CAMERACALIBRATION1, writer); 1266f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1267f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (!singleIlluminant) { 1268f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry2 = 1269f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM2); 127047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry2, env, TAG_CAMERACALIBRATION2, writer); 1271f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk int32_t calibrationTransform2[entry2.count * 2]; 1272f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1273f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ctr = 0; 1274f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk for(size_t i = 0; i < entry2.count; ++i) { 1275f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk calibrationTransform2[ctr++] = entry2.data.r[i].numerator; 1276f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk calibrationTransform2[ctr++] = entry2.data.r[i].denominator; 1277f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1278f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1279b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_CAMERACALIBRATION2, entry2.count, 12802377cd319f8a77f147f3d70a7ddc75fa9e9fe87cAndreas Gampe calibrationTransform2, TIFF_IFD_0), env, TAG_CAMERACALIBRATION2, writer); 1281f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1282f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1283f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1284f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1285f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set forward transforms 1286f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry1 = 1287f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX1); 128847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry1, env, TAG_FORWARDMATRIX1, writer); 1289f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1290f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk int32_t forwardTransform1[entry1.count * 2]; 1291f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1292f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk size_t ctr = 0; 1293f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk for(size_t i = 0; i < entry1.count; ++i) { 1294f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk forwardTransform1[ctr++] = entry1.data.r[i].numerator; 1295f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk forwardTransform1[ctr++] = entry1.data.r[i].denominator; 1296f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1297f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1298f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_FORWARDMATRIX1, entry1.count, forwardTransform1, 129947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_FORWARDMATRIX1, writer); 1300f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1301f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (!singleIlluminant) { 1302f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry2 = 1303f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX2); 130447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry2, env, TAG_FORWARDMATRIX2, writer); 1305f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk int32_t forwardTransform2[entry2.count * 2]; 1306f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1307f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ctr = 0; 1308f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk for(size_t i = 0; i < entry2.count; ++i) { 1309f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk forwardTransform2[ctr++] = entry2.data.r[i].numerator; 1310f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk forwardTransform2[ctr++] = entry2.data.r[i].denominator; 1311f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1312f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1313f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_FORWARDMATRIX2, entry2.count, forwardTransform2, 131447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_FORWARDMATRIX2, writer); 1315f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1316f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1317f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1318f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1319f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Set camera neutral 1320f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry = 1321f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk results.find(ANDROID_SENSOR_NEUTRAL_COLOR_POINT); 132247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_EMPTY(entry, env, TAG_ASSHOTNEUTRAL, writer); 1323f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t cameraNeutral[entry.count * 2]; 1324f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1325f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk size_t ctr = 0; 1326f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk for(size_t i = 0; i < entry.count; ++i) { 1327f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk cameraNeutral[ctr++] = 1328f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk static_cast<uint32_t>(entry.data.r[i].numerator); 1329f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk cameraNeutral[ctr++] = 1330f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk static_cast<uint32_t>(entry.data.r[i].denominator); 1331f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1332f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1333f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_ASSHOTNEUTRAL, entry.count, cameraNeutral, 133447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_ASSHOTNEUTRAL, writer); 1335f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1336f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1337f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1338f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Setup data strips 1339f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // TODO: Switch to tiled implementation. 134047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer->addStrip(TIFF_IFD_0) != OK) { 134147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Could not setup strip tags.", __FUNCTION__); 134247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalStateException", 134347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Failed to setup strip tags."); 134447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 134547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 1346f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1347f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1348f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1349f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Setup default crop + crop origin tags 1350f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t margin = 8; // Default margin recommended by Adobe for interpolation. 1351f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t dimensionLimit = 128; // Smallest image dimension crop margin from. 1352f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (imageWidth >= dimensionLimit && imageHeight >= dimensionLimit) { 1353f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t defaultCropOrigin[] = {margin, margin}; 1354f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint32_t defaultCropSize[] = {imageWidth - margin, imageHeight - margin}; 1355f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTCROPORIGIN, 2, defaultCropOrigin, 135647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_DEFAULTCROPORIGIN, writer); 1357f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTCROPSIZE, 2, defaultCropSize, 135847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_DEFAULTCROPSIZE, writer); 1359f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1360f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1361f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1362f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1363f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Setup unique camera model tag 1364f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk char model[PROPERTY_VALUE_MAX]; 1365f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk property_get("ro.product.model", model, ""); 1366f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1367f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk char manufacturer[PROPERTY_VALUE_MAX]; 1368f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk property_get("ro.product.manufacturer", manufacturer, ""); 1369f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1370f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk char brand[PROPERTY_VALUE_MAX]; 1371f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk property_get("ro.product.brand", brand, ""); 1372f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1373f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk String8 cameraModel(model); 1374f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk cameraModel += "-"; 1375f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk cameraModel += manufacturer; 1376f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk cameraModel += "-"; 1377f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk cameraModel += brand; 1378f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1379f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_UNIQUECAMERAMODEL, cameraModel.size() + 1, 1380f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk reinterpret_cast<const uint8_t*>(cameraModel.string()), TIFF_IFD_0), env, 138147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_UNIQUECAMERAMODEL, writer); 1382f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1383f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1384f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk { 1385b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk // Setup sensor noise model 1386b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk camera_metadata_entry entry = 1387b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk results.find(ANDROID_SENSOR_NOISE_PROFILE); 1388b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk 1389d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk const status_t numPlaneColors = 3; 1390d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk const status_t numCfaChannels = 4; 1391d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 1392d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk uint8_t cfaOut[numCfaChannels]; 1393d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk if ((err = convertCFA(cfaEnum, /*out*/cfaOut)) != OK) { 1394d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk jniThrowException(env, "java/lang/IllegalArgumentException", 1395d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk "Invalid CFA from camera characteristics"); 1396d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk return; 1397d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 1398d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 1399d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk double noiseProfile[numPlaneColors * 2]; 1400d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 1401b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk if (entry.count > 0) { 1402d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk if (entry.count != numCfaChannels * 2) { 140346d8444631b4b1253a76bfcc78a29d26014d022fDan Albert ALOGW("%s: Invalid entry count %zu for noise profile returned " 140446d8444631b4b1253a76bfcc78a29d26014d022fDan Albert "in characteristics, no noise profile tag written...", 140546d8444631b4b1253a76bfcc78a29d26014d022fDan Albert __FUNCTION__, entry.count); 1406d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } else { 1407d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk if ((err = generateNoiseProfile(entry.data.d, cfaOut, numCfaChannels, 1408d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk cfaPlaneColor, numPlaneColors, /*out*/ noiseProfile)) == OK) { 1409d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk 1410d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_NOISEPROFILE, numPlaneColors * 2, 1411d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk noiseProfile, TIFF_IFD_0), env, TAG_NOISEPROFILE, writer); 1412d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } else { 1413d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk ALOGW("%s: Error converting coefficients for noise profile, no noise profile" 1414d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk " tag written...", __FUNCTION__); 1415d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 1416d70132c373eee01b4e0a35250bd4246672e7a02eRuben Brunk } 1417b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk } else { 1418b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk ALOGW("%s: No noise profile found in result metadata. Image quality may be reduced.", 1419b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk __FUNCTION__); 1420b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk } 1421b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk } 1422b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk 1423b1971dc8a69b8cee91208b7d3017c52b36e55721Ruben Brunk { 1424f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk // Setup opcode List 2 1425f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry1 = 1426f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk characteristics.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE); 142747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 142847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t lsmWidth = 0; 142947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t lsmHeight = 0; 143047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 143147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (entry1.count != 0) { 143247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk lsmWidth = static_cast<uint32_t>(entry1.data.i32[0]); 143347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk lsmHeight = static_cast<uint32_t>(entry1.data.i32[1]); 143447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 1435f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1436f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk camera_metadata_entry entry2 = 1437f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk results.find(ANDROID_STATISTICS_LENS_SHADING_MAP); 143847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 143947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (entry2.count > 0 && entry2.count == lsmWidth * lsmHeight * 4) { 1440f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1441f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk OpcodeListBuilder builder; 1442f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk status_t err = builder.addGainMapsForMetadata(lsmWidth, 1443f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk lsmHeight, 1444f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 0, 1445f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 0, 1446f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk imageHeight, 1447f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk imageWidth, 1448f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk opcodeCfaLayout, 1449f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk entry2.data.f); 1450f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (err == OK) { 1451f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk size_t listSize = builder.getSize(); 1452f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk uint8_t opcodeListBuf[listSize]; 1453f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk err = builder.buildOpList(opcodeListBuf); 1454f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk if (err == OK) { 1455f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf, 145647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_OPCODELIST2, writer); 1457f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } else { 1458f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGE("%s: Could not build Lens shading map opcode.", __FUNCTION__); 1459f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jniThrowRuntimeException(env, "failed to construct lens shading map opcode."); 1460f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1461f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } else { 1462f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGE("%s: Could not add Lens shading map.", __FUNCTION__); 1463f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jniThrowRuntimeException(env, "failed to add lens shading map."); 1464f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1465f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } else { 146647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGW("%s: No lens shading map found in result metadata. Image quality may be reduced.", 146747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk __FUNCTION__); 1468f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1469f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1470f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 147147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk DngCreator_setNativeContext(env, thiz, nativeContext); 1472f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 1473f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1474f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatic void DngCreator_destroy(JNIEnv* env, jobject thiz) { 1475f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGV("%s:", __FUNCTION__); 147647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk DngCreator_setNativeContext(env, thiz, NULL); 1477f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 1478f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 147947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic void DngCreator_nativeSetOrientation(JNIEnv* env, jobject thiz, jint orient) { 1480f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGV("%s:", __FUNCTION__); 1481f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 148247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TiffWriter* writer = DngCreator_getCreator(env, thiz); 148347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer == NULL) { 148447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Failed to initialize DngCreator", __FUNCTION__); 148547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/AssertionError", 148647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "setOrientation called with uninitialized DngCreator"); 148747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 148847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 148947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 149047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint16_t orientation = static_cast<uint16_t>(orient); 149147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_0), env, 149247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_ORIENTATION, writer); 149347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 149447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Set main image orientation also if in a separate IFD 149547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer->hasIfd(TIFF_IFD_SUB1)) { 149647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_SUB1), env, 149747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_ORIENTATION, writer); 149847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 1499f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 1500f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 150147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic void DngCreator_nativeSetDescription(JNIEnv* env, jobject thiz, jstring description) { 1502f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGV("%s:", __FUNCTION__); 150347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 150447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TiffWriter* writer = DngCreator_getCreator(env, thiz); 150547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer == NULL) { 150647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Failed to initialize DngCreator", __FUNCTION__); 150747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/AssertionError", 150847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "setDescription called with uninitialized DngCreator"); 150947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 151047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 151147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 151247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk const char* desc = env->GetStringUTFChars(description, NULL); 151347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk size_t len = strlen(desc) + 1; 151447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 151547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer->addEntry(TAG_IMAGEDESCRIPTION, len, 151647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk reinterpret_cast<const uint8_t*>(desc), TIFF_IFD_0) != OK) { 151747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 151847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Invalid metadata for tag %x", TAG_IMAGEDESCRIPTION); 151947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 152047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 152147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env->ReleaseStringUTFChars(description, desc); 1522f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 1523f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 152447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic void DngCreator_nativeSetGpsTags(JNIEnv* env, jobject thiz, jintArray latTag, jstring latRef, 152547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jintArray longTag, jstring longRef, jstring dateTag, jintArray timeTag) { 1526f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGV("%s:", __FUNCTION__); 1527f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 152847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TiffWriter* writer = DngCreator_getCreator(env, thiz); 152947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer == NULL) { 153047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Failed to initialize DngCreator", __FUNCTION__); 153147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/AssertionError", 153247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "setGpsTags called with uninitialized DngCreator"); 1533f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; 1534f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1535f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 153647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!writer->hasIfd(TIFF_IFD_GPSINFO)) { 153747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer->addSubIfd(TIFF_IFD_0, TIFF_IFD_GPSINFO, TiffWriter::GPSINFO) != OK) { 153847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Failed to add GpsInfo IFD %u to IFD %u", __FUNCTION__, TIFF_IFD_GPSINFO, 153947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0); 154047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalStateException", "Failed to add GPSINFO"); 154147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 154247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 154347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 154447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 154547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk const jsize GPS_VALUE_LENGTH = 6; 154647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jsize latLen = env->GetArrayLength(latTag); 154747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jsize longLen = env->GetArrayLength(longTag); 154847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jsize timeLen = env->GetArrayLength(timeTag); 154947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (latLen != GPS_VALUE_LENGTH) { 155047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalArgumentException", 155147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "invalid latitude tag length"); 155247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 155347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } else if (longLen != GPS_VALUE_LENGTH) { 155447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalArgumentException", 155547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "invalid longitude tag length"); 1556f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; 155747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } else if (timeLen != GPS_VALUE_LENGTH) { 155847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalArgumentException", 155947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "invalid time tag length"); 156047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 156147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 156247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 156347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t latitude[GPS_VALUE_LENGTH]; 156447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t longitude[GPS_VALUE_LENGTH]; 156547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t timestamp[GPS_VALUE_LENGTH]; 156647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 156747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env->GetIntArrayRegion(latTag, 0, static_cast<jsize>(GPS_VALUE_LENGTH), 156847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk reinterpret_cast<jint*>(&latitude)); 156947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env->GetIntArrayRegion(longTag, 0, static_cast<jsize>(GPS_VALUE_LENGTH), 157047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk reinterpret_cast<jint*>(&longitude)); 157147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env->GetIntArrayRegion(timeTag, 0, static_cast<jsize>(GPS_VALUE_LENGTH), 157247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk reinterpret_cast<jint*>(×tamp)); 157347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 157447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk const jsize GPS_REF_LENGTH = 2; 157547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk const jsize GPS_DATE_LENGTH = 11; 157647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint8_t latitudeRef[GPS_REF_LENGTH]; 157747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint8_t longitudeRef[GPS_REF_LENGTH]; 157847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint8_t date[GPS_DATE_LENGTH]; 157947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 158047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env->GetStringUTFRegion(latRef, 0, 1, reinterpret_cast<char*>(&latitudeRef)); 158147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk latitudeRef[GPS_REF_LENGTH - 1] = '\0'; 158247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env->GetStringUTFRegion(longRef, 0, 1, reinterpret_cast<char*>(&longitudeRef)); 158347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk longitudeRef[GPS_REF_LENGTH - 1] = '\0'; 158447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 158547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env->GetStringUTFRegion(dateTag, 0, GPS_DATE_LENGTH - 1, reinterpret_cast<char*>(&date)); 158647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk date[GPS_DATE_LENGTH - 1] = '\0'; 158747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 158847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 158947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint8_t version[] = {2, 3, 0, 0}; 159047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_GPSVERSIONID, 4, version, 159147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_GPSINFO), env, TAG_GPSVERSIONID, writer); 159247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 159347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 159447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 159547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_GPSLATITUDEREF, GPS_REF_LENGTH, latitudeRef, 159647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_GPSINFO), env, TAG_GPSLATITUDEREF, writer); 159747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 159847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 159947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 160047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_GPSLONGITUDEREF, GPS_REF_LENGTH, longitudeRef, 160147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_GPSINFO), env, TAG_GPSLONGITUDEREF, writer); 1602f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1603f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 160447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 160547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_GPSLATITUDE, 3, latitude, 160647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_GPSINFO), env, TAG_GPSLATITUDE, writer); 160747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 160847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 160947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 161047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_GPSLONGITUDE, 3, longitude, 161147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_GPSINFO), env, TAG_GPSLONGITUDE, writer); 161247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 161347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 161447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 161547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_GPSTIMESTAMP, 3, timestamp, 161647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_GPSINFO), env, TAG_GPSTIMESTAMP, writer); 161747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 161847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 161947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 162047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_GPSDATESTAMP, GPS_DATE_LENGTH, date, 162147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_GPSINFO), env, TAG_GPSDATESTAMP, writer); 162247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 162347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 162447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 162547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic void DngCreator_nativeSetThumbnail(JNIEnv* env, jobject thiz, jobject buffer, jint width, 162647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jint height) { 162747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s:", __FUNCTION__); 162847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 162947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk NativeContext* context = DngCreator_getNativeContext(env, thiz); 1630f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk TiffWriter* writer = DngCreator_getCreator(env, thiz); 163147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer == NULL || context == NULL) { 1632f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGE("%s: Failed to initialize DngCreator", __FUNCTION__); 1633f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk jniThrowException(env, "java/lang/AssertionError", 163447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "setThumbnail called with uninitialized DngCreator"); 1635f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; 1636f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 163747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 163847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk size_t fullSize = width * height * BYTES_PER_RGB_PIXEL; 163947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jlong capacity = env->GetDirectBufferCapacity(buffer); 16400f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe if (static_cast<uint64_t>(capacity) != static_cast<uint64_t>(fullSize)) { 164147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(env, "java/lang/AssertionError", 164247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Invalid size %d for thumbnail, expected size was %d", 164347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk capacity, fullSize); 1644f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; 1645f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1646f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 164747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint8_t* pixelBytes = reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(buffer)); 164847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (pixelBytes == NULL) { 164947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Could not get native ByteBuffer", __FUNCTION__); 165047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid ByteBuffer"); 1651f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; 1652f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1653f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 165447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!writer->hasIfd(TIFF_IFD_SUB1)) { 165547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer->addSubIfd(TIFF_IFD_0, TIFF_IFD_SUB1) != OK) { 165647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Failed to add SubIFD %u to IFD %u", __FUNCTION__, TIFF_IFD_SUB1, 165747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0); 165847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalStateException", "Failed to add SubIFD"); 165947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 166047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 1661f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 166247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk Vector<uint16_t> tagsToMove; 166347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_ORIENTATION); 166447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_NEWSUBFILETYPE); 166547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_BITSPERSAMPLE); 166647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_COMPRESSION); 166747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_IMAGEWIDTH); 166847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_IMAGELENGTH); 166947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_PHOTOMETRICINTERPRETATION); 167047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_BLACKLEVEL); 167147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_BLACKLEVELREPEATDIM); 167247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_SAMPLESPERPIXEL); 167347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_PLANARCONFIGURATION); 167447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_CFAREPEATPATTERNDIM); 167547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_CFAPATTERN); 167647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_CFAPLANECOLOR); 167747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_CFALAYOUT); 167847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_XRESOLUTION); 167947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_YRESOLUTION); 168047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_RESOLUTIONUNIT); 168147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_WHITELEVEL); 168247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_DEFAULTSCALE); 168347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_ROWSPERSTRIP); 168447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_STRIPBYTECOUNTS); 168547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_STRIPOFFSETS); 168647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_DEFAULTCROPORIGIN); 168747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_DEFAULTCROPSIZE); 168847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk tagsToMove.add(TAG_OPCODELIST2); 168947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 169047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (moveEntries(writer, TIFF_IFD_0, TIFF_IFD_SUB1, tagsToMove) != OK) { 169147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalStateException", "Failed to move entries"); 169247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 169347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 1694f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 169547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Make sure both IFDs get the same orientation tag 169647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sp<TiffEntry> orientEntry = writer->getEntry(TAG_ORIENTATION, TIFF_IFD_SUB1); 169747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (orientEntry != NULL) { 169847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk writer->addEntry(orientEntry, TIFF_IFD_0); 1699f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 170047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 170147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 170247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Setup thumbnail tags 170347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 170447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 170547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Set photometric interpretation 170647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint16_t interpretation = 2; // RGB 170747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_PHOTOMETRICINTERPRETATION, 1, &interpretation, 170847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TIFF_IFD_0), env, TAG_PHOTOMETRICINTERPRETATION, writer); 170947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 171047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 171147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 171247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Set planar configuration 171347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint16_t config = 1; // Chunky 171447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_PLANARCONFIGURATION, 1, &config, TIFF_IFD_0), 171547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_PLANARCONFIGURATION, writer); 171647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 171747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 171847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 171947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Set samples per pixel 172047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint16_t samples = SAMPLES_PER_RGB_PIXEL; 172147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_SAMPLESPERPIXEL, 1, &samples, TIFF_IFD_0), 172247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_SAMPLESPERPIXEL, writer); 172347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 172447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 172547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 172647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Set bits per sample 172747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint16_t bits = BITS_PER_RGB_SAMPLE; 172847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_BITSPERSAMPLE, 1, &bits, TIFF_IFD_0), env, 172947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_BITSPERSAMPLE, writer); 173047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 173147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 173247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 173347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Set subfiletype 173447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t subfileType = 1; // Thumbnail image 173547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_NEWSUBFILETYPE, 1, &subfileType, TIFF_IFD_0), env, 173647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_NEWSUBFILETYPE, writer); 173747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 173847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 173947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 174047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Set compression 174147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint16_t compression = 1; // None 174247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_COMPRESSION, 1, &compression, TIFF_IFD_0), env, 174347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_COMPRESSION, writer); 174447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 174547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 174647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 174747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Set dimensions 174847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t uWidth = static_cast<uint32_t>(width); 174947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t uHeight = static_cast<uint32_t>(height); 175047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_IMAGEWIDTH, 1, &uWidth, TIFF_IFD_0), env, 175147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_IMAGEWIDTH, writer); 175247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_IMAGELENGTH, 1, &uHeight, TIFF_IFD_0), env, 175347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TAG_IMAGELENGTH, writer); 175447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 175547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 175647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 175747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // x resolution 175847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t xres[] = { 72, 1 }; // default 72 ppi 175947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_XRESOLUTION, 1, xres, TIFF_IFD_0), 176047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_XRESOLUTION, writer); 176147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 176247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // y resolution 176347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t yres[] = { 72, 1 }; // default 72 ppi 176447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_YRESOLUTION, 1, yres, TIFF_IFD_0), 176547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_YRESOLUTION, writer); 176647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 176747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint16_t unit = 2; // inches 176847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk BAIL_IF_INVALID(writer->addEntry(TAG_RESOLUTIONUNIT, 1, &unit, TIFF_IFD_0), 176947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk env, TAG_RESOLUTIONUNIT, writer); 177047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 177147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 177247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk { 177347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Setup data strips 177447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer->addStrip(TIFF_IFD_0) != OK) { 177547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Could not setup thumbnail strip tags.", __FUNCTION__); 177647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalStateException", 177747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Failed to setup thumbnail strip tags."); 177847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 177947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 178047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer->addStrip(TIFF_IFD_SUB1) != OK) { 178147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Could not main image strip tags.", __FUNCTION__); 178247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalStateException", 178347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Failed to setup main image strip tags."); 178447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 178547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 178647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 178747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 178847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!context->setThumbnail(pixelBytes, width, height)) { 178947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalStateException", 179047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Failed to set thumbnail."); 1791f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; 1792f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 179347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk} 1794f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 179547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk// TODO: Refactor out common preamble for the two nativeWrite methods. 179647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunkstatic void DngCreator_nativeWriteImage(JNIEnv* env, jobject thiz, jobject outStream, jint width, 179747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jint height, jobject inBuffer, jint rowStride, jint pixStride, jlong offset, 179847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jboolean isDirect) { 179947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s:", __FUNCTION__); 180046d8444631b4b1253a76bfcc78a29d26014d022fDan Albert ALOGV("%s: nativeWriteImage called with: width=%d, height=%d, " 180146d8444631b4b1253a76bfcc78a29d26014d022fDan Albert "rowStride=%d, pixStride=%d, offset=%" PRId64, __FUNCTION__, width, 180246d8444631b4b1253a76bfcc78a29d26014d022fDan Albert height, rowStride, pixStride, offset); 180347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t rStride = static_cast<uint32_t>(rowStride); 180447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t pStride = static_cast<uint32_t>(pixStride); 180547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t uWidth = static_cast<uint32_t>(width); 180647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t uHeight = static_cast<uint32_t>(height); 180747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint64_t uOffset = static_cast<uint64_t>(offset); 180847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 180947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sp<JniOutputStream> out = new JniOutputStream(env, outStream); 181047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if(env->ExceptionCheck()) { 181147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Could not allocate buffers for output stream", __FUNCTION__); 1812f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; 1813f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1814f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 181547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TiffWriter* writer = DngCreator_getCreator(env, thiz); 181647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk NativeContext* context = DngCreator_getNativeContext(env, thiz); 181747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer == NULL || context == NULL) { 181847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Failed to initialize DngCreator", __FUNCTION__); 181947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/AssertionError", 182047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Write called with uninitialized DngCreator"); 182147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 182247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 182347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 182447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Validate DNG header 182547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!validateDngHeader(env, writer, width, height)) { 182647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 182747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 182847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 182947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sp<JniInputByteBuffer> inBuf; 183047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk Vector<StripSource*> sources; 183147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sp<DirectStripSource> thumbnailSource; 183247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t targetIfd = TIFF_IFD_0; 183347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 183447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk bool hasThumbnail = writer->hasIfd(TIFF_IFD_SUB1); 183547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 183647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (hasThumbnail) { 183747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s: Adding thumbnail strip sources.", __FUNCTION__); 183847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t bytesPerPixel = SAMPLES_PER_RGB_PIXEL * BYTES_PER_RGB_SAMPLE; 183947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t thumbWidth = context->getThumbnailWidth(); 184047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk thumbnailSource = new DirectStripSource(env, context->getThumbnail(), TIFF_IFD_0, 184147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk thumbWidth, context->getThumbnailHeight(), bytesPerPixel, 184247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk bytesPerPixel * thumbWidth, /*offset*/0, BYTES_PER_RGB_SAMPLE, 184347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk SAMPLES_PER_RGB_PIXEL); 184447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sources.add(thumbnailSource.get()); 184547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk targetIfd = TIFF_IFD_SUB1; 184647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 184747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 184847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (isDirect) { 184947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk size_t fullSize = rStride * uHeight; 185047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jlong capacity = env->GetDirectBufferCapacity(inBuffer); 185147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (capacity < 0 || fullSize + uOffset > static_cast<uint64_t>(capacity)) { 185247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(env, "java/lang/IllegalStateException", 185347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Invalid size %d for Image, size given in metadata is %d at current stride", 185447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk capacity, fullSize); 1855f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return; 1856f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 185747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 185847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint8_t* pixelBytes = reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(inBuffer)); 185947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (pixelBytes == NULL) { 186047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Could not get native ByteBuffer", __FUNCTION__); 186147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid ByteBuffer"); 186247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 186347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 186447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 186547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s: Using direct-type strip source.", __FUNCTION__); 186647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk DirectStripSource stripSource(env, pixelBytes, targetIfd, uWidth, uHeight, pStride, 186747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk rStride, uOffset, BYTES_PER_SAMPLE, SAMPLES_PER_RAW_PIXEL); 186847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sources.add(&stripSource); 186947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 187047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk status_t ret = OK; 187147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if ((ret = writer->write(out.get(), sources.editArray(), sources.size())) != OK) { 187247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: write failed with error %d.", __FUNCTION__, ret); 187347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!env->ExceptionCheck()) { 187447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(env, "java/io/IOException", 187547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Encountered error %d while writing file.", ret); 1876f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 187747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 1878f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1879f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } else { 188047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk inBuf = new JniInputByteBuffer(env, inBuffer); 188147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 188247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s: Using input-type strip source.", __FUNCTION__); 188347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk InputStripSource stripSource(env, *inBuf, targetIfd, uWidth, uHeight, pStride, 188447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk rStride, uOffset, BYTES_PER_SAMPLE, SAMPLES_PER_RAW_PIXEL); 188547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sources.add(&stripSource); 188647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 188747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk status_t ret = OK; 188847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if ((ret = writer->write(out.get(), sources.editArray(), sources.size())) != OK) { 188947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: write failed with error %d.", __FUNCTION__, ret); 189047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!env->ExceptionCheck()) { 189147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(env, "java/io/IOException", 189247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Encountered error %d while writing file.", ret); 1893f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 189447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 1895f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1896f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk } 1897f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 1898f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1899f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatic void DngCreator_nativeWriteInputStream(JNIEnv* env, jobject thiz, jobject outStream, 190047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jobject inStream, jint width, jint height, jlong offset) { 1901f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk ALOGV("%s:", __FUNCTION__); 190247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 190347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t rowStride = width * BYTES_PER_SAMPLE; 190447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t pixStride = BYTES_PER_SAMPLE; 190547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t uWidth = static_cast<uint32_t>(width); 190647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t uHeight = static_cast<uint32_t>(height); 190747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint64_t uOffset = static_cast<uint32_t>(offset); 190847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 190946d8444631b4b1253a76bfcc78a29d26014d022fDan Albert ALOGV("%s: nativeWriteInputStream called with: width=%d, height=%d, " 191046d8444631b4b1253a76bfcc78a29d26014d022fDan Albert "rowStride=%d, pixStride=%d, offset=%" PRId64, __FUNCTION__, width, 191146d8444631b4b1253a76bfcc78a29d26014d022fDan Albert height, rowStride, pixStride, offset); 191247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 191347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sp<JniOutputStream> out = new JniOutputStream(env, outStream); 191446d8444631b4b1253a76bfcc78a29d26014d022fDan Albert if (env->ExceptionCheck()) { 191547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Could not allocate buffers for output stream", __FUNCTION__); 191647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 191747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 191847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 191947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk TiffWriter* writer = DngCreator_getCreator(env, thiz); 192047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk NativeContext* context = DngCreator_getNativeContext(env, thiz); 192147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (writer == NULL || context == NULL) { 192247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: Failed to initialize DngCreator", __FUNCTION__); 192347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowException(env, "java/lang/AssertionError", 192447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Write called with uninitialized DngCreator"); 192547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 192647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 192747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 192847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk // Validate DNG header 192947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!validateDngHeader(env, writer, width, height)) { 193047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 193147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 193247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 193347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sp<DirectStripSource> thumbnailSource; 193447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t targetIfd = TIFF_IFD_0; 193547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk bool hasThumbnail = writer->hasIfd(TIFF_IFD_SUB1); 193647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk Vector<StripSource*> sources; 193747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 193847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (hasThumbnail) { 193947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s: Adding thumbnail strip sources.", __FUNCTION__); 194047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t bytesPerPixel = SAMPLES_PER_RGB_PIXEL * BYTES_PER_RGB_SAMPLE; 194147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk uint32_t width = context->getThumbnailWidth(); 194247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk thumbnailSource = new DirectStripSource(env, context->getThumbnail(), TIFF_IFD_0, 194347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk width, context->getThumbnailHeight(), bytesPerPixel, 194447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk bytesPerPixel * width, /*offset*/0, BYTES_PER_RGB_SAMPLE, 194547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk SAMPLES_PER_RGB_PIXEL); 194647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sources.add(thumbnailSource.get()); 194747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk targetIfd = TIFF_IFD_SUB1; 194847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 194947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 195047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sp<JniInputStream> in = new JniInputStream(env, inStream); 195147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 195247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGV("%s: Using input-type strip source.", __FUNCTION__); 195347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk InputStripSource stripSource(env, *in, targetIfd, uWidth, uHeight, pixStride, 195447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk rowStride, uOffset, BYTES_PER_SAMPLE, SAMPLES_PER_RAW_PIXEL); 195547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk sources.add(&stripSource); 195647e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk 195747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk status_t ret = OK; 195847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if ((ret = writer->write(out.get(), sources.editArray(), sources.size())) != OK) { 195947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk ALOGE("%s: write failed with error %d.", __FUNCTION__, ret); 196047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk if (!env->ExceptionCheck()) { 196147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk jniThrowExceptionFmt(env, "java/io/IOException", 196247e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk "Encountered error %d while writing file.", ret); 196347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 196447e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk return; 196547e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk } 1966f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 1967f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1968f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} /*extern "C" */ 1969f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1970f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatic JNINativeMethod gDngCreatorMethods[] = { 1971f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk {"nativeClassInit", "()V", (void*) DngCreator_nativeClassInit}, 1972f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk {"nativeInit", "(Landroid/hardware/camera2/impl/CameraMetadataNative;" 1973b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk "Landroid/hardware/camera2/impl/CameraMetadataNative;Ljava/lang/String;)V", 1974b8df8e07d6fc530c82d21ca3199411e2e60975b1Ruben Brunk (void*) DngCreator_init}, 1975f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk {"nativeDestroy", "()V", (void*) DngCreator_destroy}, 1976f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk {"nativeSetOrientation", "(I)V", (void*) DngCreator_nativeSetOrientation}, 197747e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk {"nativeSetDescription", "(Ljava/lang/String;)V", (void*) DngCreator_nativeSetDescription}, 197847e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk {"nativeSetGpsTags", "([ILjava/lang/String;[ILjava/lang/String;Ljava/lang/String;[I)V", 197947e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk (void*) DngCreator_nativeSetGpsTags}, 198047e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk {"nativeSetThumbnail","(Ljava/nio/ByteBuffer;II)V", (void*) DngCreator_nativeSetThumbnail}, 198147e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk {"nativeWriteImage", "(Ljava/io/OutputStream;IILjava/nio/ByteBuffer;IIJZ)V", 1982f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk (void*) DngCreator_nativeWriteImage}, 198347e91f20952e5eb2290146ba6e33a694dd2e45e8Ruben Brunk {"nativeWriteInputStream", "(Ljava/io/OutputStream;Ljava/io/InputStream;IIJ)V", 1984f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk (void*) DngCreator_nativeWriteInputStream}, 1985f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk}; 1986f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk 1987b6079005ed0631c3972ff427f56e12523ec214a7Ruben Brunkint register_android_hardware_camera2_DngCreator(JNIEnv *env) { 1988f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk return AndroidRuntime::registerNativeMethods(env, 1989b6079005ed0631c3972ff427f56e12523ec214a7Ruben Brunk "android/hardware/camera2/DngCreator", gDngCreatorMethods, 1990b6079005ed0631c3972ff427f56e12523ec214a7Ruben Brunk NELEM(gDngCreatorMethods)); 1991f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} 1992