From e752e918283acf95c1ed33d92a7bf34bbca83071 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Mon, 4 Apr 2011 23:49:40 -0700
Subject: [PATCH] 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(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 10d6ffb685c..31d3e18877e 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<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, bool use_discard_level, int discard_level, bool use_region, int* region)
+LLPointer<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, bool output_stats)
 {
 	LLPointer<LLImageFormatted> image = create_image(src_filename);
 	
@@ -150,13 +150,11 @@ 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))
+	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<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, bool output_stats)
 {
 	LLPointer<LLImageFormatted> 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<LLImageRaw> raw_image = load_image(*in_file, image_stats, use_discard_level, discard_level, use_region, region);
+		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;
@@ -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 6b49f3de889..a90df0f1c17 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 7af1c139216..6bba81aab53 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -57,6 +57,7 @@ class LLImageJ2C : public LLImageFormatted
 	/*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 @@ class LLImageJ2CImpl
 	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 11c826e41a0..8288fa1f5c3 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 d5f2f7a2d1d..9c7cc09fcbc 100644
--- a/indra/llimagej2coj/llimagej2coj.h
+++ b/indra/llimagej2coj/llimagej2coj.h
@@ -40,6 +40,7 @@ class LLImageJ2COJ : public LLImageJ2CImpl
 	/*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 e51cfee6eb7..8d2ed8f8c4e 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 8231004f2c4..9fce58b7625 100644
--- a/indra/llkdu/llimagej2ckdu.h
+++ b/indra/llkdu/llimagej2ckdu.h
@@ -59,6 +59,7 @@ class LLImageJ2CKDU : public LLImageJ2CImpl
 	/*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 @@ class LLImageJ2CKDU : public LLImageJ2CImpl
 	kdu_codestream *mCodeStreamp;
 	kdu_coords *mTPosp; // tile position
 	kdu_dims *mTileIndicesp;
+	int mBlocksSize;
+	int mPrecinctsSize;
 
 	// Temporary variables for in-progress decodes...
 	LLImageRaw *mRawImagep;
-- 
GitLab