📄 jp2.cpp
字号:
void jp2_channels::set_premult_mapping(int colour_idx, int codestream_component, int palette_component){ assert((state != NULL) && (colour_idx >= 0) && (colour_idx < state->num_colours)); if (palette_component < 0) palette_component = -1; // Standardize to allow comparisons in `finalize' colour_idx += 6; state->channel_functions[colour_idx].source_component = codestream_component; state->channel_functions[colour_idx].palette_component = palette_component;}/*****************************************************************************//* jp2_channels::get_num_colours *//*****************************************************************************/int jp2_channels::get_num_colours(){ assert(state != NULL); return state->num_colours;}/*****************************************************************************//* jp2_channels::get_colour_mapping *//*****************************************************************************/bool jp2_channels::get_colour_mapping(int colour_idx, int &codestream_component, int &palette_component){ assert((state != NULL) && (colour_idx >= 0) && (colour_idx < state->num_colours)); if (state->channel_functions[colour_idx].source_component < 0) return false; codestream_component = state->channel_functions[colour_idx].source_component; palette_component = state->channel_functions[colour_idx].palette_component; return true;}/*****************************************************************************//* jp2_channels::get_opacity_mapping *//*****************************************************************************/bool jp2_channels::get_opacity_mapping(int colour_idx, int &codestream_component, int &palette_component){ assert((state != NULL) && (colour_idx >= 0) && (colour_idx < state->num_colours)); colour_idx += 3; if (state->channel_functions[colour_idx].source_component < 0) return false; codestream_component = state->channel_functions[colour_idx].source_component; palette_component = state->channel_functions[colour_idx].palette_component; return true;}/*****************************************************************************//* jp2_channels::get_premult_mapping *//*****************************************************************************/bool jp2_channels::get_premult_mapping(int colour_idx, int &codestream_component, int &palette_component){ assert((state != NULL) && (colour_idx >= 0) && (colour_idx < state->num_colours)); colour_idx += 6; if (state->channel_functions[colour_idx].source_component < 0) return false; codestream_component = state->channel_functions[colour_idx].source_component; palette_component = state->channel_functions[colour_idx].palette_component; return true;}/* ========================================================================= *//* j2_icc_profile *//* ========================================================================= *//*****************************************************************************//* j2_icc_profile::init (profile buf) *//*****************************************************************************/void j2_icc_profile::init(kdu_byte *profile_buf, bool donate_buffer){ kdu_uint32 val32; buffer = profile_buf; num_buffer_bytes = 4; read(val32,0); num_buffer_bytes = (int) val32; if (!donate_buffer) buffer = NULL; // Just in case we get destroyed thru an exception catcher if (num_buffer_bytes < 132) { kdu_error e; e << "Embedded ICC profile for JP2 file does not have a " "complete header."; } // Copy the buffer. if (!donate_buffer) { buffer = new kdu_byte[num_buffer_bytes]; memcpy(buffer,profile_buf,(size_t) num_buffer_bytes); } // Check the profile and locate the relevant tags, recording their locations // and lengths in the relevant member arrays. read(val32,12); // Get profile/device class signature. if (val32 != icc_input_device) { kdu_error e; e << "Embedded ICC profile for JP2 file must contain " "an input device profile (as opposed to a display profile, output " "profile, link profile, etc.)."; } read(val32,16); if (val32 == icc_gray_data) num_colours = 1; else num_colours = 3; read(val32,128); num_tags = (int) val32; int t; for (t=0; t < 3; t++) trc_offsets[t] = colorant_offsets[t] = 0; for (t=0; t < num_tags; t++) { kdu_uint32 signature, offset, length; if (!(read(signature,12*t+132) && read(offset,12*t+136) && read(length,12*t+140))) { kdu_error e; e << "Embedded ICC profile for JP2 file appears to " "have been truncated!"; } if (signature == icc_gray_trc) trc_offsets[0] = get_curve_data_offset(offset,length); else if (signature == icc_red_trc) trc_offsets[0] = get_curve_data_offset(offset,length); else if (signature == icc_green_trc) trc_offsets[1] = get_curve_data_offset(offset,length); else if (signature == icc_blue_trc) trc_offsets[2] = get_curve_data_offset(offset,length); else if (signature == icc_red_colorant) colorant_offsets[0] = get_xyz_data_offset(offset,length); else if (signature == icc_green_colorant) colorant_offsets[1] = get_xyz_data_offset(offset,length); else if (signature == icc_blue_colorant) colorant_offsets[2] = get_xyz_data_offset(offset,length); } for (t=0; t < num_colours; t++) if (trc_offsets[t] == 0) { kdu_error e; e << "Embedded ICC profile for JP2 file does not contain " "a complete set of tone reproduction curves!"; } if (num_colours == 3) for (t=0; t < 3; t++) if (colorant_offsets[t] == 0) { kdu_error e; e << "Embedded ICC profile for JP2 file does not " "contain a complete set of primary colorant specifications."; }}/*****************************************************************************//* j2_icc_profile::get_lut *//*****************************************************************************/void j2_icc_profile::get_lut(int channel_idx, float lut[], int index_bits){ kdu_uint32 val32; kdu_uint16 val16; assert((channel_idx >= 0) && (channel_idx < num_colours)); int offset = trc_offsets[channel_idx]; assert(offset > 128); int p, num_points; read(val32,offset); num_points = val32; offset += 4; // Get offset to first data point. int n, lut_entries = 1<<index_bits; if (num_points == 0) { // Curve is straight line from 0 to 1. float delta = 1.0F / ((float)(lut_entries-1)); for (n=0; n < lut_entries; n++) lut[n] = n*delta; } else if (num_points == 1) { // Curve is a pure power law. read(val16,offset); offset += 2; float exponent = ((float) val16) / 256.0F; float delta = 1.0F / ((float)(lut_entries-1)); for (n=0; n < lut_entries; n++) lut[n] = (float) pow(n*delta,exponent); } else { float lut_delta = ((float)(num_points-1)) / ((float)(lut_entries-1)); // Holds the separation between lut entries, relative to that // between curve data points. float lut_pos = 0.0F; read(val16,offset); offset += 2; float last_val = ((float) val16) / ((float)((1<<16)-1)); read(val16,offset); offset += 2; float next_val = ((float) val16) / ((float)((1<<16)-1)); for (p=1, n=0; n < lut_entries; n++, lut_pos += lut_delta) { while (lut_pos > 1.0F) { // Need to advance points. last_val = next_val; lut_pos -= 1.0F; p++; if (p < num_points) { read(val16,offset); offset += 2; next_val = ((float) val16) / ((float)((1<<16)-1)); } } lut[n] = next_val*lut_pos + last_val*(1.0F-lut_pos); } } assert ((offset-trc_offsets[channel_idx]) == (2*num_points+4));}/*****************************************************************************//* j2_icc_profile::get_matrix *//*****************************************************************************/void j2_icc_profile::get_matrix(float matrix3x3[]){ assert(num_colours == 3); for (int c=0; c < 3; c++) { int offset = colorant_offsets[c]; assert(offset > 128); for (int t=0; t < 3; t++) { kdu_uint32 uval; read(uval,offset); offset += 4; kdu_int32 sval = (kdu_int32) uval; matrix3x3[c+3*t] = ((float) sval) / ((float)(1<<16)); } }}/*****************************************************************************//* j2_icc_profile::get_curve_data_offset *//*****************************************************************************/int j2_icc_profile::get_curve_data_offset(int tag_offset, int tag_length){ if ((tag_length+tag_offset) > num_buffer_bytes) { kdu_error e; e << "Illegal tag offset or length value supplied in " "the JP2 embedded icc profile."; } kdu_uint32 val32; read(val32,tag_offset); if ((val32 != icc_curve_type) || (tag_length < 12)) { kdu_error e; e << "Did not find a valid `curv' data type " "in the embedded ICC profile's tone reproduction curve tag."; } read(val32,tag_offset+4); read(val32,tag_offset+8); int num_points = (int) val32; if (tag_length != ((2*num_points)+12)) { kdu_error e; e << "The `curv' data type used to represent an embedded " "ICC profile's tone reproduction curve appears to have been truncated.";} return tag_offset+8;}/*****************************************************************************//* j2_icc_profile::get_xyz_data_offset *//*****************************************************************************/int j2_icc_profile::get_xyz_data_offset(int tag_offset, int tag_length){ if ((tag_length+tag_offset) > num_buffer_bytes) { kdu_error e; e << "Illegal tag offset or length value supplied in " "JP2 embedded icc profile."; } kdu_uint32 val32; read(val32,tag_offset); if ((val32 != icc_xyz_type) || (tag_length < 20)) { kdu_error e; e << "Did not find a valid `XYZ ' data type " "in the embedded ICC profile's colorant description tag."; } return tag_offset + 8;}/* ========================================================================= *//* j2_colour *//* ========================================================================= *//*****************************************************************************//* j2_colour::init (space) *//*****************************************************************************/void j2_colour::init(jp2_colour_space space){ if ((num_colours != 0) || (icc_profile != NULL)) { kdu_error e; e << "JP2 colour information may be initialized only once!"; } assert((space != JP2_iccLUM_SPACE) && (space != JP2_iccRGB_SPACE)); this->space = space; this->icc_profile = NULL; this->num_colours = (space == JP2_sLUM_SPACE)?1:3;}/*****************************************************************************//* j2_colour::init (icc) *//*****************************************************************************/void j2_colour::init(j2_icc_profile *profile){ if ((num_colours != 0) || (icc_profile != NULL)) { kdu_error e; e << "JP2 colour information may be initialized only once!"; } assert(profile != NULL); icc_profile = profile; num_colours = profile->get_num_colours(); space = (num_colours==1)?JP2_iccLUM_SPACE:JP2_iccRGB_SPACE;}/*****************************************************************************//* j2_colour::init (box) *//*****************************************************************************/void j2_colour::init(j2_input_box *colr){ if ((num_colours != 0) || (icc_profile != NULL)) { // Ignore all but the first colour box. colr->close(); return; } assert(colr->get_box_type() == j2_colour_box); kdu_byte meth, prec, approx; if (!(colr->read(meth) && colr->read(prec) && colr->read(approx) && (meth >= 1) && (meth <= 2))) { kdu_error e; e << "Malformed colour specification (colr) box found in " "JP2 file. Insufficient or illegal fields found in box."; } if (meth == 1) { // Enumerated colour space method kdu_uint32 enum_cs; if (!(colr->read(enum_cs) && ((enum_cs == 16) || (enum_cs == 17) || (enum_cs == 22)))) { kdu_error e; e << "Illegal enumerated colour space found in JP2 " "colour specification (colr) box. Allowed values are 16, 17 and " "22, corresponding to sRGB, sLUM and sYCC, respectively."; } if (enum_cs == 16) { space = JP2_sRGB_SPACE; num_colours = 3; } else if (enum_cs == 17) { space = JP2_sLUM_SPACE; num_colours = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -