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>
TiffEntryImpl(uint16_t tag,TagType type,uint32_t count,Endianness end,const T * data)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>
~TiffEntryImpl()73 TiffEntryImpl<T>::~TiffEntryImpl() {}
74
75 template<typename T>
getCount()76 uint32_t TiffEntryImpl<T>::getCount() const {
77 return mCount;
78 }
79
80 template<typename T>
getTag()81 uint16_t TiffEntryImpl<T>::getTag() const {
82 return mTag;
83 }
84
85 template<typename T>
getType()86 TagType TiffEntryImpl<T>::getType() const {
87 return static_cast<TagType>(mType);
88 }
89
90 template<typename T>
getDataHelper()91 const void* TiffEntryImpl<T>::getDataHelper() const {
92 return reinterpret_cast<const void*>(mData.array());
93 }
94
95 template<typename T>
getSize()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>
getActualSize()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>
getEndianness()113 Endianness TiffEntryImpl<T>::getEndianness() const {
114 return mEnd;
115 }
116
117 template<typename T>
getComparableValue()118 uint32_t TiffEntryImpl<T>::getComparableValue() const {
119 return mTag;
120 }
121
122 template<typename T>
writeTagInfo(uint32_t offset,EndianOutput * out)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>
writeData(uint32_t,EndianOutput * out)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<>
writeTagInfo(uint32_t offset,EndianOutput * out)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<>
getActualSize()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<>
writeData(uint32_t offset,EndianOutput * out)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