/* * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef IMG_UTILS_TIFF_ENTRY_IMPL #define IMG_UTILS_TIFF_ENTRY_IMPL #include #include #include #include #include #include #include #include #include #include namespace android { namespace img_utils { template class TiffEntryImpl : public TiffEntry { public: TiffEntryImpl(uint16_t tag, TagType type, uint32_t count, Endianness end, const T* data); virtual ~TiffEntryImpl(); status_t writeData(uint32_t offset, /*out*/EndianOutput* out) const; status_t writeTagInfo(uint32_t offset, /*out*/EndianOutput* out) const; uint32_t getCount() const; uint16_t getTag() const; TagType getType() const; Endianness getEndianness() const; size_t getSize() const; uint32_t getComparableValue() const; protected: const void* getDataHelper() const; uint32_t getActualSize() const; uint16_t mTag; uint16_t mType; uint32_t mCount; Endianness mEnd; Vector mData; }; template TiffEntryImpl::TiffEntryImpl(uint16_t tag, TagType type, uint32_t count, Endianness end, const T* data) : mTag(tag), mType(static_cast(type)), mCount(count), mEnd(end) { count = (type == RATIONAL || type == SRATIONAL) ? count * 2 : count; ssize_t index = mData.appendArray(data, count); LOG_ALWAYS_FATAL_IF(index < 0, "%s: Could not allocate vector for data.", __FUNCTION__); } template TiffEntryImpl::~TiffEntryImpl() {} template uint32_t TiffEntryImpl::getCount() const { return mCount; } template uint16_t TiffEntryImpl::getTag() const { return mTag; } template TagType TiffEntryImpl::getType() const { return static_cast(mType); } template const void* TiffEntryImpl::getDataHelper() const { return reinterpret_cast(mData.array()); } template size_t TiffEntryImpl::getSize() const { uint32_t total = getActualSize(); WORD_ALIGN(total) return (total <= OFFSET_SIZE) ? 0 : total; } template uint32_t TiffEntryImpl::getActualSize() const { uint32_t total = sizeof(T) * mCount; if (getType() == RATIONAL || getType() == SRATIONAL) { // 2 ints stored for each rational, multiply by 2 total <<= 1; } return total; } template Endianness TiffEntryImpl::getEndianness() const { return mEnd; } template uint32_t TiffEntryImpl::getComparableValue() const { return mTag; } template status_t TiffEntryImpl::writeTagInfo(uint32_t offset, /*out*/EndianOutput* out) const { assert((offset % TIFF_WORD_SIZE) == 0); status_t ret = OK; BAIL_ON_FAIL(out->write(&mTag, 0, 1), ret); BAIL_ON_FAIL(out->write(&mType, 0, 1), ret); BAIL_ON_FAIL(out->write(&mCount, 0, 1), ret); uint32_t dataSize = getActualSize(); if (dataSize > OFFSET_SIZE) { BAIL_ON_FAIL(out->write(&offset, 0, 1), ret); } else { uint32_t count = mCount; if (getType() == RATIONAL || getType() == SRATIONAL) { /** * Rationals are stored as an array of ints. Each * rational is represented by 2 ints. To recover the * size of the array here, multiply the count by 2. */ count <<= 1; } BAIL_ON_FAIL(out->write(mData.array(), 0, count), ret); ZERO_TILL_WORD(out, dataSize, ret); } return ret; } template status_t TiffEntryImpl::writeData(uint32_t /*offset*/, EndianOutput* out) const { status_t ret = OK; // Some tags have fixed-endian value output Endianness tmp = UNDEFINED_ENDIAN; if (mEnd != UNDEFINED_ENDIAN) { tmp = out->getEndianness(); out->setEndianness(mEnd); } uint32_t count = mCount; if (getType() == RATIONAL || getType() == SRATIONAL) { /** * Rationals are stored as an array of ints. Each * rational is represented by 2 ints. To recover the * size of the array here, multiply the count by 2. */ count <<= 1; } BAIL_ON_FAIL(out->write(mData.array(), 0, count), ret); if (mEnd != UNDEFINED_ENDIAN) { out->setEndianness(tmp); } // Write to next word alignment ZERO_TILL_WORD(out, sizeof(T) * count, ret); return ret; } template<> inline status_t TiffEntryImpl >::writeTagInfo(uint32_t offset, /*out*/EndianOutput* out) const { assert((offset % TIFF_WORD_SIZE) == 0); status_t ret = OK; BAIL_ON_FAIL(out->write(&mTag, 0, 1), ret); BAIL_ON_FAIL(out->write(&mType, 0, 1), ret); BAIL_ON_FAIL(out->write(&mCount, 0, 1), ret); BAIL_ON_FAIL(out->write(&offset, 0, 1), ret); return ret; } template<> inline uint32_t TiffEntryImpl >::getActualSize() const { uint32_t total = 0; for (size_t i = 0; i < mData.size(); ++i) { total += mData[i]->getSize(); } return total; } template<> inline status_t TiffEntryImpl >::writeData(uint32_t offset, EndianOutput* out) const { status_t ret = OK; for (uint32_t i = 0; i < mCount; ++i) { BAIL_ON_FAIL(mData[i]->writeData(offset, out), ret); offset += mData[i]->getSize(); } return ret; } } /*namespace img_utils*/ } /*namespace android*/ #endif /*IMG_UTILS_TIFF_ENTRY_IMPL*/