📄 blocks.cpp
字号:
/*****************************************************************************/// File: blocks.cpp [scope = CORESYS/COMPRESSED]// 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: Implements a part of the compressed data management machinery, inrelation to code-blocks. Includes packet header parsing and construction.Note that the internal representation employed for code-block stateinformation has been carefully paired down to a point where it would bedifficult to implement packet operations with substantially lessmemory.******************************************************************************/#include <string.h>#include <assert.h>#include "kdu_elementary.h"#include "kdu_messaging.h"#include "kdu_compressed.h"#include "compressed_local.h"/* ========================================================================= *//* kdu_block *//* ========================================================================= *//*****************************************************************************//* kdu_block::kdu_block *//*****************************************************************************/kdu_block::kdu_block(){ transpose = vflip = hflip = false; pass_lengths = NULL; pass_slopes = NULL; max_passes = 0; byte_buffer = NULL; max_bytes = 0; sample_buffer = NULL; max_samples = 0; context_buffer = NULL; max_contexts = 0; cpu_iterations = 0; cpu_time = 0; cpu_unique_samples = 0; resilient = fussy = false;}/*****************************************************************************//* kdu_block::~kdu_block *//*****************************************************************************/kdu_block::~kdu_block(){ if (pass_lengths != NULL) delete[] pass_lengths; if (pass_slopes != NULL) delete[] pass_slopes; if (byte_buffer != NULL) delete[] (byte_buffer-1); if (sample_buffer != NULL) delete[] sample_buffer; if (context_buffer != NULL) delete[] context_buffer;}/*****************************************************************************//* kdu_block::set_max_passes *//*****************************************************************************/void kdu_block::set_max_passes(int new_passes, bool copy_existing){ if (max_passes >= new_passes) return; if (max_passes == 0) copy_existing = false; if (copy_existing) { int *new_pass_lengths = new int[new_passes]; kdu_uint16 *new_pass_slopes = new kdu_uint16[new_passes]; for (int n=0; n < max_passes; n++) { new_pass_lengths[n] = pass_lengths[n]; new_pass_slopes[n] = pass_slopes[n]; } delete[] pass_lengths; delete[] pass_slopes; pass_lengths = new_pass_lengths; pass_slopes = new_pass_slopes; } else { if (pass_lengths != NULL) delete[] pass_lengths; if (pass_slopes != NULL) delete[] pass_slopes; pass_lengths = new int[new_passes]; pass_slopes = new kdu_uint16[new_passes]; } max_passes = new_passes;}/*****************************************************************************//* kdu_block::set_max_bytes *//*****************************************************************************/void kdu_block::set_max_bytes(int new_bytes, bool copy_existing){ if (max_bytes >= new_bytes) return; if (max_bytes == 0) copy_existing = false; if (copy_existing) { kdu_byte *new_buf = (new kdu_byte[new_bytes+1])+1; memcpy(new_buf,byte_buffer,max_bytes); delete[] (byte_buffer-1); byte_buffer = new_buf; } else { if (byte_buffer != NULL) delete[] (byte_buffer-1); byte_buffer = (new kdu_byte[new_bytes+1])+1; } max_bytes = new_bytes;}/*****************************************************************************//* kdu_block::set_max_samples *//*****************************************************************************/void kdu_block::set_max_samples(int new_samples){ if (max_samples >= new_samples) return; if (sample_buffer != NULL) delete[] sample_buffer; sample_buffer = new kdu_int32[new_samples]; max_samples = new_samples;}/*****************************************************************************//* kdu_block::set_max_contexts *//*****************************************************************************/void kdu_block::set_max_contexts(int new_contexts){ if (max_contexts >= new_contexts) return; if (context_buffer != NULL) delete[] context_buffer; context_buffer = new kdu_int32[new_contexts]; max_contexts = new_contexts;}/* ========================================================================= *//* kd_block *//* ========================================================================= *//*****************************************************************************//* kd_block::cleanup *//*****************************************************************************/void kd_block::cleanup(kd_precinct_band *pband){ kd_codestream *codestream = pband->subband->codestream; kd_code_buffer *tmp; while ((tmp=first_buf) != NULL) { first_buf = tmp->next; codestream->buf_server->release(tmp); }}/*****************************************************************************//* kd_block::parse_packet_header *//*****************************************************************************/int kd_block::parse_packet_header(kd_header_in &head, kd_buf_server *buf_server, int layer_idx){ // Parse inclusion information first. temp_length = 0; if (beta == 0) { // Not yet included. Tag tree decoding for `layer_w'. assert(layer_wbar == layer_w); kd_block *scan, *prev, *next; // Walk up to the root node in the tree. scan=this; prev=NULL; while ((next=scan->up_down) != NULL) { scan->up_down=prev; prev=scan; scan=next; } scan->up_down = prev; // Walk back down the tree, performing the decoding steps. kdu_uint16 wbar_min = 0; kdu_uint16 threshold = (kdu_uint16)(layer_idx+1); prev = NULL; while (scan != NULL) { if (scan->layer_wbar < wbar_min) { scan->layer_wbar = wbar_min; scan->layer_w = wbar_min; } while ((scan->layer_w == scan->layer_wbar) && (scan->layer_wbar < threshold)) { scan->layer_wbar++; if (head.get_bit() == 0) scan->layer_w++; } wbar_min = scan->layer_w; next=scan->up_down; scan->up_down=prev; prev=scan; scan=next; } if (layer_wbar == layer_w) return 0; // Nothing included yet. if (layer_w != (kdu_uint16) layer_idx) throw KDU_EXCEPTION_ILLEGAL_LAYER; } else { // Already included. if (head.get_bit() == 0) return 0; } // If we get here, the code-block does contribute to the current layer. bool discard_block = (num_passes == 255); if (beta == 0) { // First time contribution. Need to get MSB's and set up buffering. while (msbs_w == msbs_wbar) { // Run tag tree decoder. kd_block *scan, *prev, *next; // Walk up to the root note in the tree. scan=this; prev=NULL; while ((next=scan->up_down) != NULL) { scan->up_down=prev; prev=scan; scan=next; } scan->up_down = prev; // Walk back down the tree, performing the decoding steps. kdu_byte wbar_min = 0; kdu_byte threshold = msbs_wbar+1; prev = NULL; while (scan != NULL) { if (scan->msbs_wbar < wbar_min) { scan->msbs_wbar = wbar_min; scan->msbs_w = wbar_min; } while ((scan->msbs_w == scan->msbs_wbar) && (scan->msbs_wbar < threshold)) { scan->msbs_wbar++; if (head.get_bit() == 0) scan->msbs_w++; } wbar_min = scan->msbs_w; next=scan->up_down; scan->up_down=prev; prev=scan; scan=next; } } num_bytes = 0; beta = 3; assert(pass_idx == 0); if (!discard_block) start_buffering(buf_server); } if (!discard_block) { // Record the layer index for this new contribution. put_byte((kdu_byte)(layer_idx>>8),buf_server); put_byte((kdu_byte) layer_idx,buf_server); } // Decode number of passes. int new_passes = 1; new_passes += head.get_bit(); if (new_passes >= 2) { new_passes += head.get_bit(); if (new_passes >= 3) { new_passes += head.get_bits(2); if (new_passes >= 6) { new_passes += head.get_bits(5); if (new_passes >= 37) new_passes += head.get_bits(7); } } } // Finally, decode the length information. while (head.get_bit()) { if (beta == 255) throw KDU_EXCEPTION_PRECISION; beta++; } bool bypass_term = ((((int) modes) & Cmodes_BYPASS) != 0); bool all_term = ((((int) modes) & Cmodes_RESTART) != 0); if (all_term) bypass_term = false; int segment_passes, segment_bytes; int length_bits; int idx = pass_idx; while (new_passes > 0) { if (all_term) segment_passes = 1; else if (bypass_term) { if (idx < 10) segment_passes = 10-idx; else if (((idx-10) % 3) == 0) segment_passes = 2; else segment_passes = 1; if (segment_passes > new_passes) segment_passes = new_passes; } else segment_passes = new_passes; for (length_bits=0; (1<<length_bits) <= segment_passes; length_bits++); length_bits--; length_bits += beta; segment_bytes = head.get_bits(length_bits); if ((segment_bytes >= (1<<15)) || (segment_bytes >= ((1<<16) - (int) temp_length))) throw KDU_EXCEPTION_PRECISION; temp_length += segment_bytes; idx += segment_passes; new_passes -= segment_passes; if (new_passes > 0) segment_bytes |= (1<<15); // Continuation flag. if (!discard_block) { // Record the number of bytes and the number of passes in the segment put_byte((kdu_byte)(segment_bytes>>8),buf_server); put_byte((kdu_byte) segment_bytes,buf_server); put_byte((kdu_byte) segment_passes,buf_server); } } pass_idx = (kdu_byte) idx; if (!discard_block) num_passes = pass_idx; return temp_length;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -