From e507721000647a7d8afe44c63ef7fd04ef8971b1 Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Mon, 28 Apr 2014 16:39:12 -0700 Subject: camera2: Adding TIFF writing utilities. Adds a native image utilities library with support for: - Writing TIFF 6.0 and TIFF EP compliant file headers. - Additional tags defined in EXIF 2.3 and DNG 1.4 specs. Change-Id: I7a4fef74bd5254d92baf08a3cf61af5de1b7ca83 --- .../img_utils/include/img_utils/ByteArrayOutput.h | 82 ++ media/img_utils/include/img_utils/DngUtils.h | 132 +++ media/img_utils/include/img_utils/EndianUtils.h | 250 +++++ media/img_utils/include/img_utils/FileInput.h | 76 ++ media/img_utils/include/img_utils/FileOutput.h | 46 + media/img_utils/include/img_utils/Input.h | 63 ++ media/img_utils/include/img_utils/Orderable.h | 57 + media/img_utils/include/img_utils/Output.h | 61 ++ media/img_utils/include/img_utils/Pair.h | 44 + .../include/img_utils/SortedEntryVector.h | 53 + media/img_utils/include/img_utils/TagDefinitions.h | 1139 ++++++++++++++++++++ media/img_utils/include/img_utils/TiffEntry.h | 129 +++ media/img_utils/include/img_utils/TiffEntryImpl.h | 190 ++++ media/img_utils/include/img_utils/TiffHelpers.h | 132 +++ media/img_utils/include/img_utils/TiffIfd.h | 124 +++ media/img_utils/include/img_utils/TiffWritable.h | 60 ++ media/img_utils/include/img_utils/TiffWriter.h | 267 +++++ 17 files changed, 2905 insertions(+) create mode 100644 media/img_utils/include/img_utils/ByteArrayOutput.h create mode 100644 media/img_utils/include/img_utils/DngUtils.h create mode 100644 media/img_utils/include/img_utils/EndianUtils.h create mode 100644 media/img_utils/include/img_utils/FileInput.h create mode 100644 media/img_utils/include/img_utils/FileOutput.h create mode 100644 media/img_utils/include/img_utils/Input.h create mode 100644 media/img_utils/include/img_utils/Orderable.h create mode 100644 media/img_utils/include/img_utils/Output.h create mode 100644 media/img_utils/include/img_utils/Pair.h create mode 100644 media/img_utils/include/img_utils/SortedEntryVector.h create mode 100644 media/img_utils/include/img_utils/TagDefinitions.h create mode 100644 media/img_utils/include/img_utils/TiffEntry.h create mode 100644 media/img_utils/include/img_utils/TiffEntryImpl.h create mode 100644 media/img_utils/include/img_utils/TiffHelpers.h create mode 100644 media/img_utils/include/img_utils/TiffIfd.h create mode 100644 media/img_utils/include/img_utils/TiffWritable.h create mode 100644 media/img_utils/include/img_utils/TiffWriter.h (limited to 'media/img_utils/include') diff --git a/media/img_utils/include/img_utils/ByteArrayOutput.h b/media/img_utils/include/img_utils/ByteArrayOutput.h new file mode 100644 index 0000000..ba73977 --- /dev/null +++ b/media/img_utils/include/img_utils/ByteArrayOutput.h @@ -0,0 +1,82 @@ +/* + * 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_BYTE_ARRAY_OUTPUT_H +#define IMG_UTILS_BYTE_ARRAY_OUTPUT_H + +#include + +#include +#include + +#include +#include + +namespace android { +namespace img_utils { + +/** + * Utility class that accumulates written bytes into a buffer. + */ +class ANDROID_API ByteArrayOutput : public Output { + public: + + ByteArrayOutput(); + + virtual ~ByteArrayOutput(); + + /** + * Open this ByteArrayOutput. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t open(); + + /** + * Write bytes from the given buffer. The number of bytes given in the count + * argument will be written. Bytes will be written from the given buffer starting + * at the index given in the offset argument. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t write(const uint8_t* buf, size_t offset, size_t count); + + /** + * Close this ByteArrayOutput. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t close(); + + /** + * Get current size of the array of bytes written. + */ + virtual size_t getSize() const; + + /** + * Get pointer to array of bytes written. It is not valid to use this pointer if + * open, write, or close is called after this method. + */ + virtual const uint8_t* getArray() const; + + protected: + Vector mByteArray; +}; + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_BYTE_ARRAY_OUTPUT_H*/ diff --git a/media/img_utils/include/img_utils/DngUtils.h b/media/img_utils/include/img_utils/DngUtils.h new file mode 100644 index 0000000..4389b02 --- /dev/null +++ b/media/img_utils/include/img_utils/DngUtils.h @@ -0,0 +1,132 @@ +/* + * 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_DNG_UTILS_H +#define IMG_UTILS_DNG_UTILS_H + +#include +#include + +#include +#include +#include + +#include +#include + +namespace android { +namespace img_utils { + +#define NELEMS(x) ((int) (sizeof(x) / sizeof((x)[0]))) + +/** + * Utility class for building values for the OpcodeList tags specified + * in the Adobe DNG 1.4 spec. + */ +class ANDROID_API OpcodeListBuilder : public LightRefBase { + public: + enum CfaLayout { + CFA_RGGB = 0, + CFA_GRBG, + CFA_GBRG, + CFA_BGGR, + }; + + OpcodeListBuilder(); + virtual ~OpcodeListBuilder(); + + /** + * Get the total size of this opcode list in bytes. + */ + virtual size_t getSize() const; + + /** + * Get the number of opcodes defined in this list. + */ + virtual uint32_t getCount() const; + + /** + * Write the opcode list into the given buffer. This buffer + * must be able to hold at least as many elements as returned + * by calling the getSize() method. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t buildOpList(/*out*/ uint8_t* buf) const; + + /** + * Add GainMap opcode(s) for the given metadata parameters. The given + * CFA layout must match the layout of the shading map passed into the + * lensShadingMap parameter. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t addGainMapsForMetadata(uint32_t lsmWidth, + uint32_t lsmHeight, + uint32_t activeAreaTop, + uint32_t activeAreaLeft, + uint32_t activeAreaBottom, + uint32_t activeAreaRight, + CfaLayout cfa, + const float* lensShadingMap); + + + /** + * Add a GainMap opcode with the given fields. The mapGains array + * must have mapPointsV * mapPointsH * mapPlanes elements. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t addGainMap(uint32_t top, + uint32_t left, + uint32_t bottom, + uint32_t right, + uint32_t plane, + uint32_t planes, + uint32_t rowPitch, + uint32_t colPitch, + uint32_t mapPointsV, + uint32_t mapPointsH, + double mapSpacingV, + double mapSpacingH, + double mapOriginV, + double mapOriginH, + uint32_t mapPlanes, + const float* mapGains); + + // TODO: Add other Opcode methods + protected: + static const uint32_t FLAG_OPTIONAL = 0x1u; + static const uint32_t FLAG_OPTIONAL_FOR_PREVIEW = 0x2u; + + enum { + GAIN_MAP_ID = 9, + LSM_R_IND = 0, + LSM_GE_IND = 1, + LSM_GO_IND = 2, + LSM_B_IND = 3, + }; + + uint32_t mCount; + ByteArrayOutput mOpList; + EndianOutput mEndianOut; + +}; + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_DNG_UTILS_H*/ diff --git a/media/img_utils/include/img_utils/EndianUtils.h b/media/img_utils/include/img_utils/EndianUtils.h new file mode 100644 index 0000000..e99be1a --- /dev/null +++ b/media/img_utils/include/img_utils/EndianUtils.h @@ -0,0 +1,250 @@ +/* + * 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_ENDIAN_UTILS +#define IMG_UTILS_ENDIAN_UTILS + +#include + +#include +#include +#include +#include +#include + +namespace android { +namespace img_utils { + +/** + * Endianness types supported. + */ +enum ANDROID_API Endianness { + UNDEFINED_ENDIAN, // Default endianness will be used. + BIG, + LITTLE +}; + +/** + * Convert from the native device endianness to big endian. + */ +template +T convertToBigEndian(T in); + +/** + * Convert from the native device endianness to little endian. + */ +template +T convertToLittleEndian(T in); + +/** + * A utility class for writing to an Output with the given endianness. + */ +class ANDROID_API EndianOutput : public Output { + public: + /** + * Wrap the given Output. Calling write methods will result in + * writes to this output. + */ + EndianOutput(Output* out, Endianness end=LITTLE); + + virtual ~EndianOutput(); + + /** + * Call open on the wrapped output. + */ + virtual status_t open(); + + /** + * Call close on the wrapped output. + */ + virtual status_t close(); + + /** + * Set the endianness to use when writing. + */ + virtual void setEndianness(Endianness end); + + /** + * Get the currently configured endianness. + */ + virtual Endianness getEndianness() const; + + /** + * Get the current number of bytes written by this EndianOutput. + */ + virtual uint32_t getCurrentOffset() const; + + + // TODO: switch write methods to uint32_t instead of size_t, + // the max size of a TIFF files is bounded + + /** + * The following methods will write elements from given input buffer to the output. + * Count elements in the buffer will be written with the endianness set for this + * EndianOutput. If the given offset is greater than zero, that many elements will + * be skipped in the buffer before writing. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t write(const uint8_t* buf, size_t offset, size_t count); + + virtual status_t write(const int8_t* buf, size_t offset, size_t count); + + virtual status_t write(const uint16_t* buf, size_t offset, size_t count); + + virtual status_t write(const int16_t* buf, size_t offset, size_t count); + + virtual status_t write(const uint32_t* buf, size_t offset, size_t count); + + virtual status_t write(const int32_t* buf, size_t offset, size_t count); + + virtual status_t write(const uint64_t* buf, size_t offset, size_t count); + + virtual status_t write(const int64_t* buf, size_t offset, size_t count); + + virtual status_t write(const float* buf, size_t offset, size_t count); + + virtual status_t write(const double* buf, size_t offset, size_t count); + + protected: + template + inline status_t writeHelper(const T* buf, size_t offset, size_t count); + + uint32_t mOffset; + Output* mOutput; + Endianness mEndian; +}; + +template +inline status_t EndianOutput::writeHelper(const T* buf, size_t offset, size_t count) { + assert(offset <= count); + status_t res = OK; + size_t size = sizeof(T); + switch(mEndian) { + case BIG: { + for (size_t i = offset; i < count; ++i) { + T tmp = convertToBigEndian(buf[offset + i]); + if ((res = mOutput->write(reinterpret_cast(&tmp), 0, size)) + != OK) { + return res; + } + mOffset += size; + } + break; + } + case LITTLE: { + for (size_t i = offset; i < count; ++i) { + T tmp = convertToLittleEndian(buf[offset + i]); + if ((res = mOutput->write(reinterpret_cast(&tmp), 0, size)) + != OK) { + return res; + } + mOffset += size; + } + break; + } + default: { + return BAD_VALUE; + } + } + return res; +} + +template<> +inline uint8_t convertToBigEndian(uint8_t in) { + return in; +} + +template<> +inline int8_t convertToBigEndian(int8_t in) { + return in; +} + +template<> +inline uint16_t convertToBigEndian(uint16_t in) { + return htobe16(in); +} + +template<> +inline int16_t convertToBigEndian(int16_t in) { + return htobe16(in); +} + +template<> +inline uint32_t convertToBigEndian(uint32_t in) { + return htobe32(in); +} + +template<> +inline int32_t convertToBigEndian(int32_t in) { + return htobe32(in); +} + +template<> +inline uint64_t convertToBigEndian(uint64_t in) { + return htobe64(in); +} + +template<> +inline int64_t convertToBigEndian(int64_t in) { + return htobe64(in); +} + +template<> +inline uint8_t convertToLittleEndian(uint8_t in) { + return in; +} + +template<> +inline int8_t convertToLittleEndian(int8_t in) { + return in; +} + +template<> +inline uint16_t convertToLittleEndian(uint16_t in) { + return htole16(in); +} + +template<> +inline int16_t convertToLittleEndian(int16_t in) { + return htole16(in); +} + +template<> +inline uint32_t convertToLittleEndian(uint32_t in) { + return htole32(in); +} + +template<> +inline int32_t convertToLittleEndian(int32_t in) { + return htole32(in); +} + +template<> +inline uint64_t convertToLittleEndian(uint64_t in) { + return htole64(in); +} + +template<> +inline int64_t convertToLittleEndian(int64_t in) { + return htole64(in); +} + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_ENDIAN_UTILS*/ + diff --git a/media/img_utils/include/img_utils/FileInput.h b/media/img_utils/include/img_utils/FileInput.h new file mode 100644 index 0000000..d3c5ec1 --- /dev/null +++ b/media/img_utils/include/img_utils/FileInput.h @@ -0,0 +1,76 @@ +/* + * 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_FILE_INPUT_H +#define IMG_UTILS_FILE_INPUT_H + +#include + +#include +#include +#include +#include +#include + +namespace android { +namespace img_utils { + +/** + * Utility class for reading from a file. + */ +class ANDROID_API FileInput : public Input { + public: + /** + * Create a file input for the given path. + */ + FileInput(String8 path); + + virtual ~FileInput(); + + /** + * Open a file descriptor to the path given in the constructor. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t open(); + + /** + * Read bytes from the file into the given buffer. At most, the number + * of bytes given in the count argument will be read. Bytes will be written + * into the given buffer starting at the index given in the offset argument. + * + * Returns the number of bytes read. If an error has occurred, the value pointed + * to by the given status_t pointer will be set to a negative error code. + */ + virtual size_t read(uint8_t* buf, size_t offset, size_t count, status_t* err); + + /** + * Close the file descriptor to the path given in the constructor. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t close(); + private: + FILE *mFp; + String8 mPath; + bool mOpen; +}; + +} /*namespace img_utils*/ +} /*namespace android*/ + + +#endif /*IMG_UTILS_INPUT_H*/ diff --git a/media/img_utils/include/img_utils/FileOutput.h b/media/img_utils/include/img_utils/FileOutput.h new file mode 100644 index 0000000..fd5be27 --- /dev/null +++ b/media/img_utils/include/img_utils/FileOutput.h @@ -0,0 +1,46 @@ +/* + * 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_FILE_OUTPUT_H +#define IMG_UTILS_FILE_OUTPUT_H + +#include +#include +#include +#include +#include +#include + +namespace android { +namespace img_utils { + +class ANDROID_API FileOutput : public Output { + public: + FileOutput(String8 path); + virtual ~FileOutput(); + virtual status_t open(); + virtual status_t write(const uint8_t* buf, size_t offset, size_t count); + virtual status_t close(); + private: + FILE *mFp; + String8 mPath; + bool mOpen; +}; + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_FILE_OUTPUT_H*/ diff --git a/media/img_utils/include/img_utils/Input.h b/media/img_utils/include/img_utils/Input.h new file mode 100644 index 0000000..2166601 --- /dev/null +++ b/media/img_utils/include/img_utils/Input.h @@ -0,0 +1,63 @@ +/* + * 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_INPUT_H +#define IMG_UTILS_INPUT_H + +#include +#include +#include + +namespace android { +namespace img_utils { + +/** + * Utility class used as a source of bytes. + */ +class ANDROID_API Input { + public: + virtual ~Input(); + + /** + * Open this Input. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t open(); + + /** + * Read bytes into the given buffer. At most, the number of bytes given in the + * count argument will be read. Bytes will be written into the given buffer starting + * at the index given in the offset argument. + * + * Returns the number of bytes read. If an error has occurred, the value pointed + * to by the given status_t pointer will be set to a negative error code. + */ + virtual size_t read(uint8_t* buf, size_t offset, size_t count, status_t* err) = 0; + + /** + * Close the Input. It is not valid to call open on a previously closed Input. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t close(); +}; + +} /*namespace img_utils*/ +} /*namespace android*/ + + +#endif /*IMG_UTILS_INPUT_H*/ diff --git a/media/img_utils/include/img_utils/Orderable.h b/media/img_utils/include/img_utils/Orderable.h new file mode 100644 index 0000000..87253a4 --- /dev/null +++ b/media/img_utils/include/img_utils/Orderable.h @@ -0,0 +1,57 @@ +/* + * 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_ORDERABLE +#define IMG_UTILS_ORDERABLE + +#include +#include + +namespace android { +namespace img_utils { + +#define COMPARE_DEF(op) \ +inline bool operator op (const Orderable& orderable) const; + +/** + * Subclasses of Orderable can be compared and sorted. This is + * intended to be used to create sorted arrays of TIFF entries + * and IFDs. + */ +class ANDROID_API Orderable { + public: + virtual ~Orderable(); + + /** + * Comparison operatotors are based on the value returned + * from this method. + */ + virtual uint32_t getComparableValue() const = 0; + + COMPARE_DEF(>) + COMPARE_DEF(<) + COMPARE_DEF(>=) + COMPARE_DEF(<=) + COMPARE_DEF(==) + COMPARE_DEF(!=) +}; + +#undef COMPARE_DEF + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_ORDERABLE*/ diff --git a/media/img_utils/include/img_utils/Output.h b/media/img_utils/include/img_utils/Output.h new file mode 100644 index 0000000..35fae23 --- /dev/null +++ b/media/img_utils/include/img_utils/Output.h @@ -0,0 +1,61 @@ +/* + * 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_OUTPUT_H +#define IMG_UTILS_OUTPUT_H + +#include +#include +#include + +namespace android { +namespace img_utils { + +/** + * Utility class used to output bytes. + */ +class ANDROID_API Output { + public: + virtual ~Output(); + + /** + * Open this Output. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t open(); + + /** + * Write bytes from the given buffer. The number of bytes given in the count + * argument will be written. Bytes will be written from the given buffer starting + * at the index given in the offset argument. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t write(const uint8_t* buf, size_t offset, size_t count) = 0; + + /** + * Close this Output. It is not valid to call open on a previously closed Output. + * + * Returns OK on success, or a negative error code. + */ + virtual status_t close(); +}; + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_OUTPUT_H*/ diff --git a/media/img_utils/include/img_utils/Pair.h b/media/img_utils/include/img_utils/Pair.h new file mode 100644 index 0000000..d651cac --- /dev/null +++ b/media/img_utils/include/img_utils/Pair.h @@ -0,0 +1,44 @@ +/* + * 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_PAIR_H +#define IMG_UTILS_PAIR_H + +#include + +namespace android { +namespace img_utils { + +/** + * Generic pair utility class. Nothing special here. + */ +template +class ANDROID_API Pair { + public: + F first; + S second; + + Pair() {} + + Pair(const Pair& o) : first(o.first), second(o.second) {} + + Pair(const F& f, const S& s) : first(f), second(s) {} +}; + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_PAIR_H*/ diff --git a/media/img_utils/include/img_utils/SortedEntryVector.h b/media/img_utils/include/img_utils/SortedEntryVector.h new file mode 100644 index 0000000..f059a82 --- /dev/null +++ b/media/img_utils/include/img_utils/SortedEntryVector.h @@ -0,0 +1,53 @@ +/* + * 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_SORTED_ENTRY_VECTOR_H +#define IMG_UTILS_SORTED_ENTRY_VECTOR_H + +#include + +#include +#include + +namespace android { +namespace img_utils { + +/** + * Subclass of SortedVector that has been extended to + * do comparisons/lookups based on the tag ID of the entries. + */ +class SortedEntryVector : public SortedVector > { + public: + virtual ~SortedEntryVector(); + + /** + * Returns the index of the entry with the given tag ID, or + * -1 if none exists. + */ + ssize_t indexOfTag(uint16_t tag) const; + + protected: + /** + * Compare tag ID. + */ + virtual int do_compare(const void* lhs, const void* rhs) const; +}; + + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_SORTED_ENTRY_VECTOR_H*/ diff --git a/media/img_utils/include/img_utils/TagDefinitions.h b/media/img_utils/include/img_utils/TagDefinitions.h new file mode 100644 index 0000000..9232e58 --- /dev/null +++ b/media/img_utils/include/img_utils/TagDefinitions.h @@ -0,0 +1,1139 @@ +/* + * 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_TAG_DEFINITION_H +#define IMG_UTILS_TIFF_TAG_DEFINITION_H + +#include +#include +#include +#include + +namespace android { +namespace img_utils { + +/** + * Tag definitions contain information about standard TIFF compatible tags. + */ +typedef struct TagDefinition { + // The specified tag ID. + uint16_t tagId; + // The default type for this tag. This must be a valid TIFF type. + TagType defaultType; + // The default Image File Directory (IFD) for this tag. + uint32_t defaultIfd; + // The valid count for this tag, or 0 if the count is not fixed. + uint32_t fixedCount; + // The endianness of the tag value, or UNDEFINED_ENDIAN if there is no fixed endian + Endianness fixedEndian; +} TagDefinition_t; + +/** + * Convenience defines for tag ids. + */ +enum { + TAG_RAWTOPREVIEWGAIN = 0xC7A8u, + TAG_NEWRAWIMAGEDIGEST = 0xC7A7u, + TAG_ORIGINALDEFAULTCROPSIZE = 0xC793u, + TAG_ORIGINALBESTQUALITYFINALSIZE = 0xC792u, + TAG_ORIGINALDEFAULTFINALSIZE = 0xC791u, + TAG_PROFILEHUESATMAPENCODING = 0xC7A3u, + TAG_PROFILELOOKTABLEENCODING = 0xC7A4u, + TAG_BASELINEEXPOSUREOFFSET = 0xC7A5u, + TAG_DEFAULTBLACKRENDER = 0xC7A6u, + TAG_DEFAULTUSERCROP = 0xC7B5u, + TAG_NOISEPROFILE = 0xC761u, + TAG_OPCODELIST3 = 0xC74Eu, + TAG_OPCODELIST2 = 0xC741u, + TAG_OPCODELIST1 = 0xC740u, + TAG_PROFILELOOKTABLEDATA = 0xC726u, + TAG_PROFILELOOKTABLEDIMS = 0xC725u, + TAG_ROWINTERLEAVEFACTOR = 0xC71Fu, + TAG_SUBTILEBLOCKSIZE = 0xC71Eu, + TAG_ORIGINALRAWFILEDIGEST = 0xC71Du, + TAG_RAWIMAGEDIGEST = 0xC71Cu, + TAG_PREVIEWDATETIME = 0xC71Bu, + TAG_PREVIEWCOLORSPACE = 0xC71Au, + TAG_PREVIEWSETTINGSDIGEST = 0xC719u, + TAG_PREVIEWSETTINGSNAME = 0xC718u, + TAG_PREVIEWAPPLICATIONVERSION = 0xC717u, + TAG_PREVIEWAPPLICATIONNAME = 0xC716u, + TAG_FORWARDMATRIX2 = 0xC715u, + TAG_FORWARDMATRIX1 = 0xC714u, + TAG_PROFILECOPYRIGHT = 0xC6FEu, + TAG_PROFILEEMBEDPOLICY = 0xC6FDu, + TAG_PROFILETONECURVE = 0xC6FCu, + TAG_PROFILEHUESATMAPDATA2 = 0xC6FBu, + TAG_PROFILEHUESATMAPDATA1 = 0xC6FAu, + TAG_PROFILEHUESATMAPDIMS = 0xC6F9u, + TAG_PROFILENAME = 0xC6F8u, + TAG_NOISEREDUCTIONAPPLIED = 0xC6F7u, + TAG_ASSHOTPROFILENAME = 0xC6F6u, + TAG_EXTRACAMERAPROFILES = 0xC6F5u, + TAG_PROFILECALIBRATIONSIGNATURE = 0xC6F4u, + TAG_CAMERACALIBRATIONSIGNATURE = 0xC6F3u, + TAG_COLORIMETRICREFERENCE = 0xC6BFu, + TAG_CURRENTPREPROFILEMATRIX = 0xC692u, + TAG_CURRENTICCPROFILE = 0xC691u, + TAG_ASSHOTPREPROFILEMATRIX = 0xC690u, + TAG_ASSHOTICCPROFILE = 0xC68Fu, + TAG_MASKEDAREAS = 0xC68Eu, + TAG_ACTIVEAREA = 0xC68Du, + TAG_ORIGINALRAWFILEDATA = 0xC68Cu, + TAG_ORIGINALRAWFILENAME = 0xC68Bu, + TAG_RAWDATAUNIQUEID = 0xC65Du, + TAG_MAKERNOTESAFETY = 0xC635u, + TAG_DNGPRIVATEDATA = 0xC634u, + TAG_SHADOWSCALE = 0xC633u, + TAG_ANTIALIASSTRENGTH = 0xC632u, + TAG_CHROMABLURRADIUS = 0xC631u, + TAG_LENSINFO = 0xC630u, + TAG_CAMERASERIALNUMBER = 0xC62Fu, + TAG_LINEARRESPONSELIMIT = 0xC62Eu, + TAG_BAYERGREENSPLIT = 0xC62Du, + TAG_BASELINESHARPNESS = 0xC62Cu, + TAG_BASELINENOISE = 0xC62Bu, + TAG_BASELINEEXPOSURE = 0xC62Au, + TAG_ASSHOTWHITEXY = 0xC629u, + TAG_ASSHOTNEUTRAL = 0xC628u, + TAG_ANALOGBALANCE = 0xC627u, + TAG_REDUCTIONMATRIX2 = 0xC626u, + TAG_REDUCTIONMATRIX1 = 0xC625u, + TAG_CAMERACALIBRATION2 = 0xC624u, + TAG_CAMERACALIBRATION1 = 0xC623u, + TAG_COLORMATRIX2 = 0xC622u, + TAG_COLORMATRIX1 = 0xC621u, + TAG_CALIBRATIONILLUMINANT2 = 0xC65Bu, + TAG_CALIBRATIONILLUMINANT1 = 0xC65Au, + TAG_DEFAULTCROPSIZE = 0xC620u, + TAG_DEFAULTCROPORIGIN = 0xC61Fu, + TAG_BESTQUALITYSCALE = 0xC65Cu, + TAG_DEFAULTSCALE = 0xC61Eu, + TAG_WHITELEVEL = 0xC61Du, + TAG_BLACKLEVELDELTAV = 0xC61Cu, + TAG_BLACKLEVELDELTAH = 0xC61Bu, + TAG_BLACKLEVEL = 0xC61Au, + TAG_BLACKLEVELREPEATDIM = 0xC619u, + TAG_LINEARIZATIONTABLE = 0xC618u, + TAG_CFALAYOUT = 0xC617u, + TAG_CFAPLANECOLOR = 0xC616u, + TAG_LOCALIZEDCAMERAMODEL = 0xC615u, + TAG_UNIQUECAMERAMODEL = 0xC614u, + TAG_DNGBACKWARDVERSION = 0xC613u, + TAG_DNGVERSION = 0xC612u, + TAG_SUBFILETYPE = 0x00FFu, + TAG_YRESOLUTION = 0x011Bu, + TAG_XRESOLUTION = 0x011Au, + TAG_THRESHHOLDING = 0x0107u, + TAG_STRIPOFFSETS = 0x0111u, + TAG_STRIPBYTECOUNTS = 0x0117u, + TAG_SOFTWARE = 0x0131u, + TAG_SAMPLESPERPIXEL = 0x0115u, + TAG_ROWSPERSTRIP = 0x0116u, + TAG_RESOLUTIONUNIT = 0x0128u, + TAG_PLANARCONFIGURATION = 0x011Cu, + TAG_PHOTOMETRICINTERPRETATION = 0x0106u, + TAG_ORIENTATION = 0x0112u, + TAG_NEWSUBFILETYPE = 0x00FEu, + TAG_MODEL = 0x0110u, + TAG_MINSAMPLEVALUE = 0x0118u, + TAG_MAXSAMPLEVALUE = 0x0119u, + TAG_MAKE = 0x010Fu, + TAG_IMAGEWIDTH = 0x0100u, + TAG_IMAGELENGTH = 0x0101u, + TAG_IMAGEDESCRIPTION = 0x010Eu, + TAG_HOSTCOMPUTER = 0x013Cu, + TAG_GRAYRESPONSEUNIT = 0x0122u, + TAG_GRAYRESPONSECURVE = 0x0123u, + TAG_FREEOFFSETS = 0x0120u, + TAG_FREEBYTECOUNTS = 0x0121u, + TAG_FILLORDER = 0x010Au, + TAG_EXTRASAMPLES = 0x0152u, + TAG_DATETIME = 0x0132u, + TAG_COPYRIGHT = 0x8298u, + TAG_COMPRESSION = 0x0103u, + TAG_COLORMAP = 0x0140u, + TAG_CELLWIDTH = 0x0108u, + TAG_CELLLENGTH = 0x0109u, + TAG_BITSPERSAMPLE = 0x0102u, + TAG_ARTIST = 0x013Bu, + TAG_EXIFVERSION = 0x9000u, + TAG_CFAREPEATPATTERNDIM = 0x828Du, + TAG_CFAPATTERN = 0x828Eu, + TAG_SUBIFDS = 0x014Au, +}; + +/** + * TIFF_EP_TAG_DEFINITIONS contains tags defined in the TIFF EP spec + */ +const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = { + { // PhotometricInterpretation + 0x0106u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // SubIfds + 0x014Au, + LONG, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // CFAPattern + 0x828Eu, + BYTE, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // CFARepeatPatternDim + 0x828Du, + SHORT, + IFD_0, + 2, + UNDEFINED_ENDIAN + }, + /*TODO: Remaining TIFF EP tags*/ +}; + +/** + * EXIF_2_3_TAG_DEFINITIONS contains tags defined in the Jeita EXIF 2.3 spec + */ +const TagDefinition_t EXIF_2_3_TAG_DEFINITIONS[] = { + { // ExifVersion + 0x9000u, + UNDEFINED, + IFD_0, + 4, + UNDEFINED_ENDIAN + }, + /*TODO: Remaining EXIF 2.3 tags*/ +}; + +/** + * TIFF_6_TAG_DEFINITIONS contains tags defined in the TIFF 6.0 spec + */ +const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = { + { // SubFileType + 0x00FFu, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // Artist + 0x013Bu, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // BitsPerSample + 0x0102u, + SHORT, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // CellLength + 0x0109u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // CellWidth + 0x0108u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // ColorMap + 0x0140u, + SHORT, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // Compression + 0x0103u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // Copyright + 0x8298u, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // DateTime + 0x0132u, + ASCII, + IFD_0, + 20, + UNDEFINED_ENDIAN + }, + { // ExtraSamples + 0x0152u, + SHORT, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // FillOrder + 0x010Au, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // FreeByteCounts + 0x0121u, + LONG, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // FreeOffsets + 0x0120u, + LONG, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // GrayResponseCurve + 0x0123u, + SHORT, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // GrayResponseUnit + 0x0122u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // HostComputer + 0x013Cu, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // ImageDescription + 0x010Eu, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // ImageLength + 0x0101u, + LONG, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // ImageWidth + 0x0100u, + LONG, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // Make + 0x010Fu, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // MaxSampleValue + 0x0119u, + SHORT, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // MinSampleValue + 0x0118u, + SHORT, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // Model + 0x0110u, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // NewSubfileType + 0x00FEu, + LONG, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // Orientation + 0x0112u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // PhotoMetricInterpretation + 0x0106u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // PlanarConfiguration + 0x011Cu, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // ResolutionUnit + 0x0128u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // RowsPerStrip + 0x0116u, + LONG, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // SamplesPerPixel + 0x0115u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // Software + 0x0131u, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // StripByteCounts + 0x0117u, + LONG, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // StripOffsets + 0x0111u, + LONG, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // SubfileType + 0x00FFu, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // Threshholding + 0x0107u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // XResolution + 0x011Au, + RATIONAL, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // YResolution + 0x011Bu, + RATIONAL, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // YResolution + 0x011Bu, + RATIONAL, + IFD_0, + 1, + UNDEFINED_ENDIAN + } +}; + +/** + * DNG_TAG_DEFINITIONS contains tags defined in the DNG 1.4 spec + */ +const TagDefinition_t DNG_TAG_DEFINITIONS[] = { + { // DNGVersion + 0xC612u, + BYTE, + IFD_0, + 4, + UNDEFINED_ENDIAN + }, + { // DNGBackwardVersion + 0xC613u, + BYTE, + IFD_0, + 4, + UNDEFINED_ENDIAN + }, + { // UniqueCameraModel + 0xC614u, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // LocalizedCameraModel + 0xC615u, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // CFAPlaneColor + 0xC616u, + BYTE, + RAW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // CFALayout + 0xC617u, + SHORT, + RAW_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // LinearizationTable + 0xC618u, + SHORT, + RAW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // BlackLevelRepeatDim + 0xC619u, + SHORT, + RAW_IFD, + 2, + UNDEFINED_ENDIAN + }, + { // BlackLevel + 0xC61Au, + LONG, + RAW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // BlackLevelDeltaH + 0xC61Bu, + SRATIONAL, + RAW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // BlackLevelDeltaV + 0xC61Cu, + SRATIONAL, + RAW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // WhiteLevel + 0xC61Du, + LONG, + RAW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // DefaultScale + 0xC61Eu, + RATIONAL, + RAW_IFD, + 2, + UNDEFINED_ENDIAN + }, + { // BestQualityScale + 0xC65Cu, + RATIONAL, + RAW_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // DefaultCropOrigin + 0xC61Fu, + LONG, + RAW_IFD, + 2, + UNDEFINED_ENDIAN + }, + { // DefaultCropSize + 0xC620u, + LONG, + RAW_IFD, + 2, + UNDEFINED_ENDIAN + }, + { // CalibrationIlluminant1 + 0xC65Au, + SHORT, + PROFILE_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // CalibrationIlluminant2 + 0xC65Bu, + SHORT, + PROFILE_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // ColorMatrix1 + 0xC621u, + SRATIONAL, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // ColorMatrix2 + 0xC622u, + SRATIONAL, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // CameraCalibration1 + 0xC623u, + SRATIONAL, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // CameraCalibration2 + 0xC624u, + SRATIONAL, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // ReductionMatrix1 + 0xC625u, + SRATIONAL, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // ReductionMatrix2 + 0xC626u, + SRATIONAL, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // AnalogBalance + 0xC627u, + RATIONAL, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // AsShotNeutral + 0xC628u, + RATIONAL, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // AsShotWhiteXY + 0xC629u, + RATIONAL, + IFD_0, + 2, + UNDEFINED_ENDIAN + }, + { // BaselineExposure + 0xC62Au, + SRATIONAL, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // BaselineNoise + 0xC62Bu, + RATIONAL, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // BaselineSharpness + 0xC62Cu, + RATIONAL, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // BayerGreenSplit + 0xC62Du, + LONG, + RAW_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // LinearResponseLimit + 0xC62Eu, + RATIONAL, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // CameraSerialNumber + 0xC62Fu, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // LensInfo + 0xC630u, + RATIONAL, + IFD_0, + 4, + UNDEFINED_ENDIAN + }, + { // ChromaBlurRadius + 0xC631u, + RATIONAL, + RAW_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // AntiAliasStrength + 0xC632u, + RATIONAL, + RAW_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // ShadowScale + 0xC633u, + RATIONAL, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // DNGPrivateData + 0xC634u, + BYTE, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // MakerNoteSafety + 0xC635u, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // RawDataUniqueID + 0xC65Du, + BYTE, + IFD_0, + 16, + UNDEFINED_ENDIAN + }, + { // OriginalRawFileName + 0xC68Bu, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // OriginalRawFileData + 0xC68Cu, + UNDEFINED, + IFD_0, + 0, + BIG + }, + { // ActiveArea + 0xC68Du, + LONG, + RAW_IFD, + 4, + UNDEFINED_ENDIAN + }, + { // MaskedAreas + 0xC68Eu, + LONG, + RAW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // AsShotICCProfile + 0xC68Fu, + UNDEFINED, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // AsShotPreProfileMatrix + 0xC690u, + SRATIONAL, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // CurrentICCProfile + 0xC691u, + UNDEFINED, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // CurrentICCProfile + 0xC691u, + UNDEFINED, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // CurrentPreProfileMatrix + 0xC692u, + SRATIONAL, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // ColorimetricReference + 0xC6BFu, + SHORT, + IFD_0, + 1, + UNDEFINED_ENDIAN + }, + { // CameraCalibrationSignature + 0xC6F3u, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // ProfileCalibrationSignature + 0xC6F4u, + ASCII, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // ExtraCameraProfiles + 0xC6F5u, + LONG, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // AsShotProfileName + 0xC6F6u, + ASCII, + IFD_0, + 0, + UNDEFINED_ENDIAN + }, + { // NoiseReductionApplied + 0xC6F7u, + RATIONAL, + RAW_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // ProfileName + 0xC6F8u, + ASCII, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // ProfileHueSatMapDims + 0xC6F9u, + LONG, + PROFILE_IFD, + 3, + UNDEFINED_ENDIAN + }, + { // ProfileHueSatMapData1 + 0xC6FAu, + FLOAT, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // ProfileHueSatMapData2 + 0xC6FBu, + FLOAT, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // ProfileToneCurve + 0xC6FCu, + FLOAT, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // ProfileEmbedPolicy + 0xC6FDu, + LONG, + PROFILE_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // ProfileCopyright + 0xC6FEu, + ASCII, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // ForwardMatrix1 + 0xC714u, + SRATIONAL, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // ForwardMatrix2 + 0xC715u, + SRATIONAL, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // PreviewApplicationName + 0xC716u, + ASCII, + PREVIEW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // PreviewApplicationVersion + 0xC717u, + ASCII, + PREVIEW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // PreviewSettingsName + 0xC718u, + ASCII, + PREVIEW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // PreviewSettingsDigest + 0xC719u, + BYTE, + PREVIEW_IFD, + 16, + UNDEFINED_ENDIAN + }, + { // PreviewColorSpace + 0xC71Au, + LONG, + PREVIEW_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // PreviewDateTime + 0xC71Bu, + ASCII, + PREVIEW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // RawImageDigest + 0xC71Cu, + BYTE, + IFD_0, + 16, + UNDEFINED_ENDIAN + }, + { // OriginalRawFileDigest + 0xC71Du, + BYTE, + IFD_0, + 16, + UNDEFINED_ENDIAN + }, + { // SubTileBlockSize + 0xC71Eu, + LONG, + RAW_IFD, + 2, + UNDEFINED_ENDIAN + }, + { // RowInterleaveFactor + 0xC71Fu, + LONG, + RAW_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // ProfileLookTableDims + 0xC725u, + LONG, + PROFILE_IFD, + 3, + UNDEFINED_ENDIAN + }, + { // ProfileLookTableData + 0xC726u, + FLOAT, + PROFILE_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // OpcodeList1 + 0xC740u, + UNDEFINED, + RAW_IFD, + 0, + BIG + }, + { // OpcodeList2 + 0xC741u, + UNDEFINED, + RAW_IFD, + 0, + BIG + }, + { // OpcodeList3 + 0xC74Eu, + UNDEFINED, + RAW_IFD, + 0, + BIG + }, + { // NoiseProfile + 0xC761u, + DOUBLE, + RAW_IFD, + 0, + UNDEFINED_ENDIAN + }, + { // DefaultUserCrop + 0xC7B5u, + RATIONAL, + RAW_IFD, + 4, + UNDEFINED_ENDIAN + }, + { // DefaultBlackRender + 0xC7A6u, + LONG, + PROFILE_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // BaselineExposureOffset + 0xC7A5u, + RATIONAL, + PROFILE_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // ProfileLookTableEncoding + 0xC7A4u, + LONG, + PROFILE_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // ProfileHueSatMapEncoding + 0xC7A3u, + LONG, + PROFILE_IFD, + 1, + UNDEFINED_ENDIAN + }, + { // OriginalDefaultFinalSize + 0xC791u, + LONG, + IFD_0, + 2, + UNDEFINED_ENDIAN + }, + { // OriginalBestQualityFinalSize + 0xC792u, + LONG, + IFD_0, + 2, + UNDEFINED_ENDIAN + }, + { // OriginalDefaultCropSize + 0xC793u, + LONG, + IFD_0, + 2, + UNDEFINED_ENDIAN + }, + { // NewRawImageDigest + 0xC7A7u, + BYTE, + IFD_0, + 16, + UNDEFINED_ENDIAN + }, + { // RawToPreviewGain + 0xC7A8u, + DOUBLE, + PREVIEW_IFD, + 1, + UNDEFINED_ENDIAN + }, +}; + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_TIFF_TAG_DEFINITION_H*/ diff --git a/media/img_utils/include/img_utils/TiffEntry.h b/media/img_utils/include/img_utils/TiffEntry.h new file mode 100644 index 0000000..cd01640 --- /dev/null +++ b/media/img_utils/include/img_utils/TiffEntry.h @@ -0,0 +1,129 @@ +/* + * 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 +#define IMG_UTILS_TIFF_ENTRY + +#include +#include +#include + +#include +#include +#include +#include + +namespace android { +namespace img_utils { + +#define COMPARE_DEF(op) \ +inline bool operator op (const TiffEntry& entry) const; + +/** + * This class holds a single TIFF IFD entry. + */ +class ANDROID_API TiffEntry : public TiffWritable { + public: + // TODO: Copy constructor/equals here. + virtual ~TiffEntry(); + + /** + * Write the 12-byte IFD entry to the output. The given offset will be + * set as the tag value if the size of the tag value exceeds the max + * size for the TIFF Value field (4 bytes), and should be word aligned. + * + * Returns OK on success, or a negative error code on failure. + */ + virtual status_t writeTagInfo(uint32_t offset, /*out*/EndianOutput* out) const = 0; + + /** + * Get the count set for this entry. This corresponds to the TIFF Count + * field. + */ + virtual uint32_t getCount() const = 0; + + /** + * Get the tag id set for this entry. This corresponds to the TIFF Tag + * field. + */ + virtual uint16_t getTag() const = 0; + + /** + * Get the type set for this entry. This corresponds to the TIFF Type + * field. + */ + virtual TagType getType() const = 0; + + /** + * Get the defined endianness for this entry. If this is defined, + * the tag value will be written with the given byte order. + */ + virtual Endianness getEndianness() const = 0; + + /** + * Get the value for this entry. This corresponds to the TIFF Value + * field. + * + * Returns NULL if the value is NULL, or if the type used does not + * match the type of this tag. + */ + template + const T* getData() const; + + String8 toString() const; + + /** + * Force the type used here to be a valid TIFF type. + * + * Returns NULL if the given value is NULL, or if the type given does + * not match the type of the value given. + */ + template + static const T* forceValidType(TagType type, const T* value); + + virtual const void* getDataHelper() const = 0; + + COMPARE_DEF(>) + COMPARE_DEF(<) + + protected: + enum { + MAX_PRINT_STRING_LENGTH = 256 + }; +}; + +#define COMPARE(op) \ +bool TiffEntry::operator op (const TiffEntry& entry) const { \ + return getComparableValue() op entry.getComparableValue(); \ +} + +COMPARE(>) +COMPARE(<) + + +template +const T* TiffEntry::getData() const { + const T* value = reinterpret_cast(getDataHelper()); + return forceValidType(getType(), value); +} + +#undef COMPARE +#undef COMPARE_DEF + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_TIFF_ENTRY*/ diff --git a/media/img_utils/include/img_utils/TiffEntryImpl.h b/media/img_utils/include/img_utils/TiffEntryImpl.h new file mode 100644 index 0000000..0e713dc --- /dev/null +++ b/media/img_utils/include/img_utils/TiffEntryImpl.h @@ -0,0 +1,190 @@ +/* + * 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 + +namespace android { +namespace img_utils { + +template +class TiffEntryImpl : public TiffEntry { + public: + // TODO: Copy constructor/equals here. + 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; + uint32_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; + T* 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; + mData = new T[count](); + for (uint32_t i = 0; i < count; ++i) { + mData[i] = data[i]; + } +} + +template +TiffEntryImpl::~TiffEntryImpl() { + if (mData) { + delete[] mData; + } +} + +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); +} + +template +uint32_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, 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, 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; +} + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_TIFF_ENTRY_IMPL*/ + + diff --git a/media/img_utils/include/img_utils/TiffHelpers.h b/media/img_utils/include/img_utils/TiffHelpers.h new file mode 100644 index 0000000..fd0ea7a --- /dev/null +++ b/media/img_utils/include/img_utils/TiffHelpers.h @@ -0,0 +1,132 @@ +/* + * 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_HELPERS_H +#define IMG_UTILS_TIFF_HELPERS_H + +#include + +namespace android { +namespace img_utils { + +const uint8_t ZERO_WORD[] = {0, 0, 0, 0}; + +#define BAIL_ON_FAIL(x, flag) \ + if ((flag = (x)) != OK) return flag; + +#define BYTES_TILL_WORD(index) \ + ((TIFF_WORD_SIZE - ((index) % TIFF_WORD_SIZE)) % TIFF_WORD_SIZE) + +#define WORD_ALIGN(count) \ + count += BYTES_TILL_WORD(count); + +#define ZERO_TILL_WORD(output, index, ret) \ + { \ + size_t remaining = BYTES_TILL_WORD(index); \ + if (remaining > 0) { \ + BAIL_ON_FAIL(output->write(ZERO_WORD, 0, remaining), ret); \ + } \ + } + +/** + * Basic TIFF header constants. + */ +enum { + BAD_OFFSET = 0, + TIFF_WORD_SIZE = 4, // Size in bytes + IFD_HEADER_SIZE = 2, // Size in bytes + IFD_FOOTER_SIZE = 4, // Size in bytes + TIFF_ENTRY_SIZE = 12, // Size in bytes + MAX_IFD_ENTRIES = UINT16_MAX, + FILE_HEADER_SIZE = 8, // Size in bytes + ENDIAN_MARKER_SIZE = 2, // Size in bytes + TIFF_MARKER_SIZE = 2, // Size in bytes + OFFSET_MARKER_SIZE = 4, // Size in bytes + TIFF_FILE_MARKER = 42, + BIG_ENDIAN_MARKER = 0x4D4Du, + LITTLE_ENDIAN_MARKER = 0x4949u +}; + +/** + * Constants for the TIFF tag types. + */ +enum TagType { + UNKNOWN_TAGTYPE = 0, + BYTE=1, + ASCII, + SHORT, + LONG, + RATIONAL, + SBYTE, + UNDEFINED, + SSHORT, + SLONG, + SRATIONAL, + FLOAT, + DOUBLE +}; + +/** + * Sizes of the TIFF entry fields (in bytes). + */ +enum { + TAG_SIZE = 2, + TYPE_SIZE = 2, + COUNT_SIZE = 4, + OFFSET_SIZE = 4 +}; + +/** + * Convenience IFD id constants. + */ +enum { + IFD_0 = 0, + RAW_IFD, + PROFILE_IFD, + PREVIEW_IFD +}; + +inline size_t getTypeSize(TagType type) { + switch(type) { + case UNDEFINED: + case ASCII: + case BYTE: + case SBYTE: + return 1; + case SHORT: + case SSHORT: + return 2; + case LONG: + case SLONG: + case FLOAT: + return 4; + case RATIONAL: + case SRATIONAL: + case DOUBLE: + return 8; + default: + return 0; + } +} + +inline uint32_t calculateIfdSize(size_t numberOfEntries) { + return IFD_HEADER_SIZE + IFD_FOOTER_SIZE + TIFF_ENTRY_SIZE * numberOfEntries; +} + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_TIFF_HELPERS_H*/ diff --git a/media/img_utils/include/img_utils/TiffIfd.h b/media/img_utils/include/img_utils/TiffIfd.h new file mode 100644 index 0000000..c35f858 --- /dev/null +++ b/media/img_utils/include/img_utils/TiffIfd.h @@ -0,0 +1,124 @@ +/* + * 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_IFD_H +#define IMG_UTILS_TIFF_IFD_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace android { +namespace img_utils { + +/** + * This class holds a single TIFF Image File Directory (IFD) structure. + * + * This maps to the TIFF IFD structure that is logically composed of: + * - A 2-byte field listing the number of entries. + * - A list of 12-byte TIFF entries. + * - A 4-byte offset to the next IFD. + */ +class ANDROID_API TiffIfd : public TiffWritable { + public: + // TODO: Copy constructor/equals here - needed for SubIfds. + TiffIfd(uint32_t ifdId); + virtual ~TiffIfd(); + + /** + * Add a TiffEntry to this IFD or replace an existing entry with the + * same tag ID. No validation is done. + * + * Returns OK on success, or a negative error code on failure. + */ + virtual status_t addEntry(const sp& entry); + + /** + * Set the pointer to the next IFD. This is used to create a linked + * list of IFDs as defined by the TIFF 6.0 spec., and is not included + * when calculating the size of IFD and entries for the getSize() + * method (unlike SubIFDs). + */ + virtual void setNextIfd(const sp& ifd); + + /** + * Get the pointer to the next IFD, or NULL if none exists. + */ + virtual sp getNextIfd() const; + + /** + * Write the IFD data. This includes the IFD header, entries, footer, + * and the corresponding values for each entry (recursively including + * sub-IFDs). The written amount should end on a word boundary, and + * the given offset should be word aligned. + * + * Returns OK on success, or a negative error code on failure. + */ + virtual status_t writeData(uint32_t offset, /*out*/EndianOutput* out) const; + + /** + * Get the size of the IFD. This includes the IFD header, entries, footer, + * and the corresponding values for each entry (recursively including + * any sub-IFDs). + */ + virtual uint32_t getSize() const; + + /** + * Get the id of this IFD. + */ + virtual uint32_t getId() const; + + /** + * Get an entry with the given tag ID. + * + * Returns a strong pointer to the entry if it exists, or an empty strong + * pointer. + */ + virtual sp getEntry(uint16_t tag) const; + + /** + * Get a formatted string representing this IFD. + */ + String8 toString() const; + + /** + * Print a formatted string representing this IFD to logcat. + */ + void log() const; + + /** + * Get value used to determine sort order. + */ + virtual uint32_t getComparableValue() const; + protected: + virtual uint32_t checkAndGetOffset(uint32_t offset) const; + SortedEntryVector mEntries; + sp mNextIfd; + uint32_t mIfdId; +}; + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_TIFF_IFD_H*/ diff --git a/media/img_utils/include/img_utils/TiffWritable.h b/media/img_utils/include/img_utils/TiffWritable.h new file mode 100644 index 0000000..a72cecc --- /dev/null +++ b/media/img_utils/include/img_utils/TiffWritable.h @@ -0,0 +1,60 @@ +/* + * 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_WRITABLE +#define IMG_UTILS_TIFF_WRITABLE + +#include +#include +#include + +#include +#include +#include +#include + +namespace android { +namespace img_utils { + +/** + * TiffWritable subclasses represent TIFF metadata objects that can be written + * to an EndianOutput object. This is used for TIFF entries and IFDs. + */ +class ANDROID_API TiffWritable : public Orderable, public LightRefBase { + public: + TiffWritable(); + virtual ~TiffWritable(); + + /** + * Write the data to the output. The given offset is used to calculate + * the header offset for values written. The offset is defined + * relative to the beginning of the TIFF header, and is word aligned. + * + * Returns OK on success, or a negative error code on failure. + */ + virtual status_t writeData(uint32_t offset, /*out*/EndianOutput* out) const = 0; + + /** + * Get the size of the data to write. + */ + virtual size_t getSize() const = 0; + +}; + +} /*namespace img_utils*/ +} /*namespace android*/ + +#endif /*IMG_UTILS_TIFF_WRITABLE*/ diff --git a/media/img_utils/include/img_utils/TiffWriter.h b/media/img_utils/include/img_utils/TiffWriter.h new file mode 100644 index 0000000..ec27fc3 --- /dev/null +++ b/media/img_utils/include/img_utils/TiffWriter.h @@ -0,0 +1,267 @@ +/* + * 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_WRITER_H +#define IMG_UTILS_TIFF_WRITER_H + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace android { +namespace img_utils { + +class TiffEntry; +class TiffIfd; +class Output; + +/** + * This class holds a collection of TIFF IFDs that can be written as a + * complete DNG file header. + * + * This maps to the TIFF header structure that is logically composed of: + * - An 8-byte file header containing an endianness indicator, the TIFF + * file marker, and the offset to the first IFD. + * - A list of TIFF IFD structures. + */ +class ANDROID_API TiffWriter : public LightRefBase { + public: + + /** + * Constructs a TiffWriter with the default tag mappings. This enables + * all of the tags defined in TagDefinitions.h, and uses the following + * mapping precedence to resolve collisions: + * (highest precedence) TIFF/EP > DNG > EXIF 2.3 > TIFF 6.0 + */ + TiffWriter(); + + /** + * Constructs a TiffWriter with the given tag mappings. The mapping + * precedence will be in the order that the definition maps are given, + * where the lower index map gets precedence. + * + * This can be used with user-defined definitions, or definitions form + * TagDefinitions.h + * + * The enabledDefinitions mapping object is owned by the caller, and must + * stay alive for the lifespan of the constructed TiffWriter object. + */ + TiffWriter(KeyedVector* enabledDefinitions, + size_t length); + + virtual ~TiffWriter(); + + /** + * Write a TIFF header containing each IFD set. This will recursively + * write all SubIFDs and tags. + * + * Returns OK on success, or a negative error code on failure. + */ + virtual status_t write(Output* out, Endianness end = LITTLE); + + /** + * Get the total size in bytes of the TIFF header. This includes all + * IFDs, tags, and values set for this TiffWriter. + */ + virtual uint32_t getTotalSize() const; + + /** + * Add the given entry to its default IFD. If that IFD does not + * exist, it will be created. + */ + virtual status_t addEntry(const sp& entry); + + /** + * Build an entry for a known tag. This tag must be one of the tags + * defined in one of the definition vectors this TIFF writer was constructed + * with. The count and type are validated. If this succeeds, the resulting + * entry will be placed in the outEntry pointer. + * + * Returns OK on success, or a negative error code on failure. Valid + * error codes for this method are: + * - BAD_INDEX - The given tag doesn't exist. + * - BAD_VALUE - The given count doesn't match the required count for + * this tag. + * - BAD_TYPE - The type of the given data isn't compatible with the + * type required for this tag. + */ + template + status_t buildEntry(uint16_t tag, uint32_t count, const T* data, + /*out*/sp* outEntry) const; + + /** + * Build an entry for a known tag and add it to the IFD with the given ID. + * This tag must be defined in one of the definition vectors this TIFF writer + * was constructed with. The count and type are validated. If this succeeds, + * the resulting entry will be placed in the outEntry pointer. + * + * Returns OK on success, or a negative error code on failure. Valid + * error codes for this method are: + * - BAD_INDEX - The given tag doesn't exist. + * - BAD_VALUE - The given count doesn't match the required count for + * this tag. + * - BAD_TYPE - The type of the given data isn't compatible with the + * type required for this tag. + * - NAME_NOT_FOUND - No ifd exists with the given ID. + */ + template + status_t addEntry(uint16_t tag, uint32_t count, const T* data, uint32_t ifd); + + /** + * Return the TIFF entry with the given tag ID in the IFD with the given ID, + * or an empty pointer if none exists. + */ + virtual sp getEntry(uint16_t tag, uint32_t ifd) const; + + /** + * Add the given IFD to the end of the top-level IFD chain. No + * validation is done. + * + * Returns OK on success, or a negative error code on failure. + */ + virtual status_t uncheckedAddIfd(const sp& ifd); + + /** + * Create an empty IFD with the given ID and add it to the end of the + * list of IFDs. + */ + virtual status_t addIfd(uint32_t ifd); + + /** + * Build an entry. No validation is done. + * + * WARNING: Using this method can result in creating poorly formatted + * TIFF files. + * + * Returns a TiffEntry with the given tag, type, count, endianness, + * and data. + */ + template + static sp uncheckedBuildEntry(uint16_t tag, TagType type, + uint32_t count, Endianness end, const T* data); + + /** + * Utility function to build atag-to-definition mapping from a given + * array of tag definitions. + */ + static KeyedVector buildTagMap( + const TagDefinition_t* definitions, size_t length); + + /** + * Returns the default type for the given tag ID. + */ + virtual TagType getDefaultType(uint16_t tag) const; + + /** + * Returns the default count for a given tag ID, or 0 if this + * tag normally has a variable count. + */ + virtual uint32_t getDefaultCount(uint16_t tag) const; + + /** + * Returns true if a definition exist for the given tag ID. + */ + virtual bool checkIfDefined(uint16_t tag) const; + + /** + * Print the currently configured IFDs and entries to logcat. + */ + virtual void log() const; + + protected: + enum { + DEFAULT_NUM_TAG_MAPS = 4, + }; + + sp findLastIfd(); + status_t writeFileHeader(EndianOutput& out); + const TagDefinition_t* lookupDefinition(uint16_t tag) const; + status_t calculateOffsets(); + + sp mIfd; + KeyedVector > mNamedIfds; + KeyedVector* mTagMaps; + size_t mNumTagMaps; + + static KeyedVector sTagMaps[]; +}; + +template +status_t TiffWriter::buildEntry(uint16_t tag, uint32_t count, const T* data, + /*out*/sp* outEntry) const { + const TagDefinition_t* definition = lookupDefinition(tag); + + if (definition == NULL) { + ALOGE("%s: No such tag exists for id %x.", __FUNCTION__, tag); + return BAD_INDEX; + } + + uint32_t fixedCount = definition->fixedCount; + if (fixedCount > 0 && fixedCount != count) { + ALOGE("%s: Invalid count %d for tag %x (expects %d).", __FUNCTION__, count, tag, + fixedCount); + return BAD_VALUE; + } + + TagType fixedType = definition->defaultType; + if (TiffEntry::forceValidType(fixedType, data) == NULL) { + ALOGE("%s: Invalid type used for tag value for tag %x.", __FUNCTION__, tag); + return BAD_TYPE; + } + + *outEntry = new TiffEntryImpl(tag, fixedType, count, + definition->fixedEndian, data); + + return OK; +} + +template +status_t TiffWriter::addEntry(uint16_t tag, uint32_t count, const T* data, uint32_t ifd) { + sp outEntry; + status_t ret = buildEntry(tag, count, data, &outEntry); + if (ret != OK) { + ALOGE("%s: Could not build entry for tag %x.", __FUNCTION__, tag); + return ret; + } + ssize_t index = mNamedIfds.indexOfKey(ifd); + if (index < 0) { + ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd); + return NAME_NOT_FOUND; + } + return mNamedIfds[index]->addEntry(outEntry); +} + +template +sp TiffWriter::uncheckedBuildEntry(uint16_t tag, TagType type, uint32_t count, + Endianness end, const T* data) { + TiffEntryImpl* entry = new TiffEntryImpl(tag, type, count, end, data); + return sp(entry); +} + +} /*namespace img_utils*/ +} /*namespace android*/ + + +#endif /*IMG_UTILS_TIFF_WRITER_H*/ -- cgit v1.1