📄 kdu_compress.cpp
字号:
kdc_component_flow_control *comp = components + n; if (comp->ratio_counter < 0) { comp->ratio_counter += comp->vert_subsampling; assert(comp->ratio_counter >= 0); assert(comp->remaining_lines > 0); comp->remaining_lines--; comp->compressor.push(comp->line,true); } }}/*****************************************************************************//* kdc_flow_control::advance_tile *//*****************************************************************************/bool kdc_flow_control::advance_tile(){ int n; if (!tile) return false; for (n=0; n < num_components; n++) { kdc_component_flow_control *comp = components + n; assert(comp->remaining_lines == 0); assert(comp->compressor.exists()); comp->compressor.destroy(); comp->line.destroy(); } tile.close(); tile = kdu_tile(NULL); tile_idx.y++; if ((tile_idx.y-valid_tile_indices.pos.y) == valid_tile_indices.size.y) return false; // Prepare for processing the next vertical tile. tile = codestream.open_tile(tile_idx); for (n=0; n < num_components; n++) { kdc_component_flow_control *comp = components + n; kdu_tile_comp tc = tile.access_component(n); comp->reversible = tc.get_reversible(); kdu_resolution res = tc.access_resolution(); kdu_dims dims; res.get_dims(dims); comp->allocator.restart(); bool use_shorts = (tc.get_bit_depth(true)>16)?false:(comp->allow_shorts); comp->line.pre_create(&(comp->allocator),dims.size.x, comp->reversible,use_shorts); kdu_roi_node *roi_node = NULL; if (roi_image != NULL) roi_node = roi_image->acquire_node(n,dims); if (res.which() == 0) comp->compressor = kdu_encoder(res.access_subband(LL_BAND),&(comp->allocator), use_shorts,1.0F,roi_node); else comp->compressor = kdu_analysis(res,&(comp->allocator),use_shorts,1.0F,roi_node); comp->allocator.finalize(); comp->line.create(); comp->ratio_counter = 0; comp->remaining_lines = dims.size.y; } use_ycc = tile.get_ycc(); if (use_ycc) assert((num_components >= 3) && (components[0].reversible == components[1].reversible) && (components[1].reversible == components[2].reversible)); return true;}/* ========================================================================= *//* External Functions *//* ========================================================================= *//*****************************************************************************//* main *//*****************************************************************************/int main(int argc, char *argv[]){ kdu_customize_warnings(&std::cout); kdu_customize_errors(&std::cerr); kdu_args args(argc,argv,"-s"); // Collect simple arguments. bool transpose, vflip, hflip; bool allow_rate_prediction, allow_shorts, mem, quiet, no_weights, no_palette; int cpu_iterations; char *ofname; std::ostream *record_stream; kdc_file_binding *inputs = // 将参数从args中提取出来,依次赋给ofname等,输入文件则赋给input parse_simple_args(args,ofname,record_stream,transpose,vflip,hflip, allow_rate_prediction,allow_shorts,no_weights, no_palette,cpu_iterations,mem,quiet); // Create appropriate output file. kdu_compressed_target *output = NULL; kdu_simple_file_target file_out; jp2_target jp2_out; if (check_jp2_suffix(ofname)) // 如果ofname后缀名为.jp2则返回True,否则返回False { output = &jp2_out; // 如果后缀名带有.jp2,则码流将被打包成JP2文件格式:前三个3个源图像分量将被视为RGB三通道,其它的则视为未定义的辅助分量。 jp2_out.open(ofname); // 如果输入文件定义了一个颜色调色板,它将被通过JP2文件格式保存,采样将被JP2读器正确反调色出来。 } // 如果这里小于3分量,第一个分量将被用RGB gamma视为高度分量,任何其它分量将被视为未定义分量。 else { output = &file_out; file_out.open(ofname); } // Collects any parameters required for raw input.
/************************************************************************************************************************************/
/* kdu_params 抽象类,必须被完全的参数类继承。每一个参数类表达了由一种单一码流分段标记具体表达的参数。参数对象可由三种途径产生: */
/* 1)描述了指定属性的字符串,比如由命定行输入的。2)从码流分段标记。3)由明确指定参数属性值。 */
/* 它可由两种方式序列化:1)写入字符串。2)写入码流分段标记。 */
/* 参数对象被收集进串。串从不同带、不用图像分量表达了相关码流分段标记。详细地说,每一个kdu_params对象通过3个坐标定义进串: */
/* 它的带索引;分量索引;实例索引。带索引从-1开始;分量索引从-1开始;实例索引从0开始。 */
/* 串首先被组织成带链,链中第一个对象其带索引必须是-1,将它定义为所有带的概要对象。这个对象被视为串头。 */
/* 每一个在这个首链中的对象用于表示跟带相关的所有分量对象的带头。这些带头对象的分量索引必须是-1,将它们定义为带中所有分量的概要对象*/
/* 一个带—分量链由每个带头和分量头建立起来,其实例索引为0。它带领了带—分量实例的链。 */
/************************************************************************************************************************************/
siz_params siz; char *string; for (string=args.get_first(); string != NULL; ) string = args.advance(siz.parse_string(string)); // Set up input image files. kdu_rgb8_palette palette; // To support paletized imagery. kdc_file_binding *iscan; int num_components; bool extra_flip=false; num_components = 0; for (iscan=inputs; iscan != NULL; iscan=iscan->next) { bool flip; iscan->first_comp_idx = num_components;
/***************************************************************************************************/
/* kdu_image_in构造器用指定的名字打开文件,它自动连系继承于kdu_image_in_base接口的正确的读文件类.*/
/* 文件中表示的第一个分量索引由next_comp_idx参数表达。返回后这个参数被更新用来反映新的总分量数。 */
/* 将这个总分量数写入'siz'对象的'Snum_component'属性是调用者的职责。
/* 如果新图像分量的维数能够从文件头中推算出来,则函数将相关维数设置进‘siz’对象中的‘Sdims’属性。*/
/* 类似的,如果比特深度或者图像采样有符号/无符号的特征可以从文件头(或文件类型)中推测出来的话,它们 */
/* 将被赋给‘siz’对象的‘Sprecision’和‘Ssigned’属性。否则,函数期待从‘siz’对象中提取这些属性,*/
/* 如果找不到的话便产生一个错误。 */
/* ‘vflip’参数被提供以支持图像的行被以bottom-up跟通常样式相反的图像格式。著名的BMP文件格式可能是*/
/* 最典型的bottom-up格式。返回之后,如果图像的行将被以bottom-up的样式提供,则'vflip'为真,这样压缩 */
/* 器将以反顺序写码流(这利用了JPEG2000的几何转换能力以避免将整个图像缓冲进内存和以top-dowm样式压缩)*/
/* 否则,函数返回时'vflip'被设为false。
/* ‘palette’参数可能是空,如果压缩文件格式支持颜色调色板信息的信号话。比如说,BMP文件可能包含调 */
/* 色数据。在这种情况下,对象的入口将被填写以反映调色被用于的图像分量的索引,伴随着调色信息本身。 */
/* 需要大于8比特索引的调色板应该被文件读器直接延展。如果‘palette’对象已经将它的'input_bits'属性设*/
/* 置为一个非零值,那么这个调色板已经在使用了,并且一个新的fe调色板不能为这个已存在的图像文件创建. */
/* 在这种情况下,或者如果没有调色板被提供,图像采样数据将被图像读器反调色,通常将提供一个一个全的颜*/
/* 色通道。
/************************************************************************/
iscan->reader = kdu_image_in(iscan->fname,&siz,num_components,flip, ((no_palette || !jp2_out)?NULL:(&palette))); iscan->num_components = num_components - iscan->first_comp_idx; if (iscan == inputs) extra_flip = flip; if (extra_flip != flip) { kdu_error e; e << "Cannot mix input file types which have different " "vertical ordering conventions (i.e., top-to-bottom and " "bottom-to-top)."; } } if (extra_flip) vflip = !vflip; siz.set(Scomponents,0,0,num_components); // Complete `siz' object. siz_params *siz_p = &siz; siz_p->finalize(); // Access func via v-table siz_params transformed_siz; // Use this one to construct code-stream. transformed_siz.copy_from(&siz,-1,-1,-1,0,0,transpose,false,false); if (jp2_out.exists()) set_jp2_attributes(jp2_out,&transformed_siz,palette,num_components,args); // Construct the `kdu_codestream' object and parse all remaining arguments. kdu_codestream codestream; codestream.create(&transformed_siz,output); for (string=args.get_first(); string != NULL; ) string = args.advance(codestream.access_siz()->parse_string(string)); if (jp2_out.exists()) set_jp2_coding_defaults(jp2_out,codestream.access_siz()); int num_layer_specs = 0;
/********************************************************************************************************/
/* 返回一个指向'num_specs'质量层比特target数组的指针。num_specs由命令行中rate或slopes的数量加上任何指 */
/* 定质量层数目的知识决定。在调用这个函数之前,必须将所有参数属性字符串分析进给予‘siz’的码流参数链中 */
/* 只要一个质量层的bit-rate没有设,返回的数组就是0。 */
/********************************************************************************************************/ int *layer_bytes = assign_layer_bytes(args,codestream.access_siz(),num_layer_specs);
/*******************************************************************************************************/
/* 返回一个指向'num_specs'slope阈值数组的指针,所有数组的值被设为0除非命令行参数包含一个清楚的对精确失 */
/* 真长度slope阈值的需求。 */
/*******************************************************************************************************/ kdu_uint16 *layer_thresholds = assign_layer_thresholds(args,num_layer_specs);
/********************************************************************************************************/
/* 如果被输入码流对象使用,该函数设置了将要从输入码流中读取的最大比特数。 */
/* 如果被输出码流对象使用,该函数为了增加估计参数使能内部机制,这些参数将被用于PCRD-opt比特分配算法, */
/* 这样块编码器将被给与反馈来在最小化编码数量中援助它。注意到,在'flush'成员函数中实际比特的分配和这里 */
/* 提供的值独立,尽管'max_bytes'被认为将等于在'flush'调用中提供的最大层比特数。 */
/* 1)比特控制预测策略依赖于对将被递增处理的图样采样的估计,所有图像分量共同在相同相对比特下处理。 */
/* 完全处理一个分量再处理下一个这是不合适的。 */
/* 2)如果图像处理的第一部分的卡压缩性与图像最后一部分的非常不同,那么预测策略可能不恰当的丢弃信息, */
/* 因此损害了压缩。尽管这种情况比较少见,但它可能是该类图像的一大问题,特别是在边缘部分包含空白区域 */
/* 的医疗图像。 */
/* 3)如果希望得到无损压缩,那么这个函数不应该被调用,不管我们提供的'max_bytes'值有多大。 */
/********************************************************************************************************/ if ((num_layer_specs > 0) && allow_rate_prediction &&
(layer_bytes[num_layer_specs-1] > 0))
codestream.set_max_bytes(layer_bytes[num_layer_specs-1]); if ((num_layer_specs > 0) && allow_rate_prediction && (layer_thresholds[num_layer_specs-1] > 0)) codestream.set_min_slope_threshold(layer_thresholds[num_layer_specs-1]); if ((num_layer_specs < 2) && !quiet) pretty_cout << "Note:\n\tIf you want quality scalability, you should " "generate multiple layers with `-rate' or by using " "the \"Clayers\" option.\n"; if ((num_components == 3) && (!no_weights)) set_default_colour_weights(codestream.access_siz(),quiet); codestream.access_siz()->finalize_all(); codestream.set_textualization(record_stream); if (cpu_iterations >= 0) codestream.collect_timing_stats(cpu_iterations); codestream.change_appearance(transpose,vflip,hflip); kdu_roi_image *roi_source = create_roi_source(codestream,args); if (args.show_unrecognized(pretty_cout) != 0) { kdu_error e; e << "There were unrecognized command line arguments!"; } // Now we are ready for sample data processing. int x_tnum;
/******************************************************************************************/
/* 返回跟当前感兴趣区域相应的带索引的范围(或者是全部的图像,如果没有感兴趣区域被指定) */
/* 感兴趣区域里第一个带的索引通过'indices.pos'返回。注意到如果通过'kdu_codestream::change */
/* _appearance'指定了几何变换,那么这些索引可能是负的。感兴趣区域里每一方向的带的数目通过 */
/* 'indices.size'返回。注意到这个带的索引是表面上索引,而不是实际码流带索引。它们不仅被主 */
/* 要感兴趣区域影响,还受几何变换标志的影响。 */
/******************************************************************************************/ kdu_dims tile_indices; codestream.get_valid_tiles(tile_indices); kdc_flow_control **tile_flows = new kdc_flow_control *[tile_indices.size.x]; for (x_tnum=0; x_tnum < tile_indices.size.x; x_tnum++) tile_flows[x_tnum] = new kdc_flow_control(inputs,codestream,x_tnum,allow_shorts,roi_source); bool done = false; while (!done) { while (!done) { // Process a row of tiles line by line. done = true; for (x_tnum=0; x_tnum < tile_indices.size.x; x_tnum++) { if (tile_flows[x_tnum]->advance_components()) { done = false; tile_flows[x_tnum]->process_components(); } } } for (x_tnum=0; x_tnum < tile_indices.size.x; x_tnum++) if (tile_flows[x_tnum]->advance_tile()) done = false; } int sample_bytes = 0; for (x_tnum=0; x_tnum < tile_indices.size.x; x_tnum++) { sampl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -