diff options
author | Merov Linden <merov@lindenlab.com> | 2011-04-04 18:37:32 -0700 |
---|---|---|
committer | Merov Linden <merov@lindenlab.com> | 2011-04-04 18:37:32 -0700 |
commit | 83ec0cd62f70888c90671ea91cd056ecb6095bc1 (patch) | |
tree | 3bfd13782f0b056e61249f17a057d5bf7ee6f882 | |
parent | dc00f42dd7ff59143869e17010ed435db009ae12 (diff) |
STORM-746 : add new arguments for precincts and blocks on output, region and level on input, add code for input loading restriction
-rw-r--r-- | indra/integration_tests/llimage_libtest/llimage_libtest.cpp | 126 | ||||
-rw-r--r-- | indra/llimage/llimagej2c.cpp | 7 | ||||
-rw-r--r-- | indra/llimage/llimagej2c.h | 2 | ||||
-rw-r--r-- | indra/llimagej2coj/llimagej2coj.cpp | 5 | ||||
-rw-r--r-- | indra/llimagej2coj/llimagej2coj.h | 1 | ||||
-rw-r--r-- | indra/llkdu/llimagej2ckdu.cpp | 38 | ||||
-rw-r--r-- | indra/llkdu/llimagej2ckdu.h | 3 |
7 files changed, 161 insertions, 21 deletions
diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 365f5f758c..10d6ffb685 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -53,12 +53,28 @@ static const char USAGE[] = "\n" " -o, --output <file1 .. file2> OR <type>\n" " List of image files to create (assumes same order as for input files)\n" " OR 3 letters file type extension to convert each input file into.\n" +" -r, --region <x0, y0, x1, y1>\n" +" Crop region on the input file in pixel.\n" +" Only used for j2c images. Default is no region cropping.\n" +" -d, --discard_level <n>\n" +" Discard level max used on input. 0 is high resolution. Max discard level is 5.\n" +" This allows the input image to be clamped in resolution when loading.\n" +" Only valid for j2c images. Default is no discard.\n" +" -p, --precincts <n>\n" +" Dimension of precincts in pixels. Precincts are assumed square and identical for\n" +" all levels. Note that this oprion also uses PLT and tile markers, \n" +" as well as RPCL order. Power of 2 must be used.\n" +" Only valid for output j2c images. Default is no precincts used.\n" +" -b, --blocks <n>\n" +" Dimension of coding blocks in pixels. Blocks are assumed square. Power of 2 must\n" +" be used. Blocks must be smaller than precincts.\n" +" Only valid for output j2c images. Default is 64.\n" " -log, --logmetrics <metric>\n" " Log performance data for <metric>. Results in <metric>.slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" -" -r, --analyzeperformance\n" +" -a, --analyzeperformance\n" " Create a report comparing <metric>_baseline.slp with current <metric>.slp\n" -" Results in <metric>_report.csv" +" Results in <metric>_report.csv\n" " -s, --image-stats\n" " Output stats for each input and output image.\n" "\n"; @@ -110,10 +126,11 @@ void output_image_stats(LLPointer<LLImageFormatted> image, const std::string &fi } // Load an image from file and return a raw (decompressed) instance of its data -LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_stats) +LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_stats, bool use_discard_level, int discard_level, bool use_region, int* region) { LLPointer<LLImageFormatted> image = create_image(src_filename); - + + // This just load the image file stream into a buffer. No decoding done. if (!image->load(src_filename)) { return NULL; @@ -131,6 +148,17 @@ LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_st } LLPointer<LLImageRaw> raw_image = new LLImageRaw; + + // Set the image restriction on load in the case of a j2c image + if ((image->getCodec() == IMG_CODEC_J2C) && (use_discard_level || use_region)) + { + int discard = (use_discard_level ? discard_level : -1); + int* reg = (use_region ? region : NULL); + // That method doesn't exist (and likely, doesn't make sense) for any other image file format + // hence the required cryptic cast. + ((LLImageJ2C*)(image.get()))->initDecode(*raw_image, discard, reg); + } + if (!image->decode(raw_image, 0.0f)) { return NULL; @@ -280,8 +308,17 @@ int main(int argc, char** argv) // List of input and output files std::list<std::string> input_filenames; std::list<std::string> output_filenames; + // Other optional parsed arguments bool analyze_performance = false; bool image_stats = false; + bool use_region = false; + int region[4]; + bool use_discard_level = false; + int discard_level = 0; + bool use_precincts = false; + int precincts_size; + bool use_blocks = false; + int blocks_size; // Init whatever is necessary ll_init_apr(); @@ -323,6 +360,81 @@ int main(int argc, char** argv) file_name = argv[arg+1]; // Next argument and loop over } } + else if ((!strcmp(argv[arg], "--region") || !strcmp(argv[arg], "-r")) && arg < argc-1) + { + std::string value_str = argv[arg+1]; + int index = 0; + while (value_str[0] != '-') // if arg starts with '-', it's the next option + { + int value = atoi(value_str.c_str()); + region[index++] = value; + arg += 1; // Definitely skip that arg now we know it's a number + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + if (index == 4) // Break out of the loop if we captured 4 values already + break; + value_str = argv[arg+1]; // Next argument and loop over + } + if (index == 4) + { + use_region = true; + } + else + { + std::cout << "--region arguments invalid" << std::endl; + } + } + else if (!strcmp(argv[arg], "--discard_level") || !strcmp(argv[arg], "-d")) + { + std::string value_str; + if ((arg + 1) < argc) + { + value_str = argv[arg+1]; + } + if (((arg + 1) >= argc) || (value_str[0] == '-')) + { + std::cout << "No valid --discard_level argument given, discard_level ignored" << std::endl; + } + else + { + use_discard_level = true; + discard_level = atoi(value_str.c_str()); + } + } + else if (!strcmp(argv[arg], "--precincts") || !strcmp(argv[arg], "-p")) + { + std::string value_str; + if ((arg + 1) < argc) + { + value_str = argv[arg+1]; + } + if (((arg + 1) >= argc) || (value_str[0] == '-')) + { + std::cout << "No valid --precincts argument given, precincts ignored" << std::endl; + } + else + { + use_precincts = true; + precincts_size = atoi(value_str.c_str()); + } + } + else if (!strcmp(argv[arg], "--blocks") || !strcmp(argv[arg], "-b")) + { + std::string value_str; + if ((arg + 1) < argc) + { + value_str = argv[arg+1]; + } + if (((arg + 1) >= argc) || (value_str[0] == '-')) + { + std::cout << "No valid --blocks argument given, blocks ignored" << std::endl; + } + else + { + use_blocks = true; + blocks_size = atoi(value_str.c_str()); + } + } else if (!strcmp(argv[arg], "--logmetrics") || !strcmp(argv[arg], "-log")) { // '--logmetrics' needs to be specified with a named test metric argument @@ -346,7 +458,7 @@ int main(int argc, char** argv) break; } } - else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-r")) + else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a")) { analyze_performance = true; } @@ -364,7 +476,7 @@ int main(int argc, char** argv) } if (analyze_performance && !LLFastTimer::sMetricLog) { - std::cout << "Cannot create perf report if no perf gathered (i.e. use argument -log <perf> with -r) -> exit" << std::endl; + std::cout << "Cannot create perf report if no perf gathered (i.e. use argument -log <perf> with -a) -> exit" << std::endl; return 0; } @@ -385,7 +497,7 @@ int main(int argc, char** argv) for (; in_file != in_end; ++in_file) { // Load file - LLPointer<LLImageRaw> raw_image = load_image(*in_file, image_stats); + LLPointer<LLImageRaw> raw_image = load_image(*in_file, image_stats, use_discard_level, discard_level, use_region, region); if (!raw_image) { std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl; diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 80fec7f8a0..6b49f3de88 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -139,6 +139,10 @@ BOOL LLImageJ2C::updateData() return res; } +BOOL LLImageJ2C::initDecode(LLImageRaw &raw_image, int discard_level, int* region) +{ + return mImpl->initDecode(*this,raw_image,discard_level,region); +} BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time) { @@ -251,6 +255,9 @@ S32 LLImageJ2C::calcHeaderSizeJ2C() //static S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate) { + // Note: this only provides an *estimate* of the size in bytes of an image level + // *TODO: find a way to read the true size (when available) and convey the fact + // that the result is an estimate in the other cases if (rate <= 0.f) rate = .125f; while (discard_level > 0) { diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h index dd5bec8b2e..7af1c13921 100644 --- a/indra/llimage/llimagej2c.h +++ b/indra/llimage/llimagej2c.h @@ -56,6 +56,7 @@ public: /*virtual*/ void resetLastError(); /*virtual*/ void setLastError(const std::string& message, const std::string& filename = std::string()); + BOOL initDecode(LLImageRaw &raw_image, int discard_level, int* region); // Encode with comment text BOOL encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0); @@ -117,6 +118,7 @@ protected: virtual BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) = 0; virtual BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0, BOOL reversible=FALSE) = 0; + virtual BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL) = 0; friend class LLImageJ2C; }; diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index 13b12c0928..11c826e41a 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -107,6 +107,11 @@ LLImageJ2COJ::~LLImageJ2COJ() { } +BOOL LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region) +{ + // No specific implementaion for this method in the OpenJpeg case + return FALSE; +} BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) { diff --git a/indra/llimagej2coj/llimagej2coj.h b/indra/llimagej2coj/llimagej2coj.h index 9476665ccb..d5f2f7a2d1 100644 --- a/indra/llimagej2coj/llimagej2coj.h +++ b/indra/llimagej2coj/llimagej2coj.h @@ -39,6 +39,7 @@ protected: /*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count); /*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0, BOOL reversible = FALSE); + /*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL); }; #endif diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 61b16c80e6..e51cfee6eb 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -106,7 +106,11 @@ const char* fallbackEngineInfoLLImageJ2CImpl() class LLKDUDecodeState { public: + LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap); + ~LLKDUDecodeState(); + BOOL processTileDecode(F32 decode_time, BOOL limit_time = TRUE); +private: S32 mNumComponents; BOOL mUseYCC; kdu_dims mDims; @@ -116,20 +120,10 @@ public: kdu_pull_ifc mEngines[4]; bool mReversible[4]; // Some components may be reversible and others not int mBitDepths[4]; // Original bit-depth may be quite different from 8 - + kdu_tile mTile; kdu_byte *mBuf; S32 mRowGap; - - LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap); - ~LLKDUDecodeState(); - BOOL processTileDecode(F32 decode_time, BOOL limit_time = TRUE); - -public: - int *AssignLayerBytes(siz_params *siz, int &num_specs); - - void setupCodeStream(BOOL keep_codestream, LLImageJ2CKDU::ECodeStreamMode mode); - BOOL initDecode(LLImageRaw &raw_image, F32 decode_time, LLImageJ2CKDU::ECodeStreamMode mode, S32 first_channel, S32 max_channel_count ); }; void ll_kdu_error( void ) @@ -327,7 +321,12 @@ void LLImageJ2CKDU::cleanupCodeStream() mTileIndicesp = NULL; } -BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count ) +BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region) +{ + return initDecode(base,raw_image,0.0f,MODE_FAST,0,4,discard_level,region); +} + +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(); @@ -340,7 +339,20 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco mRawImagep = &raw_image; mCodeStreamp->change_appearance(false, true, false); - mCodeStreamp->apply_input_restrictions(first_channel,max_channel_count,base.getRawDiscardLevel(),0,NULL); + + // 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()); + + mCodeStreamp->apply_input_restrictions( first_channel, max_channel_count, discard, 0, region_kdu); kdu_dims dims; mCodeStreamp->get_dims(0,dims); S32 channels = base.getComponents() - first_channel; diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h index 5628f69eeb..8231004f2c 100644 --- a/indra/llkdu/llimagej2ckdu.h +++ b/indra/llkdu/llimagej2ckdu.h @@ -58,11 +58,12 @@ protected: /*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count); /*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0, BOOL reversible=FALSE); + /*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL); private: + BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level = -1, int* region = NULL); void setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode); void cleanupCodeStream(); - BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count ); // Encode variable LLKDUMemSource *mInputp; |