📄 encoder.cpp
字号:
/******************************************************************************Description: Implements the functionality offered by the "kdu_encoder" object definedin "kdu_sample_processing.h". Includes quantization, subband sample bufferingand geometric appearance transformations.******************************************************************************/#include <math.h>#include <string.h>#include "kdu_messaging.h"#include "kdu_compressed.h"#include "kdu_sample_processing.h"#include "kdu_block_coding.h"#include "kdu_kernels.h"#include "kdu_roi_processing.h"/* ========================================================================= *//* Class and Structure Definitions *//* ========================================================================= *//*****************************************************************************//* kd_encoder *//*****************************************************************************/class kd_encoder : public kdu_push_ifc_base { public: // Member functions kd_encoder(kdu_subband band, kdu_sample_allocator *allocator, bool use_shorts, float normalization, kdu_roi_node *roi); protected: // These functions implement their namesakes in the base class virtual ~kd_encoder(); virtual void push(kdu_line_buf &line, bool allow_exchange); private: // Internal implementation void encode_row_of_blocks(); /* Called whenever `push' fills the line buffer. */ private: // Data kdu_block_encoder block_encoder; kdu_subband band; int K_max; // Maximum magnitude bit-planes, exclucing ROI shift int K_max_prime; // Maximum magnitude bit-planes, including ROI shift bool reversible; float delta; // For irreversible compression only. float msb_wmse; // Normalized weighted MSE associated with first mag bit float roi_weight; // Multiply `msb_wmse' by this for ROI foreground blocks kdu_dims block_indices; // Range of block indices not yet written. int subband_rows, subband_cols; int nominal_block_height; int current_block_height; int next_buffered_row; // When reaches `current_block_height' encode blocks kdu_sample_allocator *allocator; kdu_roi_node *roi_node; bool initialized; // True once line buffers allocated in first `push' call kdu_sample16 **lines16; // NULL or array of `nominal_block_height' pointers kdu_sample32 **lines32; // NULL or array of `nominal_block_height' pointers kdu_byte **roi_lines; // NULL or array of `nominal_block_height' pointers }; /* Notes: Only one of the `lines16' and `lines32' members may be non-NULL, depending on whether the transform will be pushing 16- or 32-bit sample values to us. The relevant array is pre-created during construction and actually allocated from the single block of memory associated with the `allocator' object during the first `push' call. Similar considerations apply to the `roi_lines' array, which is used only if `roi_source' is non-NULL. *//* ========================================================================= *//* Internal Functions *//* ========================================================================= *//*****************************************************************************//* STATIC find_missing_msbs *//*****************************************************************************/static int find_missing_msbs(kdu_int32 *sp, int num_rows, int num_cols){ kdu_int32 or_val = 0; int n; for (n=num_rows*num_cols; n > 3; n -= 4)//64*64 {
or_val |= *(sp++);
or_val |= *(sp++); or_val |= *(sp++);
or_val |= *(sp++);
} for (; n > 0; n--) or_val |= *(sp++); or_val &= KDU_INT32_MAX; if (or_val == 0) return 31; int missing_msbs = 0; for (or_val<<=1; or_val >= 0; or_val<<=1) missing_msbs++; return missing_msbs;}/* ========================================================================= *//* kdu_encoder *//* ========================================================================= *//*****************************************************************************//* kdu_encoder::kdu_encoder *//*****************************************************************************/kdu_encoder::kdu_encoder(kdu_subband band, kdu_sample_allocator *allocator, bool use_shorts, float normalization, kdu_roi_node *roi) // In the future, we may create separate, optimized objects for each kernel.{ state = new kd_encoder(band,allocator,use_shorts,normalization,roi);}/* ========================================================================= *//* kd_encoder *//* ========================================================================= *//*****************************************************************************//* kd_encoder::kd_encoder *//*****************************************************************************/kd_encoder::kd_encoder(kdu_subband band, kdu_sample_allocator *allocator, bool use_shorts, float normalization, kdu_roi_node *roi){ this->band = band; K_max = band.get_K_max(); K_max_prime = band.get_K_max_prime(); reversible = band.get_reversible(); delta = band.get_delta() * normalization; msb_wmse = band.get_msb_wmse(); roi_weight = 1.0F; bool have_roi_weight = band.get_roi_weight(roi_weight); kdu_dims dims; band.get_dims(dims); kdu_coords nominal_block_size, first_block_size; band.get_block_size(nominal_block_size,first_block_size); band.get_valid_blocks(block_indices); subband_cols = dims.size.x; subband_rows = dims.size.y; nominal_block_height = nominal_block_size.y; current_block_height = first_block_size.y; next_buffered_row = 0; roi_node = roi; initialized = false; lines16 = NULL; lines32 = NULL; roi_lines = NULL; this->allocator = NULL; if (!dims) { subband_rows = 0; return; } this->allocator = allocator; allocator->pre_alloc(use_shorts,0,subband_cols,nominal_block_height); if (use_shorts) lines16 = new kdu_sample16 *[nominal_block_height]; else lines32 = new kdu_sample32 *[nominal_block_height]; if (roi_node != NULL) { if ((K_max_prime == K_max) && !have_roi_weight) { roi_node->release(); roi_node = NULL; return; } allocator->pre_alloc(true,0,(subband_cols+1)>>1,nominal_block_height); roi_lines = new kdu_byte *[nominal_block_height]; }}/*****************************************************************************//* kd_encoder::~kd_encoder *//*****************************************************************************/kd_encoder::~kd_encoder(){ if (lines16 != NULL) delete[] lines16; else if (lines32 != NULL) delete[] lines32; if (roi_lines != NULL) delete[] roi_lines; if (roi_node != NULL) roi_node->release(); if (subband_rows != 0) { kdu_error e; e << "Terminating before block coding complete. Expected " << subband_rows << " additional subband rows from the DWT analysis " "engine!"; }}/*****************************************************************************//* kd_encoder::push *//*****************************************************************************/void kd_encoder::push(kdu_line_buf &line, bool allow_exchange){ if (line.get_width() == 0) return; assert(subband_rows > 0); assert(next_buffered_row < current_block_height); if (!initialized) { // Allocate all lines -- they will be aligned and contiguous in memory. int n; if (lines16 != NULL) for (n=0; n < nominal_block_height; n++) lines16[n] = allocator->alloc16(0,subband_cols); else for (n=0; n < nominal_block_height; n++) lines32[n] = allocator->alloc32(0,subband_cols); if (roi_lines != NULL) for (n=0; n < nominal_block_height; n++) roi_lines[n] = (kdu_byte *) allocator->alloc16(0,(subband_cols+1)>>1); initialized = true; } // Transfer data assert(line.get_width() == subband_cols); if (lines32 != NULL) memcpy(lines32[next_buffered_row],line.get_buf32(), (size_t)(subband_cols<<2)); else memcpy(lines16[next_buffered_row],line.get_buf16(), (size_t)(subband_cols<<1)); if (roi_node != NULL) roi_node->pull(roi_lines[next_buffered_row],subband_cols); // Update the buffer state, flushing if necessary. subband_rows--; next_buffered_row++; if (next_buffered_row == current_block_height) encode_row_of_blocks();}/*****************************************************************************//* kd_encoder::encode_row_of_blocks *//*****************************************************************************/void kd_encoder::encode_row_of_blocks(){ assert(next_buffered_row == current_block_height); assert((current_block_height > 0) && (block_indices.size.y > 0)); int offset=0; kdu_coords idx = block_indices.pos; int blocks_remaining = block_indices.size.x; kdu_coords xfer_size; kdu_block *block; kdu_uint16 estimated_slope_threshold = band.get_conservative_slope_threshold(); for (; blocks_remaining > 0; blocks_remaining--, idx.x++, offset+=xfer_size.x) { // Open the block and make sure we have enough sample buffer storage.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -