Home | History | Annotate | Download | only in img_utils
      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 #ifndef IMG_UTILS_TIFF_WRITER_H
     18 #define IMG_UTILS_TIFF_WRITER_H
     19 
     20 #include <img_utils/EndianUtils.h>
     21 #include <img_utils/StripSource.h>
     22 #include <img_utils/TiffEntryImpl.h>
     23 #include <img_utils/TagDefinitions.h>
     24 #include <img_utils/TiffIfd.h>
     25 
     26 #include <utils/Log.h>
     27 #include <utils/Errors.h>
     28 #include <utils/StrongPointer.h>
     29 #include <utils/KeyedVector.h>
     30 #include <utils/Vector.h>
     31 
     32 #include <cutils/compiler.h>
     33 #include <stdint.h>
     34 
     35 namespace android {
     36 namespace img_utils {
     37 
     38 class TiffEntry;
     39 class TiffIfd;
     40 class Output;
     41 
     42 /**
     43  * This class holds a collection of TIFF IFDs that can be written as a
     44  * complete DNG file header.
     45  *
     46  * This maps to the TIFF header structure that is logically composed of:
     47  * - An 8-byte file header containing an endianness indicator, the TIFF
     48  *   file marker, and the offset to the first IFD.
     49  * - A list of TIFF IFD structures.
     50  */
     51 class ANDROID_API TiffWriter : public LightRefBase<TiffWriter> {
     52     public:
     53         enum SubIfdType {
     54             SUBIFD = 0,
     55             GPSINFO
     56         };
     57 
     58         /**
     59          * Constructs a TiffWriter with the default tag mappings. This enables
     60          * all of the tags defined in TagDefinitions.h, and uses the following
     61          * mapping precedence to resolve collisions:
     62          * (highest precedence) TIFF/EP > DNG > EXIF 2.3 > TIFF 6.0
     63          */
     64         TiffWriter();
     65 
     66         /**
     67          * Constructs a TiffWriter with the given tag mappings.  The mapping
     68          * precedence will be in the order that the definition maps are given,
     69          * where the lower index map gets precedence.
     70          *
     71          * This can be used with user-defined definitions, or definitions form
     72          * TagDefinitions.h
     73          *
     74          * The enabledDefinitions mapping object is owned by the caller, and must
     75          * stay alive for the lifespan of the constructed TiffWriter object.
     76          */
     77         TiffWriter(KeyedVector<uint16_t, const TagDefinition_t*>* enabledDefinitions,
     78                 size_t length);
     79 
     80         virtual ~TiffWriter();
     81 
     82         /**
     83          * Write a TIFF header containing each IFD set.  This will recursively
     84          * write all SubIFDs and tags.
     85          *
     86          * Any StripSources passed in will be written to the output as image strips
     87          * at the appropriate offests.  The StripByteCounts, RowsPerStrip, and
     88          * StripOffsets tags must be set to use this.  To set these tags in a
     89          * given IFD, use the addStrip method.
     90          *
     91          * Returns OK on success, or a negative error code on failure.
     92          */
     93         virtual status_t write(Output* out, StripSource** sources, size_t sourcesCount,
     94                 Endianness end = LITTLE);
     95 
     96         /**
     97          * Write a TIFF header containing each IFD set.  This will recursively
     98          * write all SubIFDs and tags.
     99          *
    100          * Image data for strips or tiles must be written separately at the
    101          * appropriate offsets.  These offsets must not fall within the file
    102          * header written this way.  The size of the header written is given
    103          * by the getTotalSize() method.
    104          *
    105          * Returns OK on success, or a negative error code on failure.
    106          */
    107         virtual status_t write(Output* out, Endianness end = LITTLE);
    108 
    109         /**
    110          * Get the total size in bytes of the TIFF header.  This includes all
    111          * IFDs, tags, and values set for this TiffWriter.
    112          */
    113         virtual uint32_t getTotalSize() const;
    114 
    115         /**
    116          * Add an entry to the IFD with the given ID.
    117          *
    118          * Returns OK on success, or a negative error code on failure. Valid
    119          * error codes for this method are:
    120          * - BAD_INDEX - The given tag doesn't exist.
    121          * - BAD_VALUE - The given count doesn't match the required count for
    122          *               this tag.
    123          * - BAD_TYPE  - The type of the given data isn't compatible with the
    124          *               type required for this tag.
    125          * - NAME_NOT_FOUND - No ifd exists with the given ID.
    126          */
    127         virtual status_t addEntry(const sp<TiffEntry>& entry, uint32_t ifd);
    128 
    129         /**
    130          * Build an entry for a known tag and add it to the IFD with the given ID.
    131          * This tag must be defined in one of the definition vectors this TIFF writer
    132          * was constructed with. The count and type are validated.
    133          *
    134          * Returns OK on success, or a negative error code on failure. Valid
    135          * error codes for this method are:
    136          * - BAD_INDEX - The given tag doesn't exist.
    137          * - BAD_VALUE - The given count doesn't match the required count for
    138          *               this tag.
    139          * - BAD_TYPE  - The type of the given data isn't compatible with the
    140          *               type required for this tag.
    141          * - NAME_NOT_FOUND - No ifd exists with the given ID.
    142          */
    143         template<typename T>
    144         status_t addEntry(uint16_t tag, uint32_t count, const T* data, uint32_t ifd);
    145 
    146         /**
    147          * Build an entry for a known tag.  This tag must be one of the tags
    148          * defined in one of the definition vectors this TIFF writer was constructed
    149          * with. The count and type are validated. If this succeeds, the resulting
    150          * entry will be placed in the outEntry pointer.
    151          *
    152          * Returns OK on success, or a negative error code on failure. Valid
    153          * error codes for this method are:
    154          * - BAD_INDEX - The given tag doesn't exist.
    155          * - BAD_VALUE - The given count doesn't match the required count for
    156          *               this tag.
    157          * - BAD_TYPE  - The type of the given data isn't compatible with the
    158          *               type required for this tag.
    159          */
    160         template<typename T>
    161         status_t buildEntry(uint16_t tag, uint32_t count, const T* data,
    162                   /*out*/sp<TiffEntry>* outEntry) const;
    163 
    164         /**
    165          * Convenience function to set the strip related tags for a given IFD.
    166          *
    167          * Call this before using a StripSource as an input to write.
    168          * The following tags must be set before calling this method:
    169          * - ImageWidth
    170          * - ImageLength
    171          * - SamplesPerPixel
    172          * - BitsPerSample
    173          *
    174          * Returns OK on success, or a negative error code.
    175          */
    176         virtual status_t addStrip(uint32_t ifd);
    177 
    178         /**
    179          * Return the TIFF entry with the given tag ID in the IFD with the given ID,
    180          * or an empty pointer if none exists.
    181          */
    182         virtual sp<TiffEntry> getEntry(uint16_t tag, uint32_t ifd) const;
    183 
    184         /**
    185          * Remove the TIFF entry with the given tag ID in the given IFD if it exists.
    186          */
    187         virtual void removeEntry(uint16_t tag, uint32_t ifd);
    188 
    189         /**
    190          * Create an empty IFD with the given ID and add it to the end of the
    191          * list of IFDs.
    192          */
    193         virtual status_t addIfd(uint32_t ifd);
    194 
    195         /**
    196          * Create an empty IFD with the given ID and add it as a SubIfd of the
    197          * parent IFD.
    198          */
    199         virtual status_t addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type = SUBIFD);
    200 
    201         /**
    202          * Returns the default type for the given tag ID.
    203          */
    204         virtual TagType getDefaultType(uint16_t tag) const;
    205 
    206         /**
    207          * Returns the default count for a given tag ID, or 0 if this
    208          * tag normally has a variable count.
    209          */
    210         virtual uint32_t getDefaultCount(uint16_t tag) const;
    211 
    212         /**
    213          * Returns true if an IFD with the given ID exists.
    214          */
    215         virtual bool hasIfd(uint32_t ifd) const;
    216 
    217         /**
    218          * Returns true if a definition exist for the given tag ID.
    219          */
    220         virtual bool checkIfDefined(uint16_t tag) const;
    221 
    222         /**
    223          * Returns the name of the tag if a definition exists for the given tag
    224          * ID, or null if no definition exists.
    225          */
    226         virtual const char* getTagName(uint16_t tag) const;
    227 
    228         /**
    229          * Print the currently configured IFDs and entries to logcat.
    230          */
    231         virtual void log() const;
    232 
    233         /**
    234          * Build an entry.  No validation is done.
    235          *
    236          * WARNING: Using this method can result in creating poorly formatted
    237          * TIFF files.
    238          *
    239          * Returns a TiffEntry with the given tag, type, count, endianness,
    240          * and data.
    241          */
    242         template<typename T>
    243         static sp<TiffEntry> uncheckedBuildEntry(uint16_t tag, TagType type,
    244                   uint32_t count, Endianness end, const T* data);
    245 
    246         /**
    247          * Utility function to build atag-to-definition mapping from a given
    248          * array of tag definitions.
    249          */
    250         static KeyedVector<uint16_t, const TagDefinition_t*> buildTagMap(
    251                   const TagDefinition_t* definitions, size_t length);
    252 
    253     protected:
    254         enum {
    255             DEFAULT_NUM_TAG_MAPS = 4,
    256         };
    257 
    258         sp<TiffIfd> findLastIfd();
    259         status_t writeFileHeader(EndianOutput& out);
    260         const TagDefinition_t* lookupDefinition(uint16_t tag) const;
    261         status_t calculateOffsets();
    262 
    263         sp<TiffIfd> mIfd;
    264         KeyedVector<uint32_t, sp<TiffIfd> > mNamedIfds;
    265         KeyedVector<uint16_t, const TagDefinition_t*>* mTagMaps;
    266         size_t mNumTagMaps;
    267 
    268         static KeyedVector<uint16_t, const TagDefinition_t*> sTagMaps[];
    269 };
    270 
    271 template<typename T>
    272 status_t TiffWriter::buildEntry(uint16_t tag, uint32_t count, const T* data,
    273                   /*out*/sp<TiffEntry>* outEntry) const {
    274     const TagDefinition_t* definition = lookupDefinition(tag);
    275 
    276     if (definition == NULL) {
    277         ALOGE("%s: No such tag exists for id %x.", __FUNCTION__, tag);
    278         return BAD_INDEX;
    279     }
    280 
    281     uint32_t fixedCount = definition->fixedCount;
    282     if (fixedCount > 0 && fixedCount != count) {
    283         ALOGE("%s: Invalid count %d for tag %x (expects %d).", __FUNCTION__, count, tag,
    284                 fixedCount);
    285         return BAD_VALUE;
    286     }
    287 
    288     TagType fixedType = definition->defaultType;
    289     if (TiffEntry::forceValidType(fixedType, data) == NULL) {
    290         ALOGE("%s: Invalid type used for tag value for tag %x.", __FUNCTION__, tag);
    291         return BAD_TYPE;
    292     }
    293 
    294     *outEntry = new TiffEntryImpl<T>(tag, fixedType, count,
    295         definition->fixedEndian, data);
    296 
    297     return OK;
    298 }
    299 
    300 template<typename T>
    301 status_t TiffWriter::addEntry(uint16_t tag, uint32_t count, const T* data, uint32_t ifd) {
    302     sp<TiffEntry> outEntry;
    303 
    304     status_t ret = buildEntry<T>(tag, count, data, &outEntry);
    305     if (ret != OK) {
    306         ALOGE("%s: Could not build entry for tag %x.", __FUNCTION__, tag);
    307         return ret;
    308     }
    309 
    310     return addEntry(outEntry, ifd);
    311 }
    312 
    313 template<typename T>
    314 sp<TiffEntry> TiffWriter::uncheckedBuildEntry(uint16_t tag, TagType type, uint32_t count,
    315         Endianness end, const T* data) {
    316     TiffEntryImpl<T>* entry = new TiffEntryImpl<T>(tag, type, count, end, data);
    317     return sp<TiffEntry>(entry);
    318 }
    319 
    320 } /*namespace img_utils*/
    321 } /*namespace android*/
    322 
    323 
    324 #endif /*IMG_UTILS_TIFF_WRITER_H*/
    325