From 83ec0cd62f70888c90671ea91cd056ecb6095bc1 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 4 Apr 2011 18:37:32 -0700 Subject: STORM-746 : add new arguments for precincts and blocks on output, region and level on input, add code for input loading restriction --- .../llimage_libtest/llimage_libtest.cpp | 126 +++++++++++++++++++-- 1 file changed, 119 insertions(+), 7 deletions(-) (limited to 'indra/integration_tests') 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 OR \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 \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" +" 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" +" 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" +" 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 \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" -" -r, --analyzeperformance\n" +" -a, --analyzeperformance\n" " Create a report comparing _baseline.slp with current .slp\n" -" Results in _report.csv" +" Results in _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 image, const std::string &fi } // Load an image from file and return a raw (decompressed) instance of its data -LLPointer load_image(const std::string &src_filename, bool output_stats) +LLPointer load_image(const std::string &src_filename, bool output_stats, bool use_discard_level, int discard_level, bool use_region, int* region) { LLPointer 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 load_image(const std::string &src_filename, bool output_st } LLPointer 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 input_filenames; std::list 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 with -r) -> exit" << std::endl; + std::cout << "Cannot create perf report if no perf gathered (i.e. use argument -log 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 raw_image = load_image(*in_file, image_stats); + LLPointer 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; -- cgit v1.3 From e752e918283acf95c1ed33d92a7bf34bbca83071 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 4 Apr 2011 23:49:40 -0700 Subject: STORM-746 : add precincts and blocks arguments taken into account in j2c output --- .../llimage_libtest/llimage_libtest.cpp | 50 +++++++++++----------- indra/llimage/llimagej2c.cpp | 5 +++ indra/llimage/llimagej2c.h | 2 + indra/llimagej2coj/llimagej2coj.cpp | 8 +++- indra/llimagej2coj/llimagej2coj.h | 1 + indra/llkdu/llimagej2ckdu.cpp | 34 +++++++++++++-- indra/llkdu/llimagej2ckdu.h | 3 ++ 7 files changed, 74 insertions(+), 29 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 10d6ffb685..31d3e18877 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -126,7 +126,7 @@ void output_image_stats(LLPointer image, const std::string &fi } // Load an image from file and return a raw (decompressed) instance of its data -LLPointer load_image(const std::string &src_filename, bool output_stats, bool use_discard_level, int discard_level, bool use_region, int* region) +LLPointer load_image(const std::string &src_filename, int discard_level, int* region, bool output_stats) { LLPointer image = create_image(src_filename); @@ -150,13 +150,11 @@ LLPointer load_image(const std::string &src_filename, bool output_st LLPointer 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)) + if ((image->getCodec() == IMG_CODEC_J2C) && ((discard_level != -1) || (region != NULL))) { - 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); + ((LLImageJ2C*)(image.get()))->initDecode(*raw_image, discard_level, region); } if (!image->decode(raw_image, 0.0f)) @@ -168,10 +166,18 @@ LLPointer load_image(const std::string &src_filename, bool output_st } // Save a raw image instance into a file -bool save_image(const std::string &dest_filename, LLPointer raw_image, bool output_stats) +bool save_image(const std::string &dest_filename, LLPointer raw_image, int blocks_size, int precincts_size, bool output_stats) { LLPointer image = create_image(dest_filename); + // Set the image restriction on load in the case of a j2c image + if ((image->getCodec() == IMG_CODEC_J2C) && ((blocks_size != -1) || (precincts_size != -1))) + { + // 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()))->initEncode(*raw_image, blocks_size, precincts_size); + } + if (!image->encode(raw_image, 0.0f)) { return false; @@ -311,14 +317,10 @@ int main(int argc, char** argv) // 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; + int* region = NULL; + int discard_level = -1; + int precincts_size = -1; + int blocks_size = -1; // Init whatever is necessary ll_init_apr(); @@ -364,6 +366,7 @@ int main(int argc, char** argv) { std::string value_str = argv[arg+1]; int index = 0; + region = new int[4]; while (value_str[0] != '-') // if arg starts with '-', it's the next option { int value = atoi(value_str.c_str()); @@ -375,13 +378,11 @@ int main(int argc, char** argv) break; value_str = argv[arg+1]; // Next argument and loop over } - if (index == 4) - { - use_region = true; - } - else + if (index != 4) { std::cout << "--region arguments invalid" << std::endl; + delete [] region; + region = NULL; } } else if (!strcmp(argv[arg], "--discard_level") || !strcmp(argv[arg], "-d")) @@ -397,8 +398,9 @@ int main(int argc, char** argv) } else { - use_discard_level = true; discard_level = atoi(value_str.c_str()); + // Clamp to the values accepted by the viewer + discard_level = llclamp(discard_level,0,5); } } else if (!strcmp(argv[arg], "--precincts") || !strcmp(argv[arg], "-p")) @@ -414,8 +416,8 @@ int main(int argc, char** argv) } else { - use_precincts = true; precincts_size = atoi(value_str.c_str()); + // *TODO: make sure precincts_size is a power of 2 } } else if (!strcmp(argv[arg], "--blocks") || !strcmp(argv[arg], "-b")) @@ -431,8 +433,8 @@ int main(int argc, char** argv) } else { - use_blocks = true; blocks_size = atoi(value_str.c_str()); + // *TODO: make sure blocks_size is a power of 2 } } else if (!strcmp(argv[arg], "--logmetrics") || !strcmp(argv[arg], "-log")) @@ -497,7 +499,7 @@ int main(int argc, char** argv) for (; in_file != in_end; ++in_file) { // Load file - LLPointer raw_image = load_image(*in_file, image_stats, use_discard_level, discard_level, use_region, region); + LLPointer raw_image = load_image(*in_file, discard_level, region, image_stats); if (!raw_image) { std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl; @@ -507,7 +509,7 @@ int main(int argc, char** argv) // Save file if (out_file != out_end) { - if (!save_image(*out_file, raw_image, image_stats)) + if (!save_image(*out_file, raw_image, blocks_size, precincts_size, image_stats)) { std::cout << "Error: Image " << *out_file << " could not be saved" << std::endl; } diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 6b49f3de88..a90df0f1c1 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -144,6 +144,11 @@ BOOL LLImageJ2C::initDecode(LLImageRaw &raw_image, int discard_level, int* regio return mImpl->initDecode(*this,raw_image,discard_level,region); } +BOOL LLImageJ2C::initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size) +{ + return mImpl->initEncode(*this,raw_image,blocks_size,precincts_size); +} + BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time) { return decodeChannels(raw_imagep, decode_time, 0, 4); diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h index 7af1c13921..6bba81aab5 100644 --- a/indra/llimage/llimagej2c.h +++ b/indra/llimage/llimagej2c.h @@ -57,6 +57,7 @@ public: /*virtual*/ void setLastError(const std::string& message, const std::string& filename = std::string()); BOOL initDecode(LLImageRaw &raw_image, int discard_level, int* region); + BOOL initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size); // Encode with comment text BOOL encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0); @@ -119,6 +120,7 @@ protected: 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; + virtual BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1) = 0; friend class LLImageJ2C; }; diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index 11c826e41a..8288fa1f5c 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -109,7 +109,13 @@ 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 + // No specific implementation for this method in the OpenJpeg case + return FALSE; +} + +BOOL LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size) +{ + // No specific implementation for this method in the OpenJpeg case return FALSE; } diff --git a/indra/llimagej2coj/llimagej2coj.h b/indra/llimagej2coj/llimagej2coj.h index d5f2f7a2d1..9c7cc09fcb 100644 --- a/indra/llimagej2coj/llimagej2coj.h +++ b/indra/llimagej2coj/llimagej2coj.h @@ -40,6 +40,7 @@ protected: /*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); + /*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1); }; #endif diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index e51cfee6eb..8d2ed8f8c4 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -190,7 +190,9 @@ mCodeStreamp(NULL), mTPosp(NULL), mTileIndicesp(NULL), mRawImagep(NULL), -mDecodeState(NULL) +mDecodeState(NULL), +mBlocksSize(-1), +mPrecinctsSize(-1) { } @@ -326,6 +328,13 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int disc return initDecode(base,raw_image,0.0f,MODE_FAST,0,4,discard_level,region); } +BOOL LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size) +{ + mBlocksSize = blocks_size; + mPrecinctsSize = precincts_size; + 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(); @@ -623,9 +632,26 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co } } - // *TODO : Add precinct specification here - //std::string precincts_string = llformat("Cprecincts={128,128}"); - //codestream.access_siz()->parse_string(precincts_string.c_str()); + // Set up data ordering, markers, etc... if precincts or blocks specified + if ((mBlocksSize != -1) || (mPrecinctsSize != -1)) + { + if (mPrecinctsSize != -1) + { + std::string precincts_string = llformat("Cprecincts={%d,%d}",mPrecinctsSize,mPrecinctsSize); + codestream.access_siz()->parse_string(precincts_string.c_str()); + } + if (mBlocksSize != -1) + { + std::string blocks_string = llformat("Cblk={%d,%d}",mBlocksSize,mBlocksSize); + codestream.access_siz()->parse_string(blocks_string.c_str()); + } + std::string ordering_string = llformat("Corder=RPCL"); + codestream.access_siz()->parse_string(ordering_string.c_str()); + std::string PLT_string = llformat("ORGgen_plt=yes"); + codestream.access_siz()->parse_string(PLT_string.c_str()); + std::string Parts_string = llformat("ORGtparts=R"); + codestream.access_siz()->parse_string(Parts_string.c_str()); + } codestream.access_siz()->finalize_all(); codestream.change_appearance(transpose,vflip,hflip); diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h index 8231004f2c..9fce58b762 100644 --- a/indra/llkdu/llimagej2ckdu.h +++ b/indra/llkdu/llimagej2ckdu.h @@ -59,6 +59,7 @@ protected: /*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); + /*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1); 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); @@ -70,6 +71,8 @@ private: kdu_codestream *mCodeStreamp; kdu_coords *mTPosp; // tile position kdu_dims *mTileIndicesp; + int mBlocksSize; + int mPrecinctsSize; // Temporary variables for in-progress decodes... LLImageRaw *mRawImagep; -- cgit v1.3 From 379e2e138d801ebf7f13d29512f76298aacf3dc5 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 7 Apr 2011 16:41:57 -0700 Subject: STORM-746 : Fix bug in performance report output --- .../llimage_libtest/llimage_libtest.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 31d3e18877..1466e44324 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -521,25 +521,25 @@ int main(int argc, char** argv) } } - // Stop the perf gathering system if needed - if (LLFastTimer::sMetricLog) - { - LLMetricPerformanceTesterBasic::deleteTester(LLFastTimer::sLogName); - sAllDone = true; - } - // Output perf data if requested by user if (analyze_performance) { - std::cout << "Analyzing performance" << std::endl; - std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp"; std::string current_name = LLFastTimer::sLogName + ".slp"; std::string report_name = LLFastTimer::sLogName + "_report.csv"; + std::cout << "Analyzing performance, check report in : " << report_name << std::endl; + LLMetricPerformanceTesterBasic::doAnalysisMetrics(baseline_name, current_name, report_name); } + // Stop the perf gathering system if needed + if (LLFastTimer::sMetricLog) + { + LLMetricPerformanceTesterBasic::deleteTester(LLFastTimer::sLogName); + sAllDone = true; + } + // Cleanup and exit LLImage::cleanupClass(); if (fast_timer_log_thread) -- cgit v1.3 From cd363e8c87e176776f5db8fbaf60c264eabdaa3b Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 7 Apr 2011 17:26:10 -0700 Subject: STORM-746 : Clean up typos in comments --- .../integration_tests/llimage_libtest/llimage_libtest.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 1466e44324..feb63e161d 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -54,20 +54,21 @@ static const char USAGE[] = "\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 \n" -" Crop region on the input file in pixel.\n" +" Crop region applied to the input files in pixels.\n" " Only used for j2c images. Default is no region cropping.\n" " -d, --discard_level \n" -" Discard level max used on input. 0 is high resolution. Max discard level is 5.\n" +" Discard level max used on input. 0 is highest 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" " 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" +" all levels. Note that this option also add PLT and tile markers to the codestream, \n" +" and uses RPCL order. Power of 2 must be used.\n" " Only valid for output j2c images. Default is no precincts used.\n" " -b, --blocks \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" +" be used. Blocks must be smaller than precincts. Like precincts, this option adds\n" +" PLT, tile markers and uses RPCL.\n" " Only valid for output j2c images. Default is 64.\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" @@ -130,7 +131,7 @@ LLPointer load_image(const std::string &src_filename, int discard_le { LLPointer image = create_image(src_filename); - // This just load the image file stream into a buffer. No decoding done. + // This just loads the image file stream into a buffer. No decoding done. if (!image->load(src_filename)) { return NULL; @@ -170,7 +171,7 @@ bool save_image(const std::string &dest_filename, LLPointer raw_imag { LLPointer image = create_image(dest_filename); - // Set the image restriction on load in the case of a j2c image + // Set the image codestream parameters on output in the case of a j2c image if ((image->getCodec() == IMG_CODEC_J2C) && ((blocks_size != -1) || (precincts_size != -1))) { // That method doesn't exist (and likely, doesn't make sense) for any other image file format -- cgit v1.3 From 759d72a46c5d487e6881426f90c54c6ae2da4847 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 13 Apr 2011 14:05:31 -0700 Subject: EXP-669 : Refactor code to use correct LLImageFormatted methods to load images of all formats, reviewed by richard --- .../llimage_libtest/llimage_libtest.cpp | 27 +---- indra/llimage/llimage.cpp | 23 +--- indra/newview/llfloaterimagepreview.cpp | 119 +++++---------------- indra/newview/llviewermenufile.cpp | 55 +--------- indra/newview/llviewertexturelist.cpp | 110 +++++-------------- 5 files changed, 59 insertions(+), 275 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 365f5f758c..03a79532c8 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -69,31 +69,8 @@ static bool sAllDone = false; // Create an empty formatted image instance of the correct type from the filename LLPointer create_image(const std::string &filename) { - std::string exten = gDirUtilp->getExtension(filename); - U32 codec = LLImageBase::getCodecFromExtension(exten); - - LLPointer image; - switch (codec) - { - case IMG_CODEC_BMP: - image = new LLImageBMP(); - break; - case IMG_CODEC_TGA: - image = new LLImageTGA(); - break; - case IMG_CODEC_JPEG: - image = new LLImageJPEG(); - break; - case IMG_CODEC_J2C: - image = new LLImageJ2C(); - break; - case IMG_CODEC_PNG: - image = new LLImagePNG(); - break; - default: - return NULL; - } - + std::string exten = gDirUtilp->getExtension(filename); + LLPointer image = LLImageFormatted::createFromExtension(exten); return image; } diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 39211bf7fa..f0d15d9607 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1254,28 +1254,7 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip return false; } - LLPointer image; - switch(codec) - { - //case IMG_CODEC_RGB: - case IMG_CODEC_BMP: - image = new LLImageBMP(); - break; - case IMG_CODEC_TGA: - image = new LLImageTGA(); - break; - case IMG_CODEC_JPEG: - image = new LLImageJPEG(); - break; - case IMG_CODEC_J2C: - image = new LLImageJ2C(); - break; - case IMG_CODEC_DXT: - image = new LLImageDXT(); - break; - default: - return false; - } + LLPointer image = LLImageFormatted::createFromType(codec); llassert(image.notNull()); U8 *buffer = image->allocateData(length); diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index c7fbdd5745..d76e7885bc 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -325,122 +325,51 @@ void LLFloaterImagePreview::draw() bool LLFloaterImagePreview::loadImage(const std::string& src_filename) { std::string exten = gDirUtilp->getExtension(src_filename); - - U32 codec = IMG_CODEC_INVALID; - std::string temp_str; - if( exten == "bmp") - { - codec = IMG_CODEC_BMP; - } - else if( exten == "tga") - { - codec = IMG_CODEC_TGA; - } - else if( exten == "jpg" || exten == "jpeg") - { - codec = IMG_CODEC_JPEG; - } - else if( exten == "png" ) - { - codec = IMG_CODEC_PNG; - } + U32 codec = LLImageBase::getCodecFromExtension(exten); LLImageDimensionsInfo image_info; - if(!image_info.load(src_filename,codec)) + if (!image_info.load(src_filename,codec)) { mImageLoadError = image_info.getLastError(); return false; } S32 max_width = gSavedSettings.getS32("max_texture_dimension_X"); - S32 max_heigh = gSavedSettings.getS32("max_texture_dimension_Y"); + S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y"); - if(image_info.getWidth() > max_width|| image_info.getHeight() > max_heigh) + if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) { LLStringUtil::format_map_t args; args["WIDTH"] = llformat("%d", max_width); - args["HEIGHT"] = llformat("%d", max_heigh); + args["HEIGHT"] = llformat("%d", max_height); mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args); return false; } - + // Load the image + LLPointer image = LLImageFormatted::createFromType(codec); + if (image.isNull()) + { + return false; + } + if (!image->load(src_filename)) + { + return false; + } + // Decompress or expand it in a raw image structure LLPointer raw_image = new LLImageRaw; - - switch (codec) + if (!image->decode(raw_image, 0.0f)) { - case IMG_CODEC_BMP: - { - LLPointer bmp_image = new LLImageBMP; - - if (!bmp_image->load(src_filename)) - { - return false; - } - - if (!bmp_image->decode(raw_image, 0.0f)) - { - return false; - } - } - break; - case IMG_CODEC_TGA: - { - LLPointer tga_image = new LLImageTGA; - - if (!tga_image->load(src_filename)) - { - return false; - } - - if (!tga_image->decode(raw_image)) - { - return false; - } - - if( (tga_image->getComponents() != 3) && - (tga_image->getComponents() != 4) ) - { - tga_image->setLastError( "Image files with less than 3 or more than 4 components are not supported." ); - return false; - } - } - break; - case IMG_CODEC_JPEG: - { - LLPointer jpeg_image = new LLImageJPEG; - - if (!jpeg_image->load(src_filename)) - { - return false; - } - - if (!jpeg_image->decode(raw_image, 0.0f)) - { - return false; - } - } - break; - case IMG_CODEC_PNG: - { - LLPointer png_image = new LLImagePNG; - - if (!png_image->load(src_filename)) - { - return false; - } - - if (!png_image->decode(raw_image, 0.0f)) - { - return false; - } - } - break; - default: return false; } - + // Check the image constraints + if ((image->getComponents() != 3) && (image->getComponents() != 4)) + { + image->setLastError("Image files with less than 3 or more than 4 components are not supported."); + return false; + } + raw_image->biasedScaleToPowerOfTwo(1024); mRawImagep = raw_image; diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index fda291f3c1..2cf8dbec89 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -493,6 +493,7 @@ void upload_new_resource(const std::string& src_filename, std::string name, LLSD args; std::string exten = gDirUtilp->getExtension(src_filename); + U32 codec = LLImageBase::getCodecFromExtension(exten); LLAssetType::EType asset_type = LLAssetType::AT_NONE; std::string error_message; @@ -510,66 +511,20 @@ void upload_new_resource(const std::string& src_filename, std::string name, upload_error(error_message, "NoFileExtension", filename, args); return; } - else if( exten == "bmp") + else if (codec != IMG_CODEC_INVALID) { + // It's an image file, the upload procedure is the same for all asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerTextureList::createUploadFile(src_filename, - filename, - IMG_CODEC_BMP )) + if (!LLViewerTextureList::createUploadFile(src_filename, filename, codec )) { error_message = llformat( "Problem with file %s:\n\n%s\n", - src_filename.c_str(), LLImage::getLastError().c_str()); + src_filename.c_str(), LLImage::getLastError().c_str()); args["FILE"] = src_filename; args["ERROR"] = LLImage::getLastError(); upload_error(error_message, "ProblemWithFile", filename, args); return; } } - else if( exten == "tga") - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerTextureList::createUploadFile(src_filename, - filename, - IMG_CODEC_TGA )) - { - error_message = llformat("Problem with file %s:\n\n%s\n", - src_filename.c_str(), LLImage::getLastError().c_str()); - args["FILE"] = src_filename; - args["ERROR"] = LLImage::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return; - } - } - else if( exten == "jpg" || exten == "jpeg") - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerTextureList::createUploadFile(src_filename, - filename, - IMG_CODEC_JPEG )) - { - error_message = llformat("Problem with file %s:\n\n%s\n", - src_filename.c_str(), LLImage::getLastError().c_str()); - args["FILE"] = src_filename; - args["ERROR"] = LLImage::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return; - } - } - else if( exten == "png") - { - asset_type = LLAssetType::AT_TEXTURE; - if (!LLViewerTextureList::createUploadFile(src_filename, - filename, - IMG_CODEC_PNG )) - { - error_message = llformat("Problem with file %s:\n\n%s\n", - src_filename.c_str(), LLImage::getLastError().c_str()); - args["FILE"] = src_filename; - args["ERROR"] = LLImage::getLastError(); - upload_error(error_message, "ProblemWithFile", filename, args); - return; - } - } else if(exten == "wav") { asset_type = LLAssetType::AT_SOUND; // tag it as audio diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 06f6ff23c2..5afed721ac 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -927,99 +927,43 @@ void LLViewerTextureList::decodeAllImages(F32 max_time) BOOL LLViewerTextureList::createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec) -{ - // First, load the image. +{ + // Load the image + LLPointer image = LLImageFormatted::createFromType(codec); + if (image.isNull()) + { + return FALSE; + } + if (!image->load(filename)) + { + return FALSE; + } + // Decompress or expand it in a raw image structure LLPointer raw_image = new LLImageRaw; - - switch (codec) + if (!image->decode(raw_image, 0.0f)) { - case IMG_CODEC_BMP: - { - LLPointer bmp_image = new LLImageBMP; - - if (!bmp_image->load(filename)) - { - return FALSE; - } - - if (!bmp_image->decode(raw_image, 0.0f)) - { - return FALSE; - } - } - break; - case IMG_CODEC_TGA: - { - LLPointer tga_image = new LLImageTGA; - - if (!tga_image->load(filename)) - { - return FALSE; - } - - if (!tga_image->decode(raw_image)) - { - return FALSE; - } - - if( (tga_image->getComponents() != 3) && - (tga_image->getComponents() != 4) ) - { - tga_image->setLastError( "Image files with less than 3 or more than 4 components are not supported." ); - return FALSE; - } - } - break; - case IMG_CODEC_JPEG: - { - LLPointer jpeg_image = new LLImageJPEG; - - if (!jpeg_image->load(filename)) - { - return FALSE; - } - - if (!jpeg_image->decode(raw_image, 0.0f)) - { - return FALSE; - } - } - break; - case IMG_CODEC_PNG: - { - LLPointer png_image = new LLImagePNG; - - if (!png_image->load(filename)) - { - return FALSE; - } - - if (!png_image->decode(raw_image, 0.0f)) - { - return FALSE; - } - } - break; - default: - return FALSE; + return FALSE; } - - LLPointer compressedImage = convertToUploadFile(raw_image); - - if( !compressedImage->save(out_filename) ) + // Check the image constraints + if ((image->getComponents() != 3) && (image->getComponents() != 4)) { - llinfos << "Couldn't create output file " << out_filename << llendl; + image->setLastError("Image files with less than 3 or more than 4 components are not supported."); return FALSE; } - - // test to see if the encode and save worked. + // Convert to j2c (JPEG2000) and save the file locally + LLPointer compressedImage = convertToUploadFile(raw_image); + if (!compressedImage->save(out_filename)) + { + llinfos << "Couldn't create output file : " << out_filename << llendl; + return FALSE; + } + // Test to see if the encode and save worked LLPointer integrity_test = new LLImageJ2C; - if( !integrity_test->loadAndValidate( out_filename ) ) + if (!integrity_test->loadAndValidate( out_filename )) { - llinfos << "Image: " << out_filename << " is corrupt." << llendl; + llinfos << "Image file : " << out_filename << " is corrupt" << llendl; return FALSE; } - return TRUE; } -- cgit v1.3 From 6f6cebbf5dc37b36c9875b2620259541f5f60aca Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 15 Apr 2011 17:53:16 -0700 Subject: EXP-672, EXP-673 : Fix bug in encoding small textures (16x16 and under) --- .../llimage_libtest/llimage_libtest.cpp | 23 ++++++++++++++++------ indra/llkdu/llimagej2ckdu.cpp | 23 +++++++++------------- 2 files changed, 26 insertions(+), 20 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 0151016862..60ddf63b21 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -70,6 +70,9 @@ static const char USAGE[] = "\n" " be used. Blocks must be smaller than precincts. Like precincts, this option adds\n" " PLT, tile markers and uses RPCL.\n" " Only valid for output j2c images. Default is 64.\n" +" -rev, --reversible\n" +" Set the compression to be lossless (reversible in j2c parlance).\n" +" Only valid for output j2c images.\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -144,16 +147,20 @@ LLPointer load_image(const std::string &src_filename, int discard_le } // Save a raw image instance into a file -bool save_image(const std::string &dest_filename, LLPointer raw_image, int blocks_size, int precincts_size, bool output_stats) +bool save_image(const std::string &dest_filename, LLPointer raw_image, int blocks_size, int precincts_size, bool reversible, bool output_stats) { LLPointer image = create_image(dest_filename); // Set the image codestream parameters on output in the case of a j2c image - if ((image->getCodec() == IMG_CODEC_J2C) && ((blocks_size != -1) || (precincts_size != -1))) + if (image->getCodec() == IMG_CODEC_J2C) { // 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()))->initEncode(*raw_image, blocks_size, precincts_size); + if ((blocks_size != -1) || (precincts_size != -1)) + { + ((LLImageJ2C*)(image.get()))->initEncode(*raw_image, blocks_size, precincts_size); + } + ((LLImageJ2C*)(image.get()))->setReversible(reversible); } if (!image->encode(raw_image, 0.0f)) @@ -299,6 +306,7 @@ int main(int argc, char** argv) int discard_level = -1; int precincts_size = -1; int blocks_size = -1; + bool reversible = false; // Init whatever is necessary ll_init_apr(); @@ -415,6 +423,10 @@ int main(int argc, char** argv) // *TODO: make sure blocks_size is a power of 2 } } + else if (!strcmp(argv[arg], "--reversible") || !strcmp(argv[arg], "-rev")) + { + reversible = true; + } else if (!strcmp(argv[arg], "--logmetrics") || !strcmp(argv[arg], "-log")) { // '--logmetrics' needs to be specified with a named test metric argument @@ -474,7 +486,7 @@ int main(int argc, char** argv) std::list::iterator out_file = output_filenames.begin(); std::list::iterator in_end = input_filenames.end(); std::list::iterator out_end = output_filenames.end(); - for (; in_file != in_end; ++in_file) + for (; in_file != in_end; ++in_file, ++out_file) { // Load file LLPointer raw_image = load_image(*in_file, discard_level, region, image_stats); @@ -487,7 +499,7 @@ int main(int argc, char** argv) // Save file if (out_file != out_end) { - if (!save_image(*out_file, raw_image, blocks_size, precincts_size, image_stats)) + if (!save_image(*out_file, raw_image, blocks_size, precincts_size, reversible, image_stats)) { std::cout << "Error: Image " << *out_file << " could not be saved" << std::endl; } @@ -495,7 +507,6 @@ int main(int argc, char** argv) { std::cout << *in_file << " -> " << *out_file << std::endl; } - ++out_file; } } diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 5b2c045841..ae456a48be 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -545,18 +545,10 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co // Construct the `kdu_codestream' object and parse all remaining arguments U32 max_output_size = base.getWidth()*base.getHeight()*base.getComponents(); - if (max_output_size < 1000) - { - max_output_size = 1000; - } + max_output_size = (max_output_size < 1000 ? 1000 : max_output_size); U8 *output_buffer = new U8[max_output_size]; - - U32 output_size = max_output_size; // gets modified - LLKDUMemTarget output(output_buffer, output_size, base.getWidth()*base.getHeight()*base.getComponents()); - if (output_size > max_output_size) - { - llerrs << llformat("LLImageJ2C::encode output_size(%d) > max_output_size(%d)", output_size,max_output_size) << llendl; - } + 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; codestream.create(&transformed_siz,&output); @@ -583,10 +575,13 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co if (reversible) { - // If we're doing reversible (i.e. lossless compression), assumes we're not using quality layers. - // Yes, I know this is incorrect! - // *TODO: Indeed, this is incorrect and unecessary... Try using the regular layer setting... codestream.access_siz()->parse_string("Creversible=yes"); + // *TODO: we should use yuv in reversible mode and one level since those images are small. + // Don't turn this on now though as both create problems on decoding for the moment + //codestream.access_siz()->parse_string("Clevels=1"); + //codestream.access_siz()->parse_string("Cycc=no"); + // If we're doing reversible (i.e. lossless compression), assumes we're not using quality layers. + // *TODO: this is incorrect and unecessary. Try using the regular layer setting. codestream.access_siz()->parse_string("Clayers=1"); num_layer_specs = 1; layer_bytes[0] = 0; -- cgit v1.3