aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYujie Qin <yujieqin@google.com>2016-01-15 16:16:19 +0100
committerYujie Qin <yujieqin@google.com>2016-01-15 16:16:19 +0100
commitcdcebd956de2dd080bc106058db3d12f8dce8ba2 (patch)
treeccbd8f96cc99d72f0552a8b111ad001dacb262f8
parentaf7fc0e2846c0760fdd4f96acb0daca4630437b3 (diff)
downloadpiex-cdcebd956de2dd080bc106058db3d12f8dce8ba2.tar.gz
Update PIEX
-rw-r--r--src/image_type_recognition/image_type_recognition_lite.cc41
-rw-r--r--src/image_type_recognition/image_type_recognition_lite.h1
-rw-r--r--src/piex.cc117
-rw-r--r--src/piex.h6
-rw-r--r--src/piex_types.h4
-rw-r--r--src/tiff_parser.cc9
-rw-r--r--src/tiff_parser.h23
7 files changed, 166 insertions, 35 deletions
diff --git a/src/image_type_recognition/image_type_recognition_lite.cc b/src/image_type_recognition/image_type_recognition_lite.cc
index 520688a..45429fd 100644
--- a/src/image_type_recognition/image_type_recognition_lite.cc
+++ b/src/image_type_recognition/image_type_recognition_lite.cc
@@ -728,6 +728,45 @@ class Rw2TypeChecker : public TypeChecker {
}
};
+// Samsung RAW.
+class SrwTypeChecker : public TypeChecker {
+ public:
+ virtual RawImageTypes Type() const { return kSrwImage; }
+
+ virtual size_t RequestedSize() const { return 256; }
+
+ // Check multiple points:
+ // 1. valid big endianness at the beginning of the file;
+ // 2. magic numbers at the (offset == 2 and offset==4) positions of the file;
+ // 3. the signature "SAMSUNG" in the requested bytes of the file;
+ virtual bool IsMyType(const RangeCheckedBytePtr& source) const {
+ // Limits the source length to the RequestedSize(), using it guarantees that
+ // we will not read more than this size from the source.
+ RangeCheckedBytePtr limited_source =
+ source.pointerToSubArray(0 /* pos */, RequestedSize());
+
+ bool use_big_endian;
+ if (!DetermineEndianness(source, &use_big_endian)) {
+ return false;
+ }
+
+ const unsigned short kTiffMagic = 0x2A; // NOLINT
+ const unsigned int kTiffOffset = 8;
+ if (!CheckUInt16Value(limited_source, 2 /* offset */, use_big_endian,
+ kTiffMagic) ||
+ !CheckUInt32Value(limited_source, 4 /* offset */, use_big_endian,
+ kTiffOffset)) {
+ return false;
+ }
+
+ const string kSignature("SAMSUNG");
+ if (!IsSignatureFound(source, 0, RequestedSize(), kSignature, NULL)) {
+ return false;
+ }
+ return true;
+ }
+};
+
// Sigma / Polaroid RAW.
class X3fTypeChecker : public TypeChecker {
public:
@@ -769,6 +808,7 @@ class TypeCheckerList {
checkers_.push_back(new RafTypeChecker());
checkers_.push_back(new RawContaxNTypeChecker());
checkers_.push_back(new Rw2TypeChecker());
+ checkers_.push_back(new SrwTypeChecker());
checkers_.push_back(new X3fTypeChecker());
// Sort the checkers by the ascending RequestedSize() to get better
@@ -833,6 +873,7 @@ bool IsRaw(const RawImageTypes type) {
case kRafImage:
case kRawContaxNImage:
case kRw2Image:
+ case kSrwImage:
case kX3fImage: {
return true;
}
diff --git a/src/image_type_recognition/image_type_recognition_lite.h b/src/image_type_recognition/image_type_recognition_lite.h
index da9caf5..5b9ca64 100644
--- a/src/image_type_recognition/image_type_recognition_lite.h
+++ b/src/image_type_recognition/image_type_recognition_lite.h
@@ -54,6 +54,7 @@ enum RawImageTypes {
kRafImage,
kRawContaxNImage,
kRw2Image,
+ kSrwImage,
kX3fImage,
};
diff --git a/src/piex.cc b/src/piex.cc
index daef264..ed3c8f4 100644
--- a/src/piex.cc
+++ b/src/piex.cc
@@ -79,12 +79,15 @@ Error GetExifData(const std::uint32_t exif_offset, StreamInterface* stream,
}
// Reads the jpeg compressed thumbnail information.
-void GetThumbnailOffsetAndLength(StreamInterface* stream,
+void GetThumbnailOffsetAndLength(const TagSet& extended_tags,
+ StreamInterface* stream,
PreviewImageData* preview_image_data) {
+ TagSet desired_tags = {kTiffTagJpegByteCount, kTiffTagJpegOffset};
+ desired_tags.insert(extended_tags.cbegin(), extended_tags.cend());
+
const std::uint32_t kNumberOfIfds = 2;
- const TagSet extended_tags = {kTiffTagJpegByteCount, kTiffTagJpegOffset};
PreviewImageData thumbnail_data;
- if (GetPreviewData(extended_tags, kNumberOfIfds, stream, &thumbnail_data) ==
+ if (GetPreviewData(desired_tags, kNumberOfIfds, stream, &thumbnail_data) ==
kOk) {
preview_image_data->thumbnail_offset = thumbnail_data.preview_offset;
preview_image_data->thumbnail_length = thumbnail_data.preview_length;
@@ -118,7 +121,8 @@ Error GetExifIfd(const Endian endian, StreamInterface* stream,
}
Error GetMakernoteIfd(const TiffDirectory& exif_ifd, const Endian endian,
- StreamInterface* stream, std::uint32_t* makernote_offset,
+ const std::uint32_t skip_offset, StreamInterface* stream,
+ std::uint32_t* makernote_offset,
TiffDirectory* makernote_ifd) {
std::uint32_t makernote_length;
if (!exif_ifd.GetOffsetAndLength(kExifTagMakernotes,
@@ -128,10 +132,10 @@ Error GetMakernoteIfd(const TiffDirectory& exif_ifd, const Endian endian,
}
std::uint32_t next_ifd_offset;
- return ParseDirectory(
- *makernote_offset, *makernote_offset + 12, endian,
- {kTiffTagImageWidth, kOlymTagCameraSettings, kOlymTagRawProcessing},
- stream, makernote_ifd, &next_ifd_offset);
+ return ParseDirectory(*makernote_offset, *makernote_offset + skip_offset,
+ endian, {kTiffTagImageWidth, kOlymTagCameraSettings,
+ kOlymTagRawProcessing, kPentaxTagColorSpace},
+ stream, makernote_ifd, &next_ifd_offset);
}
Error GetCameraSettingsIfd(const TiffDirectory& makernote_ifd,
@@ -199,8 +203,9 @@ Error GetOlympusPreviewImage(StreamInterface* stream,
std::uint32_t makernote_offset;
TiffDirectory makernote_ifd(endian);
- error = GetMakernoteIfd(exif_ifd, endian, stream, &makernote_offset,
- &makernote_ifd);
+ const std::uint32_t kSkipMakernoteStart = 12;
+ error = GetMakernoteIfd(exif_ifd, endian, kSkipMakernoteStart, stream,
+ &makernote_offset, &makernote_ifd);
if (error != kOk) {
return error;
}
@@ -259,6 +264,39 @@ Error GetOlympusPreviewImage(StreamInterface* stream,
return kOk;
}
+Error PefGetColorSpace(StreamInterface* stream,
+ PreviewImageData* preview_image_data) {
+ Endian endian;
+ if (!GetEndianness(0 /* tiff offset */, stream, &endian)) {
+ return kFail;
+ }
+
+ TiffDirectory exif_ifd(endian);
+ Error error = GetExifIfd(endian, stream, &exif_ifd);
+ if (error != kOk) {
+ return error;
+ }
+
+ std::uint32_t makernote_offset;
+ TiffDirectory makernote_ifd(endian);
+ const std::uint32_t kSkipMakernoteStart = 6;
+ error = GetMakernoteIfd(exif_ifd, endian, kSkipMakernoteStart, stream,
+ &makernote_offset, &makernote_ifd);
+ if (error != kOk) {
+ return error;
+ }
+ if (makernote_ifd.Has(kPentaxTagColorSpace)) {
+ std::uint32_t color_space;
+ if (!makernote_ifd.Get(kPentaxTagColorSpace, &color_space)) {
+ return kFail;
+ }
+ preview_image_data->color_space = color_space == 0
+ ? PreviewImageData::kSrgb
+ : PreviewImageData::kAdobeRgb;
+ }
+ return kOk;
+}
+
// Parses the Fuji Cfa header for the image width and height.
bool RafGetDimension(StreamInterface* stream, std::uint32_t* width,
std::uint32_t* height) {
@@ -301,7 +339,7 @@ Error ArwGetPreviewData(StreamInterface* stream,
kTiffTagJpegByteCount, kTiffTagJpegOffset,
kTiffTagSubIfd};
- GetThumbnailOffsetAndLength(stream, preview_image_data);
+ GetThumbnailOffsetAndLength(TagSet(), stream, preview_image_data);
const std::uint32_t kNumberOfIfds = 1;
return GetPreviewData(extended_tags, kNumberOfIfds, stream,
@@ -313,7 +351,7 @@ Error Cr2GetPreviewData(StreamInterface* stream,
const TagSet extended_tags = {kExifTagHeight, kExifTagWidth,
kTiffTagStripByteCounts, kTiffTagStripOffsets};
- GetThumbnailOffsetAndLength(stream, preview_image_data);
+ GetThumbnailOffsetAndLength(TagSet(), stream, preview_image_data);
const std::uint32_t kNumberOfIfds = 1;
return GetPreviewData(extended_tags, kNumberOfIfds, stream,
@@ -388,7 +426,7 @@ Error NefGetPreviewData(StreamInterface* stream,
}
PreviewImageData thumbnail_data;
- GetThumbnailOffsetAndLength(stream, &thumbnail_data);
+ GetThumbnailOffsetAndLength(TagSet(), stream, &thumbnail_data);
preview_image_data->thumbnail_offset = thumbnail_data.thumbnail_offset;
preview_image_data->thumbnail_length = thumbnail_data.thumbnail_length;
@@ -434,6 +472,31 @@ Error OrfGetPreviewData(StreamInterface* stream,
return GetOlympusPreviewImage(stream, preview_image_data);
}
+Error PefGetPreviewData(StreamInterface* stream,
+ PreviewImageData* preview_image_data) {
+ const TagSet extended_tags = {kTiffTagImageWidth, kTiffTagImageLength,
+ kTiffTagJpegByteCount, kTiffTagJpegOffset,
+ kTiffTagSubIfd};
+ const std::uint32_t kNumberOfIfds = 3;
+ Error error =
+ GetPreviewData(extended_tags, kNumberOfIfds, stream, preview_image_data);
+ if (error != kOk) {
+ return error;
+ }
+
+ error = PefGetColorSpace(stream, preview_image_data);
+ if (error != kOk) {
+ return error;
+ }
+
+ PreviewImageData thumbnail_data;
+ GetThumbnailOffsetAndLength(TagSet(), stream, &thumbnail_data);
+ preview_image_data->thumbnail_offset = thumbnail_data.thumbnail_offset;
+ preview_image_data->thumbnail_length = thumbnail_data.thumbnail_length;
+
+ return kOk;
+}
+
Error RafGetPreviewData(StreamInterface* stream,
PreviewImageData* preview_image_data) {
// Parse the Fuji RAW header to get the offset and length of the preview
@@ -464,6 +527,7 @@ Error RafGetPreviewData(StreamInterface* stream,
// The preview offset and length extracted from the Exif data are actually
// the thumbnail offset and length.
preview_image_data->thumbnail_offset = preview_image_data->preview_offset;
+ preview_image_data->thumbnail_offset += 160; // Skip the cfa header.
preview_image_data->thumbnail_length = preview_image_data->preview_length;
preview_image_data->preview_offset = preview_offset;
preview_image_data->preview_length = preview_length;
@@ -493,13 +557,14 @@ Error Rw2GetPreviewData(StreamInterface* stream,
if (GetExifData(exif_offset, stream, preview_image_data) == kFail) {
return kFail;
}
+ // The preview offset and length extracted from the Exif data are actually
+ // the thumbnail offset and length.
+ preview_image_data->thumbnail_offset =
+ exif_offset + preview_image_data->preview_offset;
+ preview_image_data->thumbnail_length = preview_image_data->preview_length;
}
// Merge the Exif data with the RAW data to form the preview_image_data.
- // The preview offset and length extracted from the Exif data are actually
- // the thumbnail offset and length.
- preview_image_data->thumbnail_offset = preview_image_data->preview_offset;
- preview_image_data->thumbnail_length = preview_image_data->preview_length;
preview_image_data->preview_offset = preview_data.preview_offset;
preview_image_data->preview_length = preview_data.preview_length;
preview_image_data->iso = preview_data.iso;
@@ -509,6 +574,18 @@ Error Rw2GetPreviewData(StreamInterface* stream,
return kOk;
}
+Error SrwGetPreviewData(StreamInterface* stream,
+ PreviewImageData* preview_image_data) {
+ GetThumbnailOffsetAndLength({kTiffTagSubIfd}, stream, preview_image_data);
+
+ const TagSet extended_tags = {kExifTagWidth, kExifTagHeight,
+ kTiffTagJpegByteCount, kTiffTagJpegOffset,
+ kTiffTagSubIfd};
+ const std::uint32_t kNumberOfIfds = 1;
+ return GetPreviewData(extended_tags, kNumberOfIfds, stream,
+ preview_image_data);
+}
+
} // namespace
size_t BytesRequiredForIsRaw() {
@@ -558,10 +635,14 @@ Error GetPreviewImageData(StreamInterface* data,
return NefGetPreviewData(data, preview_image_data);
case image_type_recognition::kOrfImage:
return OrfGetPreviewData(data, preview_image_data);
+ case image_type_recognition::kPefImage:
+ return PefGetPreviewData(data, preview_image_data);
case image_type_recognition::kRafImage:
return RafGetPreviewData(data, preview_image_data);
case image_type_recognition::kRw2Image:
return Rw2GetPreviewData(data, preview_image_data);
+ case image_type_recognition::kSrwImage:
+ return SrwGetPreviewData(data, preview_image_data);
default:
return kUnsupported;
}
@@ -575,8 +656,10 @@ std::vector<std::string> SupportedExtensions() {
extensions.push_back("NEF");
extensions.push_back("NRW");
extensions.push_back("ORF");
+ extensions.push_back("PEF");
extensions.push_back("RAF");
extensions.push_back("RW2");
+ extensions.push_back("SRW");
return extensions;
}
diff --git a/src/piex.h b/src/piex.h
index 0426772..13c190f 100644
--- a/src/piex.h
+++ b/src/piex.h
@@ -42,7 +42,7 @@
// // Uncompress the JPEG as usual, e.g. on Android with the BitmapFactory:
// // In Java
// Bitmap bitmap = BitmapFactory.decodeByteArray(
-// file.at(image_data.jpeg_offset), image_data.jpeg_length);
+// file.at(image_data.preview_offset), image_data.preview_length);
#ifndef PIEX_PIEX_H_
#define PIEX_PIEX_H_
@@ -69,8 +69,8 @@ bool IsRaw(StreamInterface* data);
// Returns 'kFail' when something with the data is wrong.
// Returns 'kUnsupported' if file format is not supported.
//
-// One could check the "preview_image_data->jpeg_length != 0" for the existance
-// of a preview image.
+// One could check the "preview_image_data->preview_length != 0" for the
+// existance of a preview image.
Error GetPreviewImageData(StreamInterface* data,
PreviewImageData* preview_image_data);
diff --git a/src/piex_types.h b/src/piex_types.h
index a180d87..f0c216a 100644
--- a/src/piex_types.h
+++ b/src/piex_types.h
@@ -29,8 +29,8 @@ enum Error {
kUnsupported,
};
-// Contains relevant image information as well as the 'jpeg_offset' and the
-// 'jpeg_length' which are used to obtain the JPEG compressed preview image.
+// Contains relevant image information as well as the 'preview_offset' and the
+// 'preview_length' which are used to obtain the JPEG compressed preview image.
// 'full_width' and 'full_height' are correctly cropped but not rotated.
struct PreviewImageData {
enum ColorSpace {
diff --git a/src/tiff_parser.cc b/src/tiff_parser.cc
index a36d5c8..cad5bc4 100644
--- a/src/tiff_parser.cc
+++ b/src/tiff_parser.cc
@@ -162,7 +162,7 @@ void FillGpsPreviewImageData(const TiffDirectory& gps_directory,
Error FillPreviewImageData(const TiffDirectory& tiff_directory,
PreviewImageData* preview_image_data) {
bool success = true;
- // Get jpeg_offset and jpeg_length
+ // Get preview_offset and preview_length
if (tiff_directory.Has(kTiffTagStripOffsets) &&
tiff_directory.Has(kTiffTagStripByteCounts)) {
std::vector<std::uint32_t> strip_offsets;
@@ -190,8 +190,9 @@ Error FillPreviewImageData(const TiffDirectory& tiff_directory,
}
}
- // Get exif_orientation
- if (tiff_directory.Has(kTiffTagOrientation)) {
+ // Get exif_orientation if it was not set already.
+ if (tiff_directory.Has(kTiffTagOrientation) &&
+ preview_image_data->exif_orientation == 1) {
success &= tiff_directory.Get(kTiffTagOrientation,
&preview_image_data->exif_orientation);
}
@@ -202,7 +203,7 @@ Error FillPreviewImageData(const TiffDirectory& tiff_directory,
success &= tiff_directory.Get(kExifTagColorSpace, &color_space);
if (color_space == 1) {
preview_image_data->color_space = PreviewImageData::kSrgb;
- } else if (color_space == 65535) {
+ } else if (color_space == 65535 || color_space == 2) {
preview_image_data->color_space = PreviewImageData::kAdobeRgb;
}
}
diff --git a/src/tiff_parser.h b/src/tiff_parser.h
index 087844d..88b4006 100644
--- a/src/tiff_parser.h
+++ b/src/tiff_parser.h
@@ -28,7 +28,18 @@
namespace piex {
// Specifies all tags that might be of interest to get the preview data.
-enum Tags {
+enum GpsTags {
+ kGpsTagLatitudeRef = 1,
+ kGpsTagLatitude = 2,
+ kGpsTagLongitudeRef = 3,
+ kGpsTagLongitude = 4,
+ kGpsTagAltitudeRef = 5,
+ kGpsTagAltitude = 6,
+ kGpsTagTimeStamp = 7,
+ kGpsTagDateStamp = 29,
+};
+
+enum TiffTags {
kExifTagColorSpace = 0xA001,
kExifTagDateTimeOriginal = 0x9003,
kExifTagDefaultCropSize = 0xC620,
@@ -40,14 +51,6 @@ enum Tags {
kExifTagIsoSpeed = 0x8827,
kExifTagMakernotes = 0x927C,
kExifTagWidth = 0xA002,
- kGpsTagLatitudeRef = 1,
- kGpsTagLatitude = 2,
- kGpsTagLongitudeRef = 3,
- kGpsTagLongitude = 4,
- kGpsTagAltitudeRef = 5,
- kGpsTagAltitude = 6,
- kGpsTagTimeStamp = 7,
- kGpsTagDateStamp = 29,
kOlymTagAspectFrame = 0x1113,
kOlymTagCameraSettings = 0x2020,
kOlymTagRawProcessing = 0x2040,
@@ -57,6 +60,7 @@ enum Tags {
kPanaTagLeftBorder = 0x0005,
kPanaTagRightBorder = 0x007,
kPanaTagTopBorder = 0x0004,
+ kPentaxTagColorSpace = 0x0037,
kTiffTagArtist = 0x013B,
kTiffTagBitsPerSample = 0x0102,
kTiffTagCompression = 0x0103,
@@ -87,6 +91,7 @@ enum Tags {
kTiffTagYresolution = 0x011B,
};
+typedef int Tags;
typedef std::set<Tags> TagSet;
typedef std::vector<tiff_directory::TiffDirectory> IfdVector;