blob: c73e23134220d893706d6e5deba2faa5cbdf90d1 [file] [log] [blame]
/*
* 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 <img_utils/TiffIfd.h>
#include <img_utils/TiffEntry.h>
#include <img_utils/TiffHelpers.h>
#include <img_utils/Output.h>
#include <img_utils/EndianUtils.h>
#include <utils/Log.h>
#include <utils/Errors.h>
#include <utils/Vector.h>
#include <utils/StrongPointer.h>
#include <stdint.h>
namespace android {
namespace img_utils {
template<typename T>
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<T> mData;
};
template<typename T>
TiffEntryImpl<T>::TiffEntryImpl(uint16_t tag, TagType type, uint32_t count, Endianness end,
const T* data)
: mTag(tag), mType(static_cast<uint16_t>(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<typename T>
TiffEntryImpl<T>::~TiffEntryImpl() {}
template<typename T>
uint32_t TiffEntryImpl<T>::getCount() const {
return mCount;
}
template<typename T>
uint16_t TiffEntryImpl<T>::getTag() const {
return mTag;
}
template<typename T>
TagType TiffEntryImpl<T>::getType() const {
return static_cast<TagType>(mType);
}
template<typename T>
const void* TiffEntryImpl<T>::getDataHelper() const {
return reinterpret_cast<const void*>(mData.array());
}
template<typename T>
size_t TiffEntryImpl<T>::getSize() const {
uint32_t total = getActualSize();
WORD_ALIGN(total)
return (total <= OFFSET_SIZE) ? 0 : total;
}
template<typename T>
uint32_t TiffEntryImpl<T>::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<typename T>
Endianness TiffEntryImpl<T>::getEndianness() const {
return mEnd;
}
template<typename T>
uint32_t TiffEntryImpl<T>::getComparableValue() const {
return mTag;
}
template<typename T>
status_t TiffEntryImpl<T>::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<typename T>
status_t TiffEntryImpl<T>::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<sp<TiffIfd> >::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<sp<TiffIfd> >::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<sp<TiffIfd> >::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*/