BOOL InWorldzJ2C::getMetadata(ImageBaseForKDU* base) { if (!base) { return FALSE; } if (!base->getData()) { base->mLastErrorMsg = "trying to get meta data without data!"; return FALSE; } // *FIX: kdu calls our callback function if there's an error, and // then bombs. To regain control, we throw an exception, and // catch it here. try { setupCodeStream(*base, FALSE, MODE_FAST); return TRUE; } catch (const char* msg) { if (msg) { base->mLastErrorMsg = msg; } return FALSE; } catch (...) { base->mLastErrorMsg = "Unknown J2C error"; return FALSE; } }
BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base) { // *FIX: kdu calls our callback function if there's an error, and // then bombs. To regain control, we throw an exception, and // catch it here. try { setupCodeStream(base, FALSE, MODE_FAST); return TRUE; } catch (const char* msg) { base.setLastError(ll_safe_string(msg)); return FALSE; } catch (...) { base.setLastError( "Unknown J2C error" ); return FALSE; } }
// Find the block boundary for each discard level in the input image. // We parse the input blocks and copy them in a temporary output stream. // For the moment, we do nothing more that parsing the raw list of blocks and outputing result. void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base) { // We need the number of levels in that image before starting. getMetadata(base); for (int discard_level = 0; discard_level < mLevels; discard_level++) { //std::cout << "Parsing discard level = " << discard_level << std::endl; // Create the input codestream object. setupCodeStream(base, TRUE, MODE_FAST); mCodeStreamp->apply_input_restrictions(0, 4, discard_level, 0, NULL); mCodeStreamp->set_max_bytes(KDU_LONG_MAX,true); siz_params *siz_in = mCodeStreamp->access_siz(); // Create the output codestream object. siz_params siz; siz.copy_from(siz_in,-1,-1,-1,0,discard_level,false,false,false); siz.set(Scomponents,0,0,mCodeStreamp->get_num_components()); U32 max_output_size = base.getWidth()*base.getHeight()*base.getComponents(); max_output_size = (max_output_size < 1000 ? 1000 : max_output_size); U8 *output_buffer = new U8[max_output_size]; U32 output_size = 0; // Address updated by LLKDUMemTarget to give the final compressed buffer size LLKDUMemTarget output(output_buffer, output_size, max_output_size); kdu_codestream codestream_out; codestream_out.create(&siz,&output); //codestream_out.share_buffering(*mCodeStreamp); siz_params *siz_out = codestream_out.access_siz(); siz_out->copy_from(siz_in,-1,-1,-1,0,discard_level,false,false,false); codestream_out.access_siz()->finalize_all(-1); // Set up rate control variables kdu_long max_bytes = KDU_LONG_MAX; kdu_params *cod = siz_out->access_cluster(COD_params); int total_layers; cod->get(Clayers,0,0,total_layers); kdu_long *layer_bytes = new kdu_long[total_layers]; int nel, non_empty_layers = 0; // Now ready to perform the transfer of compressed data between streams int flush_counter = INT_MAX; kdu_dims tile_indices_in; mCodeStreamp->get_valid_tiles(tile_indices_in); kdu_dims tile_indices_out; codestream_out.get_valid_tiles(tile_indices_out); assert((tile_indices_in.size.x == tile_indices_out.size.x) && (tile_indices_in.size.y == tile_indices_out.size.y)); int num_blocks=0; kdu_coords idx; //std::cout << "Parsing tiles : x = " << tile_indices_out.size.x << " to y = " << tile_indices_out.size.y << std::endl; for (idx.y=0; idx.y < tile_indices_out.size.y; idx.y++) { for (idx.x=0; idx.x < tile_indices_out.size.x; idx.x++) { kdu_tile tile_in = mCodeStreamp->open_tile(idx+tile_indices_in.pos); int tnum_in = tile_in.get_tnum(); int tnum_out = idx.x + idx.y*tile_indices_out.size.x; siz_out->copy_from(siz_in,tnum_in,tnum_out,0,0,discard_level,false,false,false); siz_out->finalize_all(tnum_out); // Note: do not open the output tile without first copying any tile-specific code-stream parameters kdu_tile tile_out = codestream_out.open_tile(idx+tile_indices_out.pos); assert(tnum_out == tile_out.get_tnum()); copy_tile(tile_in,tile_out,tnum_in,tnum_out,siz_in,siz_out,0,num_blocks); tile_in.close(); tile_out.close(); flush_counter--; if ((flush_counter <= 0) && codestream_out.ready_for_flush()) { flush_counter = INT_MAX; nel = codestream_out.trans_out(max_bytes,layer_bytes,total_layers); non_empty_layers = (nel > non_empty_layers)?nel:non_empty_layers; } } } // Generate the output code-stream if (codestream_out.ready_for_flush()) { nel = codestream_out.trans_out(max_bytes,layer_bytes,total_layers); non_empty_layers = (nel > non_empty_layers)?nel:non_empty_layers; } if (non_empty_layers > total_layers) non_empty_layers = total_layers; // Can happen if a tile has more layers // Print out stats std::cout << "Code stream parsing for discard level = " << discard_level << std::endl; std::cout << " Total compressed memory in = " << mCodeStreamp->get_compressed_data_memory() << " bytes" << std::endl; std::cout << " Total compressed memory out = " << codestream_out.get_compressed_data_memory() << " bytes" << std::endl; //std::cout << " Output contains " << total_layers << " quality layers" << std::endl; std::cout << " Transferred " << num_blocks << " code-blocks from in to out" << std::endl; //std::cout << " Read " << mCodeStreamp->get_num_tparts() << " tile-part(s) from a total of " << (int) tile_indices_in.area() << " tile(s)" << std::endl; std::cout << " Total bytes read = " << mCodeStreamp->get_total_bytes() << std::endl; //std::cout << " Wrote " << codestream_out.get_num_tparts() << " tile-part(s) in a total of " << (int) tile_indices_out.area() << " tile(s)" << std::endl; std::cout << " Total bytes written = " << codestream_out.get_total_bytes() << std::endl; std::cout << "-------------" << std::endl; // Clean-up cleanupCodeStream(); codestream_out.destroy(); delete[] output_buffer; } return; }
BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region) { base.resetLastError(); // *FIX: kdu calls our callback function if there's an error, and then bombs. // To regain control, we throw an exception, and catch it here. try { // Merov : Test!! DO NOT COMMIT!! //findDiscardLevelsBoundaries(base); base.updateRawDiscardLevel(); setupCodeStream(base, TRUE, mode); mRawImagep = &raw_image; mCodeStreamp->change_appearance(false, true, false); // Apply loading discard level and cropping if required kdu_dims* region_kdu = NULL; if (region != NULL) { region_kdu = new kdu_dims; region_kdu->pos.x = region[0]; region_kdu->pos.y = region[1]; region_kdu->size.x = region[2] - region[0]; region_kdu->size.y = region[3] - region[1]; } int discard = (discard_level != -1 ? discard_level : base.getRawDiscardLevel()); //llinfos << "Merov debug : initDecode, discard used = " << discard << ", asked = " << discard_level << llendl; // Apply loading restrictions mCodeStreamp->apply_input_restrictions( first_channel, max_channel_count, discard, 0, region_kdu); // Clean-up if (region_kdu) { delete region_kdu; region_kdu = NULL; } // Resize raw_image according to the image to be decoded kdu_dims dims; mCodeStreamp->get_dims(0,dims); S32 channels = base.getComponents() - first_channel; channels = llmin(channels,max_channel_count); raw_image.resize(dims.size.x, dims.size.y, channels); if (!mTileIndicesp) { mTileIndicesp = new kdu_dims; } mCodeStreamp->get_valid_tiles(*mTileIndicesp); if (!mTPosp) { mTPosp = new kdu_coords; mTPosp->y = 0; mTPosp->x = 0; } } catch (const char* msg) { base.setLastError(ll_safe_string(msg)); return FALSE; } catch (...) { base.setLastError("Unknown J2C error"); return FALSE; } return TRUE; }
BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region) { base.resetLastError(); // *FIX: kdu calls our callback function if there's an error, and then bombs. // To regain control, we throw an exception, and catch it here. try { base.updateRawDiscardLevel(); setupCodeStream(base, TRUE, mode); mRawImagep = &raw_image; mCodeStreamp->change_appearance(false, true, false); // Apply loading discard level and cropping if required kdu_dims* region_kdu = NULL; if (region != NULL) { region_kdu = new kdu_dims; region_kdu->pos.x = region[0]; region_kdu->pos.y = region[1]; region_kdu->size.x = region[2] - region[0]; region_kdu->size.y = region[3] - region[1]; } int discard = (discard_level != -1 ? discard_level : base.getRawDiscardLevel()); // Apply loading restrictions mCodeStreamp->apply_input_restrictions( first_channel, max_channel_count, discard, 0, region_kdu); // Clean-up if (region_kdu) { delete region_kdu; region_kdu = NULL; } // Resize raw_image according to the image to be decoded kdu_dims dims; mCodeStreamp->get_dims(0,dims); // *TODO: Use the real number of levels read from the file throughout the code instead of relying on an infered value from dimensions //S32 levels = mCodeStreamp->get_min_dwt_levels(); S32 channels = base.getComponents() - first_channel; channels = llmin(channels,max_channel_count); raw_image.resize(dims.size.x, dims.size.y, channels); //llinfos << "j2c image dimension: width = " << dims.size.x << ", height = " << dims.size.y << ", channels = " << channels << ", levels = " << levels << llendl; if (!mTileIndicesp) { mTileIndicesp = new kdu_dims; } mCodeStreamp->get_valid_tiles(*mTileIndicesp); if (!mTPosp) { mTPosp = new kdu_coords; mTPosp->y = 0; mTPosp->x = 0; } } catch (const char* msg) { base.setLastError(ll_safe_string(msg)); return FALSE; } catch (...) { base.setLastError("Unknown J2C error"); return FALSE; } return TRUE; }