• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "image_io/jpeg/jpeg_segment_lister.h"
2 
3 #include <iomanip>
4 #include <sstream>
5 #include <string>
6 
7 #include "image_io/jpeg/jpeg_marker.h"
8 #include "image_io/jpeg/jpeg_scanner.h"
9 #include "image_io/jpeg/jpeg_segment.h"
10 
11 namespace photos_editing_formats {
12 namespace image_io {
13 
14 /// The width of the type column.
15 constexpr size_t kTypeWidth = 5;
16 
17 /// The width of the number columns.
18 constexpr size_t kNumWidth = 12;
19 
20 /// The number of bytes to dump from each segment.
21 constexpr size_t kDumpCount = 16;
22 
23 /// The width of the ascii dump column, including the surrounding [] brackets.
24 constexpr size_t kAscWidth = kDumpCount + 2;
25 
26 /// The width of the hex dump column, including the surrounding [] brackets.
27 constexpr size_t kHexWidth = 2 * kDumpCount + 2;
28 
29 using std::string;
30 using std::stringstream;
31 
32 namespace {
33 
34 /// @param value The value to convert to a string.
35 /// @return The value paraemter as a string of length kNumWidth.
Size2String(size_t value)36 string Size2String(size_t value) {
37   stringstream stream;
38   stream << std::setw(kNumWidth) << std::right << value;
39   return stream.str();
40 }
41 
42 /// @param value The value to convert to a hex string.
43 /// @return The value paraemter as a hex string of length kNumWidth.
Size2HexString(size_t value)44 string Size2HexString(size_t value) {
45   stringstream stream;
46   stream << std::hex << std::uppercase << std::setw(kNumWidth) << std::right
47          << value;
48   return stream.str();
49 }
50 
51 /// @param str The string to add brackets to.
52 /// @return The str value enclosed by square brackets.
BracketedString(const string & str)53 string BracketedString(const string& str) {
54   stringstream stream;
55   stream << '[' << str << ']';
56   return stream.str();
57 }
58 
59 /// @param str The string to center.
60 /// @param width The width to center the string in.
61 /// @return A string with leading/trailing spaces added so that it is centered.
CenteredString(const string & str,size_t width)62 string CenteredString(const string& str, size_t width) {
63   if (str.length() >= width) {
64     return str;
65   }
66   size_t spacing = width - str.length();
67   size_t leading = spacing / 2;
68   size_t trailing = spacing - leading;
69   return string(leading, ' ') + str + string(trailing, ' ');
70 }
71 
72 /// @param type The type value of the segment. If this value is empty, then a
73 ///     divider line with dashes is created.
74 /// @param begin The begin value of the segment.
75 /// @param count The count (size) of the segment.
76 /// @param hex_string The hex dump string of the segment.
77 /// @param asc_string The ascii dump string of the segment.
78 /// @return A line with the various parameters properly spaced.
SegmentLine(string type,string begin,string count,string hex_string,string asc_string)79 string SegmentLine(string type, string begin, string count, string hex_string,
80                    string asc_string) {
81   if (type.empty()) {
82     type = string(kTypeWidth, '-');
83     begin = count = string(kNumWidth, '-');
84     hex_string = string(kHexWidth, '-');
85     asc_string = string(kAscWidth, '-');
86   }
87   stringstream line_stream;
88   line_stream << std::setw(kTypeWidth) << std::left << type << " "
89               << std::setw(kNumWidth) << std::right << begin << " "
90               << std::setw(kNumWidth) << std::right << count << " "
91               << std::setw(kHexWidth) << std::right << hex_string << " "
92               << std::setw(kAscWidth) << std::right << asc_string;
93   return line_stream.str();
94 }
95 
96 /// @param type The type value of the summary. If this value is empty, then a
97 ///     divider line with dashes is created.
98 /// @param count The number of the segments of the given type.
99 /// @return A line with the parameters properly spaced.
SummaryLine(string type,string count)100 string SummaryLine(string type, string count) {
101   if (type.empty()) {
102     type = string(kTypeWidth, '-');
103     count = string(kNumWidth, '-');
104   }
105   stringstream line_stream;
106   line_stream << std::setw(kTypeWidth) << std::left << type << " "
107               << std::setw(kNumWidth) << std::right << count;
108   return line_stream.str();
109 }
110 
111 }  // namespace
112 
JpegSegmentLister()113 JpegSegmentLister::JpegSegmentLister()
114     : marker_type_counts_(kJpegMarkerArraySize, 0) {}
115 
Start(JpegScanner * scanner)116 void JpegSegmentLister::Start(JpegScanner* scanner) {
117   scanner->UpdateInterestingMarkerFlags(JpegMarker::Flags().set());
118   string divider_line = SegmentLine("", "", "", "", "");
119   lines_.push_back(divider_line);
120   lines_.push_back(SegmentLine("Type", "Offset", "Payload Size",
121                                CenteredString("Hex Payload", kHexWidth),
122                                CenteredString("Ascii Payload", kAscWidth)));
123   lines_.push_back(divider_line);
124 }
125 
Process(JpegScanner * scanner,const JpegSegment & segment)126 void JpegSegmentLister::Process(JpegScanner* scanner,
127                                 const JpegSegment& segment) {
128   JpegMarker marker = segment.GetMarker();
129   string hex_payload, ascii_payload;
130   ++marker_type_counts_[marker.GetType()];
131   segment.GetPayloadHexDumpStrings(kDumpCount, &hex_payload, &ascii_payload);
132   lines_.push_back(SegmentLine(
133       marker.GetName(), Size2HexString(segment.GetBegin()),
134       Size2HexString(segment.GetEnd() - segment.GetBegin() - 2),
135       BracketedString(hex_payload), BracketedString(ascii_payload)));
136 }
137 
Finish(JpegScanner * scanner)138 void JpegSegmentLister::Finish(JpegScanner* scanner) {
139   lines_.push_back("");
140   string divider_line = SummaryLine("", "");
141   lines_.push_back(divider_line);
142   lines_.push_back(SummaryLine("Type", "Count"));
143   lines_.push_back(divider_line);
144   int total_segments = 0;
145   for (int type = 0; type < kJpegMarkerArraySize; ++type) {
146     int count = marker_type_counts_[type];
147     if (count) {
148       total_segments += count;
149       lines_.push_back(
150           SummaryLine(JpegMarker(type).GetName(), Size2String(count)));
151     }
152   }
153   lines_.push_back(divider_line);
154   lines_.push_back(SummaryLine("TOTAL", Size2String(total_segments)));
155 }
156 
157 }  // namespace image_io
158 }  // namespace photos_editing_formats
159