1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
5
6 #include "lib/jxl/decode_to_jpeg.h"
7
8 namespace jxl {
9
10 #if JPEGXL_ENABLE_TRANSCODE_JPEG
11
Process(const uint8_t ** next_in,size_t * avail_in)12 JxlDecoderStatus JxlToJpegDecoder::Process(const uint8_t** next_in,
13 size_t* avail_in) {
14 if (!inside_box_) {
15 JXL_ABORT(
16 "processing of JPEG reconstruction data outside JPEG reconstruction "
17 "box");
18 }
19 Span<const uint8_t> to_decode;
20 if (box_until_eof_) {
21 // Until EOF means consume all data.
22 to_decode = Span<const uint8_t>(*next_in, *avail_in);
23 *next_in += *avail_in;
24 *avail_in = 0;
25 } else {
26 // Defined size means consume min(available, needed).
27 size_t avail_recon_in =
28 std::min<size_t>(*avail_in, box_size_ - buffer_.size());
29 to_decode = Span<const uint8_t>(*next_in, avail_recon_in);
30 *next_in += avail_recon_in;
31 *avail_in -= avail_recon_in;
32 }
33 bool old_data_exists = !buffer_.empty();
34 if (old_data_exists) {
35 // Append incoming data to buffer if we already had data in the buffer.
36 buffer_.insert(buffer_.end(), to_decode.data(),
37 to_decode.data() + to_decode.size());
38 to_decode = Span<const uint8_t>(buffer_.data(), buffer_.size());
39 }
40 if (!box_until_eof_ && to_decode.size() > box_size_) {
41 JXL_ABORT("JPEG reconstruction data to decode larger than expected");
42 }
43 if (box_until_eof_ || to_decode.size() == box_size_) {
44 // If undefined size, or the right size, try to decode.
45 jpeg_data_ = make_unique<jpeg::JPEGData>();
46 const auto status = jpeg::DecodeJPEGData(to_decode, jpeg_data_.get());
47 if (status.IsFatalError()) return JXL_DEC_ERROR;
48 if (status) {
49 // Successful decoding, emit event after updating state to track that we
50 // are no longer parsing JPEG reconstruction data.
51 inside_box_ = false;
52 return JXL_DEC_JPEG_RECONSTRUCTION;
53 }
54 if (box_until_eof_) {
55 // Unsuccessful decoding and undefined size, assume incomplete data. Copy
56 // the data if we haven't already.
57 if (!old_data_exists) {
58 buffer_.insert(buffer_.end(), to_decode.data(),
59 to_decode.data() + to_decode.size());
60 }
61 } else {
62 // Unsuccessful decoding of correct amount of data, assume error.
63 return JXL_DEC_ERROR;
64 }
65 } else {
66 // Not enough data, copy the data if we haven't already.
67 if (!old_data_exists) {
68 buffer_.insert(buffer_.end(), to_decode.data(),
69 to_decode.data() + to_decode.size());
70 }
71 }
72 return JXL_DEC_NEED_MORE_INPUT;
73 }
74
75 #endif // JPEGXL_ENABLE_TRANSCODE_JPEG
76
77 } // namespace jxl
78