diff options
| -rw-r--r-- | indra/integration_tests/llimage_libtest/llimage_libtest.cpp | 68 | ||||
| -rw-r--r-- | indra/llimage/llimage.cpp | 18 | ||||
| -rw-r--r-- | indra/llimage/llimage.h | 7 | ||||
| -rw-r--r-- | indra/llimage/llimagej2c.cpp | 3 | ||||
| -rw-r--r-- | indra/llkdu/llimagej2ckdu.cpp | 10 | 
5 files changed, 86 insertions, 20 deletions
diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 48e876429d..36c5b67826 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -54,6 +54,11 @@ 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" +" -load, --load_size <n>\n" +"        Portion of the input file to load, in bytes." +"        If (load == 0), it will load the whole file." +"        If (load == -1), it will load the size relevant to reach the requested discard level (see -d)." +"        Only valid for j2c images. Default is 0 (load whole file).\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" @@ -104,22 +109,52 @@ void output_image_stats(LLPointer<LLImageFormatted> image, const std::string &fi  	// 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; +	std::cout << "    with : " << (int)(image->getWidth())       << ", height : " << (int)(image->getHeight())   << std::endl; +	std::cout << "    comp : " << (int)(image->getComponents())  << ", levels : " << (int)(image->getLevels())   << 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<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, bool output_stats) +LLPointer<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, int load_size, 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)) +	// We support partial loading only for j2c images +	if (image->getCodec() == IMG_CODEC_J2C)  	{ -		return NULL; +		// Load the header +		if (!image->load(src_filename, 600)) +		{ +			return NULL; +		} +		S32 h = ((LLImageJ2C*)(image.get()))->calcHeaderSize(); +		S32 d = (load_size > 0 ? ((LLImageJ2C*)(image.get()))->calcDiscardLevelBytes(load_size) : 0); +		S8  r = ((LLImageJ2C*)(image.get()))->getRawDiscardLevel(); +		std::cout << "Merov debug : header = " << h << ", load_size = " << load_size << ", discard level = " << d << ", raw discard level = " << r << std::endl; +		for (d = 0; d < MAX_DISCARD_LEVEL; d++) +		{ +			S32 data_size = ((LLImageJ2C*)(image.get()))->calcDataSize(d); +			std::cout << "Merov debug : discard_level = " << d << ", data_size = " << data_size << std::endl; +		} +		if (load_size < 0) +		{ +			load_size = (discard_level != -1 ? ((LLImageJ2C*)(image.get()))->calcDataSize(discard_level) : 0); +		} +		// Load the requested byte range +		if (!image->load(src_filename, load_size)) +		{ +			return NULL; +		} +	} +	else  +	{ +		// This just loads the image file stream into a buffer. No decoding done. +		if (!image->load(src_filename)) +		{ +			return NULL; +		}  	}  	if(	(image->getComponents() != 3) && (image->getComponents() != 4) ) @@ -310,6 +345,7 @@ int main(int argc, char** argv)  	bool image_stats = false;  	int* region = NULL;  	int discard_level = -1; +	int load_size = 0;  	int precincts_size = -1;  	int blocks_size = -1;  	int levels = 0; @@ -396,6 +432,22 @@ int main(int argc, char** argv)  				discard_level = llclamp(discard_level,0,5);  			}  		} +		else if (!strcmp(argv[arg], "--load_size") || !strcmp(argv[arg], "-load")) +		{ +			std::string value_str; +			if ((arg + 1) < argc) +			{ +				value_str = argv[arg+1]; +			} +			if (((arg + 1) >= argc) || (value_str[0] == '-')) +			{ +				std::cout << "No valid --load_size argument given, load_size ignored" << std::endl; +			} +			else +			{ +				load_size = atoi(value_str.c_str()); +			} +		}  		else if (!strcmp(argv[arg], "--precincts") || !strcmp(argv[arg], "-p"))  		{  			std::string value_str; @@ -510,7 +562,7 @@ int main(int argc, char** argv)  	for (; in_file != in_end; ++in_file, ++out_file)  	{  		// Load file -		LLPointer<LLImageRaw> raw_image = load_image(*in_file, discard_level, region, image_stats); +		LLPointer<LLImageRaw> raw_image = load_image(*in_file, discard_level, region, load_size, image_stats);  		if (!raw_image)  		{  			std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl; diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 56e01ac851..937655a22d 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1334,7 +1334,8 @@ LLImageFormatted::LLImageFormatted(S8 codec)  	  mCodec(codec),  	  mDecoding(0),  	  mDecoded(0), -	  mDiscardLevel(-1) +	  mDiscardLevel(-1), +	  mLevels(0)  {  	mMemType = LLMemType::MTYPE_IMAGEFORMATTED;  } @@ -1561,7 +1562,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size)  //---------------------------------------------------------------------------- -BOOL LLImageFormatted::load(const std::string &filename) +BOOL LLImageFormatted::load(const std::string &filename, int load_size)  {  	resetLastError(); @@ -1580,14 +1581,19 @@ BOOL LLImageFormatted::load(const std::string &filename)  		return FALSE;  	} +	// Constrain the load size to acceptable values +	if ((load_size == 0) || (load_size > file_size)) +	{ +		load_size = file_size; +	}  	BOOL res; -	U8 *data = allocateData(file_size); -	apr_size_t bytes_read = file_size; +	U8 *data = allocateData(load_size); +	apr_size_t bytes_read = load_size;  	apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read -	if (s != APR_SUCCESS || (S32) bytes_read != file_size) +	if (s != APR_SUCCESS || (S32) bytes_read != load_size)  	{  		deleteData(); -		setLastError("Unable to read entire file",filename); +		setLastError("Unable to read file",filename);  		res = FALSE;  	}  	else diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 4469c9e860..eba8362f1c 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -294,7 +294,7 @@ public:  	// getRawDiscardLevel() by default returns mDiscardLevel, but may be overridden (LLImageJ2C)  	virtual S8  getRawDiscardLevel() { return mDiscardLevel; } -	BOOL load(const std::string& filename); +	BOOL load(const std::string& filename, int load_size = 0);  	BOOL save(const std::string& filename);  	virtual BOOL updateData() = 0; // pure virtual @@ -313,6 +313,8 @@ public:  	BOOL isDecoded()  const { return mDecoded ? TRUE : FALSE; }  	void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; }  	S8 getDiscardLevel() const { return mDiscardLevel; } +	S8 getLevels() const { return mLevels; } +	void setLevels(S8 nlevels) { mLevels = nlevels; }  	// setLastError needs to be deferred for J2C images since it may be called from a DLL  	virtual void resetLastError(); @@ -325,7 +327,8 @@ protected:  	S8 mCodec;  	S8 mDecoding;  	S8 mDecoded;  // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC -	S8 mDiscardLevel; +	S8 mDiscardLevel;	// Current resolution level worked on. 0 = full res, 1 = half res, 2 = quarter res, etc... +	S8 mLevels;			// Number of resolution levels in that image. Min is 1. 0 means unknown.  public:  	static S32 sGlobalFormattedMemory; diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index cc8cb66d73..fbf4b769e1 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -142,6 +142,7 @@ BOOL LLImageJ2C::updateData()  BOOL LLImageJ2C::initDecode(LLImageRaw &raw_image, int discard_level, int* region)  { +	setDiscardLevel(discard_level != -1 ? discard_level : 0);  	return mImpl->initDecode(*this,raw_image,discard_level,region);  } @@ -286,6 +287,8 @@ S32 LLImageJ2C::calcHeaderSize()  // calcDataSize() returns how many bytes to read   // to load discard_level (including header and higher discard levels) +// *TODO: This is deeply wrong. That size should be taken from the image file header or other  +// relevant infos. In any case, this is only an approximation.  S32 LLImageJ2C::calcDataSize(S32 discard_level)  {  	discard_level = llclamp(discard_level, 0, MAX_DISCARD_LEVEL); diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index c156ed0cef..eed4139f3f 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -291,8 +291,13 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod  		}  	} -	base.setSize(dims.size.x, dims.size.y, components); +	// Get the number of resolution levels in that image +	mLevels = mCodeStreamp->get_min_dwt_levels(); +	// Set the base dimensions +	base.setSize(dims.size.x, dims.size.y, components); +	base.setLevels(mLevels); +	  	if (!keep_codestream)  	{  		mCodeStreamp->destroy(); @@ -394,12 +399,9 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco  		// Resize raw_image according to the image to be decoded  		kdu_dims dims; mCodeStreamp->get_dims(0,dims); -		// *TODO: Use the real number of levels read from the file throughout the code instead of relying on an infered value from dimensions -		//S32 levels = mCodeStreamp->get_min_dwt_levels();  		S32 channels = base.getComponents() - first_channel;  		channels = llmin(channels,max_channel_count);  		raw_image.resize(dims.size.x, dims.size.y, channels); -		//llinfos << "j2c image dimension: width = " << dims.size.x << ", height = " << dims.size.y << ", channels = " << channels << ", levels = " << levels << llendl;  		if (!mTileIndicesp)  		{  | 
