diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 01c4b1f50ef7ac0b833866e7ed221d240309587f..a5ad2e4d4ec5a331c359934abc87d9b460915b01 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -512,6 +512,7 @@ set(viewer_SOURCE_FILES
     llsidetraypanelcontainer.cpp
     llsky.cpp
     llslurl.cpp
+    llsnapshotlivepreview.cpp
     llsociallist.cpp
     llspatialpartition.cpp
     llspeakers.cpp
@@ -1090,6 +1091,7 @@ set(viewer_HEADER_FILES
     llsidetraypanelcontainer.h
     llsky.h
     llslurl.h
+    llsnapshotlivepreview.h
     llsociallist.h
     llspatialpartition.h
     llspeakers.h
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 070360096124ad50e12f6d185312cc51ab73db87..e72de9751e1a42bd996f371b9241ca02f0d218f2 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -55,6 +55,7 @@
 #include "llviewermenufile.h"	// upload_new_resource()
 #include "llcheckboxctrl.h"
 #include "llslurl.h"
+#include "llsnapshotlivepreview.h"
 #include "lltoolfocus.h"
 #include "lltoolmgr.h"
 #include "llwebsharing.h"
@@ -92,949 +93,12 @@ LLSnapshotFloaterView* gSnapshotFloaterView = NULL;
 
 const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
 
-F32 SHINE_TIME = 0.5f;
-F32 SHINE_WIDTH = 0.6f;
-F32 SHINE_OPACITY = 0.3f;
-F32 FALL_TIME = 0.6f;
-S32 BORDER_WIDTH = 6;
-
 const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
 const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
 
 static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view");
 
-///----------------------------------------------------------------------------
-/// Class LLSnapshotLivePreview 
-///----------------------------------------------------------------------------
-class LLSnapshotLivePreview : public LLView
-{
-	LOG_CLASS(LLSnapshotLivePreview);
-public:
-	enum ESnapshotType
-	{
-		SNAPSHOT_POSTCARD,
-		SNAPSHOT_TEXTURE,
-		SNAPSHOT_LOCAL,
-		SNAPSHOT_WEB
-	};
-
-
-	struct Params : public LLInitParam::Block<Params, LLView::Params>
-	{
-		Params()
-		{
-			name = "snapshot_live_preview";
-			mouse_opaque = false;
-		}
-	};
-
-
-	LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p);
-	~LLSnapshotLivePreview();
-
-	/*virtual*/ void draw();
-	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
-	
-	void setSize(S32 w, S32 h);
-	void setWidth(S32 w) { mWidth[mCurImageIndex] = w; }
-	void setHeight(S32 h) { mHeight[mCurImageIndex] = h; }
-	void getSize(S32& w, S32& h) const;
-	S32 getWidth() const { return mWidth[mCurImageIndex]; }
-	S32 getHeight() const { return mHeight[mCurImageIndex]; }
-	S32 getDataSize() const { return mDataSize; }
-	void setMaxImageSize(S32 size) ;
-	S32  getMaxImageSize() {return mMaxImageSize ;}
-	
-	ESnapshotType getSnapshotType() const { return mSnapshotType; }
-	LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
-	BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
-	BOOL isSnapshotActive() { return mSnapshotActive; }
-	LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; }
-	S32  getThumbnailWidth() const { return mThumbnailWidth ; }
-	S32  getThumbnailHeight() const { return mThumbnailHeight ; }
-	BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
-	BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
-	LLViewerTexture* getCurrentImage();
-	F32 getImageAspect();
-	F32 getAspect() ;
-	const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; }
-	BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; }
-	void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }
-	const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }
-	
-	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
-	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
-	void setSnapshotQuality(S32 quality);
-	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
-	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
-	void saveWeb();
-	void saveTexture();
-	BOOL saveLocal();
-
-	LLPointer<LLImageFormatted>	getFormattedImage() const { return mFormattedImage; }
-	LLPointer<LLImageRaw>		getEncodedImage() const { return mPreviewImageEncoded; }
-
-	/// Sets size of preview thumbnail image and thhe surrounding rect.
-	BOOL setThumbnailImageSize() ;
-	void generateThumbnailImage(BOOL force_update = FALSE) ;
-	void resetThumbnailImage() { mThumbnailImage = NULL ; }
-	void drawPreviewRect(S32 offset_x, S32 offset_y) ;
-
-	// Returns TRUE when snapshot generated, FALSE otherwise.
-	static BOOL onIdle( void* snapshot_preview );
-
-	// callback for region name resolve
-	void regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z);
-
-private:
-	LLColor4					mColor;
-	LLPointer<LLViewerTexture>	mViewerImage[2]; //used to represent the scene when the frame is frozen.
-	LLRect						mImageRect[2];
-	S32							mWidth[2];
-	S32							mHeight[2];
-	BOOL						mImageScaled[2];
-	S32                         mMaxImageSize ;
-	
-	//thumbnail image
-	LLPointer<LLViewerTexture>	mThumbnailImage ;
-	S32                         mThumbnailWidth ;
-	S32                         mThumbnailHeight ;
-	LLRect                      mPreviewRect ;
-	BOOL                        mThumbnailUpdateLock ;
-	BOOL                        mThumbnailUpToDate ;
-
-	S32							mCurImageIndex;
-	LLPointer<LLImageRaw>		mPreviewImage;
-	LLPointer<LLImageRaw>		mPreviewImageEncoded;
-	LLPointer<LLImageFormatted>	mFormattedImage;
-	LLFrameTimer				mSnapshotDelayTimer;
-	S32							mShineCountdown;
-	LLFrameTimer				mShineAnimTimer;
-	F32							mFlashAlpha;
-	BOOL						mNeedsFlash;
-	LLVector3d					mPosTakenGlobal;
-	S32							mSnapshotQuality;
-	S32							mDataSize;
-	ESnapshotType				mSnapshotType;
-	LLFloaterSnapshot::ESnapshotFormat	mSnapshotFormat;
-	BOOL						mSnapshotUpToDate;
-	LLFrameTimer				mFallAnimTimer;
-	LLVector3					mCameraPos;
-	LLQuaternion				mCameraRot;
-	BOOL						mSnapshotActive;
-	LLViewerWindow::ESnapshotType mSnapshotBufferType;
-
-public:
-	static std::set<LLSnapshotLivePreview*> sList;
-	BOOL                        mKeepAspectRatio ;
-};
-
-std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
-
-LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p) 
-:	LLView(p),
-	mColor(1.f, 0.f, 0.f, 0.5f), 
-	mCurImageIndex(0),
-	mPreviewImage(NULL),
-	mThumbnailImage(NULL) ,
-	mThumbnailWidth(0),
-	mThumbnailHeight(0),
-	mPreviewImageEncoded(NULL),
-	mFormattedImage(NULL),
-	mShineCountdown(0),
-	mFlashAlpha(0.f),
-	mNeedsFlash(TRUE),
-	mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
-	mDataSize(0),
-	mSnapshotType(SNAPSHOT_POSTCARD),
-	mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
-	mSnapshotUpToDate(FALSE),
-	mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
-	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
-	mSnapshotActive(FALSE),
-	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR)
-{
-	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
-	mSnapshotDelayTimer.setTimerExpirySec(0.0f);
-	mSnapshotDelayTimer.start();
-// 	gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
-	sList.insert(this);
-	setFollowsAll();
-	mWidth[0] = gViewerWindow->getWindowWidthRaw();
-	mWidth[1] = gViewerWindow->getWindowWidthRaw();
-	mHeight[0] = gViewerWindow->getWindowHeightRaw();
-	mHeight[1] = gViewerWindow->getWindowHeightRaw();
-	mImageScaled[0] = FALSE;
-	mImageScaled[1] = FALSE;
-
-	mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
-	mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
-	mThumbnailUpdateLock = FALSE ;
-	mThumbnailUpToDate   = FALSE ;
-}
-
-LLSnapshotLivePreview::~LLSnapshotLivePreview()
-{
-	// delete images
-	mPreviewImage = NULL;
-	mPreviewImageEncoded = NULL;
-	mFormattedImage = NULL;
-
-// 	gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
-	sList.erase(this);
-}
-
-void LLSnapshotLivePreview::setMaxImageSize(S32 size) 
-{
-	if(size < MAX_SNAPSHOT_IMAGE_SIZE)
-	{
-		mMaxImageSize = size;
-	}
-	else
-	{
-		mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
-	}
-}
-
-LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
-{
-	return mViewerImage[mCurImageIndex];
-}
-
-F32 LLSnapshotLivePreview::getAspect()
-{
-	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
-	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
-
-	if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
-	{
-		return image_aspect_ratio;
-	}
-	else
-	{
-		return window_aspect_ratio;
-	}
-}
-
-F32 LLSnapshotLivePreview::getImageAspect()
-{
-	if (!getCurrentImage())
-	{
-		return 0.f;
-	}
-
-	return getAspect() ;	
-}
-
-void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) 
-{
-	// Invalidate current image.
-	lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl;
-	if (getSnapshotUpToDate())
-	{
-		S32 old_image_index = mCurImageIndex;
-		mCurImageIndex = (mCurImageIndex + 1) % 2; 
-		setSize(mWidth[old_image_index], mHeight[old_image_index]);
-		mFallAnimTimer.start();		
-	}
-	mSnapshotUpToDate = FALSE; 		
-
-	// Update snapshot source rect depending on whether we keep the aspect ratio.
-	LLRect& rect = mImageRect[mCurImageIndex];
-	rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
-
-	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
-	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
-
-	if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
-	{
-		if (image_aspect_ratio > window_aspect_ratio)
-		{
-			// trim off top and bottom
-			S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio); 
-			rect.mBottom += (getRect().getHeight() - new_height) / 2;
-			rect.mTop -= (getRect().getHeight() - new_height) / 2;
-		}
-		else if (image_aspect_ratio < window_aspect_ratio)
-		{
-			// trim off left and right
-			S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio); 
-			rect.mLeft += (getRect().getWidth() - new_width) / 2;
-			rect.mRight -= (getRect().getWidth() - new_width) / 2;
-		}
-	}
-
-	// Stop shining animation.
-	mShineAnimTimer.stop();
-
-	// Update snapshot if requested.
-	if (new_snapshot)
-	{
-		mSnapshotDelayTimer.start();
-		mSnapshotDelayTimer.setTimerExpirySec(delay);
-		LLFloaterSnapshot::preUpdate();
-	}
-
-	// Update thumbnail if requested.
-	if(new_thumbnail)
-	{
-		mThumbnailUpToDate = FALSE ;
-	}
-}
-
-void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
-{
-	llclamp(quality, 0, 100);
-	if (quality != mSnapshotQuality)
-	{
-		mSnapshotQuality = quality;
-		gSavedSettings.setS32("SnapshotQuality", quality);
-		mSnapshotUpToDate = FALSE;
-	}
-}
-
-void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
-{
-	F32 line_width ; 
-	glGetFloatv(GL_LINE_WIDTH, &line_width) ;
-	glLineWidth(2.0f * line_width) ;
-	LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ;
-	gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y,
-				mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ;
-	glLineWidth(line_width) ;
-
-	//draw four alpha rectangles to cover areas outside of the snapshot image
-	if(!mKeepAspectRatio)
-	{
-		LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ;
-		S32 dwl = 0, dwr = 0 ;
-		if(mThumbnailWidth > mPreviewRect.getWidth())
-		{
-			dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ;
-			dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ;
-
-			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y,
-				mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
-			gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y,
-				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
-		}
-
-		if(mThumbnailHeight > mPreviewRect.getHeight())
-		{
-			S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ;
-			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y ,
-				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ;
-
-			dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ;
-			gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh,
-				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ;
-		}
-	}
-}
-
-//called when the frame is frozen.
-void LLSnapshotLivePreview::draw()
-{
-	if (getCurrentImage() &&
-	    mPreviewImageEncoded.notNull() &&
-	    getSnapshotUpToDate())
-	{
-		LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f);
-		gl_rect_2d(getRect(), bg_color);
-		const LLRect& rect = getImageRect();
-		LLRect shadow_rect = rect;
-		shadow_rect.stretch(BORDER_WIDTH);
-		gl_drop_shadow(shadow_rect.mLeft, shadow_rect.mTop, shadow_rect.mRight, shadow_rect.mBottom, LLColor4(0.f, 0.f, 0.f, mNeedsFlash ? 0.f :0.5f), 10);
-
-		LLColor4 image_color(1.f, 1.f, 1.f, 1.f);
-		gGL.color4fv(image_color.mV);
-		gGL.getTexUnit(0)->bind(getCurrentImage());
-		// calculate UV scale
-		F32 uv_width = isImageScaled() ? 1.f : llmin((F32)getWidth() / (F32)getCurrentImage()->getWidth(), 1.f);
-		F32 uv_height = isImageScaled() ? 1.f : llmin((F32)getHeight() / (F32)getCurrentImage()->getHeight(), 1.f);
-		gGL.pushMatrix();
-		{
-			gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f);
-			gGL.begin(LLRender::QUADS);
-			{
-				gGL.texCoord2f(uv_width, uv_height);
-				gGL.vertex2i(rect.getWidth(), rect.getHeight() );
-
-				gGL.texCoord2f(0.f, uv_height);
-				gGL.vertex2i(0, rect.getHeight() );
-
-				gGL.texCoord2f(0.f, 0.f);
-				gGL.vertex2i(0, 0);
-
-				gGL.texCoord2f(uv_width, 0.f);
-				gGL.vertex2i(rect.getWidth(), 0);
-			}
-			gGL.end();
-		}
-		gGL.popMatrix();
-
-		gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha);
-		gl_rect_2d(getRect());
-		if (mNeedsFlash)
-		{
-			if (mFlashAlpha < 1.f)
-			{
-				mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f));
-			}
-			else
-			{
-				mNeedsFlash = FALSE;
-			}
-		}
-		else
-		{
-			mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
-		}
-
-		// Draw shining animation if appropriate.
-		if (mShineCountdown > 0)
-		{
-			mShineCountdown--;
-			if (mShineCountdown == 0)
-			{
-				mShineAnimTimer.start();
-			}
-		}
-		else if (mShineAnimTimer.getStarted())
-		{
-			lldebugs << "Drawing shining animation" << llendl;
-			F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
-			
-			// draw "shine" effect
-			LLLocalClipRect clip(getLocalRect());
-			{
-				// draw diagonal stripe with gradient that passes over screen
-				S32 x1 = gViewerWindow->getWindowWidthScaled() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
-				S32 x2 = x1 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
-				S32 x3 = x2 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
-				S32 y1 = 0;
-				S32 y2 = gViewerWindow->getWindowHeightScaled();
-
-				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-				gGL.begin(LLRender::QUADS);
-				{
-					gGL.color4f(1.f, 1.f, 1.f, 0.f);
-					gGL.vertex2i(x1, y1);
-					gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2);
-					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
-					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
-					gGL.vertex2i(x2, y1);
-
-					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
-					gGL.vertex2i(x2, y1);
-					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
-					gGL.color4f(1.f, 1.f, 1.f, 0.f);
-					gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2);
-					gGL.vertex2i(x3, y1);
-				}
-				gGL.end();
-			}
-
-			// if we're at the end of the animation, stop
-			if (shine_interp >= 1.f)
-			{
-				mShineAnimTimer.stop();
-			}
-		}
-	}
-
-	// draw framing rectangle
-	{
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		gGL.color4f(1.f, 1.f, 1.f, 1.f);
-		const LLRect& outline_rect = getImageRect();
-		gGL.begin(LLRender::QUADS);
-		{
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
-
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
-			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
-			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
-			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
-		}
-		gGL.end();
-	}
-
-	// draw old image dropping away
-	if (mFallAnimTimer.getStarted())
-	{
-		S32 old_image_index = (mCurImageIndex + 1) % 2;
-		if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
-		{
-			lldebugs << "Drawing fall animation" << llendl;
-			F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
-			F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
-			LLColor4 image_color(1.f, 1.f, 1.f, alpha);
-			gGL.color4fv(image_color.mV);
-			gGL.getTexUnit(0)->bind(mViewerImage[old_image_index]);
-			// calculate UV scale
-			// *FIX get this to work with old image
-			BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull();
-			F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f;
-			F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f;
-			gGL.pushMatrix();
-			{
-				LLRect& rect = mImageRect[old_image_index];
-				gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - llround(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f);
-				gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f);
-				gGL.begin(LLRender::QUADS);
-				{
-					gGL.texCoord2f(uv_width, uv_height);
-					gGL.vertex2i(rect.getWidth(), rect.getHeight() );
-
-					gGL.texCoord2f(0.f, uv_height);
-					gGL.vertex2i(0, rect.getHeight() );
-
-					gGL.texCoord2f(0.f, 0.f);
-					gGL.vertex2i(0, 0);
-
-					gGL.texCoord2f(uv_width, 0.f);
-					gGL.vertex2i(rect.getWidth(), 0);
-				}
-				gGL.end();
-			}
-			gGL.popMatrix();
-		}
-	}
-}
-
-/*virtual*/ 
-void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
-	LLRect old_rect = getRect();
-	LLView::reshape(width, height, called_from_parent);
-	if (old_rect.getWidth() != width || old_rect.getHeight() != height)
-	{
-		lldebugs << "window reshaped, updating thumbnail" << llendl;
-		updateSnapshot(FALSE, TRUE);
-	}
-}
 
-BOOL LLSnapshotLivePreview::setThumbnailImageSize()
-{
-	if(getWidth() < 10 || getHeight() < 10)
-	{
-		return FALSE ;
-	}
-	S32 window_width = gViewerWindow->getWindowWidthRaw() ;
-	S32 window_height = gViewerWindow->getWindowHeightRaw() ;
-
-	F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
-
-	// UI size for thumbnail
-	// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h.
-	const LLRect& thumbnail_rect = LLFloaterSnapshot::getThumbnailPlaceholderRect();
-	S32 max_width = thumbnail_rect.getWidth();
-	S32 max_height = thumbnail_rect.getHeight();
-
-	if (window_aspect_ratio > (F32)max_width / max_height)
-	{
-		// image too wide, shrink to width
-		mThumbnailWidth = max_width;
-		mThumbnailHeight = llround((F32)max_width / window_aspect_ratio);
-	}
-	else
-	{
-		// image too tall, shrink to height
-		mThumbnailHeight = max_height;
-		mThumbnailWidth = llround((F32)max_height * window_aspect_ratio);
-	}
-	
-	if(mThumbnailWidth > window_width || mThumbnailHeight > window_height)
-	{
-		return FALSE ;//if the window is too small, ignore thumbnail updating.
-	}
-
-	S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
-	if(!mKeepAspectRatio)
-	{
-		F32 ratio_x = (F32)getWidth() / window_width ;
-		F32 ratio_y = (F32)getHeight() / window_height ;
-
-		//if(getWidth() > window_width ||
-		//	getHeight() > window_height )
-		{
-			if(ratio_x > ratio_y)
-			{
-				top = (S32)(top * ratio_y / ratio_x) ;
-			}
-			else
-			{
-				right = (S32)(right * ratio_x / ratio_y) ;
-			}			
-		}
-		//else
-		//{
-		//	right = (S32)(right * ratio_x) ;
-		//	top = (S32)(top * ratio_y) ;
-		//}
-		left = (S32)((mThumbnailWidth - right) * 0.5f) ;
-		bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
-		top += bottom ;
-		right += left ;
-	}
-	mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ;
-
-	return TRUE ;
-}
-
-void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
-{	
-	if(mThumbnailUpdateLock) //in the process of updating
-	{
-		return ;
-	}
-	if(getThumbnailUpToDate() && !force_update)//already updated
-	{
-		return ;
-	}
-	if(getWidth() < 10 || getHeight() < 10)
-	{
-		return ;
-	}
-
-	////lock updating
-	mThumbnailUpdateLock = TRUE ;
-
-	if(!setThumbnailImageSize())
-	{
-		mThumbnailUpdateLock = FALSE ;
-		mThumbnailUpToDate = TRUE ;
-		return ;
-	}
-
-	if(mThumbnailImage)
-	{
-		resetThumbnailImage() ;
-	}		
-
-	LLPointer<LLImageRaw> raw = new LLImageRaw;
-	if(!gViewerWindow->thumbnailSnapshot(raw,
-							mThumbnailWidth, mThumbnailHeight,
-							gSavedSettings.getBOOL("RenderUIInSnapshot"),
-							FALSE,
-							mSnapshotBufferType) )								
-	{
-		raw = NULL ;
-	}
-
-	if(raw)
-	{
-		raw->expandToPowerOfTwo();
-		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); 		
-		mThumbnailUpToDate = TRUE ;
-	}
-
-	//unlock updating
-	mThumbnailUpdateLock = FALSE ;		
-}
-
-
-// Called often. Checks whether it's time to grab a new snapshot and if so, does it.
-// Returns TRUE if new snapshot generated, FALSE otherwise.
-//static 
-BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
-{
-	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
-	if (previewp->getWidth() == 0 || previewp->getHeight() == 0)
-	{
-		llwarns << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << llendl;
-		return FALSE;
-	}
-
-	// If we're in freeze-frame mode and camera has moved, update snapshot.
-	LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
-	LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
-	if (gSavedSettings.getBOOL("FreezeTime") && 
-		(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))
-	{
-		previewp->mCameraPos = new_camera_pos;
-		previewp->mCameraRot = new_camera_rot;
-		// request a new snapshot whenever the camera moves, with a time delay
-		BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot");
-		lldebugs << "camera moved, updating thumbnail" << llendl;
-		previewp->updateSnapshot(
-			autosnap, // whether a new snapshot is needed or merely invalidate the existing one
-			FALSE, // or if 1st arg is false, whether to produce a new thumbnail image.
-			autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); // shutter delay if 1st arg is true.
-	}
-
-	// see if it's time yet to snap the shot and bomb out otherwise.
-	previewp->mSnapshotActive = 
-		(previewp->mSnapshotDelayTimer.getStarted() &&	previewp->mSnapshotDelayTimer.hasExpired())
-		&& !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active
-	if ( ! previewp->mSnapshotActive)
-	{
-		return FALSE;
-	}
-
-	// time to produce a snapshot
-	previewp->setThumbnailImageSize();
-
-	lldebugs << "producing snapshot" << llendl;
-	if (!previewp->mPreviewImage)
-	{
-		previewp->mPreviewImage = new LLImageRaw;
-	}
-
-	if (!previewp->mPreviewImageEncoded)
-	{
-		previewp->mPreviewImageEncoded = new LLImageRaw;
-	}
-
-	previewp->setVisible(FALSE);
-	previewp->setEnabled(FALSE);
-	
-	previewp->getWindow()->incBusyCount();
-	previewp->setImageScaled(FALSE);
-
-	// grab the raw image and encode it into desired format
-	if(gViewerWindow->rawSnapshot(
-							previewp->mPreviewImage,
-							previewp->getWidth(),
-							previewp->getHeight(),
-							previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
-							previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
-							gSavedSettings.getBOOL("RenderUIInSnapshot"),
-							FALSE,
-							previewp->mSnapshotBufferType,
-							previewp->getMaxImageSize()))
-	{
-		previewp->mPreviewImageEncoded->resize(
-			previewp->mPreviewImage->getWidth(), 
-			previewp->mPreviewImage->getHeight(), 
-			previewp->mPreviewImage->getComponents());
-
-		if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE)
-		{
-			lldebugs << "Encoding new image of format J2C" << llendl;
-			LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
-			LLPointer<LLImageRaw> scaled = new LLImageRaw(
-				previewp->mPreviewImage->getData(),
-				previewp->mPreviewImage->getWidth(),
-				previewp->mPreviewImage->getHeight(),
-				previewp->mPreviewImage->getComponents());
-		
-			scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
-			previewp->setImageScaled(TRUE);
-			if (formatted->encode(scaled, 0.f))
-			{
-				previewp->mDataSize = formatted->getDataSize();
-				formatted->decode(previewp->mPreviewImageEncoded, 0);
-			}
-		}
-		else
-		{
-			// delete any existing image
-			previewp->mFormattedImage = NULL;
-			// now create the new one of the appropriate format.
-			LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat();
-			lldebugs << "Encoding new image of format " << format << llendl;
-
-			switch(format)
-			{
-			case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
-				previewp->mFormattedImage = new LLImagePNG(); 
-				break;
-			case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
-				previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality); 
-				break;
-			case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
-				previewp->mFormattedImage = new LLImageBMP(); 
-				break;
-			}
-			if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0))
-			{
-				previewp->mDataSize = previewp->mFormattedImage->getDataSize();
-				// special case BMP to copy instead of decode otherwise decode will crash.
-				if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
-				{
-					previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage);
-				}
-				else
-				{
-					previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0);
-				}
-			}
-		}
-
-		LLPointer<LLImageRaw> scaled = new LLImageRaw(
-			previewp->mPreviewImageEncoded->getData(),
-			previewp->mPreviewImageEncoded->getWidth(),
-			previewp->mPreviewImageEncoded->getHeight(),
-			previewp->mPreviewImageEncoded->getComponents());
-		
-		if(!scaled->isBufferInvalid())
-		{
-			// leave original image dimensions, just scale up texture buffer
-			if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
-			{
-				// go ahead and shrink image to appropriate power of 2 for display
-				scaled->biasedScaleToPowerOfTwo(1024);
-				previewp->setImageScaled(TRUE);
-			}
-			else
-			{
-				// expand image but keep original image data intact
-				scaled->expandToPowerOfTwo(1024, FALSE);
-			}
-
-			previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
-			LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
-			gGL.getTexUnit(0)->bind(curr_preview_image);
-			if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE)
-			{
-				curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT);
-			}
-			else
-			{
-				curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
-			}
-			curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
-
-			previewp->mSnapshotUpToDate = TRUE;
-			previewp->generateThumbnailImage(TRUE) ;
-
-			previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
-			previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
-		}
-	}
-	previewp->getWindow()->decBusyCount();
-	// only show fullscreen preview when in freeze frame mode
-	previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame"));
-	previewp->mSnapshotDelayTimer.stop();
-	previewp->mSnapshotActive = FALSE;
-
-	if(!previewp->getThumbnailUpToDate())
-	{
-		previewp->generateThumbnailImage() ;
-	}
-	lldebugs << "done creating snapshot" << llendl;
-	LLFloaterSnapshot::postUpdate();
-
-	return TRUE;
-}
-
-void LLSnapshotLivePreview::setSize(S32 w, S32 h)
-{
-	lldebugs << "setSize(" << w << ", " << h << ")" << llendl;
-	setWidth(w);
-	setHeight(h);
-}
-
-void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
-{
-	w = getWidth();
-	h = getHeight();
-}
-
-void LLSnapshotLivePreview::saveTexture()
-{
-	lldebugs << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << llendl;
-	// gen a new uuid for this asset
-	LLTransactionID tid;
-	tid.generate();
-	LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-		
-	LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
-	LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(),
-												  mPreviewImage->getWidth(),
-												  mPreviewImage->getHeight(),
-												  mPreviewImage->getComponents());
-	
-	scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
-	lldebugs << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << llendl;
-
-	if (formatted->encode(scaled, 0.0f))
-	{
-		LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
-		std::string pos_string;
-		LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
-		std::string who_took_it;
-		LLAgentUI::buildFullname(who_took_it);
-		LLAssetStorage::LLStoreAssetCallback callback = NULL;
-		S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
-		void *userdata = NULL;
-		upload_new_resource(tid,	// tid
-				    LLAssetType::AT_TEXTURE,
-				    "Snapshot : " + pos_string,
-				    "Taken by " + who_took_it + " at " + pos_string,
-				    0,
-				    LLFolderType::FT_SNAPSHOT_CATEGORY,
-				    LLInventoryType::IT_SNAPSHOT,
-				    PERM_ALL,  // Note: Snapshots to inventory is a special case of content upload
-				    LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads
-				    LLFloaterPerms::getEveryonePerms(),
-				    "Snapshot : " + pos_string,
-				    callback, expected_upload_cost, userdata);
-		gViewerWindow->playSnapshotAnimAndSound();
-	}
-	else
-	{
-		LLNotificationsUtil::add("ErrorEncodingSnapshot");
-		llwarns << "Error encoding snapshot" << llendl;
-	}
-
-	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT );
-	
-	mDataSize = 0;
-}
-
-BOOL LLSnapshotLivePreview::saveLocal()
-{
-	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
-
-	if(success)
-	{
-		gViewerWindow->playSnapshotAnimAndSound();
-	}
-	return success;
-}
-
-void LLSnapshotLivePreview::saveWeb()
-{
-	// *FIX: Will break if the window closes because of CloseSnapshotOnKeep!
-	// Needs to pass on ownership of the image.
-	LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get());
-	if(!jpg)
-	{
-		llwarns << "Formatted image not a JPEG" << llendl;
-		return;
-	}
-
-	LLSD metadata;
-	metadata["description"] = getChild<LLLineEditor>("description")->getText();
-
-	LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(gAgentCamera.getCameraPositionGlobal(),
-		boost::bind(&LLSnapshotLivePreview::regionNameCallback, this, jpg, metadata, _1, _2, _3, _4));
-
-	gViewerWindow->playSnapshotAnimAndSound();
-}
-
-void LLSnapshotLivePreview::regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z)
-{
-	metadata["slurl"] = LLSLURL(name, LLVector3d(x, y, z)).getSLURLString();
-
-	LLWebSharing::instance().shareSnapshot(snapshot, metadata);
-}
 
 ///----------------------------------------------------------------------------
 /// Class LLFloaterSnapshot::Impl
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5dab804c71a560044362c141fd18160b243908dd
--- /dev/null
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -0,0 +1,850 @@
+/** 
+* @file llsnapshotlivepreview.cpp
+* @brief Implementation of llsnapshotlivepreview
+* @author Gilbert@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llsnapshotlivepreview.h"
+
+
+
+const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
+
+F32 SHINE_TIME = 0.5f;
+F32 SHINE_WIDTH = 0.6f;
+F32 SHINE_OPACITY = 0.3f;
+F32 FALL_TIME = 0.6f;
+S32 BORDER_WIDTH = 6;
+
+const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
+const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
+
+std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
+
+LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p) 
+	:	LLView(p),
+	mColor(1.f, 0.f, 0.f, 0.5f), 
+	mCurImageIndex(0),
+	mPreviewImage(NULL),
+	mThumbnailImage(NULL) ,
+	mThumbnailWidth(0),
+	mThumbnailHeight(0),
+	mPreviewImageEncoded(NULL),
+	mFormattedImage(NULL),
+	mShineCountdown(0),
+	mFlashAlpha(0.f),
+	mNeedsFlash(TRUE),
+	mSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")),
+	mDataSize(0),
+	mSnapshotType(SNAPSHOT_POSTCARD),
+	mSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))),
+	mSnapshotUpToDate(FALSE),
+	mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
+	mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
+	mSnapshotActive(FALSE),
+	mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR)
+{
+	setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
+	mSnapshotDelayTimer.setTimerExpirySec(0.0f);
+	mSnapshotDelayTimer.start();
+	// 	gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
+	sList.insert(this);
+	setFollowsAll();
+	mWidth[0] = gViewerWindow->getWindowWidthRaw();
+	mWidth[1] = gViewerWindow->getWindowWidthRaw();
+	mHeight[0] = gViewerWindow->getWindowHeightRaw();
+	mHeight[1] = gViewerWindow->getWindowHeightRaw();
+	mImageScaled[0] = FALSE;
+	mImageScaled[1] = FALSE;
+
+	mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
+	mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
+	mThumbnailUpdateLock = FALSE ;
+	mThumbnailUpToDate   = FALSE ;
+}
+
+LLSnapshotLivePreview::~LLSnapshotLivePreview()
+{
+	// delete images
+	mPreviewImage = NULL;
+	mPreviewImageEncoded = NULL;
+	mFormattedImage = NULL;
+
+	// 	gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
+	sList.erase(this);
+}
+
+void LLSnapshotLivePreview::setMaxImageSize(S32 size) 
+{
+	if(size < MAX_SNAPSHOT_IMAGE_SIZE)
+	{
+		mMaxImageSize = size;
+	}
+	else
+	{
+		mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
+	}
+}
+
+LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
+{
+	return mViewerImage[mCurImageIndex];
+}
+
+F32 LLSnapshotLivePreview::getAspect()
+{
+	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
+	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
+
+	if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
+	{
+		return image_aspect_ratio;
+	}
+	else
+	{
+		return window_aspect_ratio;
+	}
+}
+
+F32 LLSnapshotLivePreview::getImageAspect()
+{
+	if (!getCurrentImage())
+	{
+		return 0.f;
+	}
+
+	return getAspect() ;	
+}
+
+void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) 
+{
+	// Invalidate current image.
+	lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl;
+	if (getSnapshotUpToDate())
+	{
+		S32 old_image_index = mCurImageIndex;
+		mCurImageIndex = (mCurImageIndex + 1) % 2; 
+		setSize(mWidth[old_image_index], mHeight[old_image_index]);
+		mFallAnimTimer.start();		
+	}
+	mSnapshotUpToDate = FALSE; 		
+
+	// Update snapshot source rect depending on whether we keep the aspect ratio.
+	LLRect& rect = mImageRect[mCurImageIndex];
+	rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
+
+	F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
+	F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
+
+	if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
+	{
+		if (image_aspect_ratio > window_aspect_ratio)
+		{
+			// trim off top and bottom
+			S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio); 
+			rect.mBottom += (getRect().getHeight() - new_height) / 2;
+			rect.mTop -= (getRect().getHeight() - new_height) / 2;
+		}
+		else if (image_aspect_ratio < window_aspect_ratio)
+		{
+			// trim off left and right
+			S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio); 
+			rect.mLeft += (getRect().getWidth() - new_width) / 2;
+			rect.mRight -= (getRect().getWidth() - new_width) / 2;
+		}
+	}
+
+	// Stop shining animation.
+	mShineAnimTimer.stop();
+
+	// Update snapshot if requested.
+	if (new_snapshot)
+	{
+		mSnapshotDelayTimer.start();
+		mSnapshotDelayTimer.setTimerExpirySec(delay);
+		LLFloaterSnapshot::preUpdate();
+	}
+
+	// Update thumbnail if requested.
+	if(new_thumbnail)
+	{
+		mThumbnailUpToDate = FALSE ;
+	}
+}
+
+void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
+{
+	llclamp(quality, 0, 100);
+	if (quality != mSnapshotQuality)
+	{
+		mSnapshotQuality = quality;
+		gSavedSettings.setS32("SnapshotQuality", quality);
+		mSnapshotUpToDate = FALSE;
+	}
+}
+
+void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
+{
+	F32 line_width ; 
+	glGetFloatv(GL_LINE_WIDTH, &line_width) ;
+	glLineWidth(2.0f * line_width) ;
+	LLColor4 color(0.0f, 0.0f, 0.0f, 1.0f) ;
+	gl_rect_2d( mPreviewRect.mLeft + offset_x, mPreviewRect.mTop + offset_y,
+		mPreviewRect.mRight + offset_x, mPreviewRect.mBottom + offset_y, color, FALSE ) ;
+	glLineWidth(line_width) ;
+
+	//draw four alpha rectangles to cover areas outside of the snapshot image
+	if(!mKeepAspectRatio)
+	{
+		LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ;
+		S32 dwl = 0, dwr = 0 ;
+		if(mThumbnailWidth > mPreviewRect.getWidth())
+		{
+			dwl = (mThumbnailWidth - mPreviewRect.getWidth()) >> 1 ;
+			dwr = mThumbnailWidth - mPreviewRect.getWidth() - dwl ;
+
+			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y,
+				mPreviewRect.mLeft + offset_x, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
+			gl_rect_2d( mPreviewRect.mRight + offset_x, mPreviewRect.mTop + offset_y,
+				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y, alpha_color, TRUE ) ;
+		}
+
+		if(mThumbnailHeight > mPreviewRect.getHeight())
+		{
+			S32 dh = (mThumbnailHeight - mPreviewRect.getHeight()) >> 1 ;
+			gl_rect_2d(mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mBottom + offset_y ,
+				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mBottom + offset_y - dh, alpha_color, TRUE ) ;
+
+			dh = mThumbnailHeight - mPreviewRect.getHeight() - dh ;
+			gl_rect_2d( mPreviewRect.mLeft + offset_x - dwl, mPreviewRect.mTop + offset_y + dh,
+				mPreviewRect.mRight + offset_x + dwr, mPreviewRect.mTop + offset_y, alpha_color, TRUE ) ;
+		}
+	}
+}
+
+//called when the frame is frozen.
+void LLSnapshotLivePreview::draw()
+{
+	if (getCurrentImage() &&
+		mPreviewImageEncoded.notNull() &&
+		getSnapshotUpToDate())
+	{
+		LLColor4 bg_color(0.f, 0.f, 0.3f, 0.4f);
+		gl_rect_2d(getRect(), bg_color);
+		const LLRect& rect = getImageRect();
+		LLRect shadow_rect = rect;
+		shadow_rect.stretch(BORDER_WIDTH);
+		gl_drop_shadow(shadow_rect.mLeft, shadow_rect.mTop, shadow_rect.mRight, shadow_rect.mBottom, LLColor4(0.f, 0.f, 0.f, mNeedsFlash ? 0.f :0.5f), 10);
+
+		LLColor4 image_color(1.f, 1.f, 1.f, 1.f);
+		gGL.color4fv(image_color.mV);
+		gGL.getTexUnit(0)->bind(getCurrentImage());
+		// calculate UV scale
+		F32 uv_width = isImageScaled() ? 1.f : llmin((F32)getWidth() / (F32)getCurrentImage()->getWidth(), 1.f);
+		F32 uv_height = isImageScaled() ? 1.f : llmin((F32)getHeight() / (F32)getCurrentImage()->getHeight(), 1.f);
+		gGL.pushMatrix();
+		{
+			gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom, 0.f);
+			gGL.begin(LLRender::QUADS);
+			{
+				gGL.texCoord2f(uv_width, uv_height);
+				gGL.vertex2i(rect.getWidth(), rect.getHeight() );
+
+				gGL.texCoord2f(0.f, uv_height);
+				gGL.vertex2i(0, rect.getHeight() );
+
+				gGL.texCoord2f(0.f, 0.f);
+				gGL.vertex2i(0, 0);
+
+				gGL.texCoord2f(uv_width, 0.f);
+				gGL.vertex2i(rect.getWidth(), 0);
+			}
+			gGL.end();
+		}
+		gGL.popMatrix();
+
+		gGL.color4f(1.f, 1.f, 1.f, mFlashAlpha);
+		gl_rect_2d(getRect());
+		if (mNeedsFlash)
+		{
+			if (mFlashAlpha < 1.f)
+			{
+				mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f));
+			}
+			else
+			{
+				mNeedsFlash = FALSE;
+			}
+		}
+		else
+		{
+			mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
+		}
+
+		// Draw shining animation if appropriate.
+		if (mShineCountdown > 0)
+		{
+			mShineCountdown--;
+			if (mShineCountdown == 0)
+			{
+				mShineAnimTimer.start();
+			}
+		}
+		else if (mShineAnimTimer.getStarted())
+		{
+			lldebugs << "Drawing shining animation" << llendl;
+			F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
+
+			// draw "shine" effect
+			LLLocalClipRect clip(getLocalRect());
+			{
+				// draw diagonal stripe with gradient that passes over screen
+				S32 x1 = gViewerWindow->getWindowWidthScaled() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
+				S32 x2 = x1 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
+				S32 x3 = x2 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
+				S32 y1 = 0;
+				S32 y2 = gViewerWindow->getWindowHeightScaled();
+
+				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+				gGL.begin(LLRender::QUADS);
+				{
+					gGL.color4f(1.f, 1.f, 1.f, 0.f);
+					gGL.vertex2i(x1, y1);
+					gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2);
+					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
+					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
+					gGL.vertex2i(x2, y1);
+
+					gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
+					gGL.vertex2i(x2, y1);
+					gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
+					gGL.color4f(1.f, 1.f, 1.f, 0.f);
+					gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2);
+					gGL.vertex2i(x3, y1);
+				}
+				gGL.end();
+			}
+
+			// if we're at the end of the animation, stop
+			if (shine_interp >= 1.f)
+			{
+				mShineAnimTimer.stop();
+			}
+		}
+	}
+
+	// draw framing rectangle
+	{
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+		gGL.color4f(1.f, 1.f, 1.f, 1.f);
+		const LLRect& outline_rect = getImageRect();
+		gGL.begin(LLRender::QUADS);
+		{
+			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
+			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
+			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
+			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
+
+			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
+			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
+			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
+			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
+
+			gGL.vertex2i(outline_rect.mLeft, outline_rect.mTop);
+			gGL.vertex2i(outline_rect.mLeft, outline_rect.mBottom);
+			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
+			gGL.vertex2i(outline_rect.mLeft - BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
+
+			gGL.vertex2i(outline_rect.mRight, outline_rect.mBottom);
+			gGL.vertex2i(outline_rect.mRight, outline_rect.mTop);
+			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mTop + BORDER_WIDTH);
+			gGL.vertex2i(outline_rect.mRight + BORDER_WIDTH, outline_rect.mBottom - BORDER_WIDTH);
+		}
+		gGL.end();
+	}
+
+	// draw old image dropping away
+	if (mFallAnimTimer.getStarted())
+	{
+		S32 old_image_index = (mCurImageIndex + 1) % 2;
+		if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
+		{
+			lldebugs << "Drawing fall animation" << llendl;
+			F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
+			F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
+			LLColor4 image_color(1.f, 1.f, 1.f, alpha);
+			gGL.color4fv(image_color.mV);
+			gGL.getTexUnit(0)->bind(mViewerImage[old_image_index]);
+			// calculate UV scale
+			// *FIX get this to work with old image
+			BOOL rescale = !mImageScaled[old_image_index] && mViewerImage[mCurImageIndex].notNull();
+			F32 uv_width = rescale ? llmin((F32)mWidth[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getWidth(), 1.f) : 1.f;
+			F32 uv_height = rescale ? llmin((F32)mHeight[old_image_index] / (F32)mViewerImage[mCurImageIndex]->getHeight(), 1.f) : 1.f;
+			gGL.pushMatrix();
+			{
+				LLRect& rect = mImageRect[old_image_index];
+				gGL.translatef((F32)rect.mLeft, (F32)rect.mBottom - llround(getRect().getHeight() * 2.f * (fall_interp * fall_interp)), 0.f);
+				gGL.rotatef(-45.f * fall_interp, 0.f, 0.f, 1.f);
+				gGL.begin(LLRender::QUADS);
+				{
+					gGL.texCoord2f(uv_width, uv_height);
+					gGL.vertex2i(rect.getWidth(), rect.getHeight() );
+
+					gGL.texCoord2f(0.f, uv_height);
+					gGL.vertex2i(0, rect.getHeight() );
+
+					gGL.texCoord2f(0.f, 0.f);
+					gGL.vertex2i(0, 0);
+
+					gGL.texCoord2f(uv_width, 0.f);
+					gGL.vertex2i(rect.getWidth(), 0);
+				}
+				gGL.end();
+			}
+			gGL.popMatrix();
+		}
+	}
+}
+
+/*virtual*/ 
+void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+	LLRect old_rect = getRect();
+	LLView::reshape(width, height, called_from_parent);
+	if (old_rect.getWidth() != width || old_rect.getHeight() != height)
+	{
+		lldebugs << "window reshaped, updating thumbnail" << llendl;
+		updateSnapshot(FALSE, TRUE);
+	}
+}
+
+BOOL LLSnapshotLivePreview::setThumbnailImageSize()
+{
+	if(getWidth() < 10 || getHeight() < 10)
+	{
+		return FALSE ;
+	}
+	S32 window_width = gViewerWindow->getWindowWidthRaw() ;
+	S32 window_height = gViewerWindow->getWindowHeightRaw() ;
+
+	F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
+
+	// UI size for thumbnail
+	// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h.
+	const LLRect& thumbnail_rect = LLFloaterSnapshot::getThumbnailPlaceholderRect();
+	S32 max_width = thumbnail_rect.getWidth();
+	S32 max_height = thumbnail_rect.getHeight();
+
+	if (window_aspect_ratio > (F32)max_width / max_height)
+	{
+		// image too wide, shrink to width
+		mThumbnailWidth = max_width;
+		mThumbnailHeight = llround((F32)max_width / window_aspect_ratio);
+	}
+	else
+	{
+		// image too tall, shrink to height
+		mThumbnailHeight = max_height;
+		mThumbnailWidth = llround((F32)max_height * window_aspect_ratio);
+	}
+
+	if(mThumbnailWidth > window_width || mThumbnailHeight > window_height)
+	{
+		return FALSE ;//if the window is too small, ignore thumbnail updating.
+	}
+
+	S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
+	if(!mKeepAspectRatio)
+	{
+		F32 ratio_x = (F32)getWidth() / window_width ;
+		F32 ratio_y = (F32)getHeight() / window_height ;
+
+		//if(getWidth() > window_width ||
+		//	getHeight() > window_height )
+		{
+			if(ratio_x > ratio_y)
+			{
+				top = (S32)(top * ratio_y / ratio_x) ;
+			}
+			else
+			{
+				right = (S32)(right * ratio_x / ratio_y) ;
+			}			
+		}
+		//else
+		//{
+		//	right = (S32)(right * ratio_x) ;
+		//	top = (S32)(top * ratio_y) ;
+		//}
+		left = (S32)((mThumbnailWidth - right) * 0.5f) ;
+		bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
+		top += bottom ;
+		right += left ;
+	}
+	mPreviewRect.set(left - 1, top + 1, right + 1, bottom - 1) ;
+
+	return TRUE ;
+}
+
+void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
+{	
+	if(mThumbnailUpdateLock) //in the process of updating
+	{
+		return ;
+	}
+	if(getThumbnailUpToDate() && !force_update)//already updated
+	{
+		return ;
+	}
+	if(getWidth() < 10 || getHeight() < 10)
+	{
+		return ;
+	}
+
+	////lock updating
+	mThumbnailUpdateLock = TRUE ;
+
+	if(!setThumbnailImageSize())
+	{
+		mThumbnailUpdateLock = FALSE ;
+		mThumbnailUpToDate = TRUE ;
+		return ;
+	}
+
+	if(mThumbnailImage)
+	{
+		resetThumbnailImage() ;
+	}		
+
+	LLPointer<LLImageRaw> raw = new LLImageRaw;
+	if(!gViewerWindow->thumbnailSnapshot(raw,
+		mThumbnailWidth, mThumbnailHeight,
+		gSavedSettings.getBOOL("RenderUIInSnapshot"),
+		FALSE,
+		mSnapshotBufferType) )								
+	{
+		raw = NULL ;
+	}
+
+	if(raw)
+	{
+		raw->expandToPowerOfTwo();
+		mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); 		
+		mThumbnailUpToDate = TRUE ;
+	}
+
+	//unlock updating
+	mThumbnailUpdateLock = FALSE ;		
+}
+
+
+// Called often. Checks whether it's time to grab a new snapshot and if so, does it.
+// Returns TRUE if new snapshot generated, FALSE otherwise.
+//static 
+BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
+{
+	LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
+	if (previewp->getWidth() == 0 || previewp->getHeight() == 0)
+	{
+		llwarns << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << llendl;
+		return FALSE;
+	}
+
+	// If we're in freeze-frame mode and camera has moved, update snapshot.
+	LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
+	LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
+	if (gSavedSettings.getBOOL("FreezeTime") && 
+		(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))
+	{
+		previewp->mCameraPos = new_camera_pos;
+		previewp->mCameraRot = new_camera_rot;
+		// request a new snapshot whenever the camera moves, with a time delay
+		BOOL autosnap = gSavedSettings.getBOOL("AutoSnapshot");
+		lldebugs << "camera moved, updating thumbnail" << llendl;
+		previewp->updateSnapshot(
+			autosnap, // whether a new snapshot is needed or merely invalidate the existing one
+			FALSE, // or if 1st arg is false, whether to produce a new thumbnail image.
+			autosnap ? AUTO_SNAPSHOT_TIME_DELAY : 0.f); // shutter delay if 1st arg is true.
+	}
+
+	// see if it's time yet to snap the shot and bomb out otherwise.
+	previewp->mSnapshotActive = 
+		(previewp->mSnapshotDelayTimer.getStarted() &&	previewp->mSnapshotDelayTimer.hasExpired())
+		&& !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active
+	if ( ! previewp->mSnapshotActive)
+	{
+		return FALSE;
+	}
+
+	// time to produce a snapshot
+	previewp->setThumbnailImageSize();
+
+	lldebugs << "producing snapshot" << llendl;
+	if (!previewp->mPreviewImage)
+	{
+		previewp->mPreviewImage = new LLImageRaw;
+	}
+
+	if (!previewp->mPreviewImageEncoded)
+	{
+		previewp->mPreviewImageEncoded = new LLImageRaw;
+	}
+
+	previewp->setVisible(FALSE);
+	previewp->setEnabled(FALSE);
+
+	previewp->getWindow()->incBusyCount();
+	previewp->setImageScaled(FALSE);
+
+	// grab the raw image and encode it into desired format
+	if(gViewerWindow->rawSnapshot(
+		previewp->mPreviewImage,
+		previewp->getWidth(),
+		previewp->getHeight(),
+		previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
+		previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
+		gSavedSettings.getBOOL("RenderUIInSnapshot"),
+		FALSE,
+		previewp->mSnapshotBufferType,
+		previewp->getMaxImageSize()))
+	{
+		previewp->mPreviewImageEncoded->resize(
+			previewp->mPreviewImage->getWidth(), 
+			previewp->mPreviewImage->getHeight(), 
+			previewp->mPreviewImage->getComponents());
+
+		if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE)
+		{
+			lldebugs << "Encoding new image of format J2C" << llendl;
+			LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
+			LLPointer<LLImageRaw> scaled = new LLImageRaw(
+				previewp->mPreviewImage->getData(),
+				previewp->mPreviewImage->getWidth(),
+				previewp->mPreviewImage->getHeight(),
+				previewp->mPreviewImage->getComponents());
+
+			scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
+			previewp->setImageScaled(TRUE);
+			if (formatted->encode(scaled, 0.f))
+			{
+				previewp->mDataSize = formatted->getDataSize();
+				formatted->decode(previewp->mPreviewImageEncoded, 0);
+			}
+		}
+		else
+		{
+			// delete any existing image
+			previewp->mFormattedImage = NULL;
+			// now create the new one of the appropriate format.
+			LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat();
+			lldebugs << "Encoding new image of format " << format << llendl;
+
+			switch(format)
+			{
+			case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+				previewp->mFormattedImage = new LLImagePNG(); 
+				break;
+			case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+				previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality); 
+				break;
+			case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+				previewp->mFormattedImage = new LLImageBMP(); 
+				break;
+			}
+			if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0))
+			{
+				previewp->mDataSize = previewp->mFormattedImage->getDataSize();
+				// special case BMP to copy instead of decode otherwise decode will crash.
+				if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
+				{
+					previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage);
+				}
+				else
+				{
+					previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0);
+				}
+			}
+		}
+
+		LLPointer<LLImageRaw> scaled = new LLImageRaw(
+			previewp->mPreviewImageEncoded->getData(),
+			previewp->mPreviewImageEncoded->getWidth(),
+			previewp->mPreviewImageEncoded->getHeight(),
+			previewp->mPreviewImageEncoded->getComponents());
+
+		if(!scaled->isBufferInvalid())
+		{
+			// leave original image dimensions, just scale up texture buffer
+			if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
+			{
+				// go ahead and shrink image to appropriate power of 2 for display
+				scaled->biasedScaleToPowerOfTwo(1024);
+				previewp->setImageScaled(TRUE);
+			}
+			else
+			{
+				// expand image but keep original image data intact
+				scaled->expandToPowerOfTwo(1024, FALSE);
+			}
+
+			previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
+			LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
+			gGL.getTexUnit(0)->bind(curr_preview_image);
+			if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE)
+			{
+				curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT);
+			}
+			else
+			{
+				curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+			}
+			curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+			previewp->mSnapshotUpToDate = TRUE;
+			previewp->generateThumbnailImage(TRUE) ;
+
+			previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
+			previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
+		}
+	}
+	previewp->getWindow()->decBusyCount();
+	// only show fullscreen preview when in freeze frame mode
+	previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame"));
+	previewp->mSnapshotDelayTimer.stop();
+	previewp->mSnapshotActive = FALSE;
+
+	if(!previewp->getThumbnailUpToDate())
+	{
+		previewp->generateThumbnailImage() ;
+	}
+	lldebugs << "done creating snapshot" << llendl;
+	LLFloaterSnapshot::postUpdate();
+
+	return TRUE;
+}
+
+void LLSnapshotLivePreview::setSize(S32 w, S32 h)
+{
+	lldebugs << "setSize(" << w << ", " << h << ")" << llendl;
+	setWidth(w);
+	setHeight(h);
+}
+
+void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
+{
+	w = getWidth();
+	h = getHeight();
+}
+
+void LLSnapshotLivePreview::saveTexture()
+{
+	lldebugs << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << llendl;
+	// gen a new uuid for this asset
+	LLTransactionID tid;
+	tid.generate();
+	LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+
+	LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
+	LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(),
+		mPreviewImage->getWidth(),
+		mPreviewImage->getHeight(),
+		mPreviewImage->getComponents());
+
+	scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
+	lldebugs << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << llendl;
+
+	if (formatted->encode(scaled, 0.0f))
+	{
+		LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
+		std::string pos_string;
+		LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
+		std::string who_took_it;
+		LLAgentUI::buildFullname(who_took_it);
+		LLAssetStorage::LLStoreAssetCallback callback = NULL;
+		S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+		void *userdata = NULL;
+		upload_new_resource(tid,	// tid
+			LLAssetType::AT_TEXTURE,
+			"Snapshot : " + pos_string,
+			"Taken by " + who_took_it + " at " + pos_string,
+			0,
+			LLFolderType::FT_SNAPSHOT_CATEGORY,
+			LLInventoryType::IT_SNAPSHOT,
+			PERM_ALL,  // Note: Snapshots to inventory is a special case of content upload
+			LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads
+			LLFloaterPerms::getEveryonePerms(),
+			"Snapshot : " + pos_string,
+			callback, expected_upload_cost, userdata);
+		gViewerWindow->playSnapshotAnimAndSound();
+	}
+	else
+	{
+		LLNotificationsUtil::add("ErrorEncodingSnapshot");
+		llwarns << "Error encoding snapshot" << llendl;
+	}
+
+	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT );
+
+	mDataSize = 0;
+}
+
+BOOL LLSnapshotLivePreview::saveLocal()
+{
+	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
+
+	if(success)
+	{
+		gViewerWindow->playSnapshotAnimAndSound();
+	}
+	return success;
+}
+
+void LLSnapshotLivePreview::saveWeb()
+{
+	// *FIX: Will break if the window closes because of CloseSnapshotOnKeep!
+	// Needs to pass on ownership of the image.
+	LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get());
+	if(!jpg)
+	{
+		llwarns << "Formatted image not a JPEG" << llendl;
+		return;
+	}
+
+	LLSD metadata;
+	metadata["description"] = getChild<LLLineEditor>("description")->getText();
+
+	LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(gAgentCamera.getCameraPositionGlobal(),
+		boost::bind(&LLSnapshotLivePreview::regionNameCallback, this, jpg, metadata, _1, _2, _3, _4));
+
+	gViewerWindow->playSnapshotAnimAndSound();
+}
+
+void LLSnapshotLivePreview::regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z)
+{
+	metadata["slurl"] = LLSLURL(name, LLVector3d(x, y, z)).getSLURLString();
+
+	LLWebSharing::instance().shareSnapshot(snapshot, metadata);
+}
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
new file mode 100644
index 0000000000000000000000000000000000000000..52cd87ea9f7e2b0bcc1b24d8f711191d51d2ba6e
--- /dev/null
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -0,0 +1,214 @@
+/** 
+* @file   llsnapshotlivepreview.h
+* @brief  Header file for llsnapshotlivepreview
+* @author Gilbert@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLSNAPSHOTLIVEPREVIEW_H
+#define LL_LLSNAPSHOTLIVEPREVIEW_H
+
+#include "llfloaterreg.h"
+
+// Viewer includes
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llcallbacklist.h"
+#include "llcriticaldamp.h"
+#include "llfloaterperms.h"
+#include "llui.h"
+#include "llfacebookconnect.h"
+#include "llfocusmgr.h"
+#include "llbutton.h"
+#include "llcombobox.h"
+#include "lleconomy.h"
+#include "lllandmarkactions.h"
+#include "llpanelsnapshot.h"
+#include "llsidetraypanelcontainer.h"
+#include "llsliderctrl.h"
+#include "llspinctrl.h"
+#include "llviewercontrol.h"
+#include "lluictrlfactory.h"
+#include "llviewerstats.h"
+#include "llviewercamera.h"
+#include "llviewerwindow.h"
+#include "llviewermenufile.h"	// upload_new_resource()
+#include "llcheckboxctrl.h"
+#include "llslurl.h"
+#include "lltoolfocus.h"
+#include "lltoolmgr.h"
+#include "llwebsharing.h"
+#include "llworld.h"
+#include "llagentui.h"
+
+// Linden library includes
+#include "llfontgl.h"
+#include "llsys.h"
+#include "llrender.h"
+#include "v3dmath.h"
+#include "llmath.h"
+#include "lldir.h"
+#include "llsdserialize.h"
+#include "llgl.h"
+#include "llglheaders.h"
+#include "llimagejpeg.h"
+#include "llimagepng.h"
+#include "llimagebmp.h"
+#include "llimagej2c.h"
+#include "lllocalcliprect.h"
+#include "llnotificationsutil.h"
+#include "llpostcard.h"
+#include "llresmgr.h"		// LLLocale
+#include "llvfile.h"
+#include "llvfs.h"
+#include "llwebprofile.h"
+#include "llwindow.h"
+
+
+///----------------------------------------------------------------------------
+/// Class LLSnapshotLivePreview 
+///----------------------------------------------------------------------------
+class LLSnapshotLivePreview : public LLView
+{
+	LOG_CLASS(LLSnapshotLivePreview);
+public:
+	enum ESnapshotType
+	{
+		SNAPSHOT_POSTCARD,
+		SNAPSHOT_TEXTURE,
+		SNAPSHOT_LOCAL,
+		SNAPSHOT_WEB
+	};
+
+
+	struct Params : public LLInitParam::Block<Params, LLView::Params>
+	{
+		Params()
+		{
+			name = "snapshot_live_preview";
+			mouse_opaque = false;
+		}
+	};
+
+
+	LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p);
+	~LLSnapshotLivePreview();
+
+	/*virtual*/ void draw();
+	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
+
+	void setSize(S32 w, S32 h);
+	void setWidth(S32 w) { mWidth[mCurImageIndex] = w; }
+	void setHeight(S32 h) { mHeight[mCurImageIndex] = h; }
+	void getSize(S32& w, S32& h) const;
+	S32 getWidth() const { return mWidth[mCurImageIndex]; }
+	S32 getHeight() const { return mHeight[mCurImageIndex]; }
+	S32 getDataSize() const { return mDataSize; }
+	void setMaxImageSize(S32 size) ;
+	S32  getMaxImageSize() {return mMaxImageSize ;}
+
+	ESnapshotType getSnapshotType() const { return mSnapshotType; }
+	LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
+	BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
+	BOOL isSnapshotActive() { return mSnapshotActive; }
+	LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; }
+	S32  getThumbnailWidth() const { return mThumbnailWidth ; }
+	S32  getThumbnailHeight() const { return mThumbnailHeight ; }
+	BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
+	BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
+	LLViewerTexture* getCurrentImage();
+	F32 getImageAspect();
+	F32 getAspect() ;
+	const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; }
+	BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; }
+	void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }
+	const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }
+
+	void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
+	void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
+	void setSnapshotQuality(S32 quality);
+	void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
+	void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
+	void saveWeb();
+	void saveTexture();
+	BOOL saveLocal();
+
+	LLPointer<LLImageFormatted>	getFormattedImage() const { return mFormattedImage; }
+	LLPointer<LLImageRaw>		getEncodedImage() const { return mPreviewImageEncoded; }
+
+	/// Sets size of preview thumbnail image and thhe surrounding rect.
+	BOOL setThumbnailImageSize() ;
+	void generateThumbnailImage(BOOL force_update = FALSE) ;
+	void resetThumbnailImage() { mThumbnailImage = NULL ; }
+	void drawPreviewRect(S32 offset_x, S32 offset_y) ;
+
+	// Returns TRUE when snapshot generated, FALSE otherwise.
+	static BOOL onIdle( void* snapshot_preview );
+
+	// callback for region name resolve
+	void regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z);
+
+private:
+	LLColor4					mColor;
+	LLPointer<LLViewerTexture>	mViewerImage[2]; //used to represent the scene when the frame is frozen.
+	LLRect						mImageRect[2];
+	S32							mWidth[2];
+	S32							mHeight[2];
+	BOOL						mImageScaled[2];
+	S32                         mMaxImageSize ;
+
+	//thumbnail image
+	LLPointer<LLViewerTexture>	mThumbnailImage ;
+	S32                         mThumbnailWidth ;
+	S32                         mThumbnailHeight ;
+	LLRect                      mPreviewRect ;
+	BOOL                        mThumbnailUpdateLock ;
+	BOOL                        mThumbnailUpToDate ;
+
+	S32							mCurImageIndex;
+	LLPointer<LLImageRaw>		mPreviewImage;
+	LLPointer<LLImageRaw>		mPreviewImageEncoded;
+	LLPointer<LLImageFormatted>	mFormattedImage;
+	LLFrameTimer				mSnapshotDelayTimer;
+	S32							mShineCountdown;
+	LLFrameTimer				mShineAnimTimer;
+	F32							mFlashAlpha;
+	BOOL						mNeedsFlash;
+	LLVector3d					mPosTakenGlobal;
+	S32							mSnapshotQuality;
+	S32							mDataSize;
+	ESnapshotType				mSnapshotType;
+	LLFloaterSnapshot::ESnapshotFormat	mSnapshotFormat;
+	BOOL						mSnapshotUpToDate;
+	LLFrameTimer				mFallAnimTimer;
+	LLVector3					mCameraPos;
+	LLQuaternion				mCameraRot;
+	BOOL						mSnapshotActive;
+	LLViewerWindow::ESnapshotType mSnapshotBufferType;
+
+public:
+	static std::set<LLSnapshotLivePreview*> sList;
+	BOOL                        mKeepAspectRatio ;
+};
+
+#endif // LL_LLSNAPSHOTLIVEPREVIEW_H
+