1 #ifndef IMAGE_IO_JPEG_JPEG_MARKER_H_  // NOLINT
2 #define IMAGE_IO_JPEG_JPEG_MARKER_H_  // NOLINT
3 
4 #include <bitset>
5 #include <string>
6 
7 #include "image_io/base/types.h"
8 
9 namespace photos_editing_formats {
10 namespace image_io {
11 
12 /// The size of the array that would be needed to reference all marker types.
13 const size_t kJpegMarkerArraySize = 256;
14 
15 /// A JpegMarker begins each JpegSegment in a JPEG file. The first byte of a
16 /// marker is 0xFF, and the second byte is the marker type value. Bytes with
17 /// values 0x00 and 0xFF indicate not a JpegMarker, but a zero byte or fill
18 /// byte, respectively. That is the sequence FF00 must be interpreted as a
19 /// single byte with a 0 value. The specification says that multiple fill bytes
20 /// may appear before a valid marker start: FFFFFFDA - the leading FFFF should
21 /// be ignored.
22 class JpegMarker {
23  public:
24   /// The length of the marker in the JPEG file. One byte for the 0xFF value,
25   /// and one byte for the marker type.
26   static const size_t kLength = 2;
27 
28   /// The offset from the start of the JpegMarker that contains the marker type.
29   static const size_t kTypeOffset = 1;
30 
31   /// The special byte value that may start a marker.
32   static const Byte kStart = 0xFF;
33 
34   /// Special marker type values referenced elsewhere in the code.
35   static const Byte kZERO = 0;
36   static const Byte kSOS = 0xDA;
37   static const Byte kSOI = 0xD8;
38   static const Byte kEOI = 0xD9;
39   static const Byte kAPP0 = 0xE0;
40   static const Byte kAPP1 = 0xE1;
41   static const Byte kAPP2 = 0xE2;
42   static const Byte kFILL = 0xFF;
43 
44   /// A set of bits, one for each type of marker.
45   using Flags = std::bitset<kJpegMarkerArraySize>;
46 
47   /// Creates a JpegMarker with the given type value.
JpegMarker(Byte type)48   explicit JpegMarker(Byte type) : type_(type) {}
49 
50   JpegMarker() = delete;
51 
52   /// Not all byte values are used to represent markers. Bytes with values 0x00
53   /// and 0xFF indicate a zero byte or fill byte, respectively.
54   /// @return Whether this is a valid marker.
IsValid()55   bool IsValid() const { return type_ != kZERO && type_ != kFILL; }
56 
57   /// @return The type of the marker.
GetType()58   Byte GetType() const { return type_; }
59 
60   /// @return The name of the marker type.
61   const std::string GetName() const;
62 
63   /// @param prefix A prefix for the returned string.
64   /// @return The <prefix>XX hex string representation of the type.
65   const std::string GetHexString(const std::string& prefix) const;
66 
67   /// Some markers have two extra bytes that indicate the size of the segment's
68   /// data payload. See https://www.w3.org/Graphics/JPEG/itu-t81.pdf, Table B-2.
69   /// @return Whether this marker type has such a variable length payload.
70   bool HasVariablePayloadSize() const;
71 
72   /// Some markers are delimiters in an otherwise continuous stream of bytes in
73   /// the JPEG file. See https://www.w3.org/Graphics/JPEG/itu-t81.pdf, Section
74   /// B.2.1.
75   /// @return Whether this is an entropy segment delimiter marker.
76   bool IsEntropySegmentDelimiter() const;
77 
78  private:
79   /// The type value of the marker.
80   Byte type_;
81 };
82 
83 }  // namespace image_io
84 }  // namespace photos_editing_formats
85 
86 #endif // IMAGE_IO_JPEG_JPEG_MARKER_H_  // NOLINT
87