summaryrefslogtreecommitdiff
path: root/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/integration_tests/llimage_libtest/llimage_libtest.cpp')
-rw-r--r--indra/integration_tests/llimage_libtest/llimage_libtest.cpp212
1 files changed, 167 insertions, 45 deletions
diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 365f5f758c..976aae08bb 100644
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -53,12 +53,36 @@ static const char USAGE[] = "\n"
" -o, --output <file1 .. file2> OR <type>\n"
" List of image files to create (assumes same order as for input files)\n"
" OR 3 letters file type extension to convert each input file into.\n"
+" -r, --region <x0, y0, x1, y1>\n"
+" Crop region applied to the input files in pixels.\n"
+" Only used for j2c images. Default is no region cropping.\n"
+" -d, --discard_level <n>\n"
+" Discard level max used on input. 0 is 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>\n"
+" Dimension of precincts in pixels. Precincts are assumed square and identical for\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>\n"
+" Dimension of coding blocks in pixels. Blocks are assumed square. Power of 2 must\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"
+" -l, --levels <n>\n"
+" Number of decomposition levels (aka discard levels) in the output image.\n"
+" The maximum number of levels authorized is 32.\n"
+" Only valid for output j2c images. Default is 5.\n"
+" -rev, --reversible\n"
+" Set the compression to be lossless (reversible in j2c parlance).\n"
+" Only valid for output j2c images.\n"
" -log, --logmetrics <metric>\n"
" Log performance data for <metric>. Results in <metric>.slp\n"
" Note: so far, only ImageCompressionTester has been tested.\n"
-" -r, --analyzeperformance\n"
+" -a, --analyzeperformance\n"
" Create a report comparing <metric>_baseline.slp with current <metric>.slp\n"
-" Results in <metric>_report.csv"
+" Results in <metric>_report.csv\n"
" -s, --image-stats\n"
" Output stats for each input and output image.\n"
"\n";
@@ -69,31 +93,8 @@ static bool sAllDone = false;
// Create an empty formatted image instance of the correct type from the filename
LLPointer<LLImageFormatted> create_image(const std::string &filename)
{
- std::string exten = gDirUtilp->getExtension(filename);
- U32 codec = LLImageBase::getCodecFromExtension(exten);
-
- LLPointer<LLImageFormatted> 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<LLImageFormatted> image = LLImageFormatted::createFromExtension(exten);
return image;
}
@@ -110,10 +111,11 @@ void output_image_stats(LLPointer<LLImageFormatted> image, const std::string &fi
}
// Load an image from file and return a raw (decompressed) instance of its data
-LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_stats)
+LLPointer<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, bool output_stats)
{
LLPointer<LLImageFormatted> image = create_image(src_filename);
-
+
+ // This just loads the image file stream into a buffer. No decoding done.
if (!image->load(src_filename))
{
return NULL;
@@ -131,6 +133,15 @@ LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_st
}
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
+
+ // Set the image restriction on load in the case of a j2c image
+ if ((image->getCodec() == IMG_CODEC_J2C) && ((discard_level != -1) || (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_level, region);
+ }
+
if (!image->decode(raw_image, 0.0f))
{
return NULL;
@@ -140,10 +151,22 @@ LLPointer<LLImageRaw> 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<LLImageRaw> raw_image, bool output_stats)
+bool save_image(const std::string &dest_filename, LLPointer<LLImageRaw> raw_image, int blocks_size, int precincts_size, int levels, bool reversible, bool output_stats)
{
LLPointer<LLImageFormatted> 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)
+ {
+ // That method doesn't exist (and likely, doesn't make sense) for any other image file format
+ // hence the required cryptic cast.
+ if ((blocks_size != -1) || (precincts_size != -1) || (levels != 0))
+ {
+ ((LLImageJ2C*)(image.get()))->initEncode(*raw_image, blocks_size, precincts_size, levels);
+ }
+ ((LLImageJ2C*)(image.get()))->setReversible(reversible);
+ }
+
if (!image->encode(raw_image, 0.0f))
{
return false;
@@ -280,8 +303,15 @@ int main(int argc, char** argv)
// List of input and output files
std::list<std::string> input_filenames;
std::list<std::string> output_filenames;
+ // Other optional parsed arguments
bool analyze_performance = false;
bool image_stats = false;
+ int* region = NULL;
+ int discard_level = -1;
+ int precincts_size = -1;
+ int blocks_size = -1;
+ int levels = 0;
+ bool reversible = false;
// Init whatever is necessary
ll_init_apr();
@@ -323,6 +353,99 @@ 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;
+ region = new int[4];
+ 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)
+ {
+ std::cout << "--region arguments invalid" << std::endl;
+ delete [] region;
+ region = NULL;
+ }
+ }
+ 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
+ {
+ 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"))
+ {
+ 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
+ {
+ 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
+ {
+ blocks_size = atoi(value_str.c_str());
+ }
+ }
+ else if (!strcmp(argv[arg], "--levels") || !strcmp(argv[arg], "-l"))
+ {
+ std::string value_str;
+ if ((arg + 1) < argc)
+ {
+ value_str = argv[arg+1];
+ }
+ if (((arg + 1) >= argc) || (value_str[0] == '-'))
+ {
+ std::cout << "No valid --levels argument given, default (5) will be used" << std::endl;
+ }
+ else
+ {
+ levels = atoi(value_str.c_str());
+ }
+ }
+ 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
@@ -346,7 +469,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 +487,7 @@ int main(int argc, char** argv)
}
if (analyze_performance && !LLFastTimer::sMetricLog)
{
- std::cout << "Cannot create perf report if no perf gathered (i.e. use argument -log <perf> with -r) -> exit" << std::endl;
+ std::cout << "Cannot create perf report if no perf gathered (i.e. use argument -log <perf> with -a) -> exit" << std::endl;
return 0;
}
@@ -382,10 +505,10 @@ int main(int argc, char** argv)
std::list<std::string>::iterator out_file = output_filenames.begin();
std::list<std::string>::iterator in_end = input_filenames.end();
std::list<std::string>::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<LLImageRaw> raw_image = load_image(*in_file, image_stats);
+ LLPointer<LLImageRaw> 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;
@@ -395,7 +518,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, levels, reversible, image_stats))
{
std::cout << "Error: Image " << *out_file << " could not be saved" << std::endl;
}
@@ -403,29 +526,28 @@ int main(int argc, char** argv)
{
std::cout << *in_file << " -> " << *out_file << std::endl;
}
- ++out_file;
}
}
- // 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)