STORM-746 : add new arguments for precincts and blocks on output, region and level on input, add code for input loading restriction
parent
dc00f42dd7
commit
83ec0cd62f
|
|
@ -53,12 +53,28 @@ static const char USAGE[] = "\n"
|
|||
" -o, --output <file1 .. file2> OR <type>\n"
|
||||
" List of image files to create (assumes same order as for input files)\n"
|
||||
" OR 3 letters file type extension to convert each input file into.\n"
|
||||
" -r, --region <x0, y0, x1, y1>\n"
|
||||
" Crop region on the input file in pixel.\n"
|
||||
" Only used for j2c images. Default is no region cropping.\n"
|
||||
" -d, --discard_level <n>\n"
|
||||
" Discard level max used on input. 0 is high resolution. Max discard level is 5.\n"
|
||||
" This allows the input image to be clamped in resolution when loading.\n"
|
||||
" Only valid for j2c images. Default is no discard.\n"
|
||||
" -p, --precincts <n>\n"
|
||||
" Dimension of precincts in pixels. Precincts are assumed square and identical for\n"
|
||||
" all levels. Note that this oprion also uses PLT and tile markers, \n"
|
||||
" as well as RPCL order. Power of 2 must be used.\n"
|
||||
" Only valid for output j2c images. Default is no precincts used.\n"
|
||||
" -b, --blocks <n>\n"
|
||||
" Dimension of coding blocks in pixels. Blocks are assumed square. Power of 2 must\n"
|
||||
" be used. Blocks must be smaller than precincts.\n"
|
||||
" Only valid for output j2c images. Default is 64.\n"
|
||||
" -log, --logmetrics <metric>\n"
|
||||
" Log performance data for <metric>. Results in <metric>.slp\n"
|
||||
" Note: so far, only ImageCompressionTester has been tested.\n"
|
||||
" -r, --analyzeperformance\n"
|
||||
" -a, --analyzeperformance\n"
|
||||
" Create a report comparing <metric>_baseline.slp with current <metric>.slp\n"
|
||||
" Results in <metric>_report.csv"
|
||||
" Results in <metric>_report.csv\n"
|
||||
" -s, --image-stats\n"
|
||||
" Output stats for each input and output image.\n"
|
||||
"\n";
|
||||
|
|
@ -110,10 +126,11 @@ void output_image_stats(LLPointer<LLImageFormatted> image, const std::string &fi
|
|||
}
|
||||
|
||||
// Load an image from file and return a raw (decompressed) instance of its data
|
||||
LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_stats)
|
||||
LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_stats, bool use_discard_level, int discard_level, bool use_region, int* region)
|
||||
{
|
||||
LLPointer<LLImageFormatted> image = create_image(src_filename);
|
||||
|
||||
|
||||
// This just load the image file stream into a buffer. No decoding done.
|
||||
if (!image->load(src_filename))
|
||||
{
|
||||
return NULL;
|
||||
|
|
@ -131,6 +148,17 @@ LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_st
|
|||
}
|
||||
|
||||
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
|
||||
|
||||
// Set the image restriction on load in the case of a j2c image
|
||||
if ((image->getCodec() == IMG_CODEC_J2C) && (use_discard_level || use_region))
|
||||
{
|
||||
int discard = (use_discard_level ? discard_level : -1);
|
||||
int* reg = (use_region ? region : NULL);
|
||||
// That method doesn't exist (and likely, doesn't make sense) for any other image file format
|
||||
// hence the required cryptic cast.
|
||||
((LLImageJ2C*)(image.get()))->initDecode(*raw_image, discard, reg);
|
||||
}
|
||||
|
||||
if (!image->decode(raw_image, 0.0f))
|
||||
{
|
||||
return NULL;
|
||||
|
|
@ -280,8 +308,17 @@ int main(int argc, char** argv)
|
|||
// List of input and output files
|
||||
std::list<std::string> input_filenames;
|
||||
std::list<std::string> output_filenames;
|
||||
// Other optional parsed arguments
|
||||
bool analyze_performance = false;
|
||||
bool image_stats = false;
|
||||
bool use_region = false;
|
||||
int region[4];
|
||||
bool use_discard_level = false;
|
||||
int discard_level = 0;
|
||||
bool use_precincts = false;
|
||||
int precincts_size;
|
||||
bool use_blocks = false;
|
||||
int blocks_size;
|
||||
|
||||
// Init whatever is necessary
|
||||
ll_init_apr();
|
||||
|
|
@ -323,6 +360,81 @@ int main(int argc, char** argv)
|
|||
file_name = argv[arg+1]; // Next argument and loop over
|
||||
}
|
||||
}
|
||||
else if ((!strcmp(argv[arg], "--region") || !strcmp(argv[arg], "-r")) && arg < argc-1)
|
||||
{
|
||||
std::string value_str = argv[arg+1];
|
||||
int index = 0;
|
||||
while (value_str[0] != '-') // if arg starts with '-', it's the next option
|
||||
{
|
||||
int value = atoi(value_str.c_str());
|
||||
region[index++] = value;
|
||||
arg += 1; // Definitely skip that arg now we know it's a number
|
||||
if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list
|
||||
break;
|
||||
if (index == 4) // Break out of the loop if we captured 4 values already
|
||||
break;
|
||||
value_str = argv[arg+1]; // Next argument and loop over
|
||||
}
|
||||
if (index == 4)
|
||||
{
|
||||
use_region = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "--region arguments invalid" << std::endl;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "--discard_level") || !strcmp(argv[arg], "-d"))
|
||||
{
|
||||
std::string value_str;
|
||||
if ((arg + 1) < argc)
|
||||
{
|
||||
value_str = argv[arg+1];
|
||||
}
|
||||
if (((arg + 1) >= argc) || (value_str[0] == '-'))
|
||||
{
|
||||
std::cout << "No valid --discard_level argument given, discard_level ignored" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
use_discard_level = true;
|
||||
discard_level = atoi(value_str.c_str());
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "--precincts") || !strcmp(argv[arg], "-p"))
|
||||
{
|
||||
std::string value_str;
|
||||
if ((arg + 1) < argc)
|
||||
{
|
||||
value_str = argv[arg+1];
|
||||
}
|
||||
if (((arg + 1) >= argc) || (value_str[0] == '-'))
|
||||
{
|
||||
std::cout << "No valid --precincts argument given, precincts ignored" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
use_precincts = true;
|
||||
precincts_size = atoi(value_str.c_str());
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "--blocks") || !strcmp(argv[arg], "-b"))
|
||||
{
|
||||
std::string value_str;
|
||||
if ((arg + 1) < argc)
|
||||
{
|
||||
value_str = argv[arg+1];
|
||||
}
|
||||
if (((arg + 1) >= argc) || (value_str[0] == '-'))
|
||||
{
|
||||
std::cout << "No valid --blocks argument given, blocks ignored" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
use_blocks = true;
|
||||
blocks_size = atoi(value_str.c_str());
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "--logmetrics") || !strcmp(argv[arg], "-log"))
|
||||
{
|
||||
// '--logmetrics' needs to be specified with a named test metric argument
|
||||
|
|
@ -346,7 +458,7 @@ int main(int argc, char** argv)
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-r"))
|
||||
else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
|
||||
{
|
||||
analyze_performance = true;
|
||||
}
|
||||
|
|
@ -364,7 +476,7 @@ int main(int argc, char** argv)
|
|||
}
|
||||
if (analyze_performance && !LLFastTimer::sMetricLog)
|
||||
{
|
||||
std::cout << "Cannot create perf report if no perf gathered (i.e. use argument -log <perf> with -r) -> exit" << std::endl;
|
||||
std::cout << "Cannot create perf report if no perf gathered (i.e. use argument -log <perf> with -a) -> exit" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -385,7 +497,7 @@ int main(int argc, char** argv)
|
|||
for (; in_file != in_end; ++in_file)
|
||||
{
|
||||
// Load file
|
||||
LLPointer<LLImageRaw> raw_image = load_image(*in_file, image_stats);
|
||||
LLPointer<LLImageRaw> raw_image = load_image(*in_file, image_stats, use_discard_level, discard_level, use_region, region);
|
||||
if (!raw_image)
|
||||
{
|
||||
std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue