1 #ifndef IMAGE_IO_JPEG_JPEG_SEGMENT_H_ // NOLINT 2 #define IMAGE_IO_JPEG_JPEG_SEGMENT_H_ // NOLINT 3 4 #include "image_io/base/data_range.h" 5 #include "image_io/base/data_segment.h" 6 #include "image_io/jpeg/jpeg_marker.h" 7 8 namespace photos_editing_formats { 9 namespace image_io { 10 11 /// A JpegSegment is an entity in a JPEG file that starts with a JpegMarker and 12 /// is followed by zero or more payload bytes. The JpegSegment has a DataRange 13 /// that indicates the position of the segment in the originating DataSource. 14 /// A JpegScanner obtains DataSegment instances from a DataSource in such a way 15 /// that it can guarantee that a JpegSegment will span at most two DataSegment 16 /// instances. Clients of JpegSegment need not be concerned with the number of 17 /// underlying DataSegments if they use the member functions defined here to 18 /// access the segment's bytes. 19 class JpegSegment { 20 public: 21 /// If a JpegSegment has a variable length data payload, the payload data is 22 /// located at this offset from the start of the payload. 23 static constexpr size_t kVariablePayloadDataOffset = 2; 24 25 /// Constructs a JpegSegment starting and ending at the indicated points in 26 /// the given DataSegment instances, the second of which may be null. 27 /// @param begin The start of JpegSegment range. 28 /// @param end The end of JpegSegment range. 29 /// @param begin_segment The DataSegment that contains the begin location of 30 /// the JpegSegment and the end if the end_segment is null. 31 /// @param end_segment The DataSegment that contains the end location of the 32 /// JpegSegment if it is not null. JpegSegment(size_t begin,size_t end,const DataSegment * begin_segment,const DataSegment * end_segment)33 JpegSegment(size_t begin, size_t end, const DataSegment* begin_segment, 34 const DataSegment* end_segment) 35 : data_range_(begin, end), 36 begin_segment_(begin_segment), 37 end_segment_(end_segment){} 38 ~JpegSegment() = default; 39 40 /// @return The DataRange of the data in the segment. GetDataRange()41 const DataRange& GetDataRange() const { return data_range_; } 42 43 /// @return The begin location of the segment's data range. GetBegin()44 size_t GetBegin() const { return data_range_.GetBegin(); } 45 46 /// @return The end location of the segment's data range. GetEnd()47 size_t GetEnd() const { return data_range_.GetEnd(); } 48 49 /// @return The length of the segment's data range. GetLength()50 size_t GetLength() const { return data_range_.GetLength(); } 51 52 /// @return True if the segment's range contains the location, else false. Contains(size_t location)53 bool Contains(size_t location) const { 54 return data_range_.Contains(location); 55 } 56 57 /// @return The location of the segment's JpegMarker. GetMarkerLocation()58 size_t GetMarkerLocation() const { return GetBegin(); } 59 60 /// @return The location of the segment's payload, which includes the payload 61 /// length if applicable for the type of segment. GetPayloadLocation()62 size_t GetPayloadLocation() const { return GetBegin() + JpegMarker::kLength; } 63 64 /// @return The location of the segment's payload's data. GetPayloadDataLocation()65 size_t GetPayloadDataLocation() const { 66 return GetMarker().HasVariablePayloadSize() 67 ? GetPayloadLocation() + kVariablePayloadDataOffset 68 : GetPayloadLocation(); 69 } 70 71 /// @param The location at which to obtain the byte value. 72 /// @return The validated byte value at the location, or 0/false if the 73 /// segment's range does not contain the location. GetValidatedByte(size_t location)74 ValidatedByte GetValidatedByte(size_t location) const { 75 return DataSegment::GetValidatedByte(location, begin_segment_, 76 end_segment_); 77 } 78 79 /// @return The payload size or zero if the segment's marker indicates the 80 /// segment does not have a payload. The payload size includes the two 81 /// bytes that encode the length of the payload. I.e., the payload data 82 /// size is two less than the value returned by this function. 83 size_t GetVariablePayloadSize() const; 84 85 /// @param location The start location of the compare operation. 86 /// @param str The string to compare the bytes with. 87 /// @return True if the segment's bytes at the given location equals the str. 88 bool BytesAtLocationStartWith(size_t location, const char* str) const; 89 90 /// @param location The start location of the search operation. 91 /// @param str The string to search for. 92 /// @return True if the segment's contains the string, starting at location. 93 bool BytesAtLocationContain(size_t location, const char* str) const; 94 95 /// @param start_location The location at which to start the search. 96 /// @param value The byte value to search for. 97 /// @return The location in the segment's bytes of the next occurrence of the 98 /// given byte value, starting at the indicated location, or the segment's 99 /// range's GetEnd() location if not found. 100 size_t Find(size_t start_location, Byte value) const; 101 102 /// @param start_location The location at which to start the search. 103 /// @param str The string to search for. 104 /// @return the location in the segment's bytes of the next occurrence of the 105 /// given string value, starting at the indicated location, or the 106 /// segment's range's GetEnd() location if not found. 107 size_t Find(size_t location, const char* str) const; 108 109 /// XMP property names have the syntax property_name="property_value". 110 /// @param segment The segment in which to look for the property name/value. 111 /// @param start_location Where to start looking for the property name. 112 /// @param property_name The name of the property to look for. 113 /// @return The string value associated with the xmp property name, or an 114 /// empty string if the property was not found. 115 std::string ExtractXmpPropertyValue(size_t start_location, 116 const char* property_name) const; 117 118 /// XMP property names have the syntax property_name="property_value". 119 /// @start_location The location in the segment to begin looking for the 120 /// property_name=" syntax. 121 /// @return The location of the next byte following the quote, or GetEnd() if 122 /// the property_name=" syntax was not found. 123 size_t FindXmpPropertyValueBegin(size_t start_location, 124 const char* property_name) const; 125 126 /// XMP property names have the syntax property_name="property_value". 127 /// @start_location The location in the segment to begin looking for the final 128 /// quote of the property value. 129 /// @return The location of quote that terminates the property_value, or 130 /// GetEnd() if the final quote was not found. 131 size_t FindXmpPropertyValueEnd(size_t start_location) const; 132 133 /// @param The DataRange to use to extract a string from the segment's bytes. 134 /// @return The string extracted from the segment at locations indicated by 135 /// the data_range, or an empty string if the data_range is not contained 136 /// in the segment's range, or any invalid or zero bytes are encountered. 137 std::string ExtractString(const DataRange& data_range) const; 138 139 /// @return the JpegMarker of this segment. GetMarker()140 JpegMarker GetMarker() const { 141 size_t marker_type_location = GetMarkerLocation() + 1; 142 // An invalid ValidatedByte has a value of 0, and a JpegMarker with a 0 143 // type value is invalid, so its ok to just grab the ValidatedByte's value. 144 return JpegMarker(GetValidatedByte(marker_type_location).value); 145 } 146 147 /// Fills two strings with byte_count bytes from the start of the segment's 148 /// payload in a form suitable for creating a "hex dump" of the segment. Note 149 /// that if the jpeg segment has a entropy delimiter type marker, there is 150 /// technically no payload to dump. However in this case, as long as a valid 151 /// byte can be obtained from the jpeg segment's underlying data segments, a 152 /// byte value will be dumped to the strings. 153 /// @param byte_count The number of bytes to dump from the segment's payload. 154 /// @param hex_string A string that will be at most 2 * byte_count in length 155 /// that will contain the hex values of the bytes. 156 /// @param ascii_string A string that will be at most byte_count in length 157 /// that will contain the printable character of the bytes, or a '.' for 158 /// non-printable byte values. 159 void GetPayloadHexDumpStrings(size_t byte_count, std::string* hex_string, 160 std::string* ascii_string) const; 161 162 private: 163 /// The DataRange of the JpegSegment. 164 DataRange data_range_; 165 166 /// The DataSegment that contains the begin of the range and possibly the 167 /// end. This DataSegment will never be null. 168 const DataSegment* begin_segment_; 169 170 /// The DataSegment, that if not null, will contain the end location of the 171 /// JPegSegment's DataRange. 172 const DataSegment* end_segment_; 173 }; 174 175 } // namespace image_io 176 } // namespace photos_editing_formats 177 178 #endif // IMAGE_IO_JPEG_JPEG_SEGMENT_H_ // NOLINT 179