📄 region_decompressor.cpp
字号:
render_dims.pos = min; render_dims.size = lim - min; kdu_coords tmp_sampling = ref_comp->sampling; tmp_sampling.x<<=1; tmp_sampling.y<<=1; // Measure offsets in half pels kdu_coords ref_offset; codestream.get_registration(ref_comp->comp_idx,tmp_sampling,ref_offset); ref_offset.x -= 1-(ref_comp->sampling.x&1); // Even sub-sampling factors yield ref_offset.y -= 1-(ref_comp->sampling.y&1); // sample positions effectively // displaced to the right (or down) by half a pel for (c=0; (c < 6) && (components[c].comp_idx >= 0); c++) { kdr_component *comp = components + c; tmp_sampling = comp->sampling; tmp_sampling.x<<=1; tmp_sampling.y<<=1; // Measure offsets in half pels kdu_coords offset; codestream.get_registration(comp->comp_idx,tmp_sampling,offset); offset -= ref_offset; // Measure offsets relative to reference component comp->interp.x = comp->dims.pos.x * comp->sampling.x - render_dims.pos.x + 1 + ((comp->sampling.x+offset.x)>>1); comp->interp.y = comp->dims.pos.y * comp->sampling.y - render_dims.pos.y + 1 + ((comp->sampling.y+offset.y)>>1); if ((c < 3) && use_ycc && ((comp->interp != components[0].interp) || (comp->sampling != components[0].sampling))) { kdu_error e; e << "The code-stream incorrectly identifies the use " "of a colour transform when the components have different " "sub-sampling or alignment properties."; } } // Pre-create channel line buffers. for (c=0; c < num_channels; c++) channels[c].line.pre_create(&allocator,render_dims.size.x,false,true); // Perform final resource allocation allocator.finalize(); for (c=0; (c < 6) && (components[c].comp_idx >= 0); c++) components[c].line.create(); for (c=0; c < num_channels; c++) channels[c].line.create();}/******************************************************************************//* kdr_region_decompressor::close_tile *//******************************************************************************/void kdr_region_decompressor::close_tile(){ int c; assert(tile_open); tile_open = false; current_tile.close(); for (c=0; c < 6; c++) { kdr_component *comp = components + c; if (comp->engine.exists()) comp->engine.destroy(); comp->line.destroy(); // Works even if it was never pre-created } for (c=0; c < num_channels; c++) channels[c].line.destroy(); allocator.restart(); // Get ready to use the allocator again in the next tile}/******************************************************************************//* kdr_region_decompressor::finish *//******************************************************************************/bool kdr_region_decompressor::finish(){ bool success; int c; success = !codestream_failure; if (success && tile_open) { try { current_tile.close(); } catch (int) // `kdu_error' can throw this exception from deep inside core { success = false; } } tile_open = false; codestream_failure = false; // Cleanup any left over resources. for (c=0; c < 6; c++) { kdr_component *comp = components + c; if (comp->engine.exists()) comp->engine.destroy(); comp->line.destroy(); } for (c=0; c < num_channels; c++) { channels[c].line.destroy(); channels[c].lut = NULL; } codestream = kdu_codestream(); // Invalidate the internal pointer for safety allocator.restart(); // Get ready to use the allocation object again. return success;}/******************************************************************************//* kdr_region_decompressor::process *//******************************************************************************/bool kdr_region_decompressor::process(kdu_byte *buffer, int buffer_row_gap, kdu_dims buffer_region, kdu_dims &incomplete_region, int suggested_increment, kdu_dims &new_region){ new_region.size = kdu_coords(0,0); // In case we decompress nothing if (codestream_failure || !incomplete_region) return false; assert(incomplete_region == (incomplete_region & buffer_region)); try { // Protect, in case a fatal error is generated by the decompressor if (!tile_open) open_tile(); kdu_dims incomplete_tile_region = render_dims & incomplete_region; if (!incomplete_tile_region) { // No intersection between tile and incomplete region. if (next_tile_idx.x == valid_tiles.pos.x) { // This is the last tile on the current row of tiles. int y = render_dims.pos.y + render_dims.size.y; if (y > incomplete_region.pos.y) { // Incomplete region must have shrunk in the meantime. y -= incomplete_region.pos.y; if (y > incomplete_region.size.y) y = incomplete_region.size.y; incomplete_region.pos.y += y; incomplete_region.size.y -= y; } } close_tile(); return true; // Let the caller get back to us for more tile processing } bool last_tile_in_row = // Advance incomplete region only when this true ((incomplete_tile_region.pos.x+incomplete_tile_region.size.x) == (incomplete_region.pos.x+incomplete_region.size.x)); // Determine an appropriate number of lines to process before returning. // Note that some or all of these lines might not intersect with the // incomplete region. assert(suggested_increment > 0); suggested_increment *= channels[0].source->sampling.x; suggested_increment *= channels[0].source->sampling.y; int new_lines = ceil_ratio(suggested_increment,render_dims.size.x); int y_lim = incomplete_tile_region.pos.y + incomplete_tile_region.size.y; if ((new_lines+render_dims.pos.y) > y_lim) new_lines = y_lim - render_dims.pos.y; assert(new_lines > 0); // Determine and process new region. new_region = incomplete_tile_region; new_region.size.y = 0; buffer += ((incomplete_tile_region.pos.y-buffer_region.pos.y)*buffer_row_gap + (incomplete_tile_region.pos.x-buffer_region.pos.x))*3; for (; new_lines > 0; new_lines--, render_dims.pos.y++, render_dims.size.y--) { int c; // Decompress new image component lines as necessary. for (c=0; (c < 6) && (components[c].comp_idx >= 0); c++) { kdr_component *comp = components + c; if (comp->dims.size.y <= 0) { // No more lines available. if (!comp->line_buf_valid) // Tile has no lines of this reset_line_buf(comp->line); // component at all. Set to 0's continue; } do { if (comp->interp.y <= 0) { comp->interp.y += comp->sampling.y; comp->line_buf_valid = false; } if (!comp->line_buf_valid) { comp->engine.pull(comp->line,true); comp->dims.size.y--; comp->dims.pos.y++; } } while ((comp->interp.y <= 0) && (comp->dims.size.y > 0)); } // Finish processing of component lines which have been invalidated if (use_ycc && !components[0].line_buf_valid) { assert((!components[1].line_buf_valid) && (!components[2].line_buf_valid)); kdu_convert_ycc_to_rgb(components[0].line,components[1].line, components[2].line); } for (c=0; (c < 6) && (components[c].comp_idx >= 0); c++) { kdr_component *comp = components + c; if (!comp->line_buf_valid) { comp->line_buf_valid = true; if (comp->palette_bits > 0) convert_samples_to_palette_indices(comp->line, comp->bit_depth,comp->is_signed,comp->palette_bits); } comp->interp.y--; // Decrement interpolation counter. } // Now process a new set of channel lines, as required if (render_dims.pos.y == incomplete_tile_region.pos.y) { // This line has non-empty intersection with the incomplete region int skip_cols = incomplete_tile_region.pos.x-render_dims.pos.x; int num_cols = incomplete_tile_region.size.x; for (c=0; c < num_channels; c++) { kdr_channel *channel = channels + c; kdr_component *comp = channel->source; if (channel->lut != NULL) interpolate_and_map(comp->line,comp->interp.x, comp->sampling.x,channel->lut, channel->line,skip_cols,num_cols); else interpolate_and_convert(comp->line,comp->interp.x, comp->sampling.x,comp->bit_depth, channel->line,skip_cols,num_cols); } if (space == JP2_sYCC_SPACE) kdu_convert_ycc_to_rgb(channels[0].line,channels[1].line, channels[2].line,num_cols); else if (space == JP2_iccLUM_SPACE) colour.convert_icc_to_slum(channels[0].line,num_cols); else if (space == JP2_iccRGB_SPACE) colour.convert_icc_to_srgb(channels[0].line,channels[1].line, channels[2].line,num_cols); for (c=0; c < num_channels; c++) transfer_fixed_point(channels[c].line,buffer+2-c,num_cols); if (num_channels == 1) { // Above code only transferred the red channel. kdu_byte *bp = buffer; for (c=num_cols; c > 0; c--, bp+=3) bp[0] = bp[1] = bp[2]; } buffer += buffer_row_gap*3; incomplete_tile_region.pos.y++; incomplete_tile_region.size.y--; new_region.size.y++; // Transferred data region grows by one row. if (last_tile_in_row) { assert(render_dims.pos.y == incomplete_region.pos.y); incomplete_region.pos.y++; incomplete_region.size.y--; } } } if (!incomplete_tile_region) { // Done all the processing we need for this tile. close_tile(); return true; } } catch (int) { codestream_failure = true; return false; } return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -