📄 mq_encoder.h
字号:
/*****************************************************************************/// File: mq_encoder.h [scope = CORESYS/CODING]// Version: Kakadu, V2.2// Author: David Taubman// Last Revised: 20 June, 2001/*****************************************************************************/// Copyright 2001, David Taubman, The University of New South Wales (UNSW)// The copyright owner is Unisearch Ltd, Australia (commercial arm of UNSW)// Neither this copyright statement, nor the licensing details below// may be removed from this file or dissociated from its contents./*****************************************************************************/// Licensee: Book Owner// License number: 99999// The Licensee has been granted a NON-COMMERCIAL license to the contents of// this source file, said Licensee being the owner of a copy of the book,// "JPEG2000: Image Compression Fundamentals, Standards and Practice," by// Taubman and Marcellin (Kluwer Academic Publishers, 2001). A brief summary// of the license appears below. This summary is not to be relied upon in// preference to the full text of the license agreement, which was accepted// upon breaking the seal of the compact disc accompanying the above-mentioned// book.// 1. The Licensee has the right to Non-Commercial Use of the Kakadu software,// Version 2.2, including distribution of one or more Applications built// using the software, provided such distribution is not for financial// return.// 2. The Licensee has the right to personal use of the Kakadu software,// Version 2.2.// 3. The Licensee has the right to distribute Reusable Code (including// source code and dynamically or statically linked libraries) to a Third// Party, provided the Third Party possesses a license to use the Kakadu// software, Version 2.2, and provided such distribution is not for// financial return./******************************************************************************Description: Defines interfaces for the low-level binary symbol operations associatedwith the MQ coder. Includes, interfaces to support the arithetic coder bypassmode as well. Also includes macros which may be used as substitutes for thecoding functions. Both the macros and the functions achieve the sameresult, although the macro implementation is more carefully tuned for speed,while the function implementation is somewhat more dydactic.******************************************************************************/#ifndef MQ_ENCODER_H#define MQ_ENCODER_H#include <assert.h>#include "kdu_messaging.h"// Defined here:struct mqe_state;struct mqe_transition;class mq_encoder;/* ========================================================================= *//* Constants *//* ========================================================================= */#define MQE_SPACER 3#define MQE_CARRY_POS (16+MQE_SPACER+8)#define MQE_CARRY_BIT ((kdu_int32)(1<<MQE_CARRY_POS))#define MQE_PARTIAL_POS (16+MQE_SPACER)#define MQE_PARTIAL_CLEAR (~(((kdu_int32)(-1))<<MQE_PARTIAL_POS))#define MQE_MSBS_POS (MQE_PARTIAL_POS+1)#define MQE_MSBS_CLEAR (~(((kdu_int32)(-1))<<MQE_MSBS_POS))#define MQE_A_MIN ((kdu_int32)(1<<15))/* ========================================================================= *//* Class Definitions *//* ========================================================================= *//*****************************************************************************//* mqe_state *//*****************************************************************************/struct mqe_state { public: // Member functions void init(int Sigma, kdu_int32 s); // Inline implementation appears later /* `Sigma' is in the range 0 to 46 and `s' is the MPS identity. */ public: // Data kdu_int32 mps_p_bar; // Holds `p_bar' + `s'*2^31 (`s' is the MPS; 0 or 1) mqe_transition *transition; }; /* Notes: This structure manages the state of the probability estimation state machine for a single coding context. The representation is redundant, of course, since all that is required is the vaue of `Sigma', in the range 0 through 46, and the value of the MPS, `s' (0 or 1). However, this expanded representation avoids unnecessary de-referencing steps by the MP encoder and so can significantly increase throughput. The `transition' pointer holds the address of the entry in `mq_encoder::transition_table' which corresponds to this element. There are 92 entries in the transition table, whose indices have the form `idx'=2*`Sigma'+s. If renormalization occurs while encoding an MPS, the state is updated according to state=state.transition->mps; if renormalization occurs while encoding an LPS, the state is updated according to state=state.transition->lps. The transition table is carefully constructed to ensure that all information is mapped correctly by this simple operation. The trick of keeping the MPS identity in the most significant bit (i.e., the sign bit) of the `mps_p_bar' member, allows the encoder to be implemented with a most common symbol path having only one comparison and very few other operations. *//*****************************************************************************//* mqe_transition *//*****************************************************************************/struct mqe_transition { /* See the definition of `mqe_state' for an explanation of this structure. */ mqe_state mps; mqe_state lps; };/*****************************************************************************//* mq_encoder *//*****************************************************************************/class mq_encoder { /* This object can be used for both MQ and raw codeword segments. */ public: // Member functions mq_encoder() { active = false; buf_start=buf_next=NULL; prev=next=NULL; } void start(kdu_byte *buffer, bool MQ_segment); /* Start a new MQ or raw codeword segment. On entry, `buffer' points to the location to which the first code byte will be written. Note carefully, however, that the MQ codeword segments actually require access to the location immediately prior to the `buffer' pointer. The value at that location is temporarily saved and restored only when the `terminate' member function is called. To allow access to `buffer'[-1], the caller should take care in allocating storage for coded bytes. The buffer is required to be large enough to hold the compressed output. If the user determines that the buffer may need to grow, the `augment_buffer' function should be used in the manner described below. This policy allows buffer size tests and potential function calls to be eliminated from all time-critical code. */ int get_bytes_used() { /* Returns the total number of bytes from the original `buffer' supplied in the `start' call which have been used by this object and any previous objects which it continues. The function is provided only to facilitate determination by the user as to whether or not buffer space will need to be augmented. There is no attempt to determine truncation lengths. */ assert((!checked_out) && (buf_start != NULL)); return (buf_next-buf_start); } void augment_buffer(kdu_byte *old_handle, kdu_byte *new_handle) { /* Use this if you need to increase the size of the buffer. You must first create the new buffer and copy the old buffer's contents into the new buffer. Then call this function for every `mqe_coder' object which is using the buffer. The object will alter its internal pointers accordingly. The `old_handle' and `new_handle' pointers should generally point to the first allocated location in each of the original and new buffers. */ if (buf_start == NULL) return; // Encoder finished working with buffer assert((!checked_out) && (old_handle != NULL) && (new_handle != NULL)); buf_start += (new_handle-old_handle); buf_next += (new_handle-old_handle); } void continues(mq_encoder *previous) { /* Use this function to continue a coding segment beyond the current coding pass. This sets up internal references between the coding objects which manage the same codeword segment, so that truncation point computation may be performed later. */ assert((!active) && (buf_start == NULL)); assert(previous->active); // Can't continue an inactive segment. assert(!previous->checked_out); *this = *previous; prev = previous; previous->next = this; previous->active = false; } int get_incremental_length(bool &final) { /* This function returns the number of additional code bytes generated by this object, beyond the point of continuation from any previous object in a continuation list. If possible, the function invokes the truncation point optimization algorithm for this object and all objects which it continues and have not already had their truncation points determined. This will not be possible if the object is still active or it has been continued by another object which has generated less than 5 additional bytes so far. If truncation point optimization is not possible, the `final' argument is set to false and the function returns a reasonable lower bound (not quite a guaranteed bound) for the length, which is the number of bytes which have actually been put onto the byte buffer beyond the point of continuation (or the start of the buffer). The return value is guaranteed to be non-negative. */ if (!truncation_point_found) { mq_encoder *scan_ahead = this; while (scan_ahead->next != NULL) scan_ahead = scan_ahead->next; mq_encoder *scan_back = scan_ahead; for (; scan_back != NULL; scan_back=scan_back->prev) { if (scan_back->truncation_point_found) break; if ((!scan_back->active) && ((scan_ahead->buf_next - scan_back->buf_next) >= 5)) scan_back->find_truncation_point(scan_ahead->buf_next); } } final = truncation_point_found; if (prev == NULL) return buf_next - buf_start; else return buf_next - prev->buf_next; } kdu_byte *terminate(bool optimal); /* This function is quite involved. It flushes the state of the coder and then determines a suitable truncation length. If `optimal' is true, it terminates to the smallest possible codeword segment which will result in correct decoding of the coded symbols. If the codeword segment has been continued across multiple coding objects, this function may be invoked only on the last such object. It automatically visits the other objects and forces optimal truncation length computation if this has not already been done (see "get_incremental_length" for a discussion of early length computation). This guarantees that their `finish' functions will return correct lengths. For a thorough discussion of optimal termination and length computation, see Section 12.3.2 of the book by Taubman and Marcellin. If `optimal' is false, the function uses the predictable termination algorithms expected by error resilient decoders. See Section 12.4 of the book by Taubman and Marcellin for a discussion of error resilient termination for MQ and raw codeword segments. The function returns a pointer to the next free location in the byte buffer; this may be used to start another codeword segment. */ void finish() { /* Invoke this function on the last element in a codeword segment (the same one which you invoked `terminate' on) to reset all objects in the segment in preparation for later calls to the `start' member function. */ assert((!active) && (next == NULL)); mq_encoder *scan, *next_scan; for (scan=this; scan != NULL; scan = next_scan) { assert(!scan->active); next_scan = scan->prev; scan->next = scan->prev = NULL; scan->truncation_point_found = false; scan->buf_start = scan->buf_next = NULL; } } public: // Functions to check out state information for use with fast macros void check_out(kdu_int32 &A, kdu_int32 &C, kdu_int32 &t, kdu_int32 &temp, kdu_byte * &store) { // Use this form for MQ codeword segments. assert(active && (!checked_out) && MQ_segment); checked_out = true; A = this->A; C = this->C; t = this->t; temp = this->temp; store = this->buf_next; } void check_out(kdu_int32 &t, kdu_int32 &temp, kdu_byte * &store) { // Use this form for raw codeword segments.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -