1e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk/* 2e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Copyright 2014 The Android Open Source Project 3e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * 4e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * you may not use this file except in compliance with the License. 6e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * You may obtain a copy of the License at 7e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * 8e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * 10e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Unless required by applicable law or agreed to in writing, software 11e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * See the License for the specific language governing permissions and 14e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * limitations under the License. 15e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk */ 16e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 174510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk#define LOG_TAG "TiffWriter" 184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 19e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <img_utils/TiffHelpers.h> 20e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <img_utils/TiffWriter.h> 21e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <img_utils/TagDefinitions.h> 22e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 23e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <assert.h> 24e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 25e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunknamespace android { 26e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunknamespace img_utils { 27e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 28e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkKeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::buildTagMap( 29e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk const TagDefinition_t* definitions, size_t length) { 30e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk KeyedVector<uint16_t, const TagDefinition_t*> map; 31e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk for(size_t i = 0; i < length; ++i) { 32e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk map.add(definitions[i].tagId, definitions + i); 33e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 34e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return map; 35e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 36e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 37e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#define COMPARE(op) \ 38e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkbool Orderable::operator op (const Orderable& orderable) const { \ 39e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return getComparableValue() op orderable.getComparableValue(); \ 40e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 41e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 42e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#define ARRAY_SIZE(array) \ 43e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk (sizeof(array) / sizeof(array[0])) 44e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 45e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkKeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::sTagMaps[] = { 46e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk buildTagMap(TIFF_EP_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_EP_TAG_DEFINITIONS)), 47e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk buildTagMap(DNG_TAG_DEFINITIONS, ARRAY_SIZE(DNG_TAG_DEFINITIONS)), 48e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk buildTagMap(EXIF_2_3_TAG_DEFINITIONS, ARRAY_SIZE(EXIF_2_3_TAG_DEFINITIONS)), 49e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk buildTagMap(TIFF_6_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_6_TAG_DEFINITIONS)) 50e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}; 51e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 52e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkTiffWriter::TiffWriter() : mTagMaps(sTagMaps), mNumTagMaps(DEFAULT_NUM_TAG_MAPS) {} 53e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 54e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkTiffWriter::TiffWriter(KeyedVector<uint16_t, const TagDefinition_t*>* enabledDefinitions, 55e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk size_t length) : mTagMaps(enabledDefinitions), mNumTagMaps(length) {} 56e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 57e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkTiffWriter::~TiffWriter() {} 58e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 594510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::write(Output* out, StripSource** sources, size_t sourcesCount, 604510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk Endianness end) { 614510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk status_t ret = OK; 624510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk EndianOutput endOut(out, end); 634510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 644510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (mIfd == NULL) { 654510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Tiff header is empty.", __FUNCTION__); 664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 674510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 694510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk uint32_t totalSize = getTotalSize(); 704510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 714510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk KeyedVector<uint32_t, uint32_t> offsetVector; 724510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 734510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk for (size_t i = 0; i < mNamedIfds.size(); ++i) { 744510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (mNamedIfds[i]->uninitializedOffsets()) { 754510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk uint32_t stripSize = mNamedIfds[i]->getStripSize(); 764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (mNamedIfds[i]->setStripOffset(totalSize) != OK) { 774510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Could not set strip offsets.", __FUNCTION__); 784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 794510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk totalSize += stripSize; 814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk WORD_ALIGN(totalSize); 824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk offsetVector.add(mNamedIfds.keyAt(i), totalSize); 834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk size_t offVecSize = offsetVector.size(); 874510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (offVecSize != sourcesCount) { 884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Mismatch between number of IFDs with uninitialized strips (%zu) and" 894510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk " sources (%zu).", __FUNCTION__, offVecSize, sourcesCount); 904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 934510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk BAIL_ON_FAIL(writeFileHeader(endOut), ret); 944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 954510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk uint32_t offset = FILE_HEADER_SIZE; 964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk sp<TiffIfd> ifd = mIfd; 974510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk while(ifd != NULL) { 984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret); 994510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk offset += ifd->getSize(); 1004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ifd = ifd->getNextIfd(); 1014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 103ca73159becc0fc0098530929e467a3d92e470571Ruben Brunk if (LOG_NDEBUG == 0) { 104ca73159becc0fc0098530929e467a3d92e470571Ruben Brunk log(); 105ca73159becc0fc0098530929e467a3d92e470571Ruben Brunk } 1064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 1074510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk for (size_t i = 0; i < offVecSize; ++i) { 1084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk uint32_t ifdKey = offsetVector.keyAt(i); 1094510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk uint32_t nextOffset = offsetVector[i]; 1104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk uint32_t sizeToWrite = mNamedIfds[ifdKey]->getStripSize(); 1114510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk bool found = false; 1124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk for (size_t j = 0; j < sourcesCount; ++j) { 1134510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (sources[j]->getIfd() == ifdKey) { 1144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if ((ret = sources[i]->writeToStream(endOut, sizeToWrite)) != OK) { 1154510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Could not write to stream, received %d.", __FUNCTION__, ret); 1164510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return ret; 1174510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ZERO_TILL_WORD(&endOut, sizeToWrite, ret); 1194510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk found = true; 1204510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk break; 1214510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1224510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1234510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (!found) { 1244510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: No stream for byte strips for IFD %u", __FUNCTION__, ifdKey); 1254510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 1264510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1274510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk assert(nextOffset == endOut.getCurrentOffset()); 1284510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1294510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 1304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return ret; 1314510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk} 1324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 133e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::write(Output* out, Endianness end) { 134e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk status_t ret = OK; 135e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk EndianOutput endOut(out, end); 136e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 137e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (mIfd == NULL) { 138e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: Tiff header is empty.", __FUNCTION__); 139e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return BAD_VALUE; 140e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 141e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk BAIL_ON_FAIL(writeFileHeader(endOut), ret); 142e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 143e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint32_t offset = FILE_HEADER_SIZE; 144e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> ifd = mIfd; 145e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk while(ifd != NULL) { 146e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret); 147e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk offset += ifd->getSize(); 148e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ifd = ifd->getNextIfd(); 149e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 150e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return ret; 151e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 152e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 153e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 154e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkconst TagDefinition_t* TiffWriter::lookupDefinition(uint16_t tag) const { 155e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk const TagDefinition_t* definition = NULL; 156e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk for (size_t i = 0; i < mNumTagMaps; ++i) { 157e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ssize_t index = mTagMaps[i].indexOfKey(tag); 158e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (index >= 0) { 159e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk definition = mTagMaps[i][index]; 160e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 161e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 162e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 163e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 164e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (definition == NULL) { 165e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: No definition exists for tag with id %x.", __FUNCTION__, tag); 166e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 167e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return definition; 168e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 169e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 170e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunksp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const { 171e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 172e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (index < 0) { 173e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd); 174e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return NULL; 175e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 176e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return mNamedIfds[index]->getEntry(tag); 177e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 178e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 1794510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkvoid TiffWriter::removeEntry(uint16_t tag, uint32_t ifd) { 1804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 1814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (index >= 0) { 1824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mNamedIfds[index]->removeEntry(tag); 1834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk} 185e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 1864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addEntry(const sp<TiffEntry>& entry, uint32_t ifd) { 187e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint16_t tag = entry->getTag(); 188e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 189e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk const TagDefinition_t* definition = lookupDefinition(tag); 190e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 191e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (definition == NULL) { 1924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: No definition exists for tag 0x%x.", __FUNCTION__, tag); 193e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return BAD_INDEX; 194e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 195e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 1964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 197e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 198e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Add a new IFD if necessary 199e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (index < 0) { 2004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: No IFD %u exists.", __FUNCTION__, ifd); 2014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return NAME_NOT_FOUND; 202e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 203e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 204e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> selectedIfd = mNamedIfds[index]; 205e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return selectedIfd->addEntry(entry); 206e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 207e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 2084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addStrip(uint32_t ifd) { 2094510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 2104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (index < 0) { 2114510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Ifd %u doesn't exist, cannot add strip entries.", __FUNCTION__, ifd); 2124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 213e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 2144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk sp<TiffIfd> selected = mNamedIfds[index]; 2154510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return selected->validateAndSetStripTags(); 216e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 217e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 218e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::addIfd(uint32_t ifd) { 219e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 220e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (index >= 0) { 221e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd); 222e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return BAD_VALUE; 223e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 2244510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 225e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> newIfd = new TiffIfd(ifd); 226e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (mIfd == NULL) { 227e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk mIfd = newIfd; 228e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } else { 229e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> last = findLastIfd(); 230e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk last->setNextIfd(newIfd); 231e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 2324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if(mNamedIfds.add(ifd, newIfd) < 0) { 2344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd); 2354510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2374510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2384510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return OK; 2394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk} 2404510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type) { 2424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 2434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (index >= 0) { 2444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd); 2454510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2474510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2484510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t parentIndex = mNamedIfds.indexOfKey(parentIfd); 2494510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (parentIndex < 0) { 2504510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Parent IFD with ID 0x%x does not exist.", __FUNCTION__, parentIfd); 2514510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2524510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2534510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2544510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk sp<TiffIfd> parent = mNamedIfds[parentIndex]; 2554510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk sp<TiffIfd> newIfd = new TiffIfd(ifd); 2564510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2574510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk uint16_t subIfdTag; 2584510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (type == SUBIFD) { 2594510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk subIfdTag = TAG_SUBIFDS; 2604510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else if (type == GPSINFO) { 2614510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk subIfdTag = TAG_GPSINFO; 2624510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else { 2634510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Unknown SubIFD type %d.", __FUNCTION__, type); 2644510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2654510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2674510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk sp<TiffEntry> subIfds = parent->getEntry(subIfdTag); 2684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (subIfds == NULL) { 2694510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (buildEntry(subIfdTag, 1, &newIfd, &subIfds) < 0) { 2704510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 2714510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2724510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2734510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else { 2744510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (type == GPSINFO) { 2754510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Cannot add GPSInfo SubIFD to IFD %u, one already exists.", __FUNCTION__, 2764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ifd); 2774510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2794510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk Vector<sp<TiffIfd> > subIfdList; 2814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk const sp<TiffIfd>* oldIfdArray = subIfds->getData<sp<TiffIfd> >(); 2824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (subIfdList.appendArray(oldIfdArray, subIfds->getCount()) < 0) { 2834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 2844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2874510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (subIfdList.add(newIfd) < 0) { 2884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 2894510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk uint32_t count = subIfdList.size(); 2934510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (buildEntry(subIfdTag, count, subIfdList.array(), &subIfds) < 0) { 2944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 2954510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2974510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2994510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (parent->addEntry(subIfds) < 0) { 3004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to add SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 3014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 3024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3034510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 3044510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if(mNamedIfds.add(ifd, newIfd) < 0) { 3054510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd); 3064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 3074510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 309e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return OK; 310e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 311e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 312e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkTagType TiffWriter::getDefaultType(uint16_t tag) const { 313e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk const TagDefinition_t* definition = lookupDefinition(tag); 314e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (definition == NULL) { 315e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag); 316e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return UNKNOWN_TAGTYPE; 317e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 318e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return definition->defaultType; 319e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 320e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 321e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkuint32_t TiffWriter::getDefaultCount(uint16_t tag) const { 322e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk const TagDefinition_t* definition = lookupDefinition(tag); 323e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (definition == NULL) { 324e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag); 325e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return 0; 326e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 327e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return definition->fixedCount; 328e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 329e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 3304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkbool TiffWriter::hasIfd(uint32_t ifd) const { 3314510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 3324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return index >= 0; 3334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk} 3344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 335e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkbool TiffWriter::checkIfDefined(uint16_t tag) const { 336e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return lookupDefinition(tag) != NULL; 337e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 338e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 3394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkconst char* TiffWriter::getTagName(uint16_t tag) const { 3404510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk const TagDefinition_t* definition = lookupDefinition(tag); 3414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (definition == NULL) { 3424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return NULL; 3434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return definition->tagName; 3454510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk} 3464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 347e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunksp<TiffIfd> TiffWriter::findLastIfd() { 348e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> ifd = mIfd; 349e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk while(ifd != NULL) { 350e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> nextIfd = ifd->getNextIfd(); 351e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (nextIfd == NULL) { 352e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 353e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 354e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ifd = nextIfd; 355e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 356e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return ifd; 357e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 358e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 359e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::writeFileHeader(EndianOutput& out) { 360e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk status_t ret = OK; 361e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint16_t endMarker = (out.getEndianness() == BIG) ? BIG_ENDIAN_MARKER : LITTLE_ENDIAN_MARKER; 362e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk BAIL_ON_FAIL(out.write(&endMarker, 0, 1), ret); 363e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 364e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint16_t tiffMarker = TIFF_FILE_MARKER; 365e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk BAIL_ON_FAIL(out.write(&tiffMarker, 0, 1), ret); 366e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 367e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint32_t offsetMarker = FILE_HEADER_SIZE; 368e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk BAIL_ON_FAIL(out.write(&offsetMarker, 0, 1), ret); 369e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return ret; 370e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 371e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 372e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkuint32_t TiffWriter::getTotalSize() const { 373e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint32_t totalSize = FILE_HEADER_SIZE; 374e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> ifd = mIfd; 375e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk while(ifd != NULL) { 376e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk totalSize += ifd->getSize(); 377e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ifd = ifd->getNextIfd(); 378e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 379e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return totalSize; 380e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 381e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 382e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkvoid TiffWriter::log() const { 383e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGI("%s: TiffWriter:", __FUNCTION__); 3844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk size_t length = mNamedIfds.size(); 3854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk for (size_t i = 0; i < length; ++i) { 3864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mNamedIfds[i]->log(); 387e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 388e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 389e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 390e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} /*namespace img_utils*/ 391e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} /*namespace android*/ 392