summaryrefslogtreecommitdiff
path: root/src/jpeg/jpeg_segment_lister.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/jpeg/jpeg_segment_lister.cc')
-rw-r--r--src/jpeg/jpeg_segment_lister.cc158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/jpeg/jpeg_segment_lister.cc b/src/jpeg/jpeg_segment_lister.cc
new file mode 100644
index 0000000..ffdd3f2
--- /dev/null
+++ b/src/jpeg/jpeg_segment_lister.cc
@@ -0,0 +1,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