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 
32 namespace android {
33 namespace 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  */
43 class 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