summaryrefslogtreecommitdiffstats
path: root/media/img_utils
diff options
context:
space:
mode:
authorRuben Brunk <rubenbrunk@google.com>2014-05-28 18:42:37 -0700
committerRuben Brunk <rubenbrunk@google.com>2014-07-10 15:37:26 -0700
commit4510de26e5361f3a9f07057ec6f26483c888c1fa (patch)
tree5a474839318779c1e6eff96a4f98e3e1f74ef85a /media/img_utils
parent5c68f959eaa2e02fed5643c78e281fff42bcc0a2 (diff)
downloadframeworks_av-4510de26e5361f3a9f07057ec6f26483c888c1fa.zip
frameworks_av-4510de26e5361f3a9f07057ec6f26483c888c1fa.tar.gz
frameworks_av-4510de26e5361f3a9f07057ec6f26483c888c1fa.tar.bz2
DNG: Update TiffWriter to handle thumbnails and SubIfds.
- Fix SubIfd handling. - Add StripSources, convenience functions for writing image strips. - Update Input classes to use with JNI. - Add skip method. - Add tag definitions for GPS tags. - Add name string to tag definitions. Bug: 15112503 Change-Id: I9535b21261027f6c06a041c1621de8f865a0ad32
Diffstat (limited to 'media/img_utils')
-rw-r--r--media/img_utils/include/img_utils/FileInput.h6
-rw-r--r--media/img_utils/include/img_utils/Input.h14
-rw-r--r--media/img_utils/include/img_utils/StripSource.h53
-rw-r--r--media/img_utils/include/img_utils/TagDefinitions.h229
-rw-r--r--media/img_utils/include/img_utils/TiffEntry.h13
-rw-r--r--media/img_utils/include/img_utils/TiffEntryImpl.h56
-rw-r--r--media/img_utils/include/img_utils/TiffHelpers.h2
-rw-r--r--media/img_utils/include/img_utils/TiffIfd.h46
-rw-r--r--media/img_utils/include/img_utils/TiffWriter.h145
-rw-r--r--media/img_utils/src/Android.mk1
-rw-r--r--media/img_utils/src/FileInput.cpp13
-rw-r--r--media/img_utils/src/Input.cpp28
-rw-r--r--media/img_utils/src/StripSource.cpp25
-rw-r--r--media/img_utils/src/TiffEntry.cpp10
-rw-r--r--media/img_utils/src/TiffEntryImpl.cpp19
-rw-r--r--media/img_utils/src/TiffIfd.cpp208
-rw-r--r--media/img_utils/src/TiffWriter.cpp219
17 files changed, 938 insertions, 149 deletions
diff --git a/media/img_utils/include/img_utils/FileInput.h b/media/img_utils/include/img_utils/FileInput.h
index d3c5ec1..4d4f22b 100644
--- a/media/img_utils/include/img_utils/FileInput.h
+++ b/media/img_utils/include/img_utils/FileInput.h
@@ -52,10 +52,10 @@ class ANDROID_API FileInput : public Input {
* 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.
+ * Returns the number of bytes read, or NOT_ENOUGH_DATA if at the end of the file. If an
+ * error has occurred, this will return a negative error code other than NOT_ENOUGH_DATA.
*/
- virtual size_t read(uint8_t* buf, size_t offset, size_t count, status_t* err);
+ virtual ssize_t read(uint8_t* buf, size_t offset, size_t count);
/**
* Close the file descriptor to the path given in the constructor.
diff --git a/media/img_utils/include/img_utils/Input.h b/media/img_utils/include/img_utils/Input.h
index 2166601..6a03647 100644
--- a/media/img_utils/include/img_utils/Input.h
+++ b/media/img_utils/include/img_utils/Input.h
@@ -43,10 +43,18 @@ class ANDROID_API Input {
* 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.
+ * Returns the number of bytes read, or NOT_ENOUGH_DATA if at the end of the file. If an
+ * error has occurred, this will return a negative error code other than NOT_ENOUGH_DATA.
*/
- virtual size_t read(uint8_t* buf, size_t offset, size_t count, status_t* err) = 0;
+ virtual ssize_t read(uint8_t* buf, size_t offset, size_t count) = 0;
+
+ /**
+ * Skips bytes in the input.
+ *
+ * Returns the number of bytes skipped, or NOT_ENOUGH_DATA if at the end of the file. If an
+ * error has occurred, this will return a negative error code other than NOT_ENOUGH_DATA.
+ */
+ virtual ssize_t skip(size_t count);
/**
* Close the Input. It is not valid to call open on a previously closed Input.
diff --git a/media/img_utils/include/img_utils/StripSource.h b/media/img_utils/include/img_utils/StripSource.h
new file mode 100644
index 0000000..b5c6b60
--- /dev/null
+++ b/media/img_utils/include/img_utils/StripSource.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_STRIP_SOURCE_H
+#define IMG_UTILS_STRIP_SOURCE_H
+
+#include <img_utils/Output.h>
+
+#include <cutils/compiler.h>
+#include <utils/Errors.h>
+
+#include <stdint.h>
+
+namespace android {
+namespace img_utils {
+
+/**
+ * This class acts as a data source for strips set in a TiffIfd.
+ */
+class ANDROID_API StripSource {
+ public:
+ virtual ~StripSource();
+
+ /**
+ * Write count bytes to the stream.
+ *
+ * Returns OK on success, or a negative error code.
+ */
+ virtual status_t writeToStream(Output& stream, uint32_t count) = 0;
+
+ /**
+ * Return the source IFD.
+ */
+ virtual uint32_t getIfd() const = 0;
+};
+
+} /*namespace img_utils*/
+} /*namespace android*/
+
+#endif /*IMG_UTILS_STRIP_SOURCE_H*/
diff --git a/media/img_utils/include/img_utils/TagDefinitions.h b/media/img_utils/include/img_utils/TagDefinitions.h
index 6cc42b2..e9a7480 100644
--- a/media/img_utils/include/img_utils/TagDefinitions.h
+++ b/media/img_utils/include/img_utils/TagDefinitions.h
@@ -29,16 +29,18 @@ namespace img_utils {
* Tag definitions contain information about standard TIFF compatible tags.
*/
typedef struct TagDefinition {
+ // The tag name.
+ const char* tagName;
// The specified tag ID.
- uint16_t tagId;
+ const uint16_t tagId;
// The default type for this tag. This must be a valid TIFF type.
- TagType defaultType;
+ const TagType defaultType;
// The default Image File Directory (IFD) for this tag.
- uint32_t defaultIfd;
+ const uint32_t defaultIfd;
// The valid count for this tag, or 0 if the count is not fixed.
- uint32_t fixedCount;
+ const uint32_t fixedCount;
// The endianness of the tag value, or UNDEFINED_ENDIAN if there is no fixed endian
- Endianness fixedEndian;
+ const Endianness fixedEndian;
} TagDefinition_t;
/**
@@ -180,6 +182,14 @@ enum {
TAG_ISOSPEEDRATINGS = 0x8827u,
TAG_FOCALLENGTH = 0x920Au,
TAG_FNUMBER = 0x829Du,
+ TAG_GPSINFO = 0x8825u,
+ TAG_GPSVERSIONID = 0x0u,
+ TAG_GPSLATITUDEREF = 0x1u,
+ TAG_GPSLATITUDE = 0x2u,
+ TAG_GPSLONGITUDEREF = 0x3u,
+ TAG_GPSLONGITUDE = 0x4u,
+ TAG_GPSTIMESTAMP = 0x7u,
+ TAG_GPSDATESTAMP = 0x001Du,
};
/**
@@ -187,6 +197,7 @@ enum {
*/
const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
{ // PhotometricInterpretation
+ "PhotometricInterpretation",
0x0106u,
SHORT,
IFD_0,
@@ -194,6 +205,7 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // SubIfds
+ "SubIfds",
0x014Au,
LONG,
IFD_0,
@@ -201,6 +213,7 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CFAPattern
+ "CFAPattern",
0x828Eu,
BYTE,
IFD_0,
@@ -208,6 +221,7 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CFARepeatPatternDim
+ "CFARepeatPatternDim",
0x828Du,
SHORT,
IFD_0,
@@ -215,6 +229,7 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // DateTimeOriginal
+ "DateTimeOriginal",
0x9003u,
ASCII,
IFD_0,
@@ -222,6 +237,7 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // Tiff/EPStandardID
+ "Tiff",
0x9216u,
BYTE,
IFD_0,
@@ -229,6 +245,7 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ExposureTime
+ "ExposureTime",
0x829Au,
RATIONAL,
IFD_0,
@@ -236,6 +253,7 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ISOSpeedRatings
+ "ISOSpeedRatings",
0x8827u,
SHORT,
IFD_0,
@@ -243,6 +261,7 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // FocalLength
+ "FocalLength",
0x920Au,
RATIONAL,
IFD_0,
@@ -250,12 +269,69 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // FNumber
+ "FNumber",
0x829Du,
RATIONAL,
IFD_0,
0,
UNDEFINED_ENDIAN
},
+ { // GPSInfo
+ "GPSInfo",
+ 0x8825u,
+ LONG,
+ IFD_0,
+ 1,
+ UNDEFINED_ENDIAN
+ },
+ { // GPSVersionID
+ "GPSVersionID",
+ 0x0u,
+ BYTE,
+ IFD_0,
+ 4,
+ UNDEFINED_ENDIAN
+ },
+ { // GPSLatitudeRef
+ "GPSLatitudeRef",
+ 0x1u,
+ ASCII,
+ IFD_0,
+ 2,
+ UNDEFINED_ENDIAN
+ },
+ { // GPSLatitude
+ "GPSLatitude",
+ 0x2u,
+ RATIONAL,
+ IFD_0,
+ 3,
+ UNDEFINED_ENDIAN
+ },
+ { // GPSLongitudeRef
+ "GPSLongitudeRef",
+ 0x3u,
+ ASCII,
+ IFD_0,
+ 2,
+ UNDEFINED_ENDIAN
+ },
+ { // GPSLongitude
+ "GPSLongitude",
+ 0x4u,
+ RATIONAL,
+ IFD_0,
+ 3,
+ UNDEFINED_ENDIAN
+ },
+ { // GPSTimeStamp
+ "GPSTimeStamp",
+ 0x7u,
+ RATIONAL,
+ IFD_0,
+ 3,
+ UNDEFINED_ENDIAN
+ },
/*TODO: Remaining TIFF EP tags*/
};
@@ -264,12 +340,21 @@ const TagDefinition_t TIFF_EP_TAG_DEFINITIONS[] = {
*/
const TagDefinition_t EXIF_2_3_TAG_DEFINITIONS[] = {
{ // ExifVersion
+ "ExifVersion",
0x9000u,
UNDEFINED,
IFD_0,
4,
UNDEFINED_ENDIAN
},
+ { // GPSDateStamp
+ "GPSDateStamp",
+ 0x001Du,
+ ASCII,
+ IFD_0,
+ 11,
+ UNDEFINED_ENDIAN
+ },
/*TODO: Remaining EXIF 2.3 tags*/
};
@@ -278,6 +363,7 @@ const TagDefinition_t EXIF_2_3_TAG_DEFINITIONS[] = {
*/
const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
{ // SubFileType
+ "SubFileType",
0x00FFu,
SHORT,
IFD_0,
@@ -285,6 +371,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // Artist
+ "Artist",
0x013Bu,
ASCII,
IFD_0,
@@ -292,6 +379,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BitsPerSample
+ "BitsPerSample",
0x0102u,
SHORT,
IFD_0,
@@ -299,6 +387,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CellLength
+ "CellLength",
0x0109u,
SHORT,
IFD_0,
@@ -306,6 +395,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CellWidth
+ "CellWidth",
0x0108u,
SHORT,
IFD_0,
@@ -313,6 +403,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ColorMap
+ "ColorMap",
0x0140u,
SHORT,
IFD_0,
@@ -320,6 +411,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // Compression
+ "Compression",
0x0103u,
SHORT,
IFD_0,
@@ -327,6 +419,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // Copyright
+ "Copyright",
0x8298u,
ASCII,
IFD_0,
@@ -334,6 +427,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // DateTime
+ "DateTime",
0x0132u,
ASCII,
IFD_0,
@@ -341,6 +435,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ExtraSamples
+ "ExtraSamples",
0x0152u,
SHORT,
IFD_0,
@@ -348,6 +443,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // FillOrder
+ "FillOrder",
0x010Au,
SHORT,
IFD_0,
@@ -355,6 +451,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // FreeByteCounts
+ "FreeByteCounts",
0x0121u,
LONG,
IFD_0,
@@ -362,6 +459,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // FreeOffsets
+ "FreeOffsets",
0x0120u,
LONG,
IFD_0,
@@ -369,6 +467,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // GrayResponseCurve
+ "GrayResponseCurve",
0x0123u,
SHORT,
IFD_0,
@@ -376,6 +475,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // GrayResponseUnit
+ "GrayResponseUnit",
0x0122u,
SHORT,
IFD_0,
@@ -383,6 +483,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // HostComputer
+ "HostComputer",
0x013Cu,
ASCII,
IFD_0,
@@ -390,6 +491,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ImageDescription
+ "ImageDescription",
0x010Eu,
ASCII,
IFD_0,
@@ -397,6 +499,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ImageLength
+ "ImageLength",
0x0101u,
LONG,
IFD_0,
@@ -404,6 +507,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ImageWidth
+ "ImageWidth",
0x0100u,
LONG,
IFD_0,
@@ -411,6 +515,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // Make
+ "Make",
0x010Fu,
ASCII,
IFD_0,
@@ -418,6 +523,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // MaxSampleValue
+ "MaxSampleValue",
0x0119u,
SHORT,
IFD_0,
@@ -425,6 +531,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // MinSampleValue
+ "MinSampleValue",
0x0118u,
SHORT,
IFD_0,
@@ -432,6 +539,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // Model
+ "Model",
0x0110u,
ASCII,
IFD_0,
@@ -439,6 +547,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // NewSubfileType
+ "NewSubfileType",
0x00FEu,
LONG,
IFD_0,
@@ -446,6 +555,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // Orientation
+ "Orientation",
0x0112u,
SHORT,
IFD_0,
@@ -453,6 +563,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // PhotoMetricInterpretation
+ "PhotoMetricInterpretation",
0x0106u,
SHORT,
IFD_0,
@@ -460,6 +571,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // PlanarConfiguration
+ "PlanarConfiguration",
0x011Cu,
SHORT,
IFD_0,
@@ -467,6 +579,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ResolutionUnit
+ "ResolutionUnit",
0x0128u,
SHORT,
IFD_0,
@@ -474,6 +587,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // RowsPerStrip
+ "RowsPerStrip",
0x0116u,
LONG,
IFD_0,
@@ -481,6 +595,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // SamplesPerPixel
+ "SamplesPerPixel",
0x0115u,
SHORT,
IFD_0,
@@ -488,6 +603,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // Software
+ "Software",
0x0131u,
ASCII,
IFD_0,
@@ -495,6 +611,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // StripByteCounts
+ "StripByteCounts",
0x0117u,
LONG,
IFD_0,
@@ -502,6 +619,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // StripOffsets
+ "StripOffsets",
0x0111u,
LONG,
IFD_0,
@@ -509,6 +627,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // SubfileType
+ "SubfileType",
0x00FFu,
SHORT,
IFD_0,
@@ -516,6 +635,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // Threshholding
+ "Threshholding",
0x0107u,
SHORT,
IFD_0,
@@ -523,6 +643,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // XResolution
+ "XResolution",
0x011Au,
RATIONAL,
IFD_0,
@@ -530,19 +651,13 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // YResolution
+ "YResolution",
0x011Bu,
RATIONAL,
IFD_0,
1,
UNDEFINED_ENDIAN
},
- { // YResolution
- 0x011Bu,
- RATIONAL,
- IFD_0,
- 1,
- UNDEFINED_ENDIAN
- }
};
/**
@@ -550,6 +665,7 @@ const TagDefinition_t TIFF_6_TAG_DEFINITIONS[] = {
*/
const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
{ // DNGVersion
+ "DNGVersion",
0xC612u,
BYTE,
IFD_0,
@@ -557,6 +673,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // DNGBackwardVersion
+ "DNGBackwardVersion",
0xC613u,
BYTE,
IFD_0,
@@ -564,6 +681,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // UniqueCameraModel
+ "UniqueCameraModel",
0xC614u,
ASCII,
IFD_0,
@@ -571,6 +689,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // LocalizedCameraModel
+ "LocalizedCameraModel",
0xC615u,
ASCII,
IFD_0,
@@ -578,6 +697,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CFAPlaneColor
+ "CFAPlaneColor",
0xC616u,
BYTE,
RAW_IFD,
@@ -585,6 +705,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CFALayout
+ "CFALayout",
0xC617u,
SHORT,
RAW_IFD,
@@ -592,6 +713,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // LinearizationTable
+ "LinearizationTable",
0xC618u,
SHORT,
RAW_IFD,
@@ -599,6 +721,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BlackLevelRepeatDim
+ "BlackLevelRepeatDim",
0xC619u,
SHORT,
RAW_IFD,
@@ -606,6 +729,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BlackLevel
+ "BlackLevel",
0xC61Au,
LONG,
RAW_IFD,
@@ -613,6 +737,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BlackLevelDeltaH
+ "BlackLevelDeltaH",
0xC61Bu,
SRATIONAL,
RAW_IFD,
@@ -620,6 +745,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BlackLevelDeltaV
+ "BlackLevelDeltaV",
0xC61Cu,
SRATIONAL,
RAW_IFD,
@@ -627,6 +753,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // WhiteLevel
+ "WhiteLevel",
0xC61Du,
LONG,
RAW_IFD,
@@ -634,6 +761,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // DefaultScale
+ "DefaultScale",
0xC61Eu,
RATIONAL,
RAW_IFD,
@@ -641,6 +769,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BestQualityScale
+ "BestQualityScale",
0xC65Cu,
RATIONAL,
RAW_IFD,
@@ -648,6 +777,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // DefaultCropOrigin
+ "DefaultCropOrigin",
0xC61Fu,
LONG,
RAW_IFD,
@@ -655,6 +785,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // DefaultCropSize
+ "DefaultCropSize",
0xC620u,
LONG,
RAW_IFD,
@@ -662,6 +793,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CalibrationIlluminant1
+ "CalibrationIlluminant1",
0xC65Au,
SHORT,
PROFILE_IFD,
@@ -669,6 +801,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CalibrationIlluminant2
+ "CalibrationIlluminant2",
0xC65Bu,
SHORT,
PROFILE_IFD,
@@ -676,6 +809,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ColorMatrix1
+ "ColorMatrix1",
0xC621u,
SRATIONAL,
PROFILE_IFD,
@@ -683,6 +817,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ColorMatrix2
+ "ColorMatrix2",
0xC622u,
SRATIONAL,
PROFILE_IFD,
@@ -690,6 +825,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CameraCalibration1
+ "CameraCalibration1",
0xC623u,
SRATIONAL,
IFD_0,
@@ -697,6 +833,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CameraCalibration2
+ "CameraCalibration2",
0xC624u,
SRATIONAL,
IFD_0,
@@ -704,6 +841,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ReductionMatrix1
+ "ReductionMatrix1",
0xC625u,
SRATIONAL,
PROFILE_IFD,
@@ -711,6 +849,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ReductionMatrix2
+ "ReductionMatrix2",
0xC626u,
SRATIONAL,
PROFILE_IFD,
@@ -718,6 +857,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // AnalogBalance
+ "AnalogBalance",
0xC627u,
RATIONAL,
IFD_0,
@@ -725,6 +865,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // AsShotNeutral
+ "AsShotNeutral",
0xC628u,
RATIONAL,
IFD_0,
@@ -732,6 +873,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // AsShotWhiteXY
+ "AsShotWhiteXY",
0xC629u,
RATIONAL,
IFD_0,
@@ -739,6 +881,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BaselineExposure
+ "BaselineExposure",
0xC62Au,
SRATIONAL,
IFD_0,
@@ -746,6 +889,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BaselineNoise
+ "BaselineNoise",
0xC62Bu,
RATIONAL,
IFD_0,
@@ -753,6 +897,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BaselineSharpness
+ "BaselineSharpness",
0xC62Cu,
RATIONAL,
IFD_0,
@@ -760,6 +905,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BayerGreenSplit
+ "BayerGreenSplit",
0xC62Du,
LONG,
RAW_IFD,
@@ -767,6 +913,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // LinearResponseLimit
+ "LinearResponseLimit",
0xC62Eu,
RATIONAL,
IFD_0,
@@ -774,6 +921,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CameraSerialNumber
+ "CameraSerialNumber",
0xC62Fu,
ASCII,
IFD_0,
@@ -781,6 +929,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // LensInfo
+ "LensInfo",
0xC630u,
RATIONAL,
IFD_0,
@@ -788,6 +937,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ChromaBlurRadius
+ "ChromaBlurRadius",
0xC631u,
RATIONAL,
RAW_IFD,
@@ -795,6 +945,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // AntiAliasStrength
+ "AntiAliasStrength",
0xC632u,
RATIONAL,
RAW_IFD,
@@ -802,6 +953,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ShadowScale
+ "ShadowScale",
0xC633u,
RATIONAL,
IFD_0,
@@ -809,6 +961,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // DNGPrivateData
+ "DNGPrivateData",
0xC634u,
BYTE,
IFD_0,
@@ -816,6 +969,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // MakerNoteSafety
+ "MakerNoteSafety",
0xC635u,
SHORT,
IFD_0,
@@ -823,6 +977,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // RawDataUniqueID
+ "RawDataUniqueID",
0xC65Du,
BYTE,
IFD_0,
@@ -830,6 +985,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // OriginalRawFileName
+ "OriginalRawFileName",
0xC68Bu,
ASCII,
IFD_0,
@@ -837,6 +993,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // OriginalRawFileData
+ "OriginalRawFileData",
0xC68Cu,
UNDEFINED,
IFD_0,
@@ -844,6 +1001,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
BIG
},
{ // ActiveArea
+ "ActiveArea",
0xC68Du,
LONG,
RAW_IFD,
@@ -851,6 +1009,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // MaskedAreas
+ "MaskedAreas",
0xC68Eu,
LONG,
RAW_IFD,
@@ -858,6 +1017,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // AsShotICCProfile
+ "AsShotICCProfile",
0xC68Fu,
UNDEFINED,
IFD_0,
@@ -865,6 +1025,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // AsShotPreProfileMatrix
+ "AsShotPreProfileMatrix",
0xC690u,
SRATIONAL,
IFD_0,
@@ -872,6 +1033,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CurrentICCProfile
+ "CurrentICCProfile",
0xC691u,
UNDEFINED,
IFD_0,
@@ -879,6 +1041,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CurrentICCProfile
+ "CurrentICCProfile",
0xC691u,
UNDEFINED,
IFD_0,
@@ -886,6 +1049,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CurrentPreProfileMatrix
+ "CurrentPreProfileMatrix",
0xC692u,
SRATIONAL,
IFD_0,
@@ -893,6 +1057,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ColorimetricReference
+ "ColorimetricReference",
0xC6BFu,
SHORT,
IFD_0,
@@ -900,6 +1065,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // CameraCalibrationSignature
+ "CameraCalibrationSignature",
0xC6F3u,
ASCII,
IFD_0,
@@ -907,6 +1073,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileCalibrationSignature
+ "ProfileCalibrationSignature",
0xC6F4u,
ASCII,
PROFILE_IFD,
@@ -914,6 +1081,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ExtraCameraProfiles
+ "ExtraCameraProfiles",
0xC6F5u,
LONG,
IFD_0,
@@ -921,6 +1089,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // AsShotProfileName
+ "AsShotProfileName",
0xC6F6u,
ASCII,
IFD_0,
@@ -928,6 +1097,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // NoiseReductionApplied
+ "NoiseReductionApplied",
0xC6F7u,
RATIONAL,
RAW_IFD,
@@ -935,6 +1105,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileName
+ "ProfileName",
0xC6F8u,
ASCII,
PROFILE_IFD,
@@ -942,6 +1113,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileHueSatMapDims
+ "ProfileHueSatMapDims",
0xC6F9u,
LONG,
PROFILE_IFD,
@@ -949,6 +1121,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileHueSatMapData1
+ "ProfileHueSatMapData1",
0xC6FAu,
FLOAT,
PROFILE_IFD,
@@ -956,6 +1129,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileHueSatMapData2
+ "ProfileHueSatMapData2",
0xC6FBu,
FLOAT,
PROFILE_IFD,
@@ -963,6 +1137,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileToneCurve
+ "ProfileToneCurve",
0xC6FCu,
FLOAT,
PROFILE_IFD,
@@ -970,6 +1145,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileEmbedPolicy
+ "ProfileEmbedPolicy",
0xC6FDu,
LONG,
PROFILE_IFD,
@@ -977,6 +1153,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileCopyright
+ "ProfileCopyright",
0xC6FEu,
ASCII,
PROFILE_IFD,
@@ -984,6 +1161,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ForwardMatrix1
+ "ForwardMatrix1",
0xC714u,
SRATIONAL,
PROFILE_IFD,
@@ -991,6 +1169,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ForwardMatrix2
+ "ForwardMatrix2",
0xC715u,
SRATIONAL,
PROFILE_IFD,
@@ -998,6 +1177,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // PreviewApplicationName
+ "PreviewApplicationName",
0xC716u,
ASCII,
PREVIEW_IFD,
@@ -1005,6 +1185,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // PreviewApplicationVersion
+ "PreviewApplicationVersion",
0xC717u,
ASCII,
PREVIEW_IFD,
@@ -1012,6 +1193,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // PreviewSettingsName
+ "PreviewSettingsName",
0xC718u,
ASCII,
PREVIEW_IFD,
@@ -1019,6 +1201,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // PreviewSettingsDigest
+ "PreviewSettingsDigest",
0xC719u,
BYTE,
PREVIEW_IFD,
@@ -1026,6 +1209,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // PreviewColorSpace
+ "PreviewColorSpace",
0xC71Au,
LONG,
PREVIEW_IFD,
@@ -1033,6 +1217,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // PreviewDateTime
+ "PreviewDateTime",
0xC71Bu,
ASCII,
PREVIEW_IFD,
@@ -1040,6 +1225,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // RawImageDigest
+ "RawImageDigest",
0xC71Cu,
BYTE,
IFD_0,
@@ -1047,6 +1233,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // OriginalRawFileDigest
+ "OriginalRawFileDigest",
0xC71Du,
BYTE,
IFD_0,
@@ -1054,6 +1241,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // SubTileBlockSize
+ "SubTileBlockSize",
0xC71Eu,
LONG,
RAW_IFD,
@@ -1061,6 +1249,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // RowInterleaveFactor
+ "RowInterleaveFactor",
0xC71Fu,
LONG,
RAW_IFD,
@@ -1068,6 +1257,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileLookTableDims
+ "ProfileLookTableDims",
0xC725u,
LONG,
PROFILE_IFD,
@@ -1075,6 +1265,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileLookTableData
+ "ProfileLookTableData",
0xC726u,
FLOAT,
PROFILE_IFD,
@@ -1082,6 +1273,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // OpcodeList1
+ "OpcodeList1",
0xC740u,
UNDEFINED,
RAW_IFD,
@@ -1089,6 +1281,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
BIG
},
{ // OpcodeList2
+ "OpcodeList2",
0xC741u,
UNDEFINED,
RAW_IFD,
@@ -1096,6 +1289,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
BIG
},
{ // OpcodeList3
+ "OpcodeList3",
0xC74Eu,
UNDEFINED,
RAW_IFD,
@@ -1103,6 +1297,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
BIG
},
{ // NoiseProfile
+ "NoiseProfile",
0xC761u,
DOUBLE,
RAW_IFD,
@@ -1110,6 +1305,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // DefaultUserCrop
+ "DefaultUserCrop",
0xC7B5u,
RATIONAL,
RAW_IFD,
@@ -1117,6 +1313,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // DefaultBlackRender
+ "DefaultBlackRender",
0xC7A6u,
LONG,
PROFILE_IFD,
@@ -1124,6 +1321,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // BaselineExposureOffset
+ "BaselineExposureOffset",
0xC7A5u,
RATIONAL,
PROFILE_IFD,
@@ -1131,6 +1329,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileLookTableEncoding
+ "ProfileLookTableEncoding",
0xC7A4u,
LONG,
PROFILE_IFD,
@@ -1138,6 +1337,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // ProfileHueSatMapEncoding
+ "ProfileHueSatMapEncoding",
0xC7A3u,
LONG,
PROFILE_IFD,
@@ -1145,6 +1345,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // OriginalDefaultFinalSize
+ "OriginalDefaultFinalSize",
0xC791u,
LONG,
IFD_0,
@@ -1152,6 +1353,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // OriginalBestQualityFinalSize
+ "OriginalBestQualityFinalSize",
0xC792u,
LONG,
IFD_0,
@@ -1159,6 +1361,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // OriginalDefaultCropSize
+ "OriginalDefaultCropSize",
0xC793u,
LONG,
IFD_0,
@@ -1166,6 +1369,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // NewRawImageDigest
+ "NewRawImageDigest",
0xC7A7u,
BYTE,
IFD_0,
@@ -1173,6 +1377,7 @@ const TagDefinition_t DNG_TAG_DEFINITIONS[] = {
UNDEFINED_ENDIAN
},
{ // RawToPreviewGain
+ "RawToPreviewGain",
0xC7A8u,
DOUBLE,
PREVIEW_IFD,
diff --git a/media/img_utils/include/img_utils/TiffEntry.h b/media/img_utils/include/img_utils/TiffEntry.h
index cd01640..4d672b2 100644
--- a/media/img_utils/include/img_utils/TiffEntry.h
+++ b/media/img_utils/include/img_utils/TiffEntry.h
@@ -34,10 +34,11 @@ inline bool operator op (const TiffEntry& entry) const;
/**
* This class holds a single TIFF IFD entry.
+ *
+ * Subclasses are expected to support assignment and copying operations.
*/
class ANDROID_API TiffEntry : public TiffWritable {
public:
- // TODO: Copy constructor/equals here.
virtual ~TiffEntry();
/**
@@ -83,7 +84,7 @@ class ANDROID_API TiffEntry : public TiffWritable {
template<typename T>
const T* getData() const;
- String8 toString() const;
+ virtual String8 toString() const;
/**
* Force the type used here to be a valid TIFF type.
@@ -99,10 +100,10 @@ class ANDROID_API TiffEntry : public TiffWritable {
COMPARE_DEF(>)
COMPARE_DEF(<)
- protected:
- enum {
- MAX_PRINT_STRING_LENGTH = 256
- };
+ protected:
+ enum {
+ MAX_PRINT_STRING_LENGTH = 256
+ };
};
#define COMPARE(op) \
diff --git a/media/img_utils/include/img_utils/TiffEntryImpl.h b/media/img_utils/include/img_utils/TiffEntryImpl.h
index cbe0e9a..f5ccb5e 100644
--- a/media/img_utils/include/img_utils/TiffEntryImpl.h
+++ b/media/img_utils/include/img_utils/TiffEntryImpl.h
@@ -17,6 +17,7 @@
#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>
@@ -24,6 +25,8 @@
#include <utils/Log.h>
#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <utils/StrongPointer.h>
#include <stdint.h>
namespace android {
@@ -32,7 +35,6 @@ namespace img_utils {
template<typename T>
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();
@@ -54,7 +56,7 @@ class TiffEntryImpl : public TiffEntry {
uint16_t mType;
uint32_t mCount;
Endianness mEnd;
- T* mData;
+ Vector<T> mData;
};
@@ -63,18 +65,12 @@ TiffEntryImpl<T>::TiffEntryImpl(uint16_t tag, TagType type, uint32_t count, Endi
const T* data)
: mTag(tag), mType(static_cast<uint16_t>(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];
- }
+ 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() {
- if (mData) {
- delete[] mData;
- }
-}
+TiffEntryImpl<T>::~TiffEntryImpl() {}
template<typename T>
uint32_t TiffEntryImpl<T>::getCount() const {
@@ -93,7 +89,7 @@ TagType TiffEntryImpl<T>::getType() const {
template<typename T>
const void* TiffEntryImpl<T>::getDataHelper() const {
- return reinterpret_cast<const void*>(mData);
+ return reinterpret_cast<const void*>(mData.array());
}
template<typename T>
@@ -144,7 +140,7 @@ status_t TiffEntryImpl<T>::writeTagInfo(uint32_t offset, /*out*/EndianOutput* ou
*/
count <<= 1;
}
- BAIL_ON_FAIL(out->write(mData, 0, count), ret);
+ BAIL_ON_FAIL(out->write(mData.array(), 0, count), ret);
ZERO_TILL_WORD(out, dataSize, ret);
}
return ret;
@@ -171,7 +167,7 @@ status_t TiffEntryImpl<T>::writeData(uint32_t offset, EndianOutput* out) const {
count <<= 1;
}
- BAIL_ON_FAIL(out->write(mData, 0, count), ret);
+ BAIL_ON_FAIL(out->write(mData.array(), 0, count), ret);
if (mEnd != UNDEFINED_ENDIAN) {
out->setEndianness(tmp);
@@ -182,6 +178,38 @@ status_t TiffEntryImpl<T>::writeData(uint32_t offset, EndianOutput* out) const {
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*/
diff --git a/media/img_utils/include/img_utils/TiffHelpers.h b/media/img_utils/include/img_utils/TiffHelpers.h
index fd0ea7a..0969e4d 100644
--- a/media/img_utils/include/img_utils/TiffHelpers.h
+++ b/media/img_utils/include/img_utils/TiffHelpers.h
@@ -37,7 +37,7 @@ const uint8_t ZERO_WORD[] = {0, 0, 0, 0};
{ \
size_t remaining = BYTES_TILL_WORD(index); \
if (remaining > 0) { \
- BAIL_ON_FAIL(output->write(ZERO_WORD, 0, remaining), ret); \
+ BAIL_ON_FAIL((output)->write(ZERO_WORD, 0, remaining), ret); \
} \
}
diff --git a/media/img_utils/include/img_utils/TiffIfd.h b/media/img_utils/include/img_utils/TiffIfd.h
index 9400456..51b5c9a 100644
--- a/media/img_utils/include/img_utils/TiffIfd.h
+++ b/media/img_utils/include/img_utils/TiffIfd.h
@@ -42,7 +42,6 @@ namespace img_utils {
*/
class ANDROID_API TiffIfd : public TiffWritable {
public:
- // TODO: Copy constructor/equals here - needed for SubIfds.
TiffIfd(uint32_t ifdId);
virtual ~TiffIfd();
@@ -98,9 +97,50 @@ class ANDROID_API TiffIfd : public TiffWritable {
virtual sp<TiffEntry> getEntry(uint16_t tag) const;
/**
+ * Remove the entry with the given tag ID if it exists.
+ */
+ virtual void removeEntry(uint16_t tag);
+
+ /**
+ * Convenience method to validate and set strip-related image tags.
+ *
+ * This sets all strip related tags, but leaves offset values unitialized.
+ * setStripOffsets must be called with the desired offset before writing.
+ * The strip tag values are calculated from the existing tags for image
+ * dimensions and pixel type set in the IFD.
+ *
+ * Does not handle planar image configurations (PlanarConfiguration != 1).
+ *
+ * Returns OK on success, or a negative error code.
+ */
+ virtual status_t validateAndSetStripTags();
+
+ /**
+ * Returns true if validateAndSetStripTags has been called, but not setStripOffsets.
+ */
+ virtual bool uninitializedOffsets() const;
+
+ /**
+ * Convenience method to set beginning offset for strips.
+ *
+ * Call this to update the strip offsets before calling writeData.
+ *
+ * Returns OK on success, or a negative error code.
+ */
+ virtual status_t setStripOffset(uint32_t offset);
+
+ /**
+ * Get the total size of the strips in bytes.
+ *
+ * This sums the byte count at each strip offset, and returns
+ * the total count of bytes stored in strips for this IFD.
+ */
+ virtual uint32_t getStripSize() const;
+
+ /**
* Get a formatted string representing this IFD.
*/
- String8 toString() const;
+ virtual String8 toString() const;
/**
* Print a formatted string representing this IFD to logcat.
@@ -111,11 +151,13 @@ class ANDROID_API TiffIfd : public TiffWritable {
* Get value used to determine sort order.
*/
virtual uint32_t getComparableValue() const;
+
protected:
virtual uint32_t checkAndGetOffset(uint32_t offset) const;
SortedEntryVector mEntries;
sp<TiffIfd> mNextIfd;
uint32_t mIfdId;
+ bool mStripOffsetsInitialized;
};
} /*namespace img_utils*/
diff --git a/media/img_utils/include/img_utils/TiffWriter.h b/media/img_utils/include/img_utils/TiffWriter.h
index ec27fc3..b7af239 100644
--- a/media/img_utils/include/img_utils/TiffWriter.h
+++ b/media/img_utils/include/img_utils/TiffWriter.h
@@ -18,8 +18,10 @@
#define IMG_UTILS_TIFF_WRITER_H
#include <img_utils/EndianUtils.h>
+#include <img_utils/StripSource.h>
#include <img_utils/TiffEntryImpl.h>
#include <img_utils/TagDefinitions.h>
+#include <img_utils/TiffIfd.h>
#include <utils/Log.h>
#include <utils/Errors.h>
@@ -48,6 +50,10 @@ class Output;
*/
class ANDROID_API TiffWriter : public LightRefBase<TiffWriter> {
public:
+ enum SubIfdType {
+ SUBIFD = 0,
+ GPSINFO
+ };
/**
* Constructs a TiffWriter with the default tag mappings. This enables
@@ -77,6 +83,25 @@ class ANDROID_API TiffWriter : public LightRefBase<TiffWriter> {
* Write a TIFF header containing each IFD set. This will recursively
* write all SubIFDs and tags.
*
+ * Any StripSources passed in will be written to the output as image strips
+ * at the appropriate offests. The StripByteCounts, RowsPerStrip, and
+ * StripOffsets tags must be set to use this. To set these tags in a
+ * given IFD, use the addStrip method.
+ *
+ * Returns OK on success, or a negative error code on failure.
+ */
+ virtual status_t write(Output* out, StripSource** sources, size_t sourcesCount,
+ Endianness end = LITTLE);
+
+ /**
+ * Write a TIFF header containing each IFD set. This will recursively
+ * write all SubIFDs and tags.
+ *
+ * Image data for strips or tiles must be written separately at the
+ * appropriate offsets. These offsets must not fall within the file
+ * header written this way. The size of the header written is given
+ * by the getTotalSize() method.
+ *
* Returns OK on success, or a negative error code on failure.
*/
virtual status_t write(Output* out, Endianness end = LITTLE);
@@ -88,16 +113,7 @@ class ANDROID_API TiffWriter : public LightRefBase<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<TiffEntry>& 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.
+ * Add an entry to the IFD with the given ID.
*
* Returns OK on success, or a negative error code on failure. Valid
* error codes for this method are:
@@ -106,16 +122,14 @@ class ANDROID_API TiffWriter : public LightRefBase<TiffWriter> {
* 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<typename T>
- status_t buildEntry(uint16_t tag, uint32_t count, const T* data,
- /*out*/sp<TiffEntry>* outEntry) const;
+ virtual status_t addEntry(const sp<TiffEntry>& entry, uint32_t ifd);
- /**
+ /**
* 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.
+ * was constructed with. The count and type are validated.
*
* Returns OK on success, or a negative error code on failure. Valid
* error codes for this method are:
@@ -130,18 +144,47 @@ class ANDROID_API TiffWriter : public LightRefBase<TiffWriter> {
status_t addEntry(uint16_t tag, uint32_t count, const T* data, uint32_t ifd);
/**
+ * 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<typename T>
+ status_t buildEntry(uint16_t tag, uint32_t count, const T* data,
+ /*out*/sp<TiffEntry>* outEntry) const;
+
+ /**
+ * Convenience function to set the strip related tags for a given IFD.
+ *
+ * Call this before using a StripSource as an input to write.
+ * The following tags must be set before calling this method:
+ * - ImageWidth
+ * - ImageLength
+ * - SamplesPerPixel
+ * - BitsPerSample
+ *
+ * Returns OK on success, or a negative error code.
+ */
+ virtual status_t addStrip(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<TiffEntry> 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.
+ * Remove the TIFF entry with the given tag ID in the given IFD if it exists.
*/
- virtual status_t uncheckedAddIfd(const sp<TiffIfd>& ifd);
+ virtual void removeEntry(uint16_t tag, uint32_t ifd);
/**
* Create an empty IFD with the given ID and add it to the end of the
@@ -150,24 +193,10 @@ class ANDROID_API TiffWriter : public LightRefBase<TiffWriter> {
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.
+ * Create an empty IFD with the given ID and add it as a SubIfd of the
+ * parent IFD.
*/
- template<typename T>
- static sp<TiffEntry> 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<uint16_t, const TagDefinition_t*> buildTagMap(
- const TagDefinition_t* definitions, size_t length);
+ virtual status_t addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type = SUBIFD);
/**
* Returns the default type for the given tag ID.
@@ -181,15 +210,46 @@ class ANDROID_API TiffWriter : public LightRefBase<TiffWriter> {
virtual uint32_t getDefaultCount(uint16_t tag) const;
/**
+ * Returns true if an IFD with the given ID exists.
+ */
+ virtual bool hasIfd(uint32_t ifd) const;
+
+ /**
* Returns true if a definition exist for the given tag ID.
*/
virtual bool checkIfDefined(uint16_t tag) const;
/**
+ * Returns the name of the tag if a definition exists for the given tag
+ * ID, or null if no definition exists.
+ */
+ virtual const char* getTagName(uint16_t tag) const;
+
+ /**
* Print the currently configured IFDs and entries to logcat.
*/
virtual void log() const;
+ /**
+ * 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<typename T>
+ static sp<TiffEntry> 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<uint16_t, const TagDefinition_t*> buildTagMap(
+ const TagDefinition_t* definitions, size_t length);
+
protected:
enum {
DEFAULT_NUM_TAG_MAPS = 4,
@@ -240,17 +300,14 @@ status_t TiffWriter::buildEntry(uint16_t tag, uint32_t count, const T* data,
template<typename T>
status_t TiffWriter::addEntry(uint16_t tag, uint32_t count, const T* data, uint32_t ifd) {
sp<TiffEntry> outEntry;
+
status_t ret = buildEntry<T>(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);
+
+ return addEntry(outEntry, ifd);
}
template<typename T>
diff --git a/media/img_utils/src/Android.mk b/media/img_utils/src/Android.mk
index 80893be..4074849 100644
--- a/media/img_utils/src/Android.mk
+++ b/media/img_utils/src/Android.mk
@@ -31,6 +31,7 @@ LOCAL_SRC_FILES := \
TiffEntryImpl.cpp \
ByteArrayOutput.cpp \
DngUtils.cpp \
+ StripSource.cpp \
LOCAL_SHARED_LIBRARIES := \
libexpat \
diff --git a/media/img_utils/src/FileInput.cpp b/media/img_utils/src/FileInput.cpp
index e43fd53..498e715 100644
--- a/media/img_utils/src/FileInput.cpp
+++ b/media/img_utils/src/FileInput.cpp
@@ -45,19 +45,24 @@ status_t FileInput::open() {
return OK;
}
-size_t FileInput::read(uint8_t* buf, size_t offset, size_t count, status_t* err) {
+ssize_t FileInput::read(uint8_t* buf, size_t offset, size_t count) {
if (!mOpen) {
ALOGE("%s: Could not read file %s, file not open.", __FUNCTION__, mPath.string());
- if (err != NULL) *err = BAD_VALUE;
- return 0;
+ return BAD_VALUE;
}
size_t bytesRead = ::fread(buf + offset, sizeof(uint8_t), count, mFp);
int error = ::ferror(mFp);
if (error != 0) {
ALOGE("%s: Error %d occurred while reading file %s.", __FUNCTION__, error, mPath.string());
- if (err != NULL) *err = BAD_VALUE;
+ return BAD_VALUE;
}
+
+ // End of file reached
+ if (::feof(mFp) != 0 && bytesRead == 0) {
+ return NOT_ENOUGH_DATA;
+ }
+
return bytesRead;
}
diff --git a/media/img_utils/src/Input.cpp b/media/img_utils/src/Input.cpp
index 1e51e10..3782014 100644
--- a/media/img_utils/src/Input.cpp
+++ b/media/img_utils/src/Input.cpp
@@ -20,9 +20,37 @@ namespace android {
namespace img_utils {
Input::~Input() {}
+
status_t Input::open() { return OK; }
+
status_t Input::close() { return OK; }
+ssize_t Input::skip(size_t count) {
+ const size_t SKIP_BUF_SIZE = 1024;
+ uint8_t skipBuf[SKIP_BUF_SIZE];
+
+ size_t remaining = count;
+ while (remaining > 0) {
+ size_t amt = (SKIP_BUF_SIZE > remaining) ? remaining : SKIP_BUF_SIZE;
+ ssize_t ret = read(skipBuf, 0, amt);
+ if (ret < 0) {
+ if(ret == NOT_ENOUGH_DATA) {
+ // End of file encountered
+ if (remaining == count) {
+ // Read no bytes, return EOF
+ return NOT_ENOUGH_DATA;
+ } else {
+ // Return num bytes read
+ return count - remaining;
+ }
+ }
+ // Return error code.
+ return ret;
+ }
+ remaining -= ret;
+ }
+ return count;
+}
} /*namespace img_utils*/
} /*namespace android*/
diff --git a/media/img_utils/src/StripSource.cpp b/media/img_utils/src/StripSource.cpp
new file mode 100644
index 0000000..57b6082
--- /dev/null
+++ b/media/img_utils/src/StripSource.cpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+#include <img_utils/StripSource.h>
+
+namespace android {
+namespace img_utils {
+
+StripSource::~StripSource() {}
+
+} /*namespace img_utils*/
+} /*namespace android*/
diff --git a/media/img_utils/src/TiffEntry.cpp b/media/img_utils/src/TiffEntry.cpp
index e028827..9cea721 100644
--- a/media/img_utils/src/TiffEntry.cpp
+++ b/media/img_utils/src/TiffEntry.cpp
@@ -32,16 +32,6 @@ TiffEntry::~TiffEntry() {}
*
* Values with types other than the ones given here should not compile.
*/
-template<>
-const Vector<sp<TiffIfd> >* TiffEntry::forceValidType<Vector<sp<TiffIfd> > >(TagType type,
- const Vector<sp<TiffIfd> >* value) {
- if (type == LONG) {
- return value;
- }
- ALOGE("%s: Value of type 'ifd vector' is not valid for tag with TIFF type %d.",
- __FUNCTION__, type);
- return NULL;
-}
template<>
const sp<TiffIfd>* TiffEntry::forceValidType<sp<TiffIfd> >(TagType type, const sp<TiffIfd>* value) {
diff --git a/media/img_utils/src/TiffEntryImpl.cpp b/media/img_utils/src/TiffEntryImpl.cpp
index 6efa458..257c266 100644
--- a/media/img_utils/src/TiffEntryImpl.cpp
+++ b/media/img_utils/src/TiffEntryImpl.cpp
@@ -15,30 +15,11 @@
*/
#include <img_utils/TiffEntryImpl.h>
-#include <img_utils/TiffIfd.h>
#include <utils/Vector.h>
namespace android {
namespace img_utils {
-template<>
-size_t TiffEntryImpl<TiffIfd>::getSize() const {
- uint32_t total = 0;
- for (uint32_t i = 0; i < mCount; ++i) {
- total += mData[i].getSize();
- }
- return total;
-}
-
-template<>
-status_t TiffEntryImpl<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);
- }
- return ret;
-}
-
} /*namespace img_utils*/
} /*namespace android*/
diff --git a/media/img_utils/src/TiffIfd.cpp b/media/img_utils/src/TiffIfd.cpp
index 1b3b40d..3fb00cc 100644
--- a/media/img_utils/src/TiffIfd.cpp
+++ b/media/img_utils/src/TiffIfd.cpp
@@ -14,8 +14,12 @@
* limitations under the License.
*/
-#include <img_utils/TiffIfd.h>
+#define LOG_TAG "TiffIfd"
+
+#include <img_utils/TagDefinitions.h>
#include <img_utils/TiffHelpers.h>
+#include <img_utils/TiffIfd.h>
+#include <img_utils/TiffWriter.h>
#include <utils/Log.h>
@@ -23,7 +27,7 @@ namespace android {
namespace img_utils {
TiffIfd::TiffIfd(uint32_t ifdId)
- : mNextIfd(), mIfdId(ifdId) {}
+ : mNextIfd(), mIfdId(ifdId), mStripOffsetsInitialized(false) {}
TiffIfd::~TiffIfd() {}
@@ -52,6 +56,14 @@ sp<TiffEntry> TiffIfd::getEntry(uint16_t tag) const {
return mEntries[index];
}
+void TiffIfd::removeEntry(uint16_t tag) {
+ ssize_t index = mEntries.indexOfTag(tag);
+ if (index >= 0) {
+ mEntries.removeAt(index);
+ }
+}
+
+
void TiffIfd::setNextIfd(const sp<TiffIfd>& ifd) {
mNextIfd = ifd;
}
@@ -156,6 +168,198 @@ uint32_t TiffIfd::getComparableValue() const {
return mIfdId;
}
+status_t TiffIfd::validateAndSetStripTags() {
+ sp<TiffEntry> widthEntry = getEntry(TAG_IMAGEWIDTH);
+ if (widthEntry == NULL) {
+ ALOGE("%s: IFD %u doesn't have a ImageWidth tag set", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ sp<TiffEntry> heightEntry = getEntry(TAG_IMAGELENGTH);
+ if (heightEntry == NULL) {
+ ALOGE("%s: IFD %u doesn't have a ImageLength tag set", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ sp<TiffEntry> samplesEntry = getEntry(TAG_SAMPLESPERPIXEL);
+ if (samplesEntry == NULL) {
+ ALOGE("%s: IFD %u doesn't have a SamplesPerPixel tag set", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ sp<TiffEntry> bitsEntry = getEntry(TAG_BITSPERSAMPLE);
+ if (bitsEntry == NULL) {
+ ALOGE("%s: IFD %u doesn't have a BitsPerSample tag set", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ uint32_t width = *(widthEntry->getData<uint32_t>());
+ uint32_t height = *(heightEntry->getData<uint32_t>());
+ uint16_t bitsPerSample = *(bitsEntry->getData<uint16_t>());
+ uint16_t samplesPerPixel = *(samplesEntry->getData<uint16_t>());
+
+ if ((bitsPerSample % 8) != 0) {
+ ALOGE("%s: BitsPerSample %d in IFD %u is not byte-aligned.", __FUNCTION__,
+ bitsPerSample, mIfdId);
+ return BAD_VALUE;
+ }
+
+ uint32_t bytesPerSample = bitsPerSample / 8;
+
+ // Choose strip size as close to 8kb as possible without splitting rows.
+ // If the row length is >8kb, each strip will only contain a single row.
+ const uint32_t rowLengthBytes = bytesPerSample * samplesPerPixel * width;
+ const uint32_t idealChunkSize = (1 << 13); // 8kb
+ uint32_t rowsPerChunk = idealChunkSize / rowLengthBytes;
+ rowsPerChunk = (rowsPerChunk == 0) ? 1 : rowsPerChunk;
+ const uint32_t actualChunkSize = rowLengthBytes * rowsPerChunk;
+
+ const uint32_t lastChunkRows = height % rowsPerChunk;
+ const uint32_t lastChunkSize = lastChunkRows * rowLengthBytes;
+
+ if (actualChunkSize > /*max strip size for TIFF/EP*/65536) {
+ ALOGE("%s: Strip length too long.", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ size_t numStrips = height / rowsPerChunk;
+
+ // Add another strip for the incomplete chunk.
+ if (lastChunkRows > 0) {
+ numStrips += 1;
+ }
+
+ // Put each row in it's own strip
+ uint32_t rowsPerStripVal = rowsPerChunk;
+ sp<TiffEntry> rowsPerStrip = TiffWriter::uncheckedBuildEntry(TAG_ROWSPERSTRIP, LONG, 1,
+ UNDEFINED_ENDIAN, &rowsPerStripVal);
+
+ if (rowsPerStrip == NULL) {
+ ALOGE("%s: Could not build entry for RowsPerStrip tag.", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ Vector<uint32_t> byteCounts;
+
+ for (size_t i = 0; i < numStrips; ++i) {
+ if (lastChunkRows > 0 && i == (numStrips - 1)) {
+ byteCounts.add(lastChunkSize);
+ } else {
+ byteCounts.add(actualChunkSize);
+ }
+ }
+
+ // Set byte counts for each strip
+ sp<TiffEntry> stripByteCounts = TiffWriter::uncheckedBuildEntry(TAG_STRIPBYTECOUNTS, LONG,
+ static_cast<uint32_t>(numStrips), UNDEFINED_ENDIAN, byteCounts.array());
+
+ if (stripByteCounts == NULL) {
+ ALOGE("%s: Could not build entry for StripByteCounts tag.", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ Vector<uint32_t> stripOffsetsVector;
+ stripOffsetsVector.resize(numStrips);
+
+ // Set uninitialized offsets
+ sp<TiffEntry> stripOffsets = TiffWriter::uncheckedBuildEntry(TAG_STRIPOFFSETS, LONG,
+ static_cast<uint32_t>(numStrips), UNDEFINED_ENDIAN, stripOffsetsVector.array());
+
+ if (stripOffsets == NULL) {
+ ALOGE("%s: Could not build entry for StripOffsets tag.", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if(addEntry(stripByteCounts) != OK) {
+ ALOGE("%s: Could not add entry for StripByteCounts to IFD %u", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ if(addEntry(rowsPerStrip) != OK) {
+ ALOGE("%s: Could not add entry for StripByteCounts to IFD %u", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ if(addEntry(stripOffsets) != OK) {
+ ALOGE("%s: Could not add entry for StripByteCounts to IFD %u", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ mStripOffsetsInitialized = true;
+ return OK;
+}
+
+bool TiffIfd::uninitializedOffsets() const {
+ return mStripOffsetsInitialized;
+}
+
+status_t TiffIfd::setStripOffset(uint32_t offset) {
+
+ // Get old offsets and bytecounts
+ sp<TiffEntry> oldOffsets = getEntry(TAG_STRIPOFFSETS);
+ if (oldOffsets == NULL) {
+ ALOGE("%s: IFD %u does not contain StripOffsets entry.", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ sp<TiffEntry> stripByteCounts = getEntry(TAG_STRIPBYTECOUNTS);
+ if (stripByteCounts == NULL) {
+ ALOGE("%s: IFD %u does not contain StripByteCounts entry.", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ uint32_t offsetsCount = oldOffsets->getCount();
+ uint32_t byteCount = stripByteCounts->getCount();
+ if (offsetsCount != byteCount) {
+ ALOGE("%s: StripOffsets count (%u) doesn't match StripByteCounts count (%u) in IFD %u",
+ __FUNCTION__, offsetsCount, byteCount, mIfdId);
+ return BAD_VALUE;
+ }
+
+ const uint32_t* stripByteCountsArray = stripByteCounts->getData<uint32_t>();
+
+ size_t numStrips = offsetsCount;
+
+ Vector<uint32_t> stripOffsets;
+
+ // Calculate updated byte offsets
+ for (size_t i = 0; i < numStrips; ++i) {
+ stripOffsets.add(offset);
+ offset += stripByteCountsArray[i];
+ }
+
+ sp<TiffEntry> newOffsets = TiffWriter::uncheckedBuildEntry(TAG_STRIPOFFSETS, LONG,
+ static_cast<uint32_t>(numStrips), UNDEFINED_ENDIAN, stripOffsets.array());
+
+ if (newOffsets == NULL) {
+ ALOGE("%s: Coult not build updated offsets entry in IFD %u", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ if (addEntry(newOffsets) != OK) {
+ ALOGE("%s: Failed to add updated offsets entry in IFD %u", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+ return OK;
+}
+
+uint32_t TiffIfd::getStripSize() const {
+ sp<TiffEntry> stripByteCounts = getEntry(TAG_STRIPBYTECOUNTS);
+ if (stripByteCounts == NULL) {
+ ALOGE("%s: IFD %u does not contain StripByteCounts entry.", __FUNCTION__, mIfdId);
+ return BAD_VALUE;
+ }
+
+ uint32_t count = stripByteCounts->getCount();
+ const uint32_t* byteCounts = stripByteCounts->getData<uint32_t>();
+
+ uint32_t total = 0;
+ for (size_t i = 0; i < static_cast<size_t>(count); ++i) {
+ total += byteCounts[i];
+ }
+ return total;
+}
+
String8 TiffIfd::toString() const {
size_t s = mEntries.size();
String8 output;
diff --git a/media/img_utils/src/TiffWriter.cpp b/media/img_utils/src/TiffWriter.cpp
index 2439033..d85289e 100644
--- a/media/img_utils/src/TiffWriter.cpp
+++ b/media/img_utils/src/TiffWriter.cpp
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#include <img_utils/TiffIfd.h>
+#define LOG_TAG "TiffWriter"
+
#include <img_utils/TiffHelpers.h>
#include <img_utils/TiffWriter.h>
#include <img_utils/TagDefinitions.h>
@@ -55,6 +56,82 @@ TiffWriter::TiffWriter(KeyedVector<uint16_t, const TagDefinition_t*>* enabledDef
TiffWriter::~TiffWriter() {}
+status_t TiffWriter::write(Output* out, StripSource** sources, size_t sourcesCount,
+ Endianness end) {
+ status_t ret = OK;
+ EndianOutput endOut(out, end);
+
+ if (mIfd == NULL) {
+ ALOGE("%s: Tiff header is empty.", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (LOG_NDEBUG == 0) {
+ log();
+ }
+
+ uint32_t totalSize = getTotalSize();
+
+ KeyedVector<uint32_t, uint32_t> offsetVector;
+
+ for (size_t i = 0; i < mNamedIfds.size(); ++i) {
+ if (mNamedIfds[i]->uninitializedOffsets()) {
+ uint32_t stripSize = mNamedIfds[i]->getStripSize();
+ if (mNamedIfds[i]->setStripOffset(totalSize) != OK) {
+ ALOGE("%s: Could not set strip offsets.", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ totalSize += stripSize;
+ WORD_ALIGN(totalSize);
+ offsetVector.add(mNamedIfds.keyAt(i), totalSize);
+ }
+ }
+
+ size_t offVecSize = offsetVector.size();
+ if (offVecSize != sourcesCount) {
+ ALOGE("%s: Mismatch between number of IFDs with uninitialized strips (%zu) and"
+ " sources (%zu).", __FUNCTION__, offVecSize, sourcesCount);
+ return BAD_VALUE;
+ }
+
+ BAIL_ON_FAIL(writeFileHeader(endOut), ret);
+
+ uint32_t offset = FILE_HEADER_SIZE;
+ sp<TiffIfd> ifd = mIfd;
+ while(ifd != NULL) {
+ BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret);
+ offset += ifd->getSize();
+ ifd = ifd->getNextIfd();
+ }
+
+ log();
+
+ for (size_t i = 0; i < offVecSize; ++i) {
+ uint32_t ifdKey = offsetVector.keyAt(i);
+ uint32_t nextOffset = offsetVector[i];
+ uint32_t sizeToWrite = mNamedIfds[ifdKey]->getStripSize();
+ bool found = false;
+ for (size_t j = 0; j < sourcesCount; ++j) {
+ if (sources[j]->getIfd() == ifdKey) {
+ if ((ret = sources[i]->writeToStream(endOut, sizeToWrite)) != OK) {
+ ALOGE("%s: Could not write to stream, received %d.", __FUNCTION__, ret);
+ return ret;
+ }
+ ZERO_TILL_WORD(&endOut, sizeToWrite, ret);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ALOGE("%s: No stream for byte strips for IFD %u", __FUNCTION__, ifdKey);
+ return BAD_VALUE;
+ }
+ assert(nextOffset == endOut.getCurrentOffset());
+ }
+
+ return ret;
+}
+
status_t TiffWriter::write(Output* out, Endianness end) {
status_t ret = OK;
EndianOutput endOut(out, end);
@@ -101,48 +178,43 @@ sp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const {
return mNamedIfds[index]->getEntry(tag);
}
+void TiffWriter::removeEntry(uint16_t tag, uint32_t ifd) {
+ ssize_t index = mNamedIfds.indexOfKey(ifd);
+ if (index >= 0) {
+ mNamedIfds[index]->removeEntry(tag);
+ }
+}
-// TODO: Fix this to handle IFD position in chain/sub-IFD tree
-status_t TiffWriter::addEntry(const sp<TiffEntry>& entry) {
+status_t TiffWriter::addEntry(const sp<TiffEntry>& entry, uint32_t ifd) {
uint16_t tag = entry->getTag();
const TagDefinition_t* definition = lookupDefinition(tag);
if (definition == NULL) {
+ ALOGE("%s: No definition exists for tag 0x%x.", __FUNCTION__, tag);
return BAD_INDEX;
}
- uint32_t ifdId = 0; // TODO: all in IFD0 for now.
- ssize_t index = mNamedIfds.indexOfKey(ifdId);
+ ssize_t index = mNamedIfds.indexOfKey(ifd);
// Add a new IFD if necessary
if (index < 0) {
- sp<TiffIfd> ifdEntry = new TiffIfd(ifdId);
- if (mIfd == NULL) {
- mIfd = ifdEntry;
- }
- index = mNamedIfds.add(ifdId, ifdEntry);
- assert(index >= 0);
+ ALOGE("%s: No IFD %u exists.", __FUNCTION__, ifd);
+ return NAME_NOT_FOUND;
}
sp<TiffIfd> selectedIfd = mNamedIfds[index];
return selectedIfd->addEntry(entry);
}
-status_t TiffWriter::uncheckedAddIfd(const sp<TiffIfd>& ifd) {
- mNamedIfds.add(ifd->getId(), ifd);
- sp<TiffIfd> last = findLastIfd();
- if (last == NULL) {
- mIfd = ifd;
- } else {
- last->setNextIfd(ifd);
- }
- last = ifd->getNextIfd();
- while (last != NULL) {
- mNamedIfds.add(last->getId(), last);
- last = last->getNextIfd();
+status_t TiffWriter::addStrip(uint32_t ifd) {
+ ssize_t index = mNamedIfds.indexOfKey(ifd);
+ if (index < 0) {
+ ALOGE("%s: Ifd %u doesn't exist, cannot add strip entries.", __FUNCTION__, ifd);
+ return BAD_VALUE;
}
- return OK;
+ sp<TiffIfd> selected = mNamedIfds[index];
+ return selected->validateAndSetStripTags();
}
status_t TiffWriter::addIfd(uint32_t ifd) {
@@ -151,6 +223,7 @@ status_t TiffWriter::addIfd(uint32_t ifd) {
ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
return BAD_VALUE;
}
+
sp<TiffIfd> newIfd = new TiffIfd(ifd);
if (mIfd == NULL) {
mIfd = newIfd;
@@ -158,7 +231,83 @@ status_t TiffWriter::addIfd(uint32_t ifd) {
sp<TiffIfd> last = findLastIfd();
last->setNextIfd(newIfd);
}
- mNamedIfds.add(ifd, newIfd);
+
+ if(mNamedIfds.add(ifd, newIfd) < 0) {
+ ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd);
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
+
+status_t TiffWriter::addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type) {
+ ssize_t index = mNamedIfds.indexOfKey(ifd);
+ if (index >= 0) {
+ ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
+ return BAD_VALUE;
+ }
+
+ ssize_t parentIndex = mNamedIfds.indexOfKey(parentIfd);
+ if (parentIndex < 0) {
+ ALOGE("%s: Parent IFD with ID 0x%x does not exist.", __FUNCTION__, parentIfd);
+ return BAD_VALUE;
+ }
+
+ sp<TiffIfd> parent = mNamedIfds[parentIndex];
+ sp<TiffIfd> newIfd = new TiffIfd(ifd);
+
+ uint16_t subIfdTag;
+ if (type == SUBIFD) {
+ subIfdTag = TAG_SUBIFDS;
+ } else if (type == GPSINFO) {
+ subIfdTag = TAG_GPSINFO;
+ } else {
+ ALOGE("%s: Unknown SubIFD type %d.", __FUNCTION__, type);
+ return BAD_VALUE;
+ }
+
+ sp<TiffEntry> subIfds = parent->getEntry(subIfdTag);
+ if (subIfds == NULL) {
+ if (buildEntry(subIfdTag, 1, &newIfd, &subIfds) < 0) {
+ ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
+ return BAD_VALUE;
+ }
+ } else {
+ if (type == GPSINFO) {
+ ALOGE("%s: Cannot add GPSInfo SubIFD to IFD %u, one already exists.", __FUNCTION__,
+ ifd);
+ return BAD_VALUE;
+ }
+
+ Vector<sp<TiffIfd> > subIfdList;
+ const sp<TiffIfd>* oldIfdArray = subIfds->getData<sp<TiffIfd> >();
+ if (subIfdList.appendArray(oldIfdArray, subIfds->getCount()) < 0) {
+ ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
+ return BAD_VALUE;
+ }
+
+ if (subIfdList.add(newIfd) < 0) {
+ ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
+ return BAD_VALUE;
+ }
+
+ uint32_t count = subIfdList.size();
+ if (buildEntry(subIfdTag, count, subIfdList.array(), &subIfds) < 0) {
+ ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
+ return BAD_VALUE;
+ }
+ }
+
+ if (parent->addEntry(subIfds) < 0) {
+ ALOGE("%s: Failed to add SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
+ return BAD_VALUE;
+ }
+
+ if(mNamedIfds.add(ifd, newIfd) < 0) {
+ ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd);
+ return BAD_VALUE;
+ }
+
return OK;
}
@@ -180,10 +329,23 @@ uint32_t TiffWriter::getDefaultCount(uint16_t tag) const {
return definition->fixedCount;
}
+bool TiffWriter::hasIfd(uint32_t ifd) const {
+ ssize_t index = mNamedIfds.indexOfKey(ifd);
+ return index >= 0;
+}
+
bool TiffWriter::checkIfDefined(uint16_t tag) const {
return lookupDefinition(tag) != NULL;
}
+const char* TiffWriter::getTagName(uint16_t tag) const {
+ const TagDefinition_t* definition = lookupDefinition(tag);
+ if (definition == NULL) {
+ return NULL;
+ }
+ return definition->tagName;
+}
+
sp<TiffIfd> TiffWriter::findLastIfd() {
sp<TiffIfd> ifd = mIfd;
while(ifd != NULL) {
@@ -221,10 +383,9 @@ uint32_t TiffWriter::getTotalSize() const {
void TiffWriter::log() const {
ALOGI("%s: TiffWriter:", __FUNCTION__);
- sp<TiffIfd> ifd = mIfd;
- while(ifd != NULL) {
- ifd->log();
- ifd = ifd->getNextIfd();
+ size_t length = mNamedIfds.size();
+ for (size_t i = 0; i < length; ++i) {
+ mNamedIfds[i]->log();
}
}