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 #define LOG_TAG "TiffWriter" 18 19 #include <img_utils/TiffHelpers.h> 20 #include <img_utils/TiffWriter.h> 21 #include <img_utils/TagDefinitions.h> 22 23 #include <assert.h> 24 25 namespace android { 26 namespace img_utils { 27 28 KeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::buildTagMap( 29 const TagDefinition_t* definitions, size_t length) { 30 KeyedVector<uint16_t, const TagDefinition_t*> map; 31 for(size_t i = 0; i < length; ++i) { 32 map.add(definitions[i].tagId, definitions + i); 33 } 34 return map; 35 } 36 37 #define COMPARE(op) \ 38 bool Orderable::operator op (const Orderable& orderable) const { \ 39 return getComparableValue() op orderable.getComparableValue(); \ 40 } 41 42 #define ARRAY_SIZE(array) \ 43 (sizeof(array) / sizeof(array[0])) 44 45 KeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::sTagMaps[] = { 46 buildTagMap(TIFF_EP_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_EP_TAG_DEFINITIONS)), 47 buildTagMap(DNG_TAG_DEFINITIONS, ARRAY_SIZE(DNG_TAG_DEFINITIONS)), 48 buildTagMap(EXIF_2_3_TAG_DEFINITIONS, ARRAY_SIZE(EXIF_2_3_TAG_DEFINITIONS)), 49 buildTagMap(TIFF_6_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_6_TAG_DEFINITIONS)) 50 }; 51 52 TiffWriter::TiffWriter() : mTagMaps(sTagMaps), mNumTagMaps(DEFAULT_NUM_TAG_MAPS) {} 53 54 TiffWriter::TiffWriter(KeyedVector<uint16_t, const TagDefinition_t*>* enabledDefinitions, 55 size_t length) : mTagMaps(enabledDefinitions), mNumTagMaps(length) {} 56 57 TiffWriter::~TiffWriter() {} 58 59 status_t TiffWriter::write(Output* out, StripSource** sources, size_t sourcesCount, 60 Endianness end) { 61 status_t ret = OK; 62 EndianOutput endOut(out, end); 63 64 if (mIfd == NULL) { 65 ALOGE("%s: Tiff header is empty.", __FUNCTION__); 66 return BAD_VALUE; 67 } 68 69 uint32_t totalSize = getTotalSize(); 70 71 KeyedVector<uint32_t, uint32_t> offsetVector; 72 73 for (size_t i = 0; i < mNamedIfds.size(); ++i) { 74 if (mNamedIfds[i]->uninitializedOffsets()) { 75 uint32_t stripSize = mNamedIfds[i]->getStripSize(); 76 if (mNamedIfds[i]->setStripOffset(totalSize) != OK) { 77 ALOGE("%s: Could not set strip offsets.", __FUNCTION__); 78 return BAD_VALUE; 79 } 80 totalSize += stripSize; 81 WORD_ALIGN(totalSize); 82 offsetVector.add(mNamedIfds.keyAt(i), totalSize); 83 } 84 } 85 86 size_t offVecSize = offsetVector.size(); 87 if (offVecSize != sourcesCount) { 88 ALOGE("%s: Mismatch between number of IFDs with uninitialized strips (%zu) and" 89 " sources (%zu).", __FUNCTION__, offVecSize, sourcesCount); 90 return BAD_VALUE; 91 } 92 93 BAIL_ON_FAIL(writeFileHeader(endOut), ret); 94 95 uint32_t offset = FILE_HEADER_SIZE; 96 sp<TiffIfd> ifd = mIfd; 97 while(ifd != NULL) { 98 BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret); 99 offset += ifd->getSize(); 100 ifd = ifd->getNextIfd(); 101 } 102 103 if (LOG_NDEBUG == 0) { 104 log(); 105 } 106 107 for (size_t i = 0; i < offVecSize; ++i) { 108 uint32_t ifdKey = offsetVector.keyAt(i); 109 uint32_t nextOffset = offsetVector[i]; 110 uint32_t sizeToWrite = mNamedIfds[ifdKey]->getStripSize(); 111 bool found = false; 112 for (size_t j = 0; j < sourcesCount; ++j) { 113 if (sources[j]->getIfd() == ifdKey) { 114 if ((ret = sources[i]->writeToStream(endOut, sizeToWrite)) != OK) { 115 ALOGE("%s: Could not write to stream, received %d.", __FUNCTION__, ret); 116 return ret; 117 } 118 ZERO_TILL_WORD(&endOut, sizeToWrite, ret); 119 found = true; 120 break; 121 } 122 } 123 if (!found) { 124 ALOGE("%s: No stream for byte strips for IFD %u", __FUNCTION__, ifdKey); 125 return BAD_VALUE; 126 } 127 assert(nextOffset == endOut.getCurrentOffset()); 128 } 129 130 return ret; 131 } 132 133 status_t TiffWriter::write(Output* out, Endianness end) { 134 status_t ret = OK; 135 EndianOutput endOut(out, end); 136 137 if (mIfd == NULL) { 138 ALOGE("%s: Tiff header is empty.", __FUNCTION__); 139 return BAD_VALUE; 140 } 141 BAIL_ON_FAIL(writeFileHeader(endOut), ret); 142 143 uint32_t offset = FILE_HEADER_SIZE; 144 sp<TiffIfd> ifd = mIfd; 145 while(ifd != NULL) { 146 BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret); 147 offset += ifd->getSize(); 148 ifd = ifd->getNextIfd(); 149 } 150 return ret; 151 } 152 153 154 const TagDefinition_t* TiffWriter::lookupDefinition(uint16_t tag) const { 155 const TagDefinition_t* definition = NULL; 156 for (size_t i = 0; i < mNumTagMaps; ++i) { 157 ssize_t index = mTagMaps[i].indexOfKey(tag); 158 if (index >= 0) { 159 definition = mTagMaps[i][index]; 160 break; 161 } 162 } 163 164 if (definition == NULL) { 165 ALOGE("%s: No definition exists for tag with id %x.", __FUNCTION__, tag); 166 } 167 return definition; 168 } 169 170 sp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const { 171 ssize_t index = mNamedIfds.indexOfKey(ifd); 172 if (index < 0) { 173 ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd); 174 return NULL; 175 } 176 return mNamedIfds[index]->getEntry(tag); 177 } 178 179 void TiffWriter::removeEntry(uint16_t tag, uint32_t ifd) { 180 ssize_t index = mNamedIfds.indexOfKey(ifd); 181 if (index >= 0) { 182 mNamedIfds[index]->removeEntry(tag); 183 } 184 } 185 186 status_t TiffWriter::addEntry(const sp<TiffEntry>& entry, uint32_t ifd) { 187 uint16_t tag = entry->getTag(); 188 189 const TagDefinition_t* definition = lookupDefinition(tag); 190 191 if (definition == NULL) { 192 ALOGE("%s: No definition exists for tag 0x%x.", __FUNCTION__, tag); 193 return BAD_INDEX; 194 } 195 196 ssize_t index = mNamedIfds.indexOfKey(ifd); 197 198 // Add a new IFD if necessary 199 if (index < 0) { 200 ALOGE("%s: No IFD %u exists.", __FUNCTION__, ifd); 201 return NAME_NOT_FOUND; 202 } 203 204 sp<TiffIfd> selectedIfd = mNamedIfds[index]; 205 return selectedIfd->addEntry(entry); 206 } 207 208 status_t TiffWriter::addStrip(uint32_t ifd) { 209 ssize_t index = mNamedIfds.indexOfKey(ifd); 210 if (index < 0) { 211 ALOGE("%s: Ifd %u doesn't exist, cannot add strip entries.", __FUNCTION__, ifd); 212 return BAD_VALUE; 213 } 214 sp<TiffIfd> selected = mNamedIfds[index]; 215 return selected->validateAndSetStripTags(); 216 } 217 218 status_t TiffWriter::addIfd(uint32_t ifd) { 219 ssize_t index = mNamedIfds.indexOfKey(ifd); 220 if (index >= 0) { 221 ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd); 222 return BAD_VALUE; 223 } 224 225 sp<TiffIfd> newIfd = new TiffIfd(ifd); 226 if (mIfd == NULL) { 227 mIfd = newIfd; 228 } else { 229 sp<TiffIfd> last = findLastIfd(); 230 last->setNextIfd(newIfd); 231 } 232 233 if(mNamedIfds.add(ifd, newIfd) < 0) { 234 ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd); 235 return BAD_VALUE; 236 } 237 238 return OK; 239 } 240 241 status_t TiffWriter::addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type) { 242 ssize_t index = mNamedIfds.indexOfKey(ifd); 243 if (index >= 0) { 244 ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd); 245 return BAD_VALUE; 246 } 247 248 ssize_t parentIndex = mNamedIfds.indexOfKey(parentIfd); 249 if (parentIndex < 0) { 250 ALOGE("%s: Parent IFD with ID 0x%x does not exist.", __FUNCTION__, parentIfd); 251 return BAD_VALUE; 252 } 253 254 sp<TiffIfd> parent = mNamedIfds[parentIndex]; 255 sp<TiffIfd> newIfd = new TiffIfd(ifd); 256 257 uint16_t subIfdTag; 258 if (type == SUBIFD) { 259 subIfdTag = TAG_SUBIFDS; 260 } else if (type == GPSINFO) { 261 subIfdTag = TAG_GPSINFO; 262 } else { 263 ALOGE("%s: Unknown SubIFD type %d.", __FUNCTION__, type); 264 return BAD_VALUE; 265 } 266 267 sp<TiffEntry> subIfds = parent->getEntry(subIfdTag); 268 if (subIfds == NULL) { 269 if (buildEntry(subIfdTag, 1, &newIfd, &subIfds) < 0) { 270 ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 271 return BAD_VALUE; 272 } 273 } else { 274 if (type == GPSINFO) { 275 ALOGE("%s: Cannot add GPSInfo SubIFD to IFD %u, one already exists.", __FUNCTION__, 276 ifd); 277 return BAD_VALUE; 278 } 279 280 Vector<sp<TiffIfd> > subIfdList; 281 const sp<TiffIfd>* oldIfdArray = subIfds->getData<sp<TiffIfd> >(); 282 if (subIfdList.appendArray(oldIfdArray, subIfds->getCount()) < 0) { 283 ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 284 return BAD_VALUE; 285 } 286 287 if (subIfdList.add(newIfd) < 0) { 288 ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 289 return BAD_VALUE; 290 } 291 292 uint32_t count = subIfdList.size(); 293 if (buildEntry(subIfdTag, count, subIfdList.array(), &subIfds) < 0) { 294 ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 295 return BAD_VALUE; 296 } 297 } 298 299 if (parent->addEntry(subIfds) < 0) { 300 ALOGE("%s: Failed to add SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 301 return BAD_VALUE; 302 } 303 304 if(mNamedIfds.add(ifd, newIfd) < 0) { 305 ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd); 306 return BAD_VALUE; 307 } 308 309 return OK; 310 } 311 312 TagType TiffWriter::getDefaultType(uint16_t tag) const { 313 const TagDefinition_t* definition = lookupDefinition(tag); 314 if (definition == NULL) { 315 ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag); 316 return UNKNOWN_TAGTYPE; 317 } 318 return definition->defaultType; 319 } 320 321 uint32_t TiffWriter::getDefaultCount(uint16_t tag) const { 322 const TagDefinition_t* definition = lookupDefinition(tag); 323 if (definition == NULL) { 324 ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag); 325 return 0; 326 } 327 return definition->fixedCount; 328 } 329 330 bool TiffWriter::hasIfd(uint32_t ifd) const { 331 ssize_t index = mNamedIfds.indexOfKey(ifd); 332 return index >= 0; 333 } 334 335 bool TiffWriter::checkIfDefined(uint16_t tag) const { 336 return lookupDefinition(tag) != NULL; 337 } 338 339 const char* TiffWriter::getTagName(uint16_t tag) const { 340 const TagDefinition_t* definition = lookupDefinition(tag); 341 if (definition == NULL) { 342 return NULL; 343 } 344 return definition->tagName; 345 } 346 347 sp<TiffIfd> TiffWriter::findLastIfd() { 348 sp<TiffIfd> ifd = mIfd; 349 while(ifd != NULL) { 350 sp<TiffIfd> nextIfd = ifd->getNextIfd(); 351 if (nextIfd == NULL) { 352 break; 353 } 354 ifd = nextIfd; 355 } 356 return ifd; 357 } 358 359 status_t TiffWriter::writeFileHeader(EndianOutput& out) { 360 status_t ret = OK; 361 uint16_t endMarker = (out.getEndianness() == BIG) ? BIG_ENDIAN_MARKER : LITTLE_ENDIAN_MARKER; 362 BAIL_ON_FAIL(out.write(&endMarker, 0, 1), ret); 363 364 uint16_t tiffMarker = TIFF_FILE_MARKER; 365 BAIL_ON_FAIL(out.write(&tiffMarker, 0, 1), ret); 366 367 uint32_t offsetMarker = FILE_HEADER_SIZE; 368 BAIL_ON_FAIL(out.write(&offsetMarker, 0, 1), ret); 369 return ret; 370 } 371 372 uint32_t TiffWriter::getTotalSize() const { 373 uint32_t totalSize = FILE_HEADER_SIZE; 374 sp<TiffIfd> ifd = mIfd; 375 while(ifd != NULL) { 376 totalSize += ifd->getSize(); 377 ifd = ifd->getNextIfd(); 378 } 379 return totalSize; 380 } 381 382 void TiffWriter::log() const { 383 ALOGI("%s: TiffWriter:", __FUNCTION__); 384 size_t length = mNamedIfds.size(); 385 for (size_t i = 0; i < length; ++i) { 386 mNamedIfds[i]->log(); 387 } 388 } 389 390 } /*namespace img_utils*/ 391 } /*namespace android*/ 392