📄 compressed.cpp
字号:
if (active->num_tparts == 0) active->num_tparts = sot_num_tparts; else if (active->num_tparts != sot_num_tparts) { kdu_error e; e << "The number of tile-parts for tile number " << sot_tnum << " is identified by different non-zero values " "in different SOT markers for the tile!"; } } // Translate tile-part header markers. kdu_params *root = codestream->siz; kd_pp_markers *ppt_markers = NULL; do { if (!codestream->marker->read()) { if (!codestream->in->failed()) { kdu_error e; e << "Found non-marker code while looking " "for SOD marker to terminate a tile-part header. " "Chances are that a marker segment length field is " "incorrect!"; } return false; } if (codestream->marker->get_code() == KDU_PPT) { if (ppt_markers == NULL) ppt_markers = new kd_pp_markers; ppt_markers->add_marker(*(codestream->marker)); } else root->translate_marker_segment(codestream->marker->get_code(), codestream->marker->get_length(), codestream->marker->get_bytes(), sot_tnum,sot_tpart); } while (codestream->marker->get_code() != KDU_SOD); // Transfer packed packet header data. if (ppt_markers != NULL) { if (codestream->ppm_markers != NULL) { kdu_error e; e << "Use of both PPM and PPT marker segments " "is illegal!"; } if (active->packed_headers == NULL) active->packed_headers = new kd_pph_input(codestream->buf_server); ppt_markers->transfer_tpart(active->packed_headers); delete ppt_markers; } else if (codestream->ppm_markers != NULL) { if (active->packed_headers == NULL) active->packed_headers = new kd_pph_input(codestream->buf_server); codestream->ppm_markers->transfer_tpart(active->packed_headers); } // Make `active' the active tile. active->next_tpart++; codestream->active_tile = active; codestream->num_tparts_used++; } if (active == KD_EXPIRED_TILE) { /* Tile has been discarded. Skip to next SOT marker, discarding any PPM info which may be available for this tile-part. */ assert(sot_tpart_length != 0); int skip_bytes = sot_tpart_length - (codestream->marker->get_length()+4); if (codestream->ppm_markers != NULL) codestream->ppm_markers->ignore_tpart(); codestream->in->ignore(skip_bytes); codestream->marker->read(); if (codestream->marker->get_code() != KDU_SOT) { if (!codestream->in->failed()) { kdu_error e; e << "Corrupt SOT length field used to " "seek over a discarded tile-part."; } return false; } } } while (this != codestream->active_tile); return true;}/*****************************************************************************//* kd_tile::finished_reading *//*****************************************************************************/void kd_tile::finished_reading(){ if (!initialized) return; // Prevent calls here while trying to initialize a tile. if (this == codestream->active_tile) { // Need to discard unread data up to the next SOT marker. assert(!exhausted); assert(codestream->in != NULL); assert(codestream->marker->get_code() != KDU_SOT); while (codestream->marker->read(true,true)) if (codestream->marker->get_code() == KDU_SOT) break; codestream->active_tile = NULL; } if (exhausted) return; exhausted = true; if (closed) { // Should never happen if the codestream object is persistent. delete this; // Self efacing. return; } for (int c=0; c < num_components; c++) { kd_tile_comp *tc = comps + c; for (int r=0; r <= tc->dwt_levels; r++) { kd_resolution *res = tc->resolutions + r; int num_precincts = res->precinct_indices.area(); for (int p=0; p < num_precincts; p++) { kd_precinct *precinct = res->precinct_refs[p]; if ((precinct == NULL) || (precinct == KD_EXPIRED_PRECINCT)) continue; if (precinct->num_outstanding_blocks == 0) delete precinct; } } }}/*****************************************************************************//* kd_tile::simulate_output *//*****************************************************************************/int kd_tile::simulate_output(int &header_bytes, int layer_idx, kdu_uint16 slope_threshold, bool finalize_layer, bool last_layer, int max_bytes, int *sloppy_bytes){ header_bytes = 0; if (layer_idx == 0) { // Include the cost of all tile-part headers. int new_bytes = 0; int try_tpart = 0; do { new_bytes = codestream->siz->generate_marker_segments(NULL,tnum,try_tpart); if ((new_bytes > 0) || (try_tpart == 0)) { new_bytes += 12; // Cost of SOT marker segment new_bytes += 2; // Cost of SOD marker } header_bytes += new_bytes; try_tpart++; } while (new_bytes != 0); } if (last_layer && (num_layers > (layer_idx+1))) { // Add in cost of empty packets header_bytes += (num_layers-1-layer_idx)*total_precincts*((use_eph)?3:1); } int total_bytes = header_bytes; if (layer_idx >= num_layers) return total_bytes; for (int c=0; c < num_components; c++) { kd_tile_comp *tc = comps + c; for (int r=0; r <= tc->dwt_levels; r++) { kd_resolution *res = tc->resolutions + r; int p=0; for (int py=0; py < res->precinct_indices.size.y; py++) for (int px=0; px < res->precinct_indices.size.x; px++, p++) { kd_precinct *precinct = res->precinct_refs[p]; assert(precinct != KD_EXPIRED_PRECINCT); if (precinct == NULL) { // Could be a precinct without any code-blocks. precinct = new kd_precinct(res,kdu_coords(px,py)); assert(precinct == res->precinct_refs[p]); if (precinct->num_outstanding_blocks != 0) { kdu_error e; e << "You may not currently flush " "compressed code-stream data without completing the " "compression of all tiles."; } } int packet_header_bytes = 0, packet_bytes = 0; if (sloppy_bytes != NULL) { assert(finalize_layer && last_layer && (*sloppy_bytes >= 0)); assert(slope_threshold < 0xFFFF); packet_bytes = precinct->simulate_packet(packet_header_bytes,layer_idx, slope_threshold+1,false,true); int packet_max_bytes = packet_bytes + *sloppy_bytes; assert((packet_max_bytes+total_bytes) <= max_bytes); // Otherwise, you are not driving this function correctly int packet_bytes = precinct->simulate_packet(packet_header_bytes,layer_idx, slope_threshold,true,true, packet_max_bytes,true); assert(packet_bytes <= packet_max_bytes); *sloppy_bytes = packet_max_bytes - packet_bytes; } else packet_bytes = precinct->simulate_packet(packet_header_bytes,layer_idx, slope_threshold,finalize_layer, last_layer,max_bytes-total_bytes); total_bytes += packet_bytes; header_bytes += packet_header_bytes; if (total_bytes > max_bytes) { assert(!finalize_layer); // Otherwise, you are not driving this function correctly return total_bytes; } } } } return total_bytes;}/*****************************************************************************//* kd_tile::generate_tile_part *//*****************************************************************************/int kd_tile::generate_tile_part(int max_layers, kdu_uint16 slope_thresholds[]){ if (num_transferred_packets == total_packets) return 0; if (next_tpart >= 255) {kdu_error e; e << "Too many tile-parts for tile " << this->tnum << ". " "No tile may have more than 255 parts."; } next_tpart++; // Makes sure packet sequencer does the right thing. int tpart_bytes = 12 + 2 + codestream->siz->generate_marker_segments(NULL,tnum,next_tpart-1); // Simulate packet sequencing to determine the tile-part length kd_precinct *precinct; sequencer->save_state(); while ((precinct = sequencer->next_in_sequence()) != NULL) { int layer_idx = precinct->next_layer_idx; assert (layer_idx < precinct->resolution->tile_comp->tile->num_layers); if ((precinct->packet_bytes == NULL) || (precinct->packet_bytes[layer_idx] == 0)) { kdu_error e; e << "Attempting to generate tile-part data without " "first determining packet lengths. This may be a consequence of " "incomplete simulation of the packet construction process."; } tpart_bytes += precinct->packet_bytes[layer_idx]; precinct->next_layer_idx++; // This will be restored later. num_transferred_packets++; } // Now generate the tile-part header kd_compressed_output *out = codestream->out; int start_bytes = out->get_bytes_written(); out->put(KDU_SOT); out->put((kdu_uint16) 10); out->put((kdu_uint16) tnum); out->put((kdu_uint32) tpart_bytes); out->put((kdu_byte)(next_tpart-1)); if (num_transferred_packets == total_packets) out->put((kdu_byte) next_tpart); // This is the last tile-part else out->put((kdu_byte) 0); // We don't know how many tile-parts might follow codestream->siz->generate_marker_segments(out,tnum,next_tpart-1); out->put(KDU_SOD); // Finally, output the packet data sequencer->restore_state(); while ((precinct = sequencer->next_in_sequence()) != NULL) { int layer_idx = precinct->next_layer_idx; if (layer_idx < max_layers) precinct->write_packet(slope_thresholds[layer_idx]); else precinct->write_packet(0,true); // Write an empty packet. } // Finish up int check_tpart_bytes = out->get_bytes_written() - start_bytes; assert(tpart_bytes == check_tpart_bytes); codestream->num_tparts_used++; return tpart_bytes;}/* ========================================================================= *//* kdu_tile *//* ========================================================================= *//*****************************************************************************//* kdu_tile::close *//*****************************************************************************/void kdu_tile::close(){ if (state->is_open) state->codestream->num_open_tiles--; else assert(0); state->is_open = false; assert(!state->closed); if (!state->codestream->persistent) { state->closed = true; if (state->exhausted) delete state; } state = NULL; // Renders the interface impotent.}/*****************************************************************************//* kdu_tile::get_tnum *//*****************************************************************************/int kdu_tile::get_tnum(){ return state->tnum;}/*****************************************************************************//* kdu_tile::get_ycc *//*****************************************************************************/bool kdu_tile::get_ycc(){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -