TiffWriter.cpp revision 4510de26e5361f3a9f07057ec6f26483c888c1fa
1e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk/*
2e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Copyright 2014 The Android Open Source Project
3e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *
4e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * you may not use this file except in compliance with the License.
6e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * You may obtain a copy of the License at
7e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *
8e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk *
10e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * See the License for the specific language governing permissions and
14e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk * limitations under the License.
15e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk */
16e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
174510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk#define LOG_TAG "TiffWriter"
184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
19e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <img_utils/TiffHelpers.h>
20e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <img_utils/TiffWriter.h>
21e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <img_utils/TagDefinitions.h>
22e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
23e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#include <assert.h>
24e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
25e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunknamespace android {
26e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunknamespace img_utils {
27e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
28e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkKeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::buildTagMap(
29e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            const TagDefinition_t* definitions, size_t length) {
30e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    KeyedVector<uint16_t, const TagDefinition_t*> map;
31e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    for(size_t i = 0; i < length; ++i) {
32e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        map.add(definitions[i].tagId, definitions + i);
33e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
34e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return map;
35e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
36e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
37e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#define COMPARE(op) \
38e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkbool Orderable::operator op (const Orderable& orderable) const { \
39e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return getComparableValue() op orderable.getComparableValue(); \
40e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
41e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
42e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk#define ARRAY_SIZE(array) \
43e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    (sizeof(array) / sizeof(array[0]))
44e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
45e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkKeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::sTagMaps[] = {
46e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    buildTagMap(TIFF_EP_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_EP_TAG_DEFINITIONS)),
47e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    buildTagMap(DNG_TAG_DEFINITIONS, ARRAY_SIZE(DNG_TAG_DEFINITIONS)),
48e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    buildTagMap(EXIF_2_3_TAG_DEFINITIONS, ARRAY_SIZE(EXIF_2_3_TAG_DEFINITIONS)),
49e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    buildTagMap(TIFF_6_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_6_TAG_DEFINITIONS))
50e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk};
51e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
52e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkTiffWriter::TiffWriter() : mTagMaps(sTagMaps), mNumTagMaps(DEFAULT_NUM_TAG_MAPS) {}
53e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
54e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkTiffWriter::TiffWriter(KeyedVector<uint16_t, const TagDefinition_t*>* enabledDefinitions,
55e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        size_t length) : mTagMaps(enabledDefinitions), mNumTagMaps(length) {}
56e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
57e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkTiffWriter::~TiffWriter() {}
58e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
594510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::write(Output* out, StripSource** sources, size_t sourcesCount,
604510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        Endianness end) {
614510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    status_t ret = OK;
624510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    EndianOutput endOut(out, end);
634510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
644510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (mIfd == NULL) {
654510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Tiff header is empty.", __FUNCTION__);
664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
674510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
694510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (LOG_NDEBUG == 0) {
704510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        log();
714510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
724510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
734510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    uint32_t totalSize = getTotalSize();
744510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
754510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    KeyedVector<uint32_t, uint32_t> offsetVector;
764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
774510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    for (size_t i = 0; i < mNamedIfds.size(); ++i) {
784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (mNamedIfds[i]->uninitializedOffsets()) {
794510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            uint32_t stripSize = mNamedIfds[i]->getStripSize();
804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            if (mNamedIfds[i]->setStripOffset(totalSize) != OK) {
814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                ALOGE("%s: Could not set strip offsets.", __FUNCTION__);
824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                return BAD_VALUE;
834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            }
844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            totalSize += stripSize;
854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            WORD_ALIGN(totalSize);
864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            offsetVector.add(mNamedIfds.keyAt(i), totalSize);
874510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
894510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    size_t offVecSize = offsetVector.size();
914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (offVecSize != sourcesCount) {
924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Mismatch between number of IFDs with uninitialized strips (%zu) and"
934510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                " sources (%zu).", __FUNCTION__, offVecSize, sourcesCount);
944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
954510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
974510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    BAIL_ON_FAIL(writeFileHeader(endOut), ret);
984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
994510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    uint32_t offset = FILE_HEADER_SIZE;
1004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    sp<TiffIfd> ifd = mIfd;
1014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    while(ifd != NULL) {
1024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret);
1034510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        offset += ifd->getSize();
1044510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ifd = ifd->getNextIfd();
1054510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
1064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
1074510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    log();
1084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
1094510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    for (size_t i = 0; i < offVecSize; ++i) {
1104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        uint32_t ifdKey = offsetVector.keyAt(i);
1114510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        uint32_t nextOffset = offsetVector[i];
1124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        uint32_t sizeToWrite = mNamedIfds[ifdKey]->getStripSize();
1134510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        bool found = false;
1144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        for (size_t j = 0; j < sourcesCount; ++j) {
1154510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            if (sources[j]->getIfd() == ifdKey) {
1164510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                if ((ret = sources[i]->writeToStream(endOut, sizeToWrite)) != OK) {
1174510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    ALOGE("%s: Could not write to stream, received %d.", __FUNCTION__, ret);
1184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    return ret;
1194510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                }
1204510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                ZERO_TILL_WORD(&endOut, sizeToWrite, ret);
1214510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                found = true;
1224510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                break;
1234510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            }
1244510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
1254510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (!found) {
1264510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: No stream for byte strips for IFD %u", __FUNCTION__, ifdKey);
1274510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
1284510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
1294510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        assert(nextOffset == endOut.getCurrentOffset());
1304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
1314510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
1324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    return ret;
1334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk}
1344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
135e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::write(Output* out, Endianness end) {
136e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    status_t ret = OK;
137e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    EndianOutput endOut(out, end);
138e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
139e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (mIfd == NULL) {
140e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: Tiff header is empty.", __FUNCTION__);
141e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return BAD_VALUE;
142e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
143e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    BAIL_ON_FAIL(writeFileHeader(endOut), ret);
144e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
145e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint32_t offset = FILE_HEADER_SIZE;
146e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    sp<TiffIfd> ifd = mIfd;
147e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    while(ifd != NULL) {
148e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret);
149e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        offset += ifd->getSize();
150e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ifd = ifd->getNextIfd();
151e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
152e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return ret;
153e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
154e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
155e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
156e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkconst TagDefinition_t* TiffWriter::lookupDefinition(uint16_t tag) const {
157e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    const TagDefinition_t* definition = NULL;
158e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    for (size_t i = 0; i < mNumTagMaps; ++i) {
159e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ssize_t index = mTagMaps[i].indexOfKey(tag);
160e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        if (index >= 0) {
161e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            definition = mTagMaps[i][index];
162e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            break;
163e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
164e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
165e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
166e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (definition == NULL) {
167e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: No definition exists for tag with id %x.", __FUNCTION__, tag);
168e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
169e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return definition;
170e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
171e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
172e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunksp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const {
173e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
174e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (index < 0) {
175e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd);
176e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return NULL;
177e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
178e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return mNamedIfds[index]->getEntry(tag);
179e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
180e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
1814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkvoid TiffWriter::removeEntry(uint16_t tag, uint32_t ifd) {
1824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
1834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (index >= 0) {
1844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mNamedIfds[index]->removeEntry(tag);
1854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
1864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk}
187e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
1884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addEntry(const sp<TiffEntry>& entry, uint32_t ifd) {
189e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint16_t tag = entry->getTag();
190e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
191e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    const TagDefinition_t* definition = lookupDefinition(tag);
192e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
193e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (definition == NULL) {
1944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: No definition exists for tag 0x%x.", __FUNCTION__, tag);
195e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return BAD_INDEX;
196e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
197e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
1984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
199e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
200e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    // Add a new IFD if necessary
201e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (index < 0) {
2024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: No IFD %u exists.", __FUNCTION__, ifd);
2034510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return NAME_NOT_FOUND;
204e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
205e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
206e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    sp<TiffIfd> selectedIfd  = mNamedIfds[index];
207e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return selectedIfd->addEntry(entry);
208e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
209e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
2104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addStrip(uint32_t ifd) {
2114510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
2124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (index < 0) {
2134510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Ifd %u doesn't exist, cannot add strip entries.", __FUNCTION__, ifd);
2144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
215e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
2164510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    sp<TiffIfd> selected = mNamedIfds[index];
2174510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    return selected->validateAndSetStripTags();
218e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
219e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
220e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::addIfd(uint32_t ifd) {
221e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
222e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (index >= 0) {
223e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
224e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return BAD_VALUE;
225e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
2264510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
227e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    sp<TiffIfd> newIfd = new TiffIfd(ifd);
228e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (mIfd == NULL) {
229e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        mIfd = newIfd;
230e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    } else {
231e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        sp<TiffIfd> last = findLastIfd();
232e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        last->setNextIfd(newIfd);
233e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
2344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2354510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if(mNamedIfds.add(ifd, newIfd) < 0) {
2364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd);
2374510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
2384510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
2394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2404510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    return OK;
2414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk}
2424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type) {
2444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
2454510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (index >= 0) {
2464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
2474510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
2484510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
2494510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2504510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t parentIndex = mNamedIfds.indexOfKey(parentIfd);
2514510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (parentIndex < 0) {
2524510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Parent IFD with ID 0x%x does not exist.", __FUNCTION__, parentIfd);
2534510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
2544510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
2554510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2564510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    sp<TiffIfd> parent = mNamedIfds[parentIndex];
2574510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    sp<TiffIfd> newIfd = new TiffIfd(ifd);
2584510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2594510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    uint16_t subIfdTag;
2604510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (type == SUBIFD) {
2614510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        subIfdTag = TAG_SUBIFDS;
2624510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    } else if (type == GPSINFO) {
2634510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        subIfdTag = TAG_GPSINFO;
2644510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    } else {
2654510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Unknown SubIFD type %d.", __FUNCTION__, type);
2664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
2674510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
2684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2694510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    sp<TiffEntry> subIfds = parent->getEntry(subIfdTag);
2704510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (subIfds == NULL) {
2714510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (buildEntry(subIfdTag, 1, &newIfd, &subIfds) < 0) {
2724510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
2734510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
2744510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
2754510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    } else {
2764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (type == GPSINFO) {
2774510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: Cannot add GPSInfo SubIFD to IFD %u, one already exists.", __FUNCTION__,
2784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    ifd);
2794510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
2804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
2814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        Vector<sp<TiffIfd> > subIfdList;
2834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        const sp<TiffIfd>* oldIfdArray = subIfds->getData<sp<TiffIfd> >();
2844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (subIfdList.appendArray(oldIfdArray, subIfds->getCount()) < 0) {
2854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
2864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
2874510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
2884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2894510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (subIfdList.add(newIfd) < 0) {
2904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
2914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
2924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
2934510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        uint32_t count = subIfdList.size();
2954510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (buildEntry(subIfdTag, count, subIfdList.array(), &subIfds) < 0) {
2964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
2974510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
2984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
2994510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
3004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
3014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (parent->addEntry(subIfds) < 0) {
3024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Failed to add SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
3034510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
3044510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
3054510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
3064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if(mNamedIfds.add(ifd, newIfd) < 0) {
3074510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd);
3084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
3094510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
3104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
311e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return OK;
312e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
313e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
314e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkTagType TiffWriter::getDefaultType(uint16_t tag) const {
315e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    const TagDefinition_t* definition = lookupDefinition(tag);
316e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (definition == NULL) {
317e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag);
318e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return UNKNOWN_TAGTYPE;
319e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
320e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return definition->defaultType;
321e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
322e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
323e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkuint32_t TiffWriter::getDefaultCount(uint16_t tag) const {
324e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    const TagDefinition_t* definition = lookupDefinition(tag);
325e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (definition == NULL) {
326e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag);
327e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return 0;
328e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
329e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return definition->fixedCount;
330e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
331e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
3324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkbool TiffWriter::hasIfd(uint32_t ifd) const {
3334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
3344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    return index >= 0;
3354510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk}
3364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
337e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkbool TiffWriter::checkIfDefined(uint16_t tag) const {
338e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return lookupDefinition(tag) != NULL;
339e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
340e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
3414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkconst char* TiffWriter::getTagName(uint16_t tag) const {
3424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    const TagDefinition_t* definition = lookupDefinition(tag);
3434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (definition == NULL) {
3444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return NULL;
3454510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
3464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    return definition->tagName;
3474510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk}
3484510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
349e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunksp<TiffIfd> TiffWriter::findLastIfd() {
350e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    sp<TiffIfd> ifd = mIfd;
351e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    while(ifd != NULL) {
352e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        sp<TiffIfd> nextIfd = ifd->getNextIfd();
353e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        if (nextIfd == NULL) {
354e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            break;
355e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
356e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ifd = nextIfd;
357e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
358e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return ifd;
359e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
360e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
361e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::writeFileHeader(EndianOutput& out) {
362e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    status_t ret = OK;
363e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint16_t endMarker = (out.getEndianness() == BIG) ? BIG_ENDIAN_MARKER : LITTLE_ENDIAN_MARKER;
364e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    BAIL_ON_FAIL(out.write(&endMarker, 0, 1), ret);
365e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
366e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint16_t tiffMarker = TIFF_FILE_MARKER;
367e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    BAIL_ON_FAIL(out.write(&tiffMarker, 0, 1), ret);
368e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
369e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint32_t offsetMarker = FILE_HEADER_SIZE;
370e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    BAIL_ON_FAIL(out.write(&offsetMarker, 0, 1), ret);
371e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return ret;
372e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
373e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
374e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkuint32_t TiffWriter::getTotalSize() const {
375e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint32_t totalSize = FILE_HEADER_SIZE;
376e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    sp<TiffIfd> ifd = mIfd;
377e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    while(ifd != NULL) {
378e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        totalSize += ifd->getSize();
379e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ifd = ifd->getNextIfd();
380e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
381e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return totalSize;
382e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
383e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
384e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkvoid TiffWriter::log() const {
385e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    ALOGI("%s: TiffWriter:", __FUNCTION__);
3864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    size_t length = mNamedIfds.size();
3874510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    for (size_t i = 0; i < length; ++i) {
3884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mNamedIfds[i]->log();
389e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
390e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
391e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
392e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} /*namespace img_utils*/
393e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} /*namespace android*/
394