35 const uint8_t* bytes =
reinterpret_cast<const uint8_t*
>(data);
36 size_t bytesRemaining = size;
38 while (bytesRemaining > 0) {
41 size_t bytesToMoveForward = 0;
43 case State::kSegmentParam: {
45 SkASSERT(fSegmentParamBytesRemaining > 0);
46 bytesToMoveForward = std::min(fSegmentParamBytesRemaining, bytesRemaining);
47 fSegmentParamBytesRemaining -= bytesToMoveForward;
48 if (fSegmentParamBytesRemaining == 0) {
49 fState = State::kEntropyCodedData;
53 case State::kEntropyCodedData: {
55 const uint8_t* sentinel =
56 reinterpret_cast<const uint8_t*
>(memchr(bytes, 0xFF, bytesRemaining));
58 bytesToMoveForward = (sentinel - bytes) + 1;
59 fState = State::kEntropyCodedDataSentinel;
61 bytesToMoveForward = bytesRemaining;
67 bytesToMoveForward = bytesRemaining;
71 bytesToMoveForward = 1;
76 fOffset += bytesToMoveForward;
77 bytes += bytesToMoveForward;
78 bytesRemaining -= bytesToMoveForward;
82void SkJpegSegmentScanner::saveCurrentSegment(uint16_t
length) {
84 fSegments.push_back(
s);
86 fCurrentSegmentMarker = 0;
87 fCurrentSegmentOffset = 0;
90void SkJpegSegmentScanner::onMarkerSecondByte(uint8_t
byte) {
91 SkASSERT(fState == State::kStartOfImageByte1 || fState == State::kSecondMarkerByte1 ||
92 fState == State::kEntropyCodedDataSentinel ||
93 fState == State::kPostEntropyCodedDataFill);
95 fCurrentSegmentMarker = byte;
96 fCurrentSegmentOffset = fOffset - 1;
98 if (
byte == fStopMarker) {
99 saveCurrentSegment(0);
100 fState = State::kDone;
102 saveCurrentSegment(0);
103 fState = State::kSecondMarkerByte0;
104 }
else if (MarkerStandsAlone(
byte)) {
105 saveCurrentSegment(0);
106 fState = State::kEntropyCodedData;
108 fCurrentSegmentMarker = byte;
109 fState = State::kSegmentParamLengthByte0;
113void SkJpegSegmentScanner::onByte(uint8_t
byte) {
115 case State::kStartOfImageByte0:
118 fState = State::kError;
121 fState = State::kStartOfImageByte1;
123 case State::kStartOfImageByte1:
126 fState = State::kError;
129 onMarkerSecondByte(
byte);
131 case State::kSecondMarkerByte0:
134 fState = State::kError;
137 fState = State::kSecondMarkerByte1;
139 case State::kSecondMarkerByte1:
142 if (
byte == 0xFF ||
byte == 0x00) {
143 SkCodecPrintf(
"SkJpegSegment marker was 0xFF,0xFF or 0xFF,0x00");
144 fState = State::kError;
147 onMarkerSecondByte(
byte);
149 case State::kSegmentParamLengthByte0:
150 fSegmentParamLengthByte0 = byte;
151 fState = State::kSegmentParamLengthByte1;
153 case State::kSegmentParamLengthByte1: {
154 uint16_t paramLength = 256u * fSegmentParamLengthByte0 + byte;
155 fSegmentParamLengthByte0 = 0;
162 SkCodecPrintf(
"SkJpegSegment payload length was %u < 2 bytes", paramLength);
163 fState = State::kError;
166 saveCurrentSegment(paramLength);
168 if (fSegmentParamBytesRemaining > 0) {
169 fState = State::kSegmentParam;
171 fState = State::kEntropyCodedData;
175 case State::kSegmentParam:
176 SkASSERT(fSegmentParamBytesRemaining > 0);
177 fSegmentParamBytesRemaining -= 1;
178 if (fSegmentParamBytesRemaining == 0) {
179 fState = State::kEntropyCodedData;
182 case State::kEntropyCodedData:
184 fState = State::kEntropyCodedDataSentinel;
187 case State::kEntropyCodedDataSentinel:
189 fState = State::kEntropyCodedData;
190 }
else if (
byte == 0xFF) {
191 fState = State::kPostEntropyCodedDataFill;
193 onMarkerSecondByte(
byte);
196 case State::kPostEntropyCodedDataFill:
201 fState = State::kPostEntropyCodedDataFill;
202 }
else if (
byte == 0x00) {
204 fState = State::kError;
207 onMarkerSecondByte(
byte);
#define SkCodecPrintf(...)
static constexpr uint8_t kJpegMarkerStartOfImage
static constexpr size_t kJpegSegmentParameterLengthSize
static constexpr size_t kJpegMarkerCodeSize
static sk_sp< SkData > MakeSubset(const SkData *src, size_t offset, size_t length)
const std::vector< SkJpegSegment > & getSegments() const
static sk_sp< SkData > GetParameters(const SkData *scannedData, const SkJpegSegment &segment)
SkJpegSegmentScanner(uint8_t stopMarker=kJpegMarkerEndOfImage)
void onBytes(const void *data, size_t size)