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 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