📄 compressed_local.h
字号:
{ /* Returns true if any of the input functions, `get', `read' or `ignore' failed to completely fulfill its objective due to exhaustion of the relevant source. */ return exhausted; } bool get(kdu_byte &byte) // throws (kdu_uint16 code): unexpected marker { /* Access a single byte, returning false if and only if the source is exhausted, in which case future calls to `failed' return true. */ if (exhausted || ((first_unread==first_unwritten) && !load_buf())) return false; // If `load_buf' fails it sets `exhausted' for us. byte = *(first_unread++); if (throw_markers) { if (have_FF && (byte > 0x8F)) process_unexpected_marker(byte); have_FF = (byte==0xFF); } return true; } void putback(kdu_byte byte) { /* You may put back more than 1 byte, but you may not call this function if a previous read has ever failed. It is also illegal to call this function while marker throwing is enabled. */ assert(!exhausted); assert(!throw_markers); assert(first_unread > buffer); *(--first_unread) = byte; } void putback(kdu_uint16 code) { /* This function is designed to improve the readability of code which puts marker codes back to the input object from which they were read. */ putback((kdu_byte) code); putback((kdu_byte)(code>>8)); } int read(kdu_byte *buf, int count); /* More efficient than `get' when the number of bytes to be read is more than 2 or 3. Returns the number of bytes actually read. If less than `count', future calls to `failed' will return true. Note that this function is less efficient if marker throwing is enabled. */ int ignore(int count); /* Skips over the indicated number of bytes, returning the number of bytes actually skipped. If less than `count', future calls to `failed' will return true. */ protected: // Data and functions used for buffer management. virtual bool load_buf() = 0; /* Returns false and sets `exhausted' to true if the source is unable to provide any more data. Otherwise, augments the internal buffer and returns true. Buffer manipulation must conform to the following conventions. The `first_unread' pointer should be set to `buffer'+KD_IBUF_PUTBACK and then bytes should be loaded into the remaining KD_IBUF_SIZE bytes of the `buffer' array. The `first_unwritten' pointer should then be set to point just beyond the last byte actually written into the buffer. */ kdu_byte buffer[KD_IBUF_SIZE+KD_IBUF_PUTBACK]; kdu_byte *first_unread; // Points to next byte to retrieve from buffer. kdu_byte *first_unwritten; // Points beyond last available byte in buffer bool exhausted; private: // Functions void process_unexpected_marker(kdu_byte last_byte); /* This function is called when marker throwing is enabled and a marker code in the range FF90 through FFFF has been found. The least significant byte of the marker code is supplied as the `last_byte' argument. The function determines whether to throw the exception or not. If not, reading continues unaffected. */ private: // Data bool throw_markers; // If true, must look for unexpected markers. bool have_FF; // Valid only with `throw_markers'. Means last byte was FF. bool reject_all; // If `false' marker throwing is only for SOP's and SOT's }; /*****************************************************************************//* kd_compressed_input *//*****************************************************************************/class kd_compressed_input : public kd_input { public: // Member functions kd_compressed_input(kdu_compressed_source *source) { this->source=source; max_bytes = bytes_available = INT_MAX; } void set_max_bytes(int limit) { if (limit >= max_bytes) return; // Only allow tighter restrictions bytes_available -= (max_bytes-limit); max_bytes = limit; if (bytes_available < 0) { // We have already loaded the buffer with too many bytes. first_unwritten += bytes_available; bytes_available = 0; if (first_unwritten < first_unread) { exhausted = true; first_unwritten = first_unread; } } } int get_bytes_read() { return (max_bytes-bytes_available)-(first_unwritten-first_unread); } protected: // Virtual functions which implement required services. virtual bool load_buf(); private: // Data kdu_compressed_source *source; int bytes_available; int max_bytes; };/*****************************************************************************//* kd_pph_input *//*****************************************************************************/class kd_pph_input : public kd_input { /* Alternate input for packet header bytes, which is used in conjunction with the PPM and PPT marker segments. */ public: // Member functions kd_pph_input(kd_buf_server *server) { buf_server = server; first_buf = read_buf = write_buf = NULL; } virtual ~kd_pph_input(); void add_bytes(kdu_byte *data, int num_bytes); /* This function is called when unpacking a PPM or PPT marker, to augment the current object. */ protected: // Virtual functions which implement required services. virtual bool load_buf(); private: // Data kd_code_buffer *first_buf; kd_code_buffer *read_buf, *write_buf; int read_pos, write_pos; kd_buf_server *buf_server; }; /* Notes: `first_buf' points to the first in a linked list of buffers used to temporarily store PPM or PPT marker segment bytes. `read_buf' points to the element in the linked list of code buffers which is currently being read; `read_pos' points to the next element of the current buffer which will be read. This may be equal to KD_CODE_BUFFER_LEN, in which case the next element in the code buffer list must be accessed when the next read attempt occurs. `write_buf' points to the last element in the linked list of code buffers and `write_pos' identifies the first unwritten byte in this element. `write_pos' may equal KD_CODE_BUFFER_LEN, in which case a new element will need to be added before further data can be written. `buf_server' points to the object which is used to add and release code buffer elements. This is a shared resource. *//*****************************************************************************//* kd_marker *//*****************************************************************************/class kd_marker { /* Objects of this class are used to read and store code-stream marker segments. The most efficient way to use the class is to construct a single serving object which is used to read the markers one by one and then copy any markers which need to be preserved into new instances of the class, using the copy constructor. This concentrates wasted buffer space in the one server marker which actually reads from the input code-stream. */ public: // Member functions kd_marker(kd_input *input) { source = input; code = 0; length = 0; max_length = 0; buf = NULL; } kd_marker(const kd_marker &orig); /* Copies any marker segment stored in `orig'. Note that the `codestream' pointer is not copied, meaning that the `read' member function may not be invoked on the copy. */ ~kd_marker() { if (buf != NULL) delete[] buf; } void print_current_code(std::ostream &out) { /* Prints a text string identifying the current marker code. */ print_marker_code(this->code,out); } bool read(bool exclude_stuff_bytes=false, bool skip_to_marker=false); /* Reads a new marker (or marker segment) from the `kd_input' object supplied during construction. Returns true if successful. Causes of failure may be: 1) the code-stream source is exhausted; 2) a valid marker code was not found; or 3) an SOP or SOT marker code was found, but followed by an invalid length field. This third cause of failure is important since it prevents the function from attempting to consume an invalid SOP or SOT marker segment, in the process of which it might consume any number of useful packets, having their own SOP markers. A valid marker code must commence with an FF. If `exclude_stuff_bytes' is true then the second byte of a valid marker code must be strictly greater than 0x8F. Otherwise, the second byte is arbitrary. If `skip_to_marker' is true, the function consumes bytes indefinitely, until the source is exhausted or a valid marker code is found. In this case, the function returns false only if the source is exhausted. Otherwise, the function expects to find a valid marker code immediately. As a convenience feature, the function automatically skips over any EOC marker it encounters. This has two advantages: 1) we can detect the end of the code-stream without having to explicitly check for an EOC marker; 2) we should not be overly troubled by EOC markers which arise due to corruption of the code-stream (this has quite a high likelihood of occurring if the code-stream is subject to corruption). In the event that the source is not exhausted but a valid marker code is not found, the function puts back any bytes it consumed before returning false. This allows the caller to continue reading from the point where the function was first called. */ kdu_uint16 get_code() { return code; } /* Returns 0 if no actual marker is available yet. */ int get_length() { return length; } /* Returns length of marker segment (not including the length specifier). Returns 0 if no actual marker available, or if the marker is a delimiter (no segment). */ kdu_byte *get_bytes() { return buf; } /* Returns pointer to marker segment bytes immediately following the length specifier. */ private: // Data kd_input *source; // If NULL, `read' may not be used. kdu_uint16 code; int length; int max_length; // Number of bytes which the buffer can store. kdu_byte *buf; };/*****************************************************************************//* kd_pp_marker_list *//*****************************************************************************/class kd_pp_marker_list : private kd_marker { friend class kd_pp_markers; private: // Member functions kd_pp_marker_list(kd_marker ©_source) : kd_marker(copy_source) { next = NULL; } private: // Data -- These fields are manipulated by `kd_pp_markers'. kd_pp_marker_list *next; int znum; int bytes_read; };/*****************************************************************************//* kd_pp_markers *//*****************************************************************************/class kd_pp_markers { public: // Member functions kd_pp_markers() { list = NULL; } ~kd_pp_markers(); void add_marker(kd_marker ©_source); /* Copies the `kd_marker' object into a new `kd_pp_marker_list' element, inserting it into the evolving list on the basis of its Zppm or Zppt index. Markers need not be added in order. */ void transfer_tpart(kd_pph_input *pph_input); /* Transfers an entire tile-part of packed packet header data from the internal marker list to the `pph_input' object, which may then be used as a source object for packet header reading. If the object is managing a list of PPM markers, the function expects to find the total number of bytes associated with the next tile-part embedded in the current marker segment. Otherwise, all marker segments are dumped into the `pph_input' object. Marker segments whose data have been consumed are deleted automatically. */ void ignore_tpart(); /* Same as `transfer_tpart' except that the data are simply discarded. This is useful when discarding a tile for which PPM marker information has been provided. */ private: // Convenience functions void advance_list(); private: // Data bool is_ppm; // Otherwise, list contains PPT markers.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -