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 sizeToWrite = mNamedIfds[ifdKey]->getStripSize(); 110 bool found = false; 111 for (size_t j = 0; j < sourcesCount; ++j) { 112 if (sources[j]->getIfd() == ifdKey) { 113 if ((ret = sources[i]->writeToStream(endOut, sizeToWrite)) != OK) { 114 ALOGE("%s: Could not write to stream, received %d.", __FUNCTION__, ret); 115 return ret; 116 } 117 ZERO_TILL_WORD(&endOut, sizeToWrite, ret); 118 found = true; 119 break; 120 } 121 } 122 if (!found) { 123 ALOGE("%s: No stream for byte strips for IFD %u", __FUNCTION__, ifdKey); 124 return BAD_VALUE; 125 } 126 assert(offsetVector[i] == endOut.getCurrentOffset()); 127 } 128 129 return ret; 130 } 131 132 status_t TiffWriter::write(Output* out, Endianness end) { 133 status_t ret = OK; 134 EndianOutput endOut(out, end); 135 136 if (mIfd == NULL) { 137 ALOGE("%s: Tiff header is empty.", __FUNCTION__); 138 return BAD_VALUE; 139 } 140 BAIL_ON_FAIL(writeFileHeader(endOut), ret); 141 142 uint32_t offset = FILE_HEADER_SIZE; 143 sp<TiffIfd> ifd = mIfd; 144 while(ifd != NULL) { 145 BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret); 146 offset += ifd->getSize(); 147 ifd = ifd->getNextIfd(); 148 } 149 return ret; 150 } 151 152 153 const TagDefinition_t* TiffWriter::lookupDefinition(uint16_t tag) const { 154 const TagDefinition_t* definition = NULL; 155 for (size_t i = 0; i < mNumTagMaps; ++i) { 156 ssize_t index = mTagMaps[i].indexOfKey(tag); 157 if (index >= 0) { 158 definition = mTagMaps[i][index]; 159 break; 160 } 161 } 162 163 if (definition == NULL) { 164 ALOGE("%s: No definition exists for tag with id %x.", __FUNCTION__, tag); 165 } 166 return definition; 167 } 168 169 sp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const { 170 ssize_t index = mNamedIfds.indexOfKey(ifd); 171 if (index < 0) { 172 ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd); 173 return NULL; 174 } 175 return mNamedIfds[index]->getEntry(tag); 176 } 177 178 void TiffWriter::removeEntry(uint16_t tag, uint32_t ifd) { 179 ssize_t index = mNamedIfds.indexOfKey(ifd); 180 if (index >= 0) { 181 mNamedIfds[index]->removeEntry(tag); 182 } 183 } 184 185 status_t TiffWriter::addEntry(const sp<TiffEntry>& entry, uint32_t ifd) { 186 uint16_t tag = entry->getTag(); 187 188 const TagDefinition_t* definition = lookupDefinition(tag); 189 190 if (definition == NULL) { 191 ALOGE("%s: No definition exists for tag 0x%x.", __FUNCTION__, tag); 192 return BAD_INDEX; 193 } 194 195 ssize_t index = mNamedIfds.indexOfKey(ifd); 196 197 // Add a new IFD if necessary 198 if (index < 0) { 199 ALOGE("%s: No IFD %u exists.", __FUNCTION__, ifd); 200 return NAME_NOT_FOUND; 201 } 202 203 sp<TiffIfd> selectedIfd = mNamedIfds[index]; 204 return selectedIfd->addEntry(entry); 205 } 206 207 status_t TiffWriter::addStrip(uint32_t ifd) { 208 ssize_t index = mNamedIfds.indexOfKey(ifd); 209 if (index < 0) { 210 ALOGE("%s: Ifd %u doesn't exist, cannot add strip entries.", __FUNCTION__, ifd); 211 return BAD_VALUE; 212 } 213 sp<TiffIfd> selected = mNamedIfds[index]; 214 return selected->validateAndSetStripTags(); 215 } 216 217 status_t TiffWriter::addIfd(uint32_t ifd) { 218 ssize_t index = mNamedIfds.indexOfKey(ifd); 219 if (index >= 0) { 220 ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd); 221 return BAD_VALUE; 222 } 223 224 sp<TiffIfd> newIfd = new TiffIfd(ifd); 225 if (mIfd == NULL) { 226 mIfd = newIfd; 227 } else { 228 sp<TiffIfd> last = findLastIfd(); 229 last->setNextIfd(newIfd); 230 } 231 232 if(mNamedIfds.add(ifd, newIfd) < 0) { 233 ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd); 234 return BAD_VALUE; 235 } 236 237 return OK; 238 } 239 240 status_t TiffWriter::addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type) { 241 ssize_t index = mNamedIfds.indexOfKey(ifd); 242 if (index >= 0) { 243 ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd); 244 return BAD_VALUE; 245 } 246 247 ssize_t parentIndex = mNamedIfds.indexOfKey(parentIfd); 248 if (parentIndex < 0) { 249 ALOGE("%s: Parent IFD with ID 0x%x does not exist.", __FUNCTION__, parentIfd); 250 return BAD_VALUE; 251 } 252 253 sp<TiffIfd> parent = mNamedIfds[parentIndex]; 254 sp<TiffIfd> newIfd = new TiffIfd(ifd); 255 256 uint16_t subIfdTag; 257 if (type == SUBIFD) { 258 subIfdTag = TAG_SUBIFDS; 259 } else if (type == GPSINFO) { 260 subIfdTag = TAG_GPSINFO; 261 } else { 262 ALOGE("%s: Unknown SubIFD type %d.", __FUNCTION__, type); 263 return BAD_VALUE; 264 } 265 266 sp<TiffEntry> subIfds = parent->getEntry(subIfdTag); 267 if (subIfds == NULL) { 268 if (buildEntry(subIfdTag, 1, &newIfd, &subIfds) < 0) { 269 ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 270 return BAD_VALUE; 271 } 272 } else { 273 if (type == GPSINFO) { 274 ALOGE("%s: Cannot add GPSInfo SubIFD to IFD %u, one already exists.", __FUNCTION__, 275 ifd); 276 return BAD_VALUE; 277 } 278 279 Vector<sp<TiffIfd> > subIfdList; 280 const sp<TiffIfd>* oldIfdArray = subIfds->getData<sp<TiffIfd> >(); 281 if (subIfdList.appendArray(oldIfdArray, subIfds->getCount()) < 0) { 282 ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 283 return BAD_VALUE; 284 } 285 286 if (subIfdList.add(newIfd) < 0) { 287 ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 288 return BAD_VALUE; 289 } 290 291 uint32_t count = subIfdList.size(); 292 if (buildEntry(subIfdTag, count, subIfdList.array(), &subIfds) < 0) { 293 ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 294 return BAD_VALUE; 295 } 296 } 297 298 if (parent->addEntry(subIfds) < 0) { 299 ALOGE("%s: Failed to add SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd); 300 return BAD_VALUE; 301 } 302 303 if(mNamedIfds.add(ifd, newIfd) < 0) { 304 ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd); 305 return BAD_VALUE; 306 } 307 308 return OK; 309 } 310 311 TagType TiffWriter::getDefaultType(uint16_t tag) const { 312 const TagDefinition_t* definition = lookupDefinition(tag); 313 if (definition == NULL) { 314 ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag); 315 return UNKNOWN_TAGTYPE; 316 } 317 return definition->defaultType; 318 } 319 320 uint32_t TiffWriter::getDefaultCount(uint16_t tag) const { 321 const TagDefinition_t* definition = lookupDefinition(tag); 322 if (definition == NULL) { 323 ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag); 324 return 0; 325 } 326 return definition->fixedCount; 327 } 328 329 bool TiffWriter::hasIfd(uint32_t ifd) const { 330 ssize_t index = mNamedIfds.indexOfKey(ifd); 331 return index >= 0; 332 } 333 334 bool TiffWriter::checkIfDefined(uint16_t tag) const { 335 return lookupDefinition(tag) != NULL; 336 } 337 338 const char* TiffWriter::getTagName(uint16_t tag) const { 339 const TagDefinition_t* definition = lookupDefinition(tag); 340 if (definition == NULL) { 341 return NULL; 342 } 343 return definition->tagName; 344 } 345 346 sp<TiffIfd> TiffWriter::findLastIfd() { 347 sp<TiffIfd> ifd = mIfd; 348 while(ifd != NULL) { 349 sp<TiffIfd> nextIfd = ifd->getNextIfd(); 350 if (nextIfd == NULL) { 351 break; 352 } 353 ifd = nextIfd; 354 } 355 return ifd; 356 } 357 358 status_t TiffWriter::writeFileHeader(EndianOutput& out) { 359 status_t ret = OK; 360 uint16_t endMarker = (out.getEndianness() == BIG) ? BIG_ENDIAN_MARKER : LITTLE_ENDIAN_MARKER; 361 BAIL_ON_FAIL(out.write(&endMarker, 0, 1), ret); 362 363 uint16_t tiffMarker = TIFF_FILE_MARKER; 364 BAIL_ON_FAIL(out.write(&tiffMarker, 0, 1), ret); 365 366 uint32_t offsetMarker = FILE_HEADER_SIZE; 367 BAIL_ON_FAIL(out.write(&offsetMarker, 0, 1), ret); 368 return ret; 369 } 370 371 uint32_t TiffWriter::getTotalSize() const { 372 uint32_t totalSize = FILE_HEADER_SIZE; 373 sp<TiffIfd> ifd = mIfd; 374 while(ifd != NULL) { 375 totalSize += ifd->getSize(); 376 ifd = ifd->getNextIfd(); 377 } 378 return totalSize; 379 } 380 381 void TiffWriter::log() const { 382 ALOGI("%s: TiffWriter:", __FUNCTION__); 383 size_t length = mNamedIfds.size(); 384 for (size_t i = 0; i < length; ++i) { 385 mNamedIfds[i]->log(); 386 } 387 } 388 389 } /*namespace img_utils*/ 390 } /*namespace android*/ 391