blob: 24390332b2af2cba93b909311c2448698a0e09ac [file] [log] [blame]
Ruben Brunke5077212014-04-28 16:39:12 -07001/*
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#include <img_utils/TiffIfd.h>
18#include <img_utils/TiffHelpers.h>
19#include <img_utils/TiffWriter.h>
20#include <img_utils/TagDefinitions.h>
21
22#include <assert.h>
23
24namespace android {
25namespace img_utils {
26
27KeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::buildTagMap(
28 const TagDefinition_t* definitions, size_t length) {
29 KeyedVector<uint16_t, const TagDefinition_t*> map;
30 for(size_t i = 0; i < length; ++i) {
31 map.add(definitions[i].tagId, definitions + i);
32 }
33 return map;
34}
35
36#define COMPARE(op) \
37bool Orderable::operator op (const Orderable& orderable) const { \
38 return getComparableValue() op orderable.getComparableValue(); \
39}
40
41#define ARRAY_SIZE(array) \
42 (sizeof(array) / sizeof(array[0]))
43
44KeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::sTagMaps[] = {
45 buildTagMap(TIFF_EP_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_EP_TAG_DEFINITIONS)),
46 buildTagMap(DNG_TAG_DEFINITIONS, ARRAY_SIZE(DNG_TAG_DEFINITIONS)),
47 buildTagMap(EXIF_2_3_TAG_DEFINITIONS, ARRAY_SIZE(EXIF_2_3_TAG_DEFINITIONS)),
48 buildTagMap(TIFF_6_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_6_TAG_DEFINITIONS))
49};
50
51TiffWriter::TiffWriter() : mTagMaps(sTagMaps), mNumTagMaps(DEFAULT_NUM_TAG_MAPS) {}
52
53TiffWriter::TiffWriter(KeyedVector<uint16_t, const TagDefinition_t*>* enabledDefinitions,
54 size_t length) : mTagMaps(enabledDefinitions), mNumTagMaps(length) {}
55
56TiffWriter::~TiffWriter() {}
57
58status_t TiffWriter::write(Output* out, Endianness end) {
59 status_t ret = OK;
60 EndianOutput endOut(out, end);
61
62 if (mIfd == NULL) {
63 ALOGE("%s: Tiff header is empty.", __FUNCTION__);
64 return BAD_VALUE;
65 }
66 BAIL_ON_FAIL(writeFileHeader(endOut), ret);
67
68 uint32_t offset = FILE_HEADER_SIZE;
69 sp<TiffIfd> ifd = mIfd;
70 while(ifd != NULL) {
71 BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret);
72 offset += ifd->getSize();
73 ifd = ifd->getNextIfd();
74 }
75 return ret;
76}
77
78
79const TagDefinition_t* TiffWriter::lookupDefinition(uint16_t tag) const {
80 const TagDefinition_t* definition = NULL;
81 for (size_t i = 0; i < mNumTagMaps; ++i) {
82 ssize_t index = mTagMaps[i].indexOfKey(tag);
83 if (index >= 0) {
84 definition = mTagMaps[i][index];
85 break;
86 }
87 }
88
89 if (definition == NULL) {
90 ALOGE("%s: No definition exists for tag with id %x.", __FUNCTION__, tag);
91 }
92 return definition;
93}
94
95sp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const {
96 ssize_t index = mNamedIfds.indexOfKey(ifd);
97 if (index < 0) {
98 ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd);
99 return NULL;
100 }
101 return mNamedIfds[index]->getEntry(tag);
102}
103
104
105// TODO: Fix this to handle IFD position in chain/sub-IFD tree
106status_t TiffWriter::addEntry(const sp<TiffEntry>& entry) {
107 uint16_t tag = entry->getTag();
108
109 const TagDefinition_t* definition = lookupDefinition(tag);
110
111 if (definition == NULL) {
112 return BAD_INDEX;
113 }
114 uint32_t ifdId = 0; // TODO: all in IFD0 for now.
115
116 ssize_t index = mNamedIfds.indexOfKey(ifdId);
117
118 // Add a new IFD if necessary
119 if (index < 0) {
120 sp<TiffIfd> ifdEntry = new TiffIfd(ifdId);
121 if (mIfd == NULL) {
122 mIfd = ifdEntry;
123 }
124 index = mNamedIfds.add(ifdId, ifdEntry);
125 assert(index >= 0);
126 }
127
128 sp<TiffIfd> selectedIfd = mNamedIfds[index];
129 return selectedIfd->addEntry(entry);
130}
131
132status_t TiffWriter::uncheckedAddIfd(const sp<TiffIfd>& ifd) {
133 mNamedIfds.add(ifd->getId(), ifd);
134 sp<TiffIfd> last = findLastIfd();
135 if (last == NULL) {
136 mIfd = ifd;
137 } else {
138 last->setNextIfd(ifd);
139 }
140 last = ifd->getNextIfd();
141 while (last != NULL) {
142 mNamedIfds.add(last->getId(), last);
143 last = last->getNextIfd();
144 }
145 return OK;
146}
147
148status_t TiffWriter::addIfd(uint32_t ifd) {
149 ssize_t index = mNamedIfds.indexOfKey(ifd);
150 if (index >= 0) {
151 ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
152 return BAD_VALUE;
153 }
154 sp<TiffIfd> newIfd = new TiffIfd(ifd);
155 if (mIfd == NULL) {
156 mIfd = newIfd;
157 } else {
158 sp<TiffIfd> last = findLastIfd();
159 last->setNextIfd(newIfd);
160 }
161 mNamedIfds.add(ifd, newIfd);
162 return OK;
163}
164
165TagType TiffWriter::getDefaultType(uint16_t tag) const {
166 const TagDefinition_t* definition = lookupDefinition(tag);
167 if (definition == NULL) {
168 ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag);
169 return UNKNOWN_TAGTYPE;
170 }
171 return definition->defaultType;
172}
173
174uint32_t TiffWriter::getDefaultCount(uint16_t tag) const {
175 const TagDefinition_t* definition = lookupDefinition(tag);
176 if (definition == NULL) {
177 ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag);
178 return 0;
179 }
180 return definition->fixedCount;
181}
182
183bool TiffWriter::checkIfDefined(uint16_t tag) const {
184 return lookupDefinition(tag) != NULL;
185}
186
187sp<TiffIfd> TiffWriter::findLastIfd() {
188 sp<TiffIfd> ifd = mIfd;
189 while(ifd != NULL) {
190 sp<TiffIfd> nextIfd = ifd->getNextIfd();
191 if (nextIfd == NULL) {
192 break;
193 }
194 ifd = nextIfd;
195 }
196 return ifd;
197}
198
199status_t TiffWriter::writeFileHeader(EndianOutput& out) {
200 status_t ret = OK;
201 uint16_t endMarker = (out.getEndianness() == BIG) ? BIG_ENDIAN_MARKER : LITTLE_ENDIAN_MARKER;
202 BAIL_ON_FAIL(out.write(&endMarker, 0, 1), ret);
203
204 uint16_t tiffMarker = TIFF_FILE_MARKER;
205 BAIL_ON_FAIL(out.write(&tiffMarker, 0, 1), ret);
206
207 uint32_t offsetMarker = FILE_HEADER_SIZE;
208 BAIL_ON_FAIL(out.write(&offsetMarker, 0, 1), ret);
209 return ret;
210}
211
212uint32_t TiffWriter::getTotalSize() const {
213 uint32_t totalSize = FILE_HEADER_SIZE;
214 sp<TiffIfd> ifd = mIfd;
215 while(ifd != NULL) {
216 totalSize += ifd->getSize();
217 ifd = ifd->getNextIfd();
218 }
219 return totalSize;
220}
221
222void TiffWriter::log() const {
223 ALOGI("%s: TiffWriter:", __FUNCTION__);
224 sp<TiffIfd> ifd = mIfd;
225 while(ifd != NULL) {
226 ifd->log();
227 ifd = ifd->getNextIfd();
228 }
229}
230
231} /*namespace img_utils*/
232} /*namespace android*/