1/*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef IMG_UTILS_TIFF_IFD_H
18#define IMG_UTILS_TIFF_IFD_H
19
20#include <img_utils/TiffWritable.h>
21#include <img_utils/TiffEntry.h>
22#include <img_utils/Output.h>
23#include <img_utils/SortedEntryVector.h>
24
25#include <cutils/compiler.h>
26#include <utils/Errors.h>
27#include <utils/String8.h>
28#include <utils/SortedVector.h>
29#include <utils/StrongPointer.h>
30#include <stdint.h>
31
32namespace android {
33namespace img_utils {
34
35/**
36 * This class holds a single TIFF Image File Directory (IFD) structure.
37 *
38 * This maps to the TIFF IFD structure that is logically composed of:
39 * - A 2-byte field listing the number of entries.
40 * - A list of 12-byte TIFF entries.
41 * - A 4-byte offset to the next IFD.
42 */
43class ANDROID_API TiffIfd : public TiffWritable {
44    public:
45        TiffIfd(uint32_t ifdId);
46        virtual ~TiffIfd();
47
48        /**
49         * Add a TiffEntry to this IFD or replace an existing entry with the
50         * same tag ID.  No validation is done.
51         *
52         * Returns OK on success, or a negative error code on failure.
53         */
54        virtual status_t addEntry(const sp<TiffEntry>& entry);
55
56        /**
57         * Set the pointer to the next IFD.  This is used to create a linked
58         * list of IFDs as defined by the TIFF 6.0 spec., and is not included
59         * when calculating the size of IFD and entries for the getSize()
60         * method (unlike SubIFDs).
61         */
62        virtual void setNextIfd(const sp<TiffIfd>& ifd);
63
64        /**
65         * Get the pointer to the next IFD, or NULL if none exists.
66         */
67        virtual sp<TiffIfd> getNextIfd() const;
68
69        /**
70         * Write the IFD data.  This includes the IFD header, entries, footer,
71         * and the corresponding values for each entry (recursively including
72         * sub-IFDs).  The written amount should end on a word boundary, and
73         * the given offset should be word aligned.
74         *
75         * Returns OK on success, or a negative error code on failure.
76         */
77        virtual status_t writeData(uint32_t offset, /*out*/EndianOutput* out) const;
78
79        /**
80         * Get the size of the IFD. This includes the IFD header, entries, footer,
81         * and the corresponding values for each entry (recursively including
82         * any sub-IFDs).
83         */
84        virtual size_t getSize() const;
85
86        /**
87         * Get the id of this IFD.
88         */
89        virtual uint32_t getId() const;
90
91        /**
92         * Get an entry with the given tag ID.
93         *
94         * Returns a strong pointer to the entry if it exists, or an empty strong
95         * pointer.
96         */
97        virtual sp<TiffEntry> getEntry(uint16_t tag) const;
98
99        /**
100         * Remove the entry with the given tag ID if it exists.
101         */
102        virtual void removeEntry(uint16_t tag);
103
104        /**
105         * Convenience method to validate and set strip-related image tags.
106         *
107         * This sets all strip related tags, but leaves offset values unitialized.
108         * setStripOffsets must be called with the desired offset before writing.
109         * The strip tag values are calculated from the existing tags for image
110         * dimensions and pixel type set in the IFD.
111         *
112         * Does not handle planar image configurations (PlanarConfiguration != 1).
113         *
114         * Returns OK on success, or a negative error code.
115         */
116        virtual status_t validateAndSetStripTags();
117
118        /**
119         * Returns true if validateAndSetStripTags has been called, but not setStripOffsets.
120         */
121        virtual bool uninitializedOffsets() const;
122
123        /**
124         * Convenience method to set beginning offset for strips.
125         *
126         * Call this to update the strip offsets before calling writeData.
127         *
128         * Returns OK on success, or a negative error code.
129         */
130        virtual status_t setStripOffset(uint32_t offset);
131
132        /**
133         * Get the total size of the strips in bytes.
134         *
135         * This sums the byte count at each strip offset, and returns
136         * the total count of bytes stored in strips for this IFD.
137         */
138        virtual uint32_t getStripSize() const;
139
140        /**
141         * Get a formatted string representing this IFD.
142         */
143        virtual String8 toString() const;
144
145        /**
146         * Print a formatted string representing this IFD to logcat.
147         */
148        void log() const;
149
150        /**
151         * Get value used to determine sort order.
152         */
153        virtual uint32_t getComparableValue() const;
154
155    protected:
156        virtual uint32_t checkAndGetOffset(uint32_t offset) const;
157        SortedEntryVector mEntries;
158        sp<TiffIfd> mNextIfd;
159        uint32_t mIfdId;
160        bool mStripOffsetsInitialized;
161};
162
163} /*namespace img_utils*/
164} /*namespace android*/
165
166#endif /*IMG_UTILS_TIFF_IFD_H*/
167