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 sizeToWrite = mNamedIfds[ifdKey]->getStripSize(); 1104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk bool found = false; 1114510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk for (size_t j = 0; j < sourcesCount; ++j) { 1124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (sources[j]->getIfd() == ifdKey) { 1134510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if ((ret = sources[i]->writeToStream(endOut, sizeToWrite)) != OK) { 1144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Could not write to stream, received %d.", __FUNCTION__, ret); 1154510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return ret; 1164510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1174510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ZERO_TILL_WORD(&endOut, sizeToWrite, ret); 1184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk found = true; 1194510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk break; 1204510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1214510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1224510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (!found) { 1234510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: No stream for byte strips for IFD %u", __FUNCTION__, ifdKey); 1244510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 1254510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1266c955eb0b4777eeade077f99bfa50e462906819aBernhard Rosenkränzer assert(offsetVector[i] == endOut.getCurrentOffset()); 1274510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1284510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 1294510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return ret; 1304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk} 1314510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 132e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::write(Output* out, Endianness end) { 133e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk status_t ret = OK; 134e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk EndianOutput endOut(out, end); 135e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 136e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (mIfd == NULL) { 137e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: Tiff header is empty.", __FUNCTION__); 138e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return BAD_VALUE; 139e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 140e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk BAIL_ON_FAIL(writeFileHeader(endOut), ret); 141e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 142e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint32_t offset = FILE_HEADER_SIZE; 143e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> ifd = mIfd; 144e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk while(ifd != NULL) { 145e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret); 146e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk offset += ifd->getSize(); 147e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ifd = ifd->getNextIfd(); 148e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 149e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return ret; 150e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 151e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 152e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 153e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkconst TagDefinition_t* TiffWriter::lookupDefinition(uint16_t tag) const { 154e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk const TagDefinition_t* definition = NULL; 155e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk for (size_t i = 0; i < mNumTagMaps; ++i) { 156e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ssize_t index = mTagMaps[i].indexOfKey(tag); 157e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (index >= 0) { 158e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk definition = mTagMaps[i][index]; 159e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 160e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 161e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 162e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 163e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (definition == NULL) { 164e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: No definition exists for tag with id %x.", __FUNCTION__, tag); 165e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 166e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return definition; 167e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 168e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 169e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunksp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const { 170e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 171e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (index < 0) { 172e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd); 173e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return NULL; 174e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 175e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return mNamedIfds[index]->getEntry(tag); 176e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 177e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 1784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkvoid TiffWriter::removeEntry(uint16_t tag, uint32_t ifd) { 1794510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 1804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (index >= 0) { 1814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mNamedIfds[index]->removeEntry(tag); 1824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 1834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk} 184e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 1854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addEntry(const sp<TiffEntry>& entry, uint32_t ifd) { 186e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint16_t tag = entry->getTag(); 187e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 188e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk const TagDefinition_t* definition = lookupDefinition(tag); 189e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 190e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (definition == NULL) { 1914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: No definition exists for tag 0x%x.", __FUNCTION__, tag); 192e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return BAD_INDEX; 193e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 194e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 1954510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 196e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 197e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk // Add a new IFD if necessary 198e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (index < 0) { 1994510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: No IFD %u exists.", __FUNCTION__, ifd); 2004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return NAME_NOT_FOUND; 201e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 202e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 203e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> selectedIfd = mNamedIfds[index]; 204e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return selectedIfd->addEntry(entry); 205e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 206e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 2074510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addStrip(uint32_t ifd) { 2084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 2094510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (index < 0) { 2104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Ifd %u doesn't exist, cannot add strip entries.", __FUNCTION__, ifd); 2114510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 212e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 2134510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk sp<TiffIfd> selected = mNamedIfds[index]; 2144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return selected->validateAndSetStripTags(); 215e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 216e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 217e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::addIfd(uint32_t ifd) { 218e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 219e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (index >= 0) { 220e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd); 221e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return BAD_VALUE; 222e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 2234510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 224e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> newIfd = new TiffIfd(ifd); 225e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (mIfd == NULL) { 226e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk mIfd = newIfd; 227e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } else { 228e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> last = findLastIfd(); 229e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk last->setNextIfd(newIfd); 230e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 2314510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if(mNamedIfds.add(ifd, newIfd) < 0) { 2334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd); 2344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2354510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2374510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return OK; 2384510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk} 2394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2404510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type) { 2414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 2424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (index >= 0) { 2434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd); 2444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2454510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2474510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t parentIndex = mNamedIfds.indexOfKey(parentIfd); 2484510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (parentIndex < 0) { 2494510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Parent IFD with ID 0x%x does not exist.", __FUNCTION__, parentIfd); 2504510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2514510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2524510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2534510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk sp<TiffIfd> parent = mNamedIfds[parentIndex]; 2544510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk sp<TiffIfd> newIfd = new TiffIfd(ifd); 2554510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2564510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk uint16_t subIfdTag; 2574510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (type == SUBIFD) { 2584510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk subIfdTag = TAG_SUBIFDS; 2594510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else if (type == GPSINFO) { 2604510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk subIfdTag = TAG_GPSINFO; 2614510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else { 2624510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Unknown SubIFD type %d.", __FUNCTION__, type); 2634510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2644510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2654510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk sp<TiffEntry> subIfds = parent->getEntry(subIfdTag); 2674510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (subIfds == NULL) { 2684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (buildEntry(subIfdTag, 1, &newIfd, &subIfds) < 0) { 2694510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 2704510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2714510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2724510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } else { 2734510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (type == GPSINFO) { 2744510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Cannot add GPSInfo SubIFD to IFD %u, one already exists.", __FUNCTION__, 2754510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ifd); 2764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2774510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2794510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk Vector<sp<TiffIfd> > subIfdList; 2804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk const sp<TiffIfd>* oldIfdArray = subIfds->getData<sp<TiffIfd> >(); 2814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (subIfdList.appendArray(oldIfdArray, subIfds->getCount()) < 0) { 2824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 2834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (subIfdList.add(newIfd) < 0) { 2874510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 2884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2894510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk uint32_t count = subIfdList.size(); 2924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (buildEntry(subIfdTag, count, subIfdList.array(), &subIfds) < 0) { 2934510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 2944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 2954510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 2974510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 2984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (parent->addEntry(subIfds) < 0) { 2994510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to add SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 3004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 3014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 3034510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if(mNamedIfds.add(ifd, newIfd) < 0) { 3044510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd); 3054510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return BAD_VALUE; 3064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3074510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 308e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return OK; 309e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 310e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 311e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkTagType TiffWriter::getDefaultType(uint16_t tag) const { 312e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk const TagDefinition_t* definition = lookupDefinition(tag); 313e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (definition == NULL) { 314e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag); 315e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return UNKNOWN_TAGTYPE; 316e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 317e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return definition->defaultType; 318e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 319e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 320e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkuint32_t TiffWriter::getDefaultCount(uint16_t tag) const { 321e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk const TagDefinition_t* definition = lookupDefinition(tag); 322e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (definition == NULL) { 323e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag); 324e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return 0; 325e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 326e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return definition->fixedCount; 327e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 328e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 3294510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkbool TiffWriter::hasIfd(uint32_t ifd) const { 3304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk ssize_t index = mNamedIfds.indexOfKey(ifd); 3314510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return index >= 0; 3324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk} 3334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 334e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkbool TiffWriter::checkIfDefined(uint16_t tag) const { 335e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return lookupDefinition(tag) != NULL; 336e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 337e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 3384510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkconst char* TiffWriter::getTagName(uint16_t tag) const { 3394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk const TagDefinition_t* definition = lookupDefinition(tag); 3404510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk if (definition == NULL) { 3414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return NULL; 3424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk } 3434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk return definition->tagName; 3444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk} 3454510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk 346e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunksp<TiffIfd> TiffWriter::findLastIfd() { 347e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> ifd = mIfd; 348e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk while(ifd != NULL) { 349e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> nextIfd = ifd->getNextIfd(); 350e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk if (nextIfd == NULL) { 351e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk break; 352e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 353e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ifd = nextIfd; 354e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 355e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return ifd; 356e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 357e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 358e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::writeFileHeader(EndianOutput& out) { 359e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk status_t ret = OK; 360e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint16_t endMarker = (out.getEndianness() == BIG) ? BIG_ENDIAN_MARKER : LITTLE_ENDIAN_MARKER; 361e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk BAIL_ON_FAIL(out.write(&endMarker, 0, 1), ret); 362e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 363e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint16_t tiffMarker = TIFF_FILE_MARKER; 364e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk BAIL_ON_FAIL(out.write(&tiffMarker, 0, 1), ret); 365e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 366e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint32_t offsetMarker = FILE_HEADER_SIZE; 367e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk BAIL_ON_FAIL(out.write(&offsetMarker, 0, 1), ret); 368e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return ret; 369e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 370e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 371e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkuint32_t TiffWriter::getTotalSize() const { 372e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk uint32_t totalSize = FILE_HEADER_SIZE; 373e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk sp<TiffIfd> ifd = mIfd; 374e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk while(ifd != NULL) { 375e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk totalSize += ifd->getSize(); 376e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ifd = ifd->getNextIfd(); 377e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 378e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk return totalSize; 379e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 380e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 381e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkvoid TiffWriter::log() const { 382e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk ALOGI("%s: TiffWriter:", __FUNCTION__); 3834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk size_t length = mNamedIfds.size(); 3844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk for (size_t i = 0; i < length; ++i) { 3854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk mNamedIfds[i]->log(); 386e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk } 387e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} 388e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk 389e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} /*namespace img_utils*/ 390e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} /*namespace android*/ 391