⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 block_encoder.cpp

📁 JPEG2000压缩解压图像源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                           kdu_uint16 estimated_threshold){  double estimated_slope_threshold = -1.0;  if ((estimated_threshold > 1) && (msb_wmse > 0.0) &&      (block->orientation != LL_BAND))    estimated_slope_threshold = slope_from_log(estimated_threshold);     /* Note: the exclusion of the LL band above is important, since LL        subband blocks do not generally have zero mean samples (far from        it) so that an approximately uniform block can yield distortion        which varies in an unpredictable manner with the number of coded        bit-planes.  These unpredictable variations can lead to a large        number of consecutive coding passes not lying on the convex hull        of the R-D curve -- a condition which would cause the coder        to quit prematurely if an estimated slope threshold were given. */  /* Allocate space on the stack for a number of largish quantities.  These     could be placed elsewhere. */  double pass_wmse_changes[MAX_POSSIBLE_PASSES];  mq_encoder pass_encoders[MAX_POSSIBLE_PASSES];  // Get dimensions.  int num_cols = block->size.x;  int num_rows = block->size.y;  int num_stripes = (num_rows+3)>>2;  int num_samples = (num_stripes<<2)*num_cols;  int context_row_gap = num_cols + EXTRA_ENCODE_CWORDS;  int num_context_words = (num_stripes+2)*context_row_gap+1;    // Prepare enough storage.  assert(block->max_samples >= num_samples);  if (block->max_contexts < num_context_words)    block->set_max_contexts((num_context_words > 1600)?num_context_words:1600);  kdu_int32 *samples = block->sample_buffer;  kdu_int32 *context_words = block->context_buffer + context_row_gap + 1;  // Determine the actual number of passes which we can accomodate.  if (block->num_passes > ((31-block->missing_msbs)*3-2))    block->num_passes = (31-block->missing_msbs)*3-2;  // Make sure we have sufficient resources to process this number of passes  if (block->max_passes < block->num_passes)    block->set_max_passes(block->num_passes+10,false); // Allocate a few extra  // Timing loop starts here.  int cpu_counter = block->start_timing();  do {      // Initialize contexts, marking OOB (Out Of Bounds) locations      memset(context_words-1,0,(size_t)((num_stripes*context_row_gap+1)<<2));      if (num_rows & 3)        {          kdu_int32 oob_marker;          if ((num_rows & 3) == 1) // Last 3 rows of last stripe unoccupied            oob_marker = (OOB_MARKER<<3) | (OOB_MARKER<<6) | (OOB_MARKER<<9);          else if ((num_rows & 3) == 2) // Last 2 rows of last stripe unused            oob_marker = (OOB_MARKER << 6) | (OOB_MARKER << 9);          else            oob_marker = (OOB_MARKER << 9);          kdu_int32 *cp = context_words + (num_stripes-1)*context_row_gap;          for (int k=num_cols; k > 0; k--)            *(cp++) = oob_marker;        }      if (context_row_gap > num_cols)        { // Initialize the extra context words between lines to OOB          kdu_int32 oob_marker =            OOB_MARKER | (OOB_MARKER<<3) | (OOB_MARKER<<6) | (OOB_MARKER<<9);          assert(context_row_gap >= (num_cols+3));          kdu_int32 *cp = context_words + num_cols;          for (int k=num_stripes; k > 0; k--, cp+=context_row_gap)            cp[0] = cp[1] = cp[2] = oob_marker; // Need 3 OOB words after line        }      double pass_wmse_scale = msb_wmse / ((double)(1<<16)) / ((double)(1<<16));      for (int i=block->missing_msbs; i > 0; i--)        pass_wmse_scale *= 0.25;      int p_max = 30 - block->missing_msbs; // Index of most significant plane      int p = p_max; // Bit-plane counter      int z = 0; // Coding pass index      int k=2; // Coding pass category; start with cleanup pass      int segment_passes = 0; // Num coding passes in current codeword segment.      kdu_byte *seg_buf = block->byte_buffer; // Start of current segment      int segment_bytes = 0; // Bytes consumed so far by this codeword segment      int first_unsized_z = 0; // First pass whose length is not yet known      int available_bytes = block->max_bytes; // For current & future segments      bool bypass = false;      bool causal = (block->modes & Cmodes_CAUSAL) != 0;      bool optimize = !(block->modes & Cmodes_ERTERM);      for (; z < block->num_passes; z++, k++)        {          if (k == 3)            { // Move on to next bit-plane.              k=0; p--;              pass_wmse_scale *= 0.25;            }          // See if we need to augment byte buffer resources to safely continue          if ((available_bytes-segment_bytes) < 4096)            { // We could build a much more thorough test for sufficiency.              assert(available_bytes >= segment_bytes); // else already overrun              kdu_byte *old_handle = block->byte_buffer;              block->set_max_bytes(block->max_bytes+8192,true);              available_bytes += 8192;              kdu_byte *new_handle = block->byte_buffer;              for (int i=0; i < z; i++)                pass_encoders[i].augment_buffer(old_handle,new_handle);              seg_buf = new_handle + (seg_buf-old_handle);            }          // Either start a new codeword segment, or continue an earlier one.          if (segment_passes == 0)            { // Need to start a new codeword segment.              segment_passes = block->num_passes;              if (block->modes & Cmodes_BYPASS)                {                  if (z < 10)                    segment_passes = 10-z;                  else if (k == 2) // Cleanup pass.                    { segment_passes = 1; bypass = false; }                  else                    {                      segment_passes = 2;                      bypass = true;                    }                }              if (block->modes & Cmodes_RESTART)                segment_passes = 1;              if ((z+segment_passes) > block->num_passes)                segment_passes = block->num_passes - z;              pass_encoders[z].start(seg_buf,!bypass);            }          else            pass_encoders[z].continues(pass_encoders+z-1);          // Encoding steps for the pass          kdu_int32 distortion_change;          bool lossless_pass = reversible && ((31-p) == block->K_max_prime);          if ((z == 0) || (block->modes & Cmodes_RESET))            reset_states();          if ((k == 0) && !bypass)            distortion_change =              encode_sig_prop_pass(pass_encoders[z],                                   states,p,causal,block->orientation,                                   samples,context_words,                                   num_cols,num_stripes,context_row_gap,                                   lossless_pass);          else if (k == 0)            distortion_change =              encode_sig_prop_pass_raw(pass_encoders[z],                                       p,causal,samples,context_words,                                       num_cols,num_stripes,context_row_gap,                                       lossless_pass);          else if ((k == 1) && !bypass)            distortion_change =              encode_mag_ref_pass(pass_encoders[z],                                  states,p,causal,samples,context_words,                                  num_cols,num_stripes,context_row_gap,                                  lossless_pass);          else if (k == 1)            distortion_change =              encode_mag_ref_pass_raw(pass_encoders[z],                                      p,causal,samples,context_words,                                      num_cols,num_stripes,context_row_gap,                                      lossless_pass);          else            distortion_change =              encode_cleanup_pass(pass_encoders[z],                                  states,p,causal,block->orientation,                                  samples,context_words,                                  num_cols,num_stripes,context_row_gap,                                  lossless_pass);          pass_wmse_changes[z] = pass_wmse_scale * distortion_change;          if ((block->modes & Cmodes_SEGMARK) && (k==2))            {              kdu_int32 segmark = 0x0A;              pass_encoders[z].mq_encode_run(segmark>>2);              pass_encoders[z].mq_encode_run(segmark & 3);            }          // Update codeword segment status.          segment_passes--;          segment_bytes = pass_encoders[z].get_bytes_used();          if (segment_passes == 0)            {              kdu_byte *new_buf = pass_encoders[z].terminate(optimize);              available_bytes -= (new_buf - seg_buf);              seg_buf = new_buf;              segment_bytes = 0;            }          { // Incrementally determine and process truncation lengths            int t;            bool final;            for  (t=first_unsized_z; t <= z; t++)              {                block->pass_lengths[t] =                  pass_encoders[t].get_incremental_length(final);                if (final)                  { assert(first_unsized_z == t); first_unsized_z++; }              }          }          if (estimated_slope_threshold > 0.0)            { // See if we can finish up early to save time and memory.              int t;              for (t=z; (t >= 0) && (t > (z-3)); t--)                {                  int delta_L = 0;                  double delta_D = 0.0;                  int u = 0;                  for (u=t; u >= 0; u--)                    {                      delta_L += block->pass_lengths[u];                      delta_D += pass_wmse_changes[u];                      if ((estimated_slope_threshold * delta_L) > delta_D)                        break;                    }                  if (u < 0)                    break;                }              if (t <= (z-3))                {                  block->num_passes = z+1; // No point in coding more passes.                  if (segment_passes > 0)                    { // Need to terminate the segment                      pass_encoders[z].terminate(optimize);                      for (t=first_unsized_z; t <= z; t++)                        {                          bool final;                          block->pass_lengths[t] =                          pass_encoders[t].get_incremental_length(final);                          assert(final);                        }                      first_unsized_z = t;                      segment_passes = 0;                    }                }            }          if (segment_passes == 0)            { // Finish cleaning up the completed codeword segment.              assert(first_unsized_z == (z+1));              pass_encoders[z].finish();            }        }      assert(segment_passes == 0);      assert(first_unsized_z == block->num_passes);      if (msb_wmse > 0.0)        { /* Form the convex hull set.  We could have done most of the work             incrementally as the lengths became available -- see above.             However, there is little value to this in the present             implementation.  A hardware implementation may prefer the             incremental calculation approach for all quantities, so that             slopes and lengths can be dispatched in a covnenient interleaved             fashion to memory as they become available. */          find_convex_hull(block->pass_lengths,pass_wmse_changes,                           block->pass_slopes,block->num_passes);          if (reversible && ((31-p) == block->K_max_prime))            { /* Must force last coding pass onto convex hull.  Otherwise, a                 decompressor using something other than the mid-point rounding                 rule can fail to achieve lossless decompression. */              z = block->num_passes-1;              if (block->pass_slopes[z] == 0)                block->pass_slopes[z] = 1; /* Works because                      `find_convex_hull_slopes' never generates slopes of 1. */            }        }    } while ((--cpu_counter) > 0);  block->finish_timing();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -