diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index a07ea146212c5e208651ef42ff9519ab11661927..ad765b641531c6122c5ed1f523f5c9641534442d 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1436,7 +1436,7 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
 bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
 {
     S32 components = getComponents();
-	if (! ((1 == components) || (3 == components) || (4 == components) ))
+    if (components != 1 && components != 3 && components != 4)
     {
         LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL;
         return false;
@@ -1512,6 +1512,55 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
 	return true ;
 }
 
+LLPointer<LLImageRaw> LLImageRaw::scaled(S32 new_width, S32 new_height)
+{
+    LLPointer<LLImageRaw> result;
+
+    S32 components = getComponents();
+    if (components != 1 && components != 3 && components != 4)
+    {
+        LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL;
+        return result;
+    }
+
+    if (isBufferInvalid())
+    {
+        LL_WARNS() << "Invalid image buffer" << LL_ENDL;
+        return result;
+    }
+
+    S32 old_width = getWidth();
+    S32 old_height = getHeight();
+
+    if ((old_width == new_width) && (old_height == new_height))
+    {
+        result = new LLImageRaw(old_width, old_height, components);
+        if (!result)
+        {
+            LL_WARNS() << "Failed to allocate new image" << LL_ENDL;
+            return result;
+        }
+        memcpy(result->getData(), getData(), getDataSize());
+    }
+    else
+    {
+        S32 new_data_size = new_width * new_height * components;
+
+        if (new_data_size > 0)
+        {
+            result = new LLImageRaw(new_width, new_height, components);
+            if (!result)
+            {
+                LL_WARNS() << "Failed to allocate new image" << LL_ENDL;
+                return result;
+            }
+            bilinear_scale(getData(), old_width, old_height, components, old_width*components, result->getData(), new_width, new_height, components, new_width*components);
+        }
+    }
+
+    return result;
+}
+
 void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
 {
 	const S32 components = getComponents();
@@ -1785,10 +1834,13 @@ static std::string find_file(std::string &name, S8 *codec)
 #endif
 EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten)
 {
-	for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++)
+	if (!exten.empty())
 	{
-		if (exten == file_extensions[i].exten)
-			return file_extensions[i].codec;
+		for (int i = 0; i < (int)(NUM_FILE_EXTENSIONS); i++)
+		{
+			if (exten == file_extensions[i].exten)
+				return file_extensions[i].codec;
+		}
 	}
 	return IMG_CODEC_INVALID;
 }
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index d0bd4a2aefe554964057bd53051c28be4241f0a5..958c9fad3d1eef2ea7f37285950e3de0f0367ee3 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -215,7 +215,8 @@ class LLImageRaw : public LLImageBase
 	void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, bool scale_image = true);
 	void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, bool scale_image = true);
 	void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
-	bool scale( S32 new_width, S32 new_height, bool scale_image = true );
+	bool scale(S32 new_width, S32 new_height, bool scale_image = true);
+    LLPointer<LLImageRaw> scaled(S32 new_width, S32 new_height);
 	
 	// Fill the buffer with a constant color
 	void fill( const LLColor4U& color );
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index e8b3842ae56bd758fa67d89135b90cfddedeecf5..f0c28041d141bc5ef3d1b2c8f0e9aab03e2e51b4 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -1987,15 +1987,13 @@ bool LLTextureCache::writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 dis
 		if(w * h *c > 0) //valid
 		{
 			//make a duplicate to keep the original raw image untouched.
-			raw = raw->duplicate();
+			raw = raw->scaled(w, h);
 			if (raw->isBufferInvalid())
 			{
 				LL_WARNS() << "Invalid image duplicate buffer" << LL_ENDL;
 				return false;
 			}
 
-			raw->scale(w, h) ;
-			
 			discardlevel += i ;
 		}
 	}
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 5de7df7b9100d7bb9bff3d7825e55e858852f0c0..e5a1bed48cbc06cda219213d65d26792c62a4e33 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1396,8 +1396,7 @@ void LLViewerFetchedTexture::addToCreateTexture()
 
 						{
 							//make a duplicate in case somebody else is using this raw image
-							mRawImage = mRawImage->duplicate(); 
-							mRawImage->scale(w >> i, h >> i) ;					
+							mRawImage = mRawImage->scaled(w >> i, h >> i);
 						}
 					}
 				}
@@ -2913,8 +2912,7 @@ void LLViewerFetchedTexture::setCachedRawImage()
 			
 			{
 				//make a duplicate in case somebody else is using this raw image
-				mRawImage = mRawImage->duplicate(); 
-				mRawImage->scale(w >> i, h >> i) ;
+				mRawImage = mRawImage->scaled(w >> i, h >> i);
 			}
 		}
 		mCachedRawImage = mRawImage;