1 /* 2 * Copyright 2023 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkJpegSegmentScan_codec_DEFINED 9 #define SkJpegSegmentScan_codec_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "src/codec/SkJpegConstants.h" 13 14 #include <cstddef> 15 #include <cstdint> 16 #include <memory> 17 #include <vector> 18 19 class SkData; 20 class SkStream; 21 22 /* 23 * A JPEG segment. 24 */ 25 struct SkJpegSegment { 26 // The offset in bytes from the initial position to where this segment starts. 27 size_t offset = 0; 28 // The second byte of the marker code, which determines the segment type. 29 uint8_t marker = 0; 30 // The length of the parameters for this segment (including the two bytes used to specify 31 // the length). 32 uint16_t parameterLength = 0; 33 }; 34 35 /* 36 * Class for scanning JPEG data. The JPEG format consists of a sequence of segments that begin with 37 * a marker, with entropy-coded data in between. 38 */ 39 class SkJpegSegmentScanner { 40 public: 41 SkJpegSegmentScanner(uint8_t stopMarker = kJpegMarkerEndOfImage); 42 isDone()43 bool isDone() const { return fState == State::kDone; } hadError()44 bool hadError() const { return fState == State::kError; } 45 46 // Provide more bytes of data to the state machine. 47 void onBytes(const void* data, size_t size); 48 49 // Return the segments that have been retrieved so far. If an error was encountered, this will 50 // include all segments up to the error. 51 const std::vector<SkJpegSegment>& getSegments() const; 52 53 // Helper function to retrieve the parameters for a segment. ScannedData must be the data that 54 // was scanned to produce segment, starting at StartOfImage. 55 static sk_sp<SkData> GetParameters(const SkData* scannedData, const SkJpegSegment& segment); 56 57 private: 58 // The scanner is a state machine. State transitions happen when a byte is read. 59 enum class State { 60 // The initial state, before we read the 0xFF,0xD8,0xFF JPEG signature. 61 kStartOfImageByte0, 62 // We have read the 0xFF of the JPEG signature. 63 kStartOfImageByte1, 64 // We have read the 0xFF,0xD8 of the JPEG signature. The next byte should be the 0xFF that 65 // completes the JPEG signature and starts the second marker (the one after StartOfImage). 66 kSecondMarkerByte0, 67 // We have read the full JPEG signature. The next byte should be the the second byte of the 68 // second marker. 69 kSecondMarkerByte1, 70 // We have read a marker that does not stand alone. The next byte is the first byte of the 71 // length of the parameters, 72 kSegmentParamLengthByte0, 73 // We have read the first byte of the length of the parameters (and it is stored in 74 // |fSegmentParamLengthByte0|). The next byte we read is the second byte of the length of 75 // the parameters. 76 kSegmentParamLengthByte1, 77 // We have read the full length of the parameters. The next |fSegmentParamBytesRemaining| 78 // bytes are the parameters. 79 kSegmentParam, 80 // We have read a marker and (optionally) its parameters, and we are now reading entropy- 81 // coded data. All subsequent bytes until we reach 0xFF are entropy-coded data. 82 kEntropyCodedData, 83 // We reached an 0xFF in entropy-coded data. If the next byte is 0x00 then we continue 84 // reading entropy-coded data. If the next byte is 0xFF then we are reading fill data. 85 // If the next byte is anything else then it is the second byte of a marker. 86 kEntropyCodedDataSentinel, 87 // We are reading fill data. If the next byte is 0xFF then we are still reading fill data, 88 // otherwise the next byte is the second byte of a marker. 89 kPostEntropyCodedDataFill, 90 // We reached |fStopMarker| and have stopped tracking our state. 91 kDone, 92 // We hit an error somewhere and have given up. 93 kError, 94 }; 95 State fState = State::kStartOfImageByte0; 96 97 // Update state transition when a single byte is read. 98 void onByte(uint8_t byte); 99 100 // Perform the appropriate state transition for when a marker is read. This will set 101 // |fCurrentSegmentMarker| and |fCurrentSegmentOffset|, and potentially call saveCurrentSegment. 102 void onMarkerSecondByte(uint8_t byte); 103 104 // Add a new entry in |segments| for |fCurrentSegmentMarker| and offset |fCurrentSegmentOffset| 105 // and the specified length. 106 void saveCurrentSegment(uint16_t length); 107 MarkerStandsAlone(uint8_t marker)108 static bool MarkerStandsAlone(uint8_t marker) { 109 // These markers are TEM (0x01), RSTm (0xD0 through 0xD7), SOI (0xD8), and 110 // EOI (0xD9). See section B.1.1.3, Marker assignments. 111 return marker == 0x01 || (marker >= 0xD0 && marker <= 0xD9); 112 } 113 114 // Stop tracking state when we hit this marker. If this is 0x00, then never stop. 115 const uint8_t fStopMarker; 116 117 // The number of bytes that have been processed so far. 118 size_t fOffset = 0; 119 120 // If |fState| is kSegmentParamLengthByte1, then this is the value of the the previous byte. 121 uint8_t fSegmentParamLengthByte0 = 0; 122 123 // If |fState| is kSegmentParam, then this is the number of bytes reamining in the current 124 // segment. 125 size_t fSegmentParamBytesRemaining = 0; 126 127 // The offset and marker for the segment started by the previous call to OnMarkerSecondByte. 128 // These are re-set when SaveCurrentSegment is called. 129 size_t fCurrentSegmentOffset = 0; 130 uint8_t fCurrentSegmentMarker = 0; 131 132 std::vector<SkJpegSegment> fSegments; 133 }; 134 135 #endif 136