diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 48e876429dfaac10b7e3085c3d4eb1324aa3b7ec..9d524367ed765bf98264363c37d9f03b9d8e762f 100644
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -104,9 +104,9 @@ 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;
 }
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 56e01ac851e7a067bf740f3bb0a29440e003691a..091e78e358a3dc24fc7f04ad825dad8bde75eb29 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;
 }
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 4469c9e86025e628d2b1100c6d8c85baaa604c93..847ba8c11c14c8bdb619bff5e02cbb8c8c7966ee 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -313,6 +313,8 @@ class LLImageFormatted : public LLImageBase
 	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 @@ class LLImageFormatted : public LLImageBase
 	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 cc8cb66d7390802f2e41297367ab90b0886f5f70..fbf4b769e1b8e287622435367509445a0a5eef2c 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 c156ed0cef40411d153e9d825b27ff1e26a04b59..eed4139f3f39b2a32f24d4312f72239876520722 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)
 		{