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    uint32_t totalSize = getTotalSize();
704510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
714510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    KeyedVector<uint32_t, uint32_t> offsetVector;
724510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
734510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    for (size_t i = 0; i < mNamedIfds.size(); ++i) {
744510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (mNamedIfds[i]->uninitializedOffsets()) {
754510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            uint32_t stripSize = mNamedIfds[i]->getStripSize();
764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            if (mNamedIfds[i]->setStripOffset(totalSize) != OK) {
774510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                ALOGE("%s: Could not set strip offsets.", __FUNCTION__);
784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                return BAD_VALUE;
794510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            }
804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            totalSize += stripSize;
814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            WORD_ALIGN(totalSize);
824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            offsetVector.add(mNamedIfds.keyAt(i), totalSize);
834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    size_t offVecSize = offsetVector.size();
874510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (offVecSize != sourcesCount) {
884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Mismatch between number of IFDs with uninitialized strips (%zu) and"
894510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                " sources (%zu).", __FUNCTION__, offVecSize, sourcesCount);
904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
934510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    BAIL_ON_FAIL(writeFileHeader(endOut), ret);
944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
954510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    uint32_t offset = FILE_HEADER_SIZE;
964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    sp<TiffIfd> ifd = mIfd;
974510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    while(ifd != NULL) {
984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret);
994510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        offset += ifd->getSize();
1004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ifd = ifd->getNextIfd();
1014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
1024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
103ca73159becc0fc0098530929e467a3d92e470571Ruben Brunk    if (LOG_NDEBUG == 0) {
104ca73159becc0fc0098530929e467a3d92e470571Ruben Brunk        log();
105ca73159becc0fc0098530929e467a3d92e470571Ruben Brunk    }
1064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
1074510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    for (size_t i = 0; i < offVecSize; ++i) {
1084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        uint32_t ifdKey = offsetVector.keyAt(i);
1094510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        uint32_t nextOffset = offsetVector[i];
1104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        uint32_t sizeToWrite = mNamedIfds[ifdKey]->getStripSize();
1114510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        bool found = false;
1124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        for (size_t j = 0; j < sourcesCount; ++j) {
1134510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            if (sources[j]->getIfd() == ifdKey) {
1144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                if ((ret = sources[i]->writeToStream(endOut, sizeToWrite)) != OK) {
1154510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    ALOGE("%s: Could not write to stream, received %d.", __FUNCTION__, ret);
1164510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    return ret;
1174510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                }
1184510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                ZERO_TILL_WORD(&endOut, sizeToWrite, ret);
1194510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                found = true;
1204510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                break;
1214510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            }
1224510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
1234510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (!found) {
1244510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: No stream for byte strips for IFD %u", __FUNCTION__, ifdKey);
1254510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
1264510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
1274510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        assert(nextOffset == endOut.getCurrentOffset());
1284510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
1294510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
1304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    return ret;
1314510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk}
1324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
133e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::write(Output* out, Endianness end) {
134e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    status_t ret = OK;
135e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    EndianOutput endOut(out, end);
136e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
137e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (mIfd == NULL) {
138e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: Tiff header is empty.", __FUNCTION__);
139e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return BAD_VALUE;
140e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
141e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    BAIL_ON_FAIL(writeFileHeader(endOut), ret);
142e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
143e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint32_t offset = FILE_HEADER_SIZE;
144e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    sp<TiffIfd> ifd = mIfd;
145e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    while(ifd != NULL) {
146e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret);
147e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        offset += ifd->getSize();
148e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ifd = ifd->getNextIfd();
149e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
150e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return ret;
151e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
152e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
153e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
154e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkconst TagDefinition_t* TiffWriter::lookupDefinition(uint16_t tag) const {
155e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    const TagDefinition_t* definition = NULL;
156e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    for (size_t i = 0; i < mNumTagMaps; ++i) {
157e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ssize_t index = mTagMaps[i].indexOfKey(tag);
158e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        if (index >= 0) {
159e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            definition = mTagMaps[i][index];
160e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            break;
161e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
162e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
163e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
164e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (definition == NULL) {
165e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: No definition exists for tag with id %x.", __FUNCTION__, tag);
166e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
167e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return definition;
168e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
169e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
170e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunksp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const {
171e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
172e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (index < 0) {
173e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd);
174e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return NULL;
175e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
176e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return mNamedIfds[index]->getEntry(tag);
177e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
178e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
1794510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkvoid TiffWriter::removeEntry(uint16_t tag, uint32_t ifd) {
1804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
1814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (index >= 0) {
1824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mNamedIfds[index]->removeEntry(tag);
1834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
1844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk}
185e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
1864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addEntry(const sp<TiffEntry>& entry, uint32_t ifd) {
187e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint16_t tag = entry->getTag();
188e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
189e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    const TagDefinition_t* definition = lookupDefinition(tag);
190e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
191e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (definition == NULL) {
1924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: No definition exists for tag 0x%x.", __FUNCTION__, tag);
193e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return BAD_INDEX;
194e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
195e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
1964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
197e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
198e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    // Add a new IFD if necessary
199e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (index < 0) {
2004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: No IFD %u exists.", __FUNCTION__, ifd);
2014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return NAME_NOT_FOUND;
202e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
203e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
204e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    sp<TiffIfd> selectedIfd  = mNamedIfds[index];
205e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return selectedIfd->addEntry(entry);
206e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
207e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
2084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addStrip(uint32_t ifd) {
2094510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
2104510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (index < 0) {
2114510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Ifd %u doesn't exist, cannot add strip entries.", __FUNCTION__, ifd);
2124510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
213e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
2144510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    sp<TiffIfd> selected = mNamedIfds[index];
2154510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    return selected->validateAndSetStripTags();
216e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
217e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
218e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::addIfd(uint32_t ifd) {
219e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
220e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (index >= 0) {
221e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
222e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return BAD_VALUE;
223e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
2244510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
225e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    sp<TiffIfd> newIfd = new TiffIfd(ifd);
226e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (mIfd == NULL) {
227e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        mIfd = newIfd;
228e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    } else {
229e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        sp<TiffIfd> last = findLastIfd();
230e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        last->setNextIfd(newIfd);
231e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
2324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if(mNamedIfds.add(ifd, newIfd) < 0) {
2344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd);
2354510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
2364510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
2374510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2384510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    return OK;
2394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk}
2404510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkstatus_t TiffWriter::addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type) {
2424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
2434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (index >= 0) {
2444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
2454510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
2464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
2474510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2484510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t parentIndex = mNamedIfds.indexOfKey(parentIfd);
2494510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (parentIndex < 0) {
2504510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Parent IFD with ID 0x%x does not exist.", __FUNCTION__, parentIfd);
2514510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
2524510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
2534510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2544510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    sp<TiffIfd> parent = mNamedIfds[parentIndex];
2554510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    sp<TiffIfd> newIfd = new TiffIfd(ifd);
2564510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2574510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    uint16_t subIfdTag;
2584510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (type == SUBIFD) {
2594510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        subIfdTag = TAG_SUBIFDS;
2604510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    } else if (type == GPSINFO) {
2614510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        subIfdTag = TAG_GPSINFO;
2624510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    } else {
2634510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Unknown SubIFD type %d.", __FUNCTION__, type);
2644510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
2654510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
2664510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2674510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    sp<TiffEntry> subIfds = parent->getEntry(subIfdTag);
2684510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (subIfds == NULL) {
2694510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (buildEntry(subIfdTag, 1, &newIfd, &subIfds) < 0) {
2704510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
2714510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
2724510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
2734510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    } else {
2744510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (type == GPSINFO) {
2754510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: Cannot add GPSInfo SubIFD to IFD %u, one already exists.", __FUNCTION__,
2764510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk                    ifd);
2774510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
2784510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
2794510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2804510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        Vector<sp<TiffIfd> > subIfdList;
2814510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        const sp<TiffIfd>* oldIfdArray = subIfds->getData<sp<TiffIfd> >();
2824510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (subIfdList.appendArray(oldIfdArray, subIfds->getCount()) < 0) {
2834510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
2844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
2854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
2864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2874510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (subIfdList.add(newIfd) < 0) {
2884510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
2894510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
2904510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
2914510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2924510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        uint32_t count = subIfdList.size();
2934510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        if (buildEntry(subIfdTag, count, subIfdList.array(), &subIfds) < 0) {
2944510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
2954510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk            return BAD_VALUE;
2964510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        }
2974510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
2984510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
2994510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (parent->addEntry(subIfds) < 0) {
3004510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Failed to add SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
3014510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
3024510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
3034510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
3044510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if(mNamedIfds.add(ifd, newIfd) < 0) {
3054510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd);
3064510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return BAD_VALUE;
3074510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
3084510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
309e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return OK;
310e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
311e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
312e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben BrunkTagType TiffWriter::getDefaultType(uint16_t tag) const {
313e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    const TagDefinition_t* definition = lookupDefinition(tag);
314e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (definition == NULL) {
315e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag);
316e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return UNKNOWN_TAGTYPE;
317e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
318e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return definition->defaultType;
319e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
320e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
321e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkuint32_t TiffWriter::getDefaultCount(uint16_t tag) const {
322e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    const TagDefinition_t* definition = lookupDefinition(tag);
323e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    if (definition == NULL) {
324e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag);
325e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        return 0;
326e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
327e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return definition->fixedCount;
328e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
329e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
3304510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkbool TiffWriter::hasIfd(uint32_t ifd) const {
3314510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    ssize_t index = mNamedIfds.indexOfKey(ifd);
3324510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    return index >= 0;
3334510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk}
3344510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
335e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkbool TiffWriter::checkIfDefined(uint16_t tag) const {
336e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return lookupDefinition(tag) != NULL;
337e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
338e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
3394510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunkconst char* TiffWriter::getTagName(uint16_t tag) const {
3404510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    const TagDefinition_t* definition = lookupDefinition(tag);
3414510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    if (definition == NULL) {
3424510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        return NULL;
3434510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    }
3444510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    return definition->tagName;
3454510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk}
3464510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk
347e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunksp<TiffIfd> TiffWriter::findLastIfd() {
348e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    sp<TiffIfd> ifd = mIfd;
349e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    while(ifd != NULL) {
350e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        sp<TiffIfd> nextIfd = ifd->getNextIfd();
351e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        if (nextIfd == NULL) {
352e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk            break;
353e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        }
354e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ifd = nextIfd;
355e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
356e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return ifd;
357e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
358e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
359e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkstatus_t TiffWriter::writeFileHeader(EndianOutput& out) {
360e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    status_t ret = OK;
361e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint16_t endMarker = (out.getEndianness() == BIG) ? BIG_ENDIAN_MARKER : LITTLE_ENDIAN_MARKER;
362e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    BAIL_ON_FAIL(out.write(&endMarker, 0, 1), ret);
363e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
364e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint16_t tiffMarker = TIFF_FILE_MARKER;
365e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    BAIL_ON_FAIL(out.write(&tiffMarker, 0, 1), ret);
366e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
367e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint32_t offsetMarker = FILE_HEADER_SIZE;
368e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    BAIL_ON_FAIL(out.write(&offsetMarker, 0, 1), ret);
369e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return ret;
370e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
371e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
372e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkuint32_t TiffWriter::getTotalSize() const {
373e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    uint32_t totalSize = FILE_HEADER_SIZE;
374e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    sp<TiffIfd> ifd = mIfd;
375e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    while(ifd != NULL) {
376e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        totalSize += ifd->getSize();
377e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk        ifd = ifd->getNextIfd();
378e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
379e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    return totalSize;
380e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
381e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
382e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunkvoid TiffWriter::log() const {
383e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    ALOGI("%s: TiffWriter:", __FUNCTION__);
3844510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    size_t length = mNamedIfds.size();
3854510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk    for (size_t i = 0; i < length; ++i) {
3864510de26e5361f3a9f07057ec6f26483c888c1faRuben Brunk        mNamedIfds[i]->log();
387e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk    }
388e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk}
389e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk
390e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} /*namespace img_utils*/
391e507721000647a7d8afe44c63ef7fd04ef8971b1Ruben Brunk} /*namespace android*/
392