1*ca0779ebSJerome Gaillard #include "image_io/jpeg/jpeg_scanner.h"
2*ca0779ebSJerome Gaillard
3*ca0779ebSJerome Gaillard #include <sstream>
4*ca0779ebSJerome Gaillard
5*ca0779ebSJerome Gaillard #include "image_io/base/message_handler.h"
6*ca0779ebSJerome Gaillard #include "image_io/jpeg/jpeg_segment.h"
7*ca0779ebSJerome Gaillard
8*ca0779ebSJerome Gaillard namespace photos_editing_formats {
9*ca0779ebSJerome Gaillard namespace image_io {
10*ca0779ebSJerome Gaillard
11*ca0779ebSJerome Gaillard using std::stringstream;
12*ca0779ebSJerome Gaillard
13*ca0779ebSJerome Gaillard /// The minimum size for the DataSegments requested from the DataSource. Using
14*ca0779ebSJerome Gaillard /// this value will guarentee that a JpegSegment will occupy at most two
15*ca0779ebSJerome Gaillard /// DataSegments.
16*ca0779ebSJerome Gaillard const size_t kMinBufferDataRequestSize = 0x10000;
17*ca0779ebSJerome Gaillard
Run(DataSource * data_source,JpegSegmentProcessor * segment_processor)18*ca0779ebSJerome Gaillard void JpegScanner::Run(DataSource* data_source,
19*ca0779ebSJerome Gaillard JpegSegmentProcessor* segment_processor) {
20*ca0779ebSJerome Gaillard if (data_source_) {
21*ca0779ebSJerome Gaillard // The Run() function is already active.
22*ca0779ebSJerome Gaillard return;
23*ca0779ebSJerome Gaillard }
24*ca0779ebSJerome Gaillard data_source_ = data_source;
25*ca0779ebSJerome Gaillard segment_processor_ = segment_processor;
26*ca0779ebSJerome Gaillard current_location_ = 0;
27*ca0779ebSJerome Gaillard done_ = false;
28*ca0779ebSJerome Gaillard has_error_ = false;
29*ca0779ebSJerome Gaillard data_source_->Reset();
30*ca0779ebSJerome Gaillard current_segment_ = data_source_->GetDataSegment(current_location_,
31*ca0779ebSJerome Gaillard kMinBufferDataRequestSize);
32*ca0779ebSJerome Gaillard segment_processor_->Start(this);
33*ca0779ebSJerome Gaillard FindAndProcessSegments();
34*ca0779ebSJerome Gaillard segment_processor_->Finish(this);
35*ca0779ebSJerome Gaillard data_source_ = nullptr;
36*ca0779ebSJerome Gaillard segment_processor_ = nullptr;
37*ca0779ebSJerome Gaillard current_segment_.reset();
38*ca0779ebSJerome Gaillard next_segment_.reset();
39*ca0779ebSJerome Gaillard }
40*ca0779ebSJerome Gaillard
FindAndProcessSegments()41*ca0779ebSJerome Gaillard void JpegScanner::FindAndProcessSegments() {
42*ca0779ebSJerome Gaillard while (!IsDone() && !HasError()) {
43*ca0779ebSJerome Gaillard size_t begin_segment_location =
44*ca0779ebSJerome Gaillard current_segment_->Find(current_location_, JpegMarker::kStart);
45*ca0779ebSJerome Gaillard if (begin_segment_location == current_segment_->GetEnd()) {
46*ca0779ebSJerome Gaillard GetNextSegment();
47*ca0779ebSJerome Gaillard if (next_segment_) {
48*ca0779ebSJerome Gaillard current_location_ =
49*ca0779ebSJerome Gaillard std::max(current_location_, next_segment_->GetBegin());
50*ca0779ebSJerome Gaillard current_segment_ = next_segment_;
51*ca0779ebSJerome Gaillard next_segment_.reset();
52*ca0779ebSJerome Gaillard continue;
53*ca0779ebSJerome Gaillard }
54*ca0779ebSJerome Gaillard SetDone();
55*ca0779ebSJerome Gaillard break;
56*ca0779ebSJerome Gaillard }
57*ca0779ebSJerome Gaillard size_t payload_size = 0;
58*ca0779ebSJerome Gaillard JpegMarker marker(
59*ca0779ebSJerome Gaillard GetByte(begin_segment_location + JpegMarker::kTypeOffset));
60*ca0779ebSJerome Gaillard if (marker.IsValid() && !HasError()) {
61*ca0779ebSJerome Gaillard payload_size = GetPayloadSize(marker, begin_segment_location);
62*ca0779ebSJerome Gaillard if (marker.IsValid() && interesting_marker_flags_[marker.GetType()]) {
63*ca0779ebSJerome Gaillard size_t end_segment_location =
64*ca0779ebSJerome Gaillard begin_segment_location + JpegMarker::kLength + payload_size;
65*ca0779ebSJerome Gaillard GetByte(end_segment_location - 1);
66*ca0779ebSJerome Gaillard if (!HasError()) {
67*ca0779ebSJerome Gaillard JpegSegment segment(begin_segment_location, end_segment_location,
68*ca0779ebSJerome Gaillard current_segment_.get(), next_segment_.get());
69*ca0779ebSJerome Gaillard segment_processor_->Process(this, segment);
70*ca0779ebSJerome Gaillard }
71*ca0779ebSJerome Gaillard }
72*ca0779ebSJerome Gaillard }
73*ca0779ebSJerome Gaillard current_location_ =
74*ca0779ebSJerome Gaillard begin_segment_location + JpegMarker::kLength + payload_size;
75*ca0779ebSJerome Gaillard }
76*ca0779ebSJerome Gaillard }
77*ca0779ebSJerome Gaillard
GetPayloadSize(const JpegMarker & marker,size_t begin_location)78*ca0779ebSJerome Gaillard size_t JpegScanner::GetPayloadSize(const JpegMarker& marker,
79*ca0779ebSJerome Gaillard size_t begin_location) {
80*ca0779ebSJerome Gaillard if (marker.HasVariablePayloadSize()) {
81*ca0779ebSJerome Gaillard return (GetByte(begin_location + JpegMarker::kLength) << 8) |
82*ca0779ebSJerome Gaillard GetByte(begin_location + JpegMarker::kLength + 1);
83*ca0779ebSJerome Gaillard } else {
84*ca0779ebSJerome Gaillard return 0;
85*ca0779ebSJerome Gaillard }
86*ca0779ebSJerome Gaillard }
87*ca0779ebSJerome Gaillard
GetValidatedByte(size_t location)88*ca0779ebSJerome Gaillard ValidatedByte JpegScanner::GetValidatedByte(size_t location) {
89*ca0779ebSJerome Gaillard if (current_segment_->Contains(location)) {
90*ca0779ebSJerome Gaillard return current_segment_->GetValidatedByte(location);
91*ca0779ebSJerome Gaillard }
92*ca0779ebSJerome Gaillard GetNextSegment();
93*ca0779ebSJerome Gaillard if (next_segment_ && next_segment_->Contains(location)) {
94*ca0779ebSJerome Gaillard return next_segment_->GetValidatedByte(location);
95*ca0779ebSJerome Gaillard }
96*ca0779ebSJerome Gaillard if (message_handler_) {
97*ca0779ebSJerome Gaillard stringstream sstream;
98*ca0779ebSJerome Gaillard sstream << location;
99*ca0779ebSJerome Gaillard message_handler_->ReportMessage(Message::kPrematureEndOfDataError,
100*ca0779ebSJerome Gaillard sstream.str());
101*ca0779ebSJerome Gaillard }
102*ca0779ebSJerome Gaillard return InvalidByte();
103*ca0779ebSJerome Gaillard }
104*ca0779ebSJerome Gaillard
GetByte(size_t location)105*ca0779ebSJerome Gaillard Byte JpegScanner::GetByte(size_t location) {
106*ca0779ebSJerome Gaillard ValidatedByte validated_byte = GetValidatedByte(location);
107*ca0779ebSJerome Gaillard if (validated_byte.is_valid) {
108*ca0779ebSJerome Gaillard return validated_byte.value;
109*ca0779ebSJerome Gaillard }
110*ca0779ebSJerome Gaillard has_error_ = true;
111*ca0779ebSJerome Gaillard return 0;
112*ca0779ebSJerome Gaillard }
113*ca0779ebSJerome Gaillard
GetNextSegment()114*ca0779ebSJerome Gaillard void JpegScanner::GetNextSegment() {
115*ca0779ebSJerome Gaillard if (!next_segment_ && current_segment_) {
116*ca0779ebSJerome Gaillard next_segment_ = data_source_->GetDataSegment(current_segment_->GetEnd(),
117*ca0779ebSJerome Gaillard kMinBufferDataRequestSize);
118*ca0779ebSJerome Gaillard }
119*ca0779ebSJerome Gaillard }
120*ca0779ebSJerome Gaillard
121*ca0779ebSJerome Gaillard } // namespace image_io
122*ca0779ebSJerome Gaillard } // namespace photos_editing_formats
123