TiffWriter.cpp revision e507721000647a7d8afe44c63ef7fd04ef8971b1
1/* 2 * Copyright 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <img_utils/TiffIfd.h> 18#include <img_utils/TiffHelpers.h> 19#include <img_utils/TiffWriter.h> 20#include <img_utils/TagDefinitions.h> 21 22#include <assert.h> 23 24namespace android { 25namespace img_utils { 26 27KeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::buildTagMap( 28 const TagDefinition_t* definitions, size_t length) { 29 KeyedVector<uint16_t, const TagDefinition_t*> map; 30 for(size_t i = 0; i < length; ++i) { 31 map.add(definitions[i].tagId, definitions + i); 32 } 33 return map; 34} 35 36#define COMPARE(op) \ 37bool Orderable::operator op (const Orderable& orderable) const { \ 38 return getComparableValue() op orderable.getComparableValue(); \ 39} 40 41#define ARRAY_SIZE(array) \ 42 (sizeof(array) / sizeof(array[0])) 43 44KeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::sTagMaps[] = { 45 buildTagMap(TIFF_EP_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_EP_TAG_DEFINITIONS)), 46 buildTagMap(DNG_TAG_DEFINITIONS, ARRAY_SIZE(DNG_TAG_DEFINITIONS)), 47 buildTagMap(EXIF_2_3_TAG_DEFINITIONS, ARRAY_SIZE(EXIF_2_3_TAG_DEFINITIONS)), 48 buildTagMap(TIFF_6_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_6_TAG_DEFINITIONS)) 49}; 50 51TiffWriter::TiffWriter() : mTagMaps(sTagMaps), mNumTagMaps(DEFAULT_NUM_TAG_MAPS) {} 52 53TiffWriter::TiffWriter(KeyedVector<uint16_t, const TagDefinition_t*>* enabledDefinitions, 54 size_t length) : mTagMaps(enabledDefinitions), mNumTagMaps(length) {} 55 56TiffWriter::~TiffWriter() {} 57 58status_t TiffWriter::write(Output* out, Endianness end) { 59 status_t ret = OK; 60 EndianOutput endOut(out, end); 61 62 if (mIfd == NULL) { 63 ALOGE("%s: Tiff header is empty.", __FUNCTION__); 64 return BAD_VALUE; 65 } 66 BAIL_ON_FAIL(writeFileHeader(endOut), ret); 67 68 uint32_t offset = FILE_HEADER_SIZE; 69 sp<TiffIfd> ifd = mIfd; 70 while(ifd != NULL) { 71 BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret); 72 offset += ifd->getSize(); 73 ifd = ifd->getNextIfd(); 74 } 75 return ret; 76} 77 78 79const TagDefinition_t* TiffWriter::lookupDefinition(uint16_t tag) const { 80 const TagDefinition_t* definition = NULL; 81 for (size_t i = 0; i < mNumTagMaps; ++i) { 82 ssize_t index = mTagMaps[i].indexOfKey(tag); 83 if (index >= 0) { 84 definition = mTagMaps[i][index]; 85 break; 86 } 87 } 88 89 if (definition == NULL) { 90 ALOGE("%s: No definition exists for tag with id %x.", __FUNCTION__, tag); 91 } 92 return definition; 93} 94 95sp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const { 96 ssize_t index = mNamedIfds.indexOfKey(ifd); 97 if (index < 0) { 98 ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd); 99 return NULL; 100 } 101 return mNamedIfds[index]->getEntry(tag); 102} 103 104 105// TODO: Fix this to handle IFD position in chain/sub-IFD tree 106status_t TiffWriter::addEntry(const sp<TiffEntry>& entry) { 107 uint16_t tag = entry->getTag(); 108 109 const TagDefinition_t* definition = lookupDefinition(tag); 110 111 if (definition == NULL) { 112 return BAD_INDEX; 113 } 114 uint32_t ifdId = 0; // TODO: all in IFD0 for now. 115 116 ssize_t index = mNamedIfds.indexOfKey(ifdId); 117 118 // Add a new IFD if necessary 119 if (index < 0) { 120 sp<TiffIfd> ifdEntry = new TiffIfd(ifdId); 121 if (mIfd == NULL) { 122 mIfd = ifdEntry; 123 } 124 index = mNamedIfds.add(ifdId, ifdEntry); 125 assert(index >= 0); 126 } 127 128 sp<TiffIfd> selectedIfd = mNamedIfds[index]; 129 return selectedIfd->addEntry(entry); 130} 131 132status_t TiffWriter::uncheckedAddIfd(const sp<TiffIfd>& ifd) { 133 mNamedIfds.add(ifd->getId(), ifd); 134 sp<TiffIfd> last = findLastIfd(); 135 if (last == NULL) { 136 mIfd = ifd; 137 } else { 138 last->setNextIfd(ifd); 139 } 140 last = ifd->getNextIfd(); 141 while (last != NULL) { 142 mNamedIfds.add(last->getId(), last); 143 last = last->getNextIfd(); 144 } 145 return OK; 146} 147 148status_t TiffWriter::addIfd(uint32_t ifd) { 149 ssize_t index = mNamedIfds.indexOfKey(ifd); 150 if (index >= 0) { 151 ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd); 152 return BAD_VALUE; 153 } 154 sp<TiffIfd> newIfd = new TiffIfd(ifd); 155 if (mIfd == NULL) { 156 mIfd = newIfd; 157 } else { 158 sp<TiffIfd> last = findLastIfd(); 159 last->setNextIfd(newIfd); 160 } 161 mNamedIfds.add(ifd, newIfd); 162 return OK; 163} 164 165TagType TiffWriter::getDefaultType(uint16_t tag) const { 166 const TagDefinition_t* definition = lookupDefinition(tag); 167 if (definition == NULL) { 168 ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag); 169 return UNKNOWN_TAGTYPE; 170 } 171 return definition->defaultType; 172} 173 174uint32_t TiffWriter::getDefaultCount(uint16_t tag) const { 175 const TagDefinition_t* definition = lookupDefinition(tag); 176 if (definition == NULL) { 177 ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag); 178 return 0; 179 } 180 return definition->fixedCount; 181} 182 183bool TiffWriter::checkIfDefined(uint16_t tag) const { 184 return lookupDefinition(tag) != NULL; 185} 186 187sp<TiffIfd> TiffWriter::findLastIfd() { 188 sp<TiffIfd> ifd = mIfd; 189 while(ifd != NULL) { 190 sp<TiffIfd> nextIfd = ifd->getNextIfd(); 191 if (nextIfd == NULL) { 192 break; 193 } 194 ifd = nextIfd; 195 } 196 return ifd; 197} 198 199status_t TiffWriter::writeFileHeader(EndianOutput& out) { 200 status_t ret = OK; 201 uint16_t endMarker = (out.getEndianness() == BIG) ? BIG_ENDIAN_MARKER : LITTLE_ENDIAN_MARKER; 202 BAIL_ON_FAIL(out.write(&endMarker, 0, 1), ret); 203 204 uint16_t tiffMarker = TIFF_FILE_MARKER; 205 BAIL_ON_FAIL(out.write(&tiffMarker, 0, 1), ret); 206 207 uint32_t offsetMarker = FILE_HEADER_SIZE; 208 BAIL_ON_FAIL(out.write(&offsetMarker, 0, 1), ret); 209 return ret; 210} 211 212uint32_t TiffWriter::getTotalSize() const { 213 uint32_t totalSize = FILE_HEADER_SIZE; 214 sp<TiffIfd> ifd = mIfd; 215 while(ifd != NULL) { 216 totalSize += ifd->getSize(); 217 ifd = ifd->getNextIfd(); 218 } 219 return totalSize; 220} 221 222void TiffWriter::log() const { 223 ALOGI("%s: TiffWriter:", __FUNCTION__); 224 sp<TiffIfd> ifd = mIfd; 225 while(ifd != NULL) { 226 ifd->log(); 227 ifd = ifd->getNextIfd(); 228 } 229} 230 231} /*namespace img_utils*/ 232} /*namespace android*/ 233