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_ENTRY_IMPL
     18 #define IMG_UTILS_TIFF_ENTRY_IMPL
     19 
     20 #include <img_utils/TiffIfd.h>
     21 #include <img_utils/TiffEntry.h>
     22 #include <img_utils/TiffHelpers.h>
     23 #include <img_utils/Output.h>
     24 #include <img_utils/EndianUtils.h>
     25 
     26 #include <utils/Log.h>
     27 #include <utils/Errors.h>
     28 #include <utils/Vector.h>
     29 #include <utils/StrongPointer.h>
     30 #include <stdint.h>
     31 
     32 namespace android {
     33 namespace img_utils {
     34 
     35 template<typename T>
     36 class TiffEntryImpl : public TiffEntry {
     37     public:
     38         TiffEntryImpl(uint16_t tag, TagType type, uint32_t count, Endianness end, const T* data);
     39         virtual ~TiffEntryImpl();
     40 
     41         status_t writeData(uint32_t offset, /*out*/EndianOutput* out) const;
     42         status_t writeTagInfo(uint32_t offset, /*out*/EndianOutput* out) const;
     43 
     44         uint32_t getCount() const;
     45         uint16_t getTag() const;
     46         TagType getType() const;
     47         Endianness getEndianness() const;
     48         size_t getSize() const;
     49         uint32_t getComparableValue() const;
     50 
     51     protected:
     52         const void* getDataHelper() const;
     53         uint32_t getActualSize() const;
     54 
     55         uint16_t mTag;
     56         uint16_t mType;
     57         uint32_t mCount;
     58         Endianness mEnd;
     59         Vector<T> mData;
     60 
     61 };
     62 
     63 template<typename T>
     64 TiffEntryImpl<T>::TiffEntryImpl(uint16_t tag, TagType type, uint32_t count, Endianness end,
     65         const T* data)
     66         : mTag(tag), mType(static_cast<uint16_t>(type)), mCount(count), mEnd(end) {
     67     count = (type == RATIONAL || type == SRATIONAL) ? count * 2 : count;
     68     ssize_t index = mData.appendArray(data, count);
     69     LOG_ALWAYS_FATAL_IF(index < 0, "%s: Could not allocate vector for data.", __FUNCTION__);
     70 }
     71 
     72 template<typename T>
     73 TiffEntryImpl<T>::~TiffEntryImpl() {}
     74 
     75 template<typename T>
     76 uint32_t TiffEntryImpl<T>::getCount() const {
     77     return mCount;
     78 }
     79 
     80 template<typename T>
     81 uint16_t TiffEntryImpl<T>::getTag() const {
     82     return mTag;
     83 }
     84 
     85 template<typename T>
     86 TagType TiffEntryImpl<T>::getType() const {
     87     return static_cast<TagType>(mType);
     88 }
     89 
     90 template<typename T>
     91 const void* TiffEntryImpl<T>::getDataHelper() const {
     92     return reinterpret_cast<const void*>(mData.array());
     93 }
     94 
     95 template<typename T>
     96 size_t TiffEntryImpl<T>::getSize() const {
     97     uint32_t total = getActualSize();
     98     WORD_ALIGN(total)
     99     return (total <= OFFSET_SIZE) ? 0 : total;
    100 }
    101 
    102 template<typename T>
    103 uint32_t TiffEntryImpl<T>::getActualSize() const {
    104     uint32_t total = sizeof(T) * mCount;
    105     if (getType() == RATIONAL || getType() == SRATIONAL) {
    106         // 2 ints stored for each rational, multiply by 2
    107         total <<= 1;
    108     }
    109     return total;
    110 }
    111 
    112 template<typename T>
    113 Endianness TiffEntryImpl<T>::getEndianness() const {
    114     return mEnd;
    115 }
    116 
    117 template<typename T>
    118 uint32_t TiffEntryImpl<T>::getComparableValue() const {
    119     return mTag;
    120 }
    121 
    122 template<typename T>
    123 status_t TiffEntryImpl<T>::writeTagInfo(uint32_t offset, /*out*/EndianOutput* out) const {
    124     assert((offset % TIFF_WORD_SIZE) == 0);
    125     status_t ret = OK;
    126     BAIL_ON_FAIL(out->write(&mTag, 0, 1), ret);
    127     BAIL_ON_FAIL(out->write(&mType, 0, 1), ret);
    128     BAIL_ON_FAIL(out->write(&mCount, 0, 1), ret);
    129 
    130     uint32_t dataSize = getActualSize();
    131     if (dataSize > OFFSET_SIZE) {
    132         BAIL_ON_FAIL(out->write(&offset, 0, 1), ret);
    133     } else {
    134         uint32_t count = mCount;
    135         if (getType() == RATIONAL || getType() == SRATIONAL) {
    136             /**
    137              * Rationals are stored as an array of ints.  Each
    138              * rational is represented by 2 ints.  To recover the
    139              * size of the array here, multiply the count by 2.
    140              */
    141             count <<= 1;
    142         }
    143         BAIL_ON_FAIL(out->write(mData.array(), 0, count), ret);
    144         ZERO_TILL_WORD(out, dataSize, ret);
    145     }
    146     return ret;
    147 }
    148 
    149 template<typename T>
    150 status_t TiffEntryImpl<T>::writeData(uint32_t /*offset*/, EndianOutput* out) const {
    151     status_t ret = OK;
    152 
    153     // Some tags have fixed-endian value output
    154     Endianness tmp = UNDEFINED_ENDIAN;
    155     if (mEnd != UNDEFINED_ENDIAN) {
    156         tmp = out->getEndianness();
    157         out->setEndianness(mEnd);
    158     }
    159 
    160     uint32_t count = mCount;
    161     if (getType() == RATIONAL || getType() == SRATIONAL) {
    162         /**
    163          * Rationals are stored as an array of ints.  Each
    164          * rational is represented by 2 ints.  To recover the
    165          * size of the array here, multiply the count by 2.
    166          */
    167         count <<= 1;
    168     }
    169 
    170     BAIL_ON_FAIL(out->write(mData.array(), 0, count), ret);
    171 
    172     if (mEnd != UNDEFINED_ENDIAN) {
    173         out->setEndianness(tmp);
    174     }
    175 
    176     // Write to next word alignment
    177     ZERO_TILL_WORD(out, sizeof(T) * count, ret);
    178     return ret;
    179 }
    180 
    181 template<>
    182 inline status_t TiffEntryImpl<sp<TiffIfd> >::writeTagInfo(uint32_t offset,
    183         /*out*/EndianOutput* out) const {
    184     assert((offset % TIFF_WORD_SIZE) == 0);
    185     status_t ret = OK;
    186     BAIL_ON_FAIL(out->write(&mTag, 0, 1), ret);
    187     BAIL_ON_FAIL(out->write(&mType, 0, 1), ret);
    188     BAIL_ON_FAIL(out->write(&mCount, 0, 1), ret);
    189 
    190     BAIL_ON_FAIL(out->write(&offset, 0, 1), ret);
    191     return ret;
    192 }
    193 
    194 template<>
    195 inline uint32_t TiffEntryImpl<sp<TiffIfd> >::getActualSize() const {
    196     uint32_t total = 0;
    197     for (size_t i = 0; i < mData.size(); ++i) {
    198         total += mData[i]->getSize();
    199     }
    200     return total;
    201 }
    202 
    203 template<>
    204 inline status_t TiffEntryImpl<sp<TiffIfd> >::writeData(uint32_t offset, EndianOutput* out) const {
    205     status_t ret = OK;
    206     for (uint32_t i = 0; i < mCount; ++i) {
    207         BAIL_ON_FAIL(mData[i]->writeData(offset, out), ret);
    208         offset += mData[i]->getSize();
    209     }
    210     return ret;
    211 }
    212 
    213 } /*namespace img_utils*/
    214 } /*namespace android*/
    215 
    216 #endif /*IMG_UTILS_TIFF_ENTRY_IMPL*/
    217 
    218 
    219