summaryrefslogtreecommitdiff
path: root/src/jpeg/jpeg_segment_lister.cc
blob: ffdd3f24e14e33824eae79278a6e6b82bd0558e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "image_io/jpeg/jpeg_segment_lister.h"

#include <iomanip>
#include <sstream>
#include <string>

#include "image_io/jpeg/jpeg_marker.h"
#include "image_io/jpeg/jpeg_scanner.h"
#include "image_io/jpeg/jpeg_segment.h"

namespace photos_editing_formats {
namespace image_io {

/// The width of the type column.
constexpr size_t kTypeWidth = 5;

/// The width of the number columns.
constexpr size_t kNumWidth = 12;

/// The number of bytes to dump from each segment.
constexpr size_t kDumpCount = 16;

/// The width of the ascii dump column, including the surrounding [] brackets.
constexpr size_t kAscWidth = kDumpCount + 2;

/// The width of the hex dump column, including the surrounding [] brackets.
constexpr size_t kHexWidth = 2 * kDumpCount + 2;

using std::string;
using std::stringstream;

namespace {

/// @param value The value to convert to a string.
/// @return The value paraemter as a string of length kNumWidth.
string Size2String(size_t value) {
  stringstream stream;
  stream << std::setw(kNumWidth) << std::right << value;
  return stream.str();
}

/// @param value The value to convert to a hex string.
/// @return The value paraemter as a hex string of length kNumWidth.
string Size2HexString(size_t value) {
  stringstream stream;
  stream << std::hex << std::uppercase << std::setw(kNumWidth) << std::right
         << value;
  return stream.str();
}

/// @param str The string to add brackets to.
/// @return The str value enclosed by square brackets.
string BracketedString(const string& str) {
  stringstream stream;
  stream << '[' << str << ']';
  return stream.str();
}

/// @param str The string to center.
/// @param width The width to center the string in.
/// @return A string with leading/trailing spaces added so that it is centered.
string CenteredString(const string& str, size_t width) {
  if (str.length() >= width) {
    return str;
  }
  size_t spacing = width - str.length();
  size_t leading = spacing / 2;
  size_t trailing = spacing - leading;
  return string(leading, ' ') + str + string(trailing, ' ');
}

/// @param type The type value of the segment. If this value is empty, then a
///     divider line with dashes is created.
/// @param begin The begin value of the segment.
/// @param count The count (size) of the segment.
/// @param hex_string The hex dump string of the segment.
/// @param asc_string The ascii dump string of the segment.
/// @return A line with the various parameters properly spaced.
string SegmentLine(string type, string begin, string count, string hex_string,
                   string asc_string) {
  if (type.empty()) {
    type = string(kTypeWidth, '-');
    begin = count = string(kNumWidth, '-');
    hex_string = string(kHexWidth, '-');
    asc_string = string(kAscWidth, '-');
  }
  stringstream line_stream;
  line_stream << std::setw(kTypeWidth) << std::left << type << " "
              << std::setw(kNumWidth) << std::right << begin << " "
              << std::setw(kNumWidth) << std::right << count << " "
              << std::setw(kHexWidth) << std::right << hex_string << " "
              << std::setw(kAscWidth) << std::right << asc_string;
  return line_stream.str();
}

/// @param type The type value of the summary. If this value is empty, then a
///     divider line with dashes is created.
/// @param count The number of the segments of the given type.
/// @return A line with the parameters properly spaced.
string SummaryLine(string type, string count) {
  if (type.empty()) {
    type = string(kTypeWidth, '-');
    count = string(kNumWidth, '-');
  }
  stringstream line_stream;
  line_stream << std::setw(kTypeWidth) << std::left << type << " "
              << std::setw(kNumWidth) << std::right << count;
  return line_stream.str();
}

}  // namespace

JpegSegmentLister::JpegSegmentLister()
    : marker_type_counts_(kJpegMarkerArraySize, 0) {}

void JpegSegmentLister::Start(JpegScanner* scanner) {
  scanner->UpdateInterestingMarkerFlags(JpegMarker::Flags().set());
  string divider_line = SegmentLine("", "", "", "", "");
  lines_.push_back(divider_line);
  lines_.push_back(SegmentLine("Type", "Offset", "Payload Size",
                               CenteredString("Hex Payload", kHexWidth),
                               CenteredString("Ascii Payload", kAscWidth)));
  lines_.push_back(divider_line);
}

void JpegSegmentLister::Process(JpegScanner* scanner,
                                const JpegSegment& segment) {
  JpegMarker marker = segment.GetMarker();
  string hex_payload, ascii_payload;
  ++marker_type_counts_[marker.GetType()];
  segment.GetPayloadHexDumpStrings(kDumpCount, &hex_payload, &ascii_payload);
  lines_.push_back(SegmentLine(
      marker.GetName(), Size2HexString(segment.GetBegin()),
      Size2HexString(segment.GetEnd() - segment.GetBegin() - 2),
      BracketedString(hex_payload), BracketedString(ascii_payload)));
}

void JpegSegmentLister::Finish(JpegScanner* scanner) {
  lines_.push_back("");
  string divider_line = SummaryLine("", "");
  lines_.push_back(divider_line);
  lines_.push_back(SummaryLine("Type", "Count"));
  lines_.push_back(divider_line);
  int total_segments = 0;
  for (int type = 0; type < kJpegMarkerArraySize; ++type) {
    int count = marker_type_counts_[type];
    if (count) {
      total_segments += count;
      lines_.push_back(
          SummaryLine(JpegMarker(type).GetName(), Size2String(count)));
    }
  }
  lines_.push_back(divider_line);
  lines_.push_back(SummaryLine("TOTAL", Size2String(total_segments)));
}

}  // namespace image_io
}  // namespace photos_editing_formats