Home | History | Annotate | Download | only in src
      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 = std::move(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