From cda7a0f8cf03b7a99e077043daa2d99ac16ace81 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 9 Feb 2011 23:32:46 -0800 Subject: STORM-987 : Create initial files for llimage_libtest (doesn't build) --- .../llimage_libtest/llimage_libtest.cpp | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 indra/integration_tests/llimage_libtest/llimage_libtest.cpp (limited to 'indra/integration_tests/llimage_libtest/llimage_libtest.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp new file mode 100644 index 0000000000..a4a4d10bcb --- /dev/null +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -0,0 +1,47 @@ +/** + * @file llimage_libtest.cpp + * @author Merov Linden + * @brief Integration test for the llimage library + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llimage_libtest.h" + +// linden library includes + +#include + +// *TODO: switch to using TUT +// *TODO: teach TeamCity about this program, run automatically after full builds + +void init_llimage() +{ +} + +int main(int argc, char** argv) +{ + init_llimage(); + + return 0; +} -- cgit v1.3 From 0ca7011b3154fd5db0a125f7d90de1c1e460105f Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 15 Feb 2011 22:43:54 -0800 Subject: STORM-987 : Add in and out command line arguments, builds and runs on Windows and Mac --- .../llimage_libtest/llimage_libtest.cpp | 123 +++++++++++++-------- 1 file changed, 78 insertions(+), 45 deletions(-) (limited to 'indra/integration_tests/llimage_libtest/llimage_libtest.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index e8fe4864fb..6549aa0207 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -41,15 +41,19 @@ // system libraries #include +// doc string provided when invoking the program with --help static const char USAGE[] = "\n" "usage:\tllimage_libtest [options]\n" "\n" " --help print this help\n" +" --in ... list of image files to load and convert\n" +" --out ... list of image files to create (assumes same order as --in files)\n" "\n"; -LLPointer load_image(const std::string &src_filename) +// 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(src_filename); + std::string exten = gDirUtilp->getExtension(filename); U32 codec = LLImageBase::getCodecFromExtension(exten); LLPointer image; @@ -73,6 +77,14 @@ LLPointer load_image(const std::string &src_filename) default: return NULL; } + + return image; +} + +// Load an image from file and return a raw (decompressed) instance of its data +LLPointer load_image(const std::string &src_filename) +{ + LLPointer image = create_image(src_filename); if (!image->load(src_filename)) { @@ -94,79 +106,100 @@ LLPointer load_image(const std::string &src_filename) return raw_image; } -bool save_image(const std::string &filepath, LLPointer raw_image) +// Save a raw image instance into a file +bool save_image(const std::string &dest_filename, LLPointer raw_image) { - std::string exten = gDirUtilp->getExtension(filepath); - 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; - } + LLPointer image = create_image(dest_filename); if (!image->encode(raw_image, 0.0f)) { return false; } - return image->save(filepath); + return image->save(dest_filename); } int main(int argc, char** argv) { + // List of input and output files + std::list input_filenames; + std::list output_filenames; + // Init whatever is necessary ll_init_apr(); LLImage::initClass(); // Analyze command line arguments - for (int arg=1; arg raw_image = load_image("lolcat-monorail.jpg"); - if (raw_image) + // Analyze the list of (input,output) files + if (input_filenames.size() == 0) { - std::cout << "Image loaded\n" << std::endl; + std::cout << "No input file, nothing to do -> exit" << std::endl; + return 0; } - else + // TODO: For the moment, we simply convert each input file to something. This needs to evolve... + if (input_filenames.size() != output_filenames.size()) { - std::cout << "Image not found\n" << std::endl; + std::cout << "Number of output and input files different -> exit" << std::endl; + return 0; } - - // Save file - if (raw_image) + + std::list::iterator in_file = input_filenames.begin(); + std::list::iterator out_file = output_filenames.begin(); + std::list::iterator end = input_filenames.end(); + for (; in_file != end; ++in_file, ++out_file) { - save_image("monorail.png",raw_image); + // Load file + LLPointer raw_image = load_image(*in_file); + if (!raw_image) + { + std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl; + continue; + } + + // Save file + if (!save_image(*out_file, raw_image)) + { + std::cout << "Error: Image " << *out_file << " could not be saved" << std::endl; + continue; + } + std::cout << *in_file << " -> " << *out_file << std::endl; + + // Output stats on each file } - - // Output stats on each file // Cleanup and exit LLImage::cleanupClass(); -- cgit v1.3 From 0dbc5a40cb83919187fed961de835726e044906d Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 16 Feb 2011 17:29:32 -0800 Subject: STORM-987 : Implement in and out list of files and pattern matching --- .../llimage_libtest/llimage_libtest.cpp | 117 ++++++++++++++++++--- 1 file changed, 105 insertions(+), 12 deletions(-) (limited to 'indra/integration_tests/llimage_libtest/llimage_libtest.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 6549aa0207..37e979b260 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -45,9 +45,10 @@ static const char USAGE[] = "\n" "usage:\tllimage_libtest [options]\n" "\n" -" --help print this help\n" -" --in ... list of image files to load and convert\n" -" --out ... list of image files to create (assumes same order as --in files)\n" +" --help print this help\n" +" --in list of image files to load and convert, patterns can be used\n" +" --out OR list of image files to create (assumes same order as --in files)\n" +" OR 3 letters file type extension to convert each input file into\n" "\n"; // Create an empty formatted image instance of the correct type from the filename @@ -119,6 +120,88 @@ bool save_image(const std::string &dest_filename, LLPointer raw_imag return image->save(dest_filename); } +void store_input_file(std::list &input_filenames, const std::string &path) +{ + // Break the incoming path in its components + std::string dir = gDirUtilp->getDirName(path); + std::string name = gDirUtilp->getBaseFileName(path); + std::string exten = gDirUtilp->getExtension(path); + + // std::cout << "store_input_file : " << path << ", dir : " << dir << ", name : " << name << ", exten : " << exten << std::endl; + + // If extension is not an image type or "*", exit + // Note: we don't support complex patterns for the extension like "j??" + // Note: on most shells, the pattern expansion is done by the shell so that pattern matching limitation is actually not a problem + if ((exten.compare("*") != 0) && (LLImageBase::getCodecFromExtension(exten) == IMG_CODEC_INVALID)) + { + return; + } + + if ((name.find('*') != -1) || ((name.find('?') != -1))) + { + // If file name is a pattern, iterate to get each file name and store + std::string next_name; + while (gDirUtilp->getNextFileInDir(dir,name,next_name)) + { + std::string file_name = dir + gDirUtilp->getDirDelimiter() + next_name; + input_filenames.push_back(file_name); + } + } + else + { + // Verify that the file does exist before storing + if (gDirUtilp->fileExists(path)) + { + input_filenames.push_back(path); + } + else + { + std::cout << "store_input_file : the file " << path << " could not be found" << std::endl; + } + } +} + +void store_output_file(std::list &output_filenames, std::list &input_filenames, const std::string &path) +{ + // Break the incoming path in its components + std::string dir = gDirUtilp->getDirName(path); + std::string name = gDirUtilp->getBaseFileName(path); + std::string exten = gDirUtilp->getExtension(path); + + // std::cout << "store_output_file : " << path << ", dir : " << dir << ", name : " << name << ", exten : " << exten << std::endl; + + if (dir.empty() && exten.empty()) + { + // If dir and exten are empty, we interpret the name as a file extension type name and will iterate through input list to populate the output list + exten = name; + // Make sure the extension is an image type + if (LLImageBase::getCodecFromExtension(exten) == IMG_CODEC_INVALID) + { + return; + } + std::string delim = gDirUtilp->getDirDelimiter(); + std::list::iterator in_file = input_filenames.begin(); + std::list::iterator end = input_filenames.end(); + for (; in_file != end; ++in_file) + { + dir = gDirUtilp->getDirName(*in_file); + name = gDirUtilp->getBaseFileName(*in_file,true); + std::string file_name = dir + delim + name + "." + exten; + output_filenames.push_back(file_name); + } + } + else + { + // Make sure the extension is an image type + if (LLImageBase::getCodecFromExtension(exten) == IMG_CODEC_INVALID) + { + return; + } + // Store the path + output_filenames.push_back(path); + } +} + int main(int argc, char** argv) { // List of input and output files @@ -143,24 +226,40 @@ int main(int argc, char** argv) std::string file_name = argv[arg+1]; while (file_name[0] != '-') // if arg starts with '-', we consider it's not a file name but some other argument { - input_filenames.push_back(file_name); // Add file name to the list + // std::cout << "input file name : " << file_name << std::endl; + store_input_file(input_filenames, file_name); arg += 1; // Skip that arg now we know it's a file name if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list break; file_name = argv[arg+1]; // Next argument and loop over } - } + // DEBUG output + std::list::iterator in_file = input_filenames.begin(); + std::list::iterator end = input_filenames.end(); + for (; in_file != end; ++in_file) + { + std::cout << "input file : " << *in_file << std::endl; + } + } else if (!strcmp(argv[arg], "--out") && arg < argc-1) { std::string file_name = argv[arg+1]; while (file_name[0] != '-') // if arg starts with '-', we consider it's not a file name but some other argument { - output_filenames.push_back(file_name); // Add file name to the list + // std::cout << "output file name : " << file_name << std::endl; + store_output_file(output_filenames, input_filenames, file_name); arg += 1; // Skip that arg now we know it's a file name if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list break; file_name = argv[arg+1]; // Next argument and loop over } + // DEBUG output + std::list::iterator out_file = output_filenames.begin(); + std::list::iterator end = output_filenames.end(); + for (; out_file != end; ++out_file) + { + std::cout << "output file : " << *out_file << std::endl; + } } } @@ -170,12 +269,6 @@ int main(int argc, char** argv) std::cout << "No input file, nothing to do -> exit" << std::endl; return 0; } - // TODO: For the moment, we simply convert each input file to something. This needs to evolve... - if (input_filenames.size() != output_filenames.size()) - { - std::cout << "Number of output and input files different -> exit" << std::endl; - return 0; - } std::list::iterator in_file = input_filenames.begin(); std::list::iterator out_file = output_filenames.begin(); -- cgit v1.3 From 7d47ea1ab254e13cbff476fee317042f81d84b25 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 16 Feb 2011 21:50:32 -0800 Subject: STORM-987 : Allow more flexibility around input and output lists --- .../llimage_libtest/llimage_libtest.cpp | 36 ++++++++++------------ 1 file changed, 16 insertions(+), 20 deletions(-) (limited to 'indra/integration_tests/llimage_libtest/llimage_libtest.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 37e979b260..4104527f83 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -233,13 +233,6 @@ int main(int argc, char** argv) break; file_name = argv[arg+1]; // Next argument and loop over } - // DEBUG output - std::list::iterator in_file = input_filenames.begin(); - std::list::iterator end = input_filenames.end(); - for (; in_file != end; ++in_file) - { - std::cout << "input file : " << *in_file << std::endl; - } } else if (!strcmp(argv[arg], "--out") && arg < argc-1) { @@ -253,13 +246,6 @@ int main(int argc, char** argv) break; file_name = argv[arg+1]; // Next argument and loop over } - // DEBUG output - std::list::iterator out_file = output_filenames.begin(); - std::list::iterator end = output_filenames.end(); - for (; out_file != end; ++out_file) - { - std::cout << "output file : " << *out_file << std::endl; - } } } @@ -270,10 +256,12 @@ int main(int argc, char** argv) return 0; } + // Perform action on each input file std::list::iterator in_file = input_filenames.begin(); std::list::iterator out_file = output_filenames.begin(); - std::list::iterator end = input_filenames.end(); - for (; in_file != end; ++in_file, ++out_file) + std::list::iterator in_end = input_filenames.end(); + std::list::iterator out_end = output_filenames.end(); + for (; in_file != in_end; ++in_file) { // Load file LLPointer raw_image = load_image(*in_file); @@ -284,16 +272,24 @@ int main(int argc, char** argv) } // Save file - if (!save_image(*out_file, raw_image)) + if (out_file != out_end) { - std::cout << "Error: Image " << *out_file << " could not be saved" << std::endl; - continue; + if (!save_image(*out_file, raw_image)) + { + std::cout << "Error: Image " << *out_file << " could not be saved" << std::endl; + } + else + { + std::cout << *in_file << " -> " << *out_file << std::endl; + } + ++out_file; } - std::cout << *in_file << " -> " << *out_file << std::endl; // Output stats on each file } + // Output perf data if required by user + // Cleanup and exit LLImage::cleanupClass(); -- cgit v1.3 From cb0dcc204dd8cd6015ffc25c19557b76cf213084 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 8 Mar 2011 23:44:00 -0800 Subject: STORM-987 : Add --logmetrics and --analyzeperformance arguments, moved analyzeMetricPerformanceLog() and doAnalysisMetrics() from LLFastTimerView to LLMetricPerformanceTesterBasic --- .../llimage_libtest/llimage_libtest.cpp | 89 +++++++++++++++++++++- indra/llcommon/llmetricperformancetester.cpp | 71 +++++++++++++++++ indra/llcommon/llmetricperformancetester.h | 3 + indra/newview/llfasttimerview.cpp | 74 +----------------- indra/newview/llfasttimerview.h | 2 - 5 files changed, 162 insertions(+), 77 deletions(-) (limited to 'indra/integration_tests/llimage_libtest/llimage_libtest.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 4104527f83..2442313ef2 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -26,6 +26,7 @@ */ #include "linden_common.h" #include "llpointer.h" +#include "lltimer.h" #include "llimage_libtest.h" @@ -49,8 +50,13 @@ static const char USAGE[] = "\n" " --in list of image files to load and convert, patterns can be used\n" " --out OR list of image files to create (assumes same order as --in files)\n" " OR 3 letters file type extension to convert each input file into\n" +" --logmetrics log performance metric and data for \n" +" --analyzeperformance create report comparing baseline with current for provided in --logmetrics\n" "\n"; +// true when all image loading is done. Used by metric logging thread to know when to stop the thread. +static bool sAllDone = false; + // Create an empty formatted image instance of the correct type from the filename LLPointer create_image(const std::string &filename) { @@ -202,15 +208,43 @@ void store_output_file(std::list &output_filenames, std::list input_filenames; std::list output_filenames; + bool analyze_performance = false; // Init whatever is necessary ll_init_apr(); LLImage::initClass(); + LogThread* fast_timer_log_thread = NULL; // For performance and metric gathering // Analyze command line arguments for (int arg = 1; arg < argc; ++arg) @@ -246,7 +280,34 @@ int main(int argc, char** argv) break; file_name = argv[arg+1]; // Next argument and loop over } - } + } + else if (!strcmp(argv[arg], "--logmetrics")) + { + // '--logmetrics' needs to be specified with a named test metric argument + // Note: for the moment, only ImageCompressionTester has been tested + std::string test_name; + if ((arg + 1) < argc) + { + test_name = argv[arg+1]; + } + if (((arg + 1) >= argc) || (test_name[0] == '-')) + { + // We don't have an argument left in the arg list or the next argument is another option + std::cout << "No --logmetrics argument given, no perf data will be gathered" << std::endl; + } + else + { + LLFastTimer::sMetricLog = TRUE; + LLFastTimer::sLogName = test_name; + arg += 1; // Skip that arg now we know it's a valid test name + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + } + } + else if (!strcmp(argv[arg], "--analyzeperformance")) + { + analyze_performance = true; + } } // Analyze the list of (input,output) files @@ -256,6 +317,14 @@ int main(int argc, char** argv) return 0; } + // Create the logging thread if required + if (LLFastTimer::sMetricLog) + { + LLFastTimer::sLogLock = new LLMutex(NULL); + fast_timer_log_thread = new LogThread(LLFastTimer::sLogName); + fast_timer_log_thread->start(); + } + // Perform action on each input file std::list::iterator in_file = input_filenames.begin(); std::list::iterator out_file = output_filenames.begin(); @@ -288,10 +357,26 @@ int main(int argc, char** argv) // Output stats on each file } - // Output perf data if required by user + 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"; + + LLMetricPerformanceTesterBasic::doAnalysisMetrics(baseline_name, current_name, report_name); + } // Cleanup and exit LLImage::cleanupClass(); + if (fast_timer_log_thread) + { + fast_timer_log_thread->shutdown(); + } return 0; } diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp index 5fa3a5ea07..1f1c633909 100644 --- a/indra/llcommon/llmetricperformancetester.cpp +++ b/indra/llcommon/llmetricperformancetester.cpp @@ -83,7 +83,78 @@ BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name) return (LLFastTimer::sMetricLog && ((LLFastTimer::sLogName == name) || (LLFastTimer::sLogName == DEFAULT_METRIC_NAME))); } +/*static*/ +LLSD LLMetricPerformanceTesterBasic::analyzeMetricPerformanceLog(std::istream& is) +{ + LLSD ret; + LLSD cur; + + while (!is.eof() && LLSDSerialize::fromXML(cur, is)) + { + for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter) + { + std::string label = iter->first; + + LLMetricPerformanceTesterBasic* tester = LLMetricPerformanceTesterBasic::getTester(iter->second["Name"].asString()) ; + if(tester) + { + ret[label]["Name"] = iter->second["Name"] ; + + S32 num_of_metrics = tester->getNumberOfMetrics() ; + for(S32 index = 0 ; index < num_of_metrics ; index++) + { + ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ; + } + } + } + } + + return ret; +} + +/*static*/ +void LLMetricPerformanceTesterBasic::doAnalysisMetrics(std::string baseline, std::string target, std::string output) +{ + if(!LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters()) + { + return ; + } + + // Open baseline and current target, exit if one is inexistent + std::ifstream base_is(baseline.c_str()); + std::ifstream target_is(target.c_str()); + if (!base_is.is_open() || !target_is.is_open()) + { + llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl; + base_is.close(); + target_is.close(); + return; + } + + //analyze baseline + LLSD base = analyzeMetricPerformanceLog(base_is); + base_is.close(); + + //analyze current + LLSD current = analyzeMetricPerformanceLog(target_is); + target_is.close(); + //output comparision + std::ofstream os(output.c_str()); + + os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n"; + for(LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin() ; + iter != LLMetricPerformanceTesterBasic::sTesterMap.end() ; ++iter) + { + LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second) ; + tester->analyzePerformance(&os, &base, ¤t) ; + } + + os.flush(); + os.close(); +} + + //---------------------------------------------------------------------------------------------- // LLMetricPerformanceTesterBasic : Tester instance methods //---------------------------------------------------------------------------------------------- diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h index 1372f48dcf..b790b636a7 100644 --- a/indra/llcommon/llmetricperformancetester.h +++ b/indra/llcommon/llmetricperformancetester.h @@ -62,6 +62,8 @@ public: */ virtual void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ; + static void doAnalysisMetrics(std::string baseline, std::string target, std::string output) ; + /** * @return Returns the number of the test metrics in this tester instance. */ @@ -116,6 +118,7 @@ protected: private: void preOutputTestResults(LLSD* sd) ; void postOutputTestResults(LLSD* sd) ; + static LLSD analyzeMetricPerformanceLog(std::istream& is) ; std::string mName ; // Name of this tester instance S32 mCount ; // Current record count diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 92a3b9b2f5..279904b740 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -1149,36 +1149,6 @@ void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target os.close(); } -//------------------------- -//static -LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is) -{ - LLSD ret; - LLSD cur; - - while (!is.eof() && LLSDSerialize::fromXML(cur, is)) - { - for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter) - { - std::string label = iter->first; - - LLMetricPerformanceTesterBasic* tester = LLMetricPerformanceTesterBasic::getTester(iter->second["Name"].asString()) ; - if(tester) - { - ret[label]["Name"] = iter->second["Name"] ; - - S32 num_of_metrics = tester->getNumberOfMetrics() ; - for(S32 index = 0 ; index < num_of_metrics ; index++) - { - ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ; - } - } - } - } - - return ret; -} - //static void LLFastTimerView::outputAllMetrics() { @@ -1193,48 +1163,6 @@ void LLFastTimerView::outputAllMetrics() } } -//static -void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target, std::string output) -{ - if(!LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters()) - { - return ; - } - - // Open baseline and current target, exit if one is inexistent - std::ifstream base_is(baseline.c_str()); - std::ifstream target_is(target.c_str()); - if (!base_is.is_open() || !target_is.is_open()) - { - llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl; - base_is.close(); - target_is.close(); - return; - } - - //analyze baseline - LLSD base = analyzeMetricPerformanceLog(base_is); - base_is.close(); - - //analyze current - LLSD current = analyzeMetricPerformanceLog(target_is); - target_is.close(); - - //output comparision - std::ofstream os(output.c_str()); - - os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n"; - for(LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin() ; - iter != LLMetricPerformanceTesterBasic::sTesterMap.end() ; ++iter) - { - LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second) ; - tester->analyzePerformance(&os, &base, ¤t) ; - } - - os.flush(); - os.close(); -} - //static void LLFastTimerView::doAnalysis(std::string baseline, std::string target, std::string output) { @@ -1246,7 +1174,7 @@ void LLFastTimerView::doAnalysis(std::string baseline, std::string target, std:: if(LLFastTimer::sMetricLog) { - doAnalysisMetrics(baseline, target, output) ; + LLMetricPerformanceTesterBasic::doAnalysisMetrics(baseline, target, output) ; return ; } } diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index 1a54a53f09..b40d7ffc1a 100644 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -42,8 +42,6 @@ public: private: static void doAnalysisDefault(std::string baseline, std::string target, std::string output) ; - static void doAnalysisMetrics(std::string baseline, std::string target, std::string output) ; - static LLSD analyzeMetricPerformanceLog(std::istream& is) ; static LLSD analyzePerformanceLogDefault(std::istream& is) ; public: -- cgit v1.3 From 7f42c02cad9dbd068bc49bed4b6cd18fd8fff606 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 9 Mar 2011 20:54:59 -0800 Subject: STORM-987 : Add the --image-stats argument, make argument passing more consistent, fix typos in comments in llimage header --- .../llimage_libtest/llimage_libtest.cpp | 66 ++++++++++++++++------ indra/llimage/llimage.h | 4 +- 2 files changed, 51 insertions(+), 19 deletions(-) (limited to 'indra/integration_tests/llimage_libtest/llimage_libtest.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 2442313ef2..e4376dd745 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -46,12 +46,19 @@ static const char USAGE[] = "\n" "usage:\tllimage_libtest [options]\n" "\n" -" --help print this help\n" -" --in list of image files to load and convert, patterns can be used\n" -" --out OR list of image files to create (assumes same order as --in files)\n" -" OR 3 letters file type extension to convert each input file into\n" -" --logmetrics log performance metric and data for \n" -" --analyzeperformance create report comparing baseline with current for provided in --logmetrics\n" +" -h, --help\n" +" Print this help\n" +" -i, --input \n" +" List of image files to load and convert, patterns can be used\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" +" -log, --logmetrics \n" +" Log performance metric and data for \n" +" -r, --analyzeperformance\n" +" Create report comparing baseline with current for provided in --logmetrics\n" +" -s, --image-stats\n" +" Output stats for each input and output image\n" "\n"; // true when all image loading is done. Used by metric logging thread to know when to stop the thread. @@ -88,8 +95,20 @@ LLPointer create_image(const std::string &filename) return image; } +void output_image_stats(LLPointer image, const std::string &filename) +{ + // Print out some statistical data on the image + std::cout << "Image stats for : " << filename << ", extension : " << image->getExtension() << std::endl; + + std::cout << " with : " << (int)(image->getWidth()) << ", height : " << (int)(image->getHeight()) << std::endl; + std::cout << " comp : " << (int)(image->getComponents()) << ", levels : " << (int)(image->getDiscardLevel()) << std::endl; + std::cout << " head : " << (int)(image->calcHeaderSize()) << ", data : " << (int)(image->getDataSize()) << std::endl; + + return; +} + // Load an image from file and return a raw (decompressed) instance of its data -LLPointer load_image(const std::string &src_filename) +LLPointer load_image(const std::string &src_filename, bool output_stats) { LLPointer image = create_image(src_filename); @@ -104,6 +123,11 @@ LLPointer load_image(const std::string &src_filename) return NULL; } + if (output_stats) + { + output_image_stats(image, src_filename); + } + LLPointer raw_image = new LLImageRaw; if (!image->decode(raw_image, 0.0f)) { @@ -114,7 +138,7 @@ LLPointer load_image(const std::string &src_filename) } // Save a raw image instance into a file -bool save_image(const std::string &dest_filename, LLPointer raw_image) +bool save_image(const std::string &dest_filename, LLPointer raw_image, bool output_stats) { LLPointer image = create_image(dest_filename); @@ -123,6 +147,11 @@ bool save_image(const std::string &dest_filename, LLPointer raw_imag return false; } + if (output_stats) + { + output_image_stats(image, dest_filename); + } + return image->save(dest_filename); } @@ -240,6 +269,7 @@ int main(int argc, char** argv) std::list input_filenames; std::list output_filenames; bool analyze_performance = false; + bool image_stats = false; // Init whatever is necessary ll_init_apr(); @@ -249,13 +279,13 @@ int main(int argc, char** argv) // Analyze command line arguments for (int arg = 1; arg < argc; ++arg) { - if (!strcmp(argv[arg], "--help")) + if (!strcmp(argv[arg], "--help") || !strcmp(argv[arg], "-h")) { // Send the usage to standard out std::cout << USAGE << std::endl; return 0; } - else if (!strcmp(argv[arg], "--in") && arg < argc-1) + else if ((!strcmp(argv[arg], "--input") || !strcmp(argv[arg], "-i")) && arg < argc-1) { std::string file_name = argv[arg+1]; while (file_name[0] != '-') // if arg starts with '-', we consider it's not a file name but some other argument @@ -268,7 +298,7 @@ int main(int argc, char** argv) file_name = argv[arg+1]; // Next argument and loop over } } - else if (!strcmp(argv[arg], "--out") && arg < argc-1) + else if ((!strcmp(argv[arg], "--output") || !strcmp(argv[arg], "-o")) && arg < argc-1) { std::string file_name = argv[arg+1]; while (file_name[0] != '-') // if arg starts with '-', we consider it's not a file name but some other argument @@ -281,7 +311,7 @@ int main(int argc, char** argv) file_name = argv[arg+1]; // Next argument and loop over } } - else if (!strcmp(argv[arg], "--logmetrics")) + else if (!strcmp(argv[arg], "--logmetrics") || !strcmp(argv[arg], "-log")) { // '--logmetrics' needs to be specified with a named test metric argument // Note: for the moment, only ImageCompressionTester has been tested @@ -304,10 +334,14 @@ int main(int argc, char** argv) break; } } - else if (!strcmp(argv[arg], "--analyzeperformance")) + else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-r")) { analyze_performance = true; } + else if (!strcmp(argv[arg], "--image-stats") || !strcmp(argv[arg], "-s")) + { + image_stats = true; + } } // Analyze the list of (input,output) files @@ -333,7 +367,7 @@ int main(int argc, char** argv) for (; in_file != in_end; ++in_file) { // Load file - LLPointer raw_image = load_image(*in_file); + LLPointer raw_image = load_image(*in_file, image_stats); if (!raw_image) { std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl; @@ -343,7 +377,7 @@ int main(int argc, char** argv) // Save file if (out_file != out_end) { - if (!save_image(*out_file, raw_image)) + if (!save_image(*out_file, raw_image, image_stats)) { std::cout << "Error: Image " << *out_file << " could not be saved" << std::endl; } @@ -353,8 +387,6 @@ int main(int argc, char** argv) } ++out_file; } - - // Output stats on each file } sAllDone = true; diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 825b9aab1a..18444f3934 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -266,13 +266,13 @@ public: // subclasses must return a prefered file extension (lowercase without a leading dot) virtual std::string getExtension() = 0; // calcHeaderSize() returns the maximum size of header; - // 0 indicates we don't know have a header and have to lead the entire file + // 0 indicates we don't have a header and have to read the entire file virtual S32 calcHeaderSize() { return 0; }; // calcDataSize() returns how many bytes to read to load discard_level (including header) virtual S32 calcDataSize(S32 discard_level); // calcDiscardLevelBytes() returns the smallest valid discard level based on the number of input bytes virtual S32 calcDiscardLevelBytes(S32 bytes); - // getRawDiscardLevel()by default returns mDiscardLevel, but may be overridden (LLImageJ2C) + // getRawDiscardLevel() by default returns mDiscardLevel, but may be overridden (LLImageJ2C) virtual S8 getRawDiscardLevel() { return mDiscardLevel; } BOOL load(const std::string& filename); -- cgit v1.3 From c2e88db89a8ba111efd0c1b61cc8dec400a007cb Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 10 Mar 2011 22:02:49 -0800 Subject: STORM-987 : Took Vadim's comment into account: check arguments consistency, make sure remaining perf data are flushed on exit. --- .../llimage_libtest/llimage_libtest.cpp | 31 ++++++++++++++++------ indra/llcommon/llmetricperformancetester.cpp | 13 ++++++++- indra/llcommon/llmetricperformancetester.h | 6 +++++ indra/llimage/llimagej2c.cpp | 1 + 4 files changed, 42 insertions(+), 9 deletions(-) (limited to 'indra/integration_tests/llimage_libtest/llimage_libtest.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index e4376dd745..2a1a2ae843 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -49,16 +49,18 @@ static const char USAGE[] = "\n" " -h, --help\n" " Print this help\n" " -i, --input \n" -" List of image files to load and convert, patterns can be used\n" +" List of image files to load and convert. Patterns with wild cards can be used.\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" +" OR 3 letters file type extension to convert each input file into.\n" " -log, --logmetrics \n" -" Log performance metric and data for \n" +" Log performance data for . Results in .slp\n" +" Note: so far, only ImageCompressionTester has been tested.\n" " -r, --analyzeperformance\n" -" Create report comparing baseline with current for provided in --logmetrics\n" +" Create a report comparing _baseline.slp with current .slp\n" +" Results in _report.csv" " -s, --image-stats\n" -" Output stats for each input and output image\n" +" Output stats for each input and output image.\n" "\n"; // true when all image loading is done. Used by metric logging thread to know when to stop the thread. @@ -259,6 +261,8 @@ public: os.flush(); ms_sleep(32); } + LLFastTimer::writeLog(os); + os.flush(); os.close(); } }; @@ -344,12 +348,18 @@ int main(int argc, char** argv) } } - // Analyze the list of (input,output) files + // Check arguments consistency. Exit with proper message if inconsistent. if (input_filenames.size() == 0) { std::cout << "No input file, nothing to do -> exit" << std::endl; return 0; } + 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; + return 0; + } + // Create the logging thread if required if (LLFastTimer::sMetricLog) @@ -388,8 +398,13 @@ int main(int argc, char** argv) ++out_file; } } - - sAllDone = true; + + // 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) diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp index 1f1c633909..41d3eb0bf3 100644 --- a/indra/llcommon/llmetricperformancetester.cpp +++ b/indra/llcommon/llmetricperformancetester.cpp @@ -63,7 +63,18 @@ BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* t sTesterMap.insert(std::make_pair(name, tester)); return TRUE; } - + +/*static*/ +void LLMetricPerformanceTesterBasic::deleteTester(std::string name) +{ + name_tester_map_t::iterator tester = sTesterMap.find(name); + if (tester != sTesterMap.end()) + { + delete tester->second; + sTesterMap.erase(tester); + } +} + /*static*/ LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::string name) { diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h index b790b636a7..1a18cdf36f 100644 --- a/indra/llcommon/llmetricperformancetester.h +++ b/indra/llcommon/llmetricperformancetester.h @@ -137,6 +137,12 @@ public: */ static LLMetricPerformanceTesterBasic* getTester(std::string name) ; + /** + * @return Delete the named tester from the list + * @param[in] name - Name of the tester instance to delete. + */ + static void deleteTester(std::string name); + /** * @return Returns TRUE if that metric *or* the default catch all metric has been requested to be logged * @param[in] name - Name of the tester queried. diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index cb2a85fa91..80fec7f8a0 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -474,6 +474,7 @@ LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTester LLImageCompressionTester::~LLImageCompressionTester() { + outputTestResults(); LLImageJ2C::sTesterp = NULL; } -- cgit v1.3 From 29bcedaf0256968ec48ed3c5791da4b4a23e42d1 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 25 Mar 2011 17:18:28 -0700 Subject: STORM-987 : Fix the creation of images in local dir --- indra/integration_tests/llimage_libtest/llimage_libtest.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'indra/integration_tests/llimage_libtest/llimage_libtest.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 2a1a2ae843..365f5f758c 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -223,7 +223,15 @@ void store_output_file(std::list &output_filenames, std::listgetDirName(*in_file); name = gDirUtilp->getBaseFileName(*in_file,true); - std::string file_name = dir + delim + name + "." + exten; + std::string file_name; + if (!dir.empty()) + { + file_name = dir + delim + name + "." + exten; + } + else + { + file_name = name + "." + exten; + } output_filenames.push_back(file_name); } } -- cgit v1.3 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 +++++++++++++++++++-- indra/llimage/llimagej2c.cpp | 7 ++ indra/llimage/llimagej2c.h | 2 + indra/llimagej2coj/llimagej2coj.cpp | 5 + indra/llimagej2coj/llimagej2coj.h | 1 + indra/llkdu/llimagej2ckdu.cpp | 38 ++++--- indra/llkdu/llimagej2ckdu.h | 3 +- 7 files changed, 161 insertions(+), 21 deletions(-) (limited to 'indra/integration_tests/llimage_libtest/llimage_libtest.cpp') 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; 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; -- 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/llimage_libtest/llimage_libtest.cpp') 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/llimage_libtest/llimage_libtest.cpp') 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/llimage_libtest/llimage_libtest.cpp') 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/llimage_libtest/llimage_libtest.cpp') 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/llimage_libtest/llimage_libtest.cpp') 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