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