TiffWriter.cpp revision ca73159becc0fc0098530929e467a3d92e470571
190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/*
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Copyright 2014 The Android Open Source Project
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * you may not use this file except in compliance with the License.
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * You may obtain a copy of the License at
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * See the License for the specific language governing permissions and
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * limitations under the License.
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define LOG_TAG "TiffWriter"
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <img_utils/TiffHelpers.h>
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <img_utils/TiffWriter.h>
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <img_utils/TagDefinitions.h>
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <assert.h>
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace android {
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace img_utils {
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)KeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::buildTagMap(
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            const TagDefinition_t* definitions, size_t length) {
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    KeyedVector<uint16_t, const TagDefinition_t*> map;
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for(size_t i = 0; i < length; ++i) {
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        map.add(definitions[i].tagId, definitions + i);
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return map;
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define COMPARE(op) \
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool Orderable::operator op (const Orderable& orderable) const { \
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return getComparableValue() op orderable.getComparableValue(); \
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define ARRAY_SIZE(array) \
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    (sizeof(array) / sizeof(array[0]))
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)KeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::sTagMaps[] = {
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    buildTagMap(TIFF_EP_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_EP_TAG_DEFINITIONS)),
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    buildTagMap(DNG_TAG_DEFINITIONS, ARRAY_SIZE(DNG_TAG_DEFINITIONS)),
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    buildTagMap(EXIF_2_3_TAG_DEFINITIONS, ARRAY_SIZE(EXIF_2_3_TAG_DEFINITIONS)),
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    buildTagMap(TIFF_6_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_6_TAG_DEFINITIONS))
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TiffWriter::TiffWriter() : mTagMaps(sTagMaps), mNumTagMaps(DEFAULT_NUM_TAG_MAPS) {}
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TiffWriter::TiffWriter(KeyedVector<uint16_t, const TagDefinition_t*>* enabledDefinitions,
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        size_t length) : mTagMaps(enabledDefinitions), mNumTagMaps(length) {}
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TiffWriter::~TiffWriter() {}
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)status_t TiffWriter::write(Output* out, StripSource** sources, size_t sourcesCount,
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        Endianness end) {
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    status_t ret = OK;
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    EndianOutput endOut(out, end);
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (mIfd == NULL) {
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Tiff header is empty.", __FUNCTION__);
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint32_t totalSize = getTotalSize();
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    KeyedVector<uint32_t, uint32_t> offsetVector;
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (size_t i = 0; i < mNamedIfds.size(); ++i) {
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (mNamedIfds[i]->uninitializedOffsets()) {
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            uint32_t stripSize = mNamedIfds[i]->getStripSize();
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            if (mNamedIfds[i]->setStripOffset(totalSize) != OK) {
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                ALOGE("%s: Could not set strip offsets.", __FUNCTION__);
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                return BAD_VALUE;
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            }
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            totalSize += stripSize;
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            WORD_ALIGN(totalSize);
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            offsetVector.add(mNamedIfds.keyAt(i), totalSize);
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size_t offVecSize = offsetVector.size();
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (offVecSize != sourcesCount) {
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Mismatch between number of IFDs with uninitialized strips (%zu) and"
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                " sources (%zu).", __FUNCTION__, offVecSize, sourcesCount);
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BAIL_ON_FAIL(writeFileHeader(endOut), ret);
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint32_t offset = FILE_HEADER_SIZE;
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sp<TiffIfd> ifd = mIfd;
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    while(ifd != NULL) {
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret);
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        offset += ifd->getSize();
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ifd = ifd->getNextIfd();
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (LOG_NDEBUG == 0) {
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        log();
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (size_t i = 0; i < offVecSize; ++i) {
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        uint32_t ifdKey = offsetVector.keyAt(i);
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        uint32_t nextOffset = offsetVector[i];
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        uint32_t sizeToWrite = mNamedIfds[ifdKey]->getStripSize();
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        bool found = false;
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        for (size_t j = 0; j < sourcesCount; ++j) {
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            if (sources[j]->getIfd() == ifdKey) {
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                if ((ret = sources[i]->writeToStream(endOut, sizeToWrite)) != OK) {
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    ALOGE("%s: Could not write to stream, received %d.", __FUNCTION__, ret);
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    return ret;
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                }
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                ZERO_TILL_WORD(&endOut, sizeToWrite, ret);
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                found = true;
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                break;
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            }
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (!found) {
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            ALOGE("%s: No stream for byte strips for IFD %u", __FUNCTION__, ifdKey);
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            return BAD_VALUE;
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        assert(nextOffset == endOut.getCurrentOffset());
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return ret;
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)status_t TiffWriter::write(Output* out, Endianness end) {
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    status_t ret = OK;
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    EndianOutput endOut(out, end);
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (mIfd == NULL) {
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Tiff header is empty.", __FUNCTION__);
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BAIL_ON_FAIL(writeFileHeader(endOut), ret);
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint32_t offset = FILE_HEADER_SIZE;
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sp<TiffIfd> ifd = mIfd;
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    while(ifd != NULL) {
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret);
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        offset += ifd->getSize();
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ifd = ifd->getNextIfd();
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return ret;
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const TagDefinition_t* TiffWriter::lookupDefinition(uint16_t tag) const {
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const TagDefinition_t* definition = NULL;
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (size_t i = 0; i < mNumTagMaps; ++i) {
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ssize_t index = mTagMaps[i].indexOfKey(tag);
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (index >= 0) {
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            definition = mTagMaps[i][index];
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            break;
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (definition == NULL) {
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: No definition exists for tag with id %x.", __FUNCTION__, tag);
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return definition;
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)sp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const {
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ssize_t index = mNamedIfds.indexOfKey(ifd);
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (index < 0) {
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd);
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return NULL;
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return mNamedIfds[index]->getEntry(tag);
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TiffWriter::removeEntry(uint16_t tag, uint32_t ifd) {
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ssize_t index = mNamedIfds.indexOfKey(ifd);
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (index >= 0) {
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        mNamedIfds[index]->removeEntry(tag);
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)status_t TiffWriter::addEntry(const sp<TiffEntry>& entry, uint32_t ifd) {
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint16_t tag = entry->getTag();
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const TagDefinition_t* definition = lookupDefinition(tag);
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (definition == NULL) {
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: No definition exists for tag 0x%x.", __FUNCTION__, tag);
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_INDEX;
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ssize_t index = mNamedIfds.indexOfKey(ifd);
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Add a new IFD if necessary
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (index < 0) {
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: No IFD %u exists.", __FUNCTION__, ifd);
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return NAME_NOT_FOUND;
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sp<TiffIfd> selectedIfd  = mNamedIfds[index];
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return selectedIfd->addEntry(entry);
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)status_t TiffWriter::addStrip(uint32_t ifd) {
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ssize_t index = mNamedIfds.indexOfKey(ifd);
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (index < 0) {
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Ifd %u doesn't exist, cannot add strip entries.", __FUNCTION__, ifd);
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sp<TiffIfd> selected = mNamedIfds[index];
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return selected->validateAndSetStripTags();
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)status_t TiffWriter::addIfd(uint32_t ifd) {
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ssize_t index = mNamedIfds.indexOfKey(ifd);
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (index >= 0) {
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sp<TiffIfd> newIfd = new TiffIfd(ifd);
22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (mIfd == NULL) {
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        mIfd = newIfd;
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        sp<TiffIfd> last = findLastIfd();
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        last->setNextIfd(newIfd);
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if(mNamedIfds.add(ifd, newIfd) < 0) {
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd);
23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return OK;
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)status_t TiffWriter::addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type) {
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ssize_t index = mNamedIfds.indexOfKey(ifd);
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (index >= 0) {
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ssize_t parentIndex = mNamedIfds.indexOfKey(parentIfd);
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (parentIndex < 0) {
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Parent IFD with ID 0x%x does not exist.", __FUNCTION__, parentIfd);
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sp<TiffIfd> parent = mNamedIfds[parentIndex];
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sp<TiffIfd> newIfd = new TiffIfd(ifd);
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint16_t subIfdTag;
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (type == SUBIFD) {
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        subIfdTag = TAG_SUBIFDS;
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else if (type == GPSINFO) {
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        subIfdTag = TAG_GPSINFO;
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Unknown SubIFD type %d.", __FUNCTION__, type);
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sp<TiffEntry> subIfds = parent->getEntry(subIfdTag);
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (subIfds == NULL) {
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (buildEntry(subIfdTag, 1, &newIfd, &subIfds) < 0) {
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            return BAD_VALUE;
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (type == GPSINFO) {
27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            ALOGE("%s: Cannot add GPSInfo SubIFD to IFD %u, one already exists.", __FUNCTION__,
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    ifd);
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            return BAD_VALUE;
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        Vector<sp<TiffIfd> > subIfdList;
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        const sp<TiffIfd>* oldIfdArray = subIfds->getData<sp<TiffIfd> >();
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (subIfdList.appendArray(oldIfdArray, subIfds->getCount()) < 0) {
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            return BAD_VALUE;
28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (subIfdList.add(newIfd) < 0) {
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            return BAD_VALUE;
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        uint32_t count = subIfdList.size();
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (buildEntry(subIfdTag, count, subIfdList.array(), &subIfds) < 0) {
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            return BAD_VALUE;
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (parent->addEntry(subIfds) < 0) {
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Failed to add SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if(mNamedIfds.add(ifd, newIfd) < 0) {
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd);
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return BAD_VALUE;
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return OK;
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TagType TiffWriter::getDefaultType(uint16_t tag) const {
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const TagDefinition_t* definition = lookupDefinition(tag);
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (definition == NULL) {
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag);
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return UNKNOWN_TAGTYPE;
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return definition->defaultType;
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)uint32_t TiffWriter::getDefaultCount(uint16_t tag) const {
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const TagDefinition_t* definition = lookupDefinition(tag);
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (definition == NULL) {
32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag);
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return 0;
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return definition->fixedCount;
32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool TiffWriter::hasIfd(uint32_t ifd) const {
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ssize_t index = mNamedIfds.indexOfKey(ifd);
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return index >= 0;
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool TiffWriter::checkIfDefined(uint16_t tag) const {
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return lookupDefinition(tag) != NULL;
33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char* TiffWriter::getTagName(uint16_t tag) const {
34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const TagDefinition_t* definition = lookupDefinition(tag);
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (definition == NULL) {
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return NULL;
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return definition->tagName;
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)sp<TiffIfd> TiffWriter::findLastIfd() {
34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sp<TiffIfd> ifd = mIfd;
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    while(ifd != NULL) {
35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        sp<TiffIfd> nextIfd = ifd->getNextIfd();
35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (nextIfd == NULL) {
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            break;
35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ifd = nextIfd;
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return ifd;
35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)status_t TiffWriter::writeFileHeader(EndianOutput& out) {
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    status_t ret = OK;
36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint16_t endMarker = (out.getEndianness() == BIG) ? BIG_ENDIAN_MARKER : LITTLE_ENDIAN_MARKER;
36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BAIL_ON_FAIL(out.write(&endMarker, 0, 1), ret);
36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint16_t tiffMarker = TIFF_FILE_MARKER;
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BAIL_ON_FAIL(out.write(&tiffMarker, 0, 1), ret);
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint32_t offsetMarker = FILE_HEADER_SIZE;
36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BAIL_ON_FAIL(out.write(&offsetMarker, 0, 1), ret);
36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return ret;
37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)uint32_t TiffWriter::getTotalSize() const {
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint32_t totalSize = FILE_HEADER_SIZE;
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    sp<TiffIfd> ifd = mIfd;
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    while(ifd != NULL) {
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        totalSize += ifd->getSize();
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ifd = ifd->getNextIfd();
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return totalSize;
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TiffWriter::log() const {
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ALOGI("%s: TiffWriter:", __FUNCTION__);
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size_t length = mNamedIfds.size();
38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (size_t i = 0; i < length; ++i) {
38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        mNamedIfds[i]->log();
38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} /*namespace img_utils*/
39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} /*namespace android*/
39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)