📄 compressed_local.h
字号:
kd_pp_marker_list *list; };/*****************************************************************************//* kd_compressed_stats *//*****************************************************************************/class kd_compressed_stats { /* An object of this class is used to monitor statistics of the compression process. One application of these statistics is the provision of feedback to the block encoder concerning a conservative lower bound to the distortion-length slope threshold which will be found by the PCRD-opt rate allocation algorithm when the image has been fully compressed. This allows the encoder to skip coding passes which are almost certain to be discarded. The current very simple implementation makes the naive assumption that the compressibility of all subband samples is the same, regardless of the subband or resolution level. This is OK if the number of samples which have been processed for each subband is proportional to the size of the subband, since then the average compressibility is a good measure to use in predicting rate control properties. In practice, though, delay through the wavelet transform means that the percentage of samples seen for higher resolution subbands is generally higher than that seen for lower frequency subbands, until everything has been compressed. Since the higher frequency subbands are almost invariably more compressible, the predicted compressibility of the source is estimated too high and so the predicted rate-distortion slope threshold passes considerably more bits than the final rate allocation will. This renders the prediction excessively conservative for most images. A good fix for this is to keep track of the percentage of subband samples which have been compressed in each resolution level and use this information to form a more reliable predictor. This improvement will be included in a future version. */ public: // Member functions kd_compressed_stats(int total_samples, int target_bytes) { this->total_samples = total_samples; next_trim = (total_samples+7) >> 3; conservative_extra_samples = 4096 + (total_samples>>4); target_rate = (total_samples==0)?1.0:(((double) target_bytes)/total_samples); num_coded_samples = 0; min_quant_slope = 4095; max_quant_slope = 0; for (int n=0; n < 4096; n++) quant_slope_rates[n] = 0; } bool update(kdu_block *block) { /* Invoked by "kdu_subband::close_block". If the function returns true, it is recommended that the compressed data be trimmed back to a size consistent with the target compressed length at this point. */ num_coded_samples += block->size.x*block->size.y; assert(num_coded_samples <= total_samples); int quant_slope, length = 0; for (int n=0; n < block->num_passes; n++) { length += block->pass_lengths[n]; if (block->pass_slopes[n] == 0) continue; quant_slope = block->pass_slopes[n] >> 4; if (quant_slope < min_quant_slope) min_quant_slope = quant_slope; if (quant_slope > max_quant_slope) max_quant_slope = quant_slope; quant_slope_rates[quant_slope] += length; length = 0; } if (num_coded_samples > next_trim) { next_trim += (total_samples+7)>>4; return true; } return false; } kdu_uint16 get_conservative_slope_threshold(bool assume_all_coded=false) { /* The slope threshold generated by PCRD-opt is unlikely to be smaller than that returned here -- remember that smaller thresholds mean that more compressed data are included in the code-stream. If `all_coded' is true, the slope threshold is based on the assumption that no bytes will be generated for any further samples. Otherwise, the assumption is that future samples will have the same average compressibility as those already coded. Note that since compressors tend to output a higher proportion of high frequency subband samples than low frequency subband samples at any point up to the end of the image, the actual compressibility of future samples can be expected to be lower on average, making our estimate more conservative. */ int max_bytes; if (assume_all_coded) max_bytes = (int)(target_rate * total_samples); else max_bytes = (int)(target_rate * (num_coded_samples + conservative_extra_samples)); int n, cumulative_bytes = 0; for (n=max_quant_slope; n >= min_quant_slope; n--) if ((cumulative_bytes += quant_slope_rates[n]) >= max_bytes) break; return (kdu_uint16)((n>0)?((n<<4)-1):1); } private: // Data double target_rate; // Expressed in bytes per sample, not bits per sample. int total_samples; // Total number of subband sample in entire image int next_trim; // Number of samples at which memory should next be trimmed int conservative_extra_samples; // Add to `num_coded_samples' to be safe. int num_coded_samples; // Number of samples already coded int quant_slope_rates[4096]; // See below int min_quant_slope, max_quant_slope; }; /* Notes: The `quant_slope_rates' array holds the total number of coded bytes which belong to each of a set of 4096 quantized distortion-length slope bins. The original distortion-length slopes have a 16-bit unsigned logarithmic representation (see discussion of the "pass_slopes" member array in the "kdu_block" structure). The index of the bin to which a given slope, lambda, belongs is given by bin = floor(lambda/16). Rounding down means that 16*bin is the smallest slope consistent with the bin so that summing the entries from bin to 4095 yields the maximum number of code-block bytes which could be contributed to the compressed image if the PCRD-opt algorithm selected a slope threshold of 16*bin. Note, however, that bin 0 represents only those slopes in the range 1 to 15, since 0 is not a valid slope threshold. *//*****************************************************************************//* kd_packet_sequencer *//*****************************************************************************/class kd_packet_sequencer { public: // Member functions kd_packet_sequencer(kd_tile *tile); void save_state(); /* Saves all quantities associated with packet sequencing, both within this object and in the associated tile and its constituent precincts, so that they can be later restored to resume sequencing from where we left off. We take advantage of the fact that this function can only be called on tile-part boundaries, at which point a new progression must be instated. Thus, the `restore_state' function can accomplish most of its task by invoking the `next_progression' function. */ void restore_state(); /* Restores the state saved by the `save_state' member function. */ kd_precinct *next_in_sequence(); /* This function returns a pointer to the next precinct for which a new packet must be sequenced. If the precinct does not exist, it is constructed automatically before the function returns. The caller normally proceeds to read or write a packet of data for the indicated precinct, which increments its `next_layer_idx' field in the process. In this case, or if the precinct is destroyed in the meantime (this can only happen if all layers have been read or written), then the next time this function is called the next packet in the sequence will be retrieved. However, there is no need for the caller to do anything at all with the returned precinct pointer. In this case, the next time the function is called, it will return the same precinct. The function returns NULL if no further packets can be sequenced based on the information available for the current tile-part. In this event, the caller must read or write another tile-part before proceeding to sequence more packets. The function determines that no further packets can be sequenced if one of the following two events occur: 1) no further instances of the POC marker are currently available; or 2) the next POC marker instance index exceeds the current tile-part index. This policy has the desirable effect that the presence of multiple POC attributes during compression results in the generation of multiple tile-parts. The function also returns NULL if all packets have been transferred to or from the code-stream. This event may be detected by checking the tile's `num_transferred_packets' field, which should be incremented whenever a packet is read or written to or from the code-stream. The current function does not modify this field itself. */ private: // Member functions bool next_progression(); /* Sets up the next progression (or the very first progression). Returns false, if no further progressions are available without starting a new tile-part. */ kd_precinct *next_in_lrcp(); // These functions return NULL if there kd_precinct *next_in_rlcp(); // are no more packets to sequence within kd_precinct *next_in_rpcl(); // the current progression order. kd_precinct *next_in_pcrl(); kd_precinct *next_in_cprl(); private: // Current sequencing bounds. int order; // One of the orders defined in the scope of `cod_params'. int res_min, comp_min; // Lower bounds (inclusive) for loops. int layer_lim, res_lim, comp_lim; // Upper bounds (exclusive) for loops. private: // Current looping state. int layer_idx; // Current layer index int comp_idx; // Current component index int res_idx; // Current resolution level index kdu_coords pos; // Position indices of precinct in current tile-comp-res. private: // Spatial sequencing parameters. bool common_grids; // True if all components have power-of-2 sub-sampling. kdu_coords grid_min; // Common grid start for position-component type loops kdu_coords grid_inc; // Common grid increments for pos-component type loops kdu_coords grid_lim; // This is the point just beyond tile on the canvas. kdu_coords grid_loc; // Common grid location for pos-component type loops private: // Access to tile and subordinate structures. kd_tile *tile; int max_dwt_levels; // Over all components. kdu_params *poc; // NULL unless POC-based sequencing. kdu_params *saved_poc; // Used by the `save_state' member function int next_poc_record; // Index of next order record in current POC. };/*****************************************************************************//* kd_codestream *//*****************************************************************************/struct kd_codestream { // State structure for the "kdu_codestream" interface public: // Member functions kd_codestream() { // We will be relying on all fields starting out as 0. memset(this,0,sizeof(*this)); } ~kd_codestream(); void construct_common(); /* Called from within `kdu_codestream::create' after some initial construction work to set the thing up for input or output. */ kd_tile *create_tile(int tnum); /* Creates and completely initializes a new tile, installing in the internal array of tile references and returning a pointer to the new tile. The pointer returned may be equal to KD_EXPIRED_TILE if the tile was found not to belong to the current region of interest. */ void var_structure_new(int num_bytes) { /* This function is called whenever a new tile, component, resolution, subband, precinct or code-block structure is created, with the size of the created structure. It keeps a tally of the number of heap bytes tied up in such structures, since they are all transient and regarded as part of the compressed data storage system. */ var_structure_bytes += num_bytes; if (var_structure_bytes > peak_var_structure_bytes) peak_var_structure_bytes = var_structure_bytes; } void var_structure_delete(int num_bytes) { /* This function is called when the elements responsible for calls to `var_structure_new' are deleted. */ var_structure_bytes -= num_bytes; assert(var_structure_bytes >= 0); } void from_apparent(kdu_coords &pt) { // Convert point from apparent to real coords pt.x=(hflip)?(-pt.x):pt.x; pt.y=(vflip)?(-pt.y):pt.y; if (transpose) pt.transpose(); } void from_apparent(kdu_dims &dims) { // Convert region from apparent to real coords if (hflip) dims.pos.x = -(dims.pos.x+dims.size.x-1); if (vflip) dims.pos.y = -(dims.pos.y+dims.size.y-1); if (transpose) dims.transpose(); } void to_apparent(kdu_coords &pt) { // Convert point from real to apparent coords if (transpose) pt.transpose(); pt.x = (hflip)?(-pt.x):pt.x; pt.y = (vflip)?(-pt.y):pt.y; } void to_apparent(kdu_dims &dims) { // Convert region from real to apparent coords
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -