//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //============================================================================= #include "jpegloader.h" #include "tier0/dbg.h" #include "tier1/utlvector.h" #include "tier0/vprof.h" #include "jpeglib/jpeglib.h" //----------------------------------------------------------------------------- // Purpose: Takes a RGBA image buffer and resizes it using linear interpolation. // // Params: bufRGBA should contain the current image, nWidth and nHeight should describe // the current images dimensions. nNewWidth and nNewHeight should be the new target size, // one, but not both, of these may be -1 which will indicate to preserve aspect ratio // and size that dimension to match the aspect ratio adjustment applied to the other // dimension which must then be specified explicitly. nNewWidth and nNewHeight may // be modified by the function and will specify the final width/height after the // function returns succesfully. If both nNewWidth and nNewHeight are specified // the content will be scaled without changing the aspect ratio and black letterboxing // will be added if appropriate //----------------------------------------------------------------------------- bool BResizeImageInternal( CUtlBuffer &bufImage, int nWidth, int nHeight, int &nNewWidth, int &nNewHeight, bool bIsRGBA = true ) { VPROF_BUDGET( "BResizeImageRGBA", VPROF_BUDGETGROUP_OTHER_VGUI ); CUtlBuffer bufImageOut; if ( nWidth == 0 || nHeight == 0 ) return false; // Must specify at least one, then we'll compute the other to preserve aspect ratio if it's set to -1 if ( nNewWidth == - 1 && nNewHeight == -1 ) return false; if ( nNewHeight == -1 ) { float flAspect = (float)nNewWidth/(float)nWidth; nNewHeight = (int)(flAspect*nHeight); } else if ( nNewWidth == -1 ) { float flAspect = (float)nNewHeight/(float)nHeight; nNewWidth = (int)(flAspect*nWidth); } if ( nNewWidth == 0 || nNewHeight == 0 ) return false; int nNewContentHeight = nNewHeight; int nNewContentWidth = nNewWidth; // Calculate the width/height of the actual content if ( nWidth/(float)nHeight > nNewContentWidth/(float)nNewContentHeight ) nNewContentHeight = ( nNewContentWidth * nHeight )/nWidth; else nNewContentWidth = ( nNewContentHeight * nWidth )/nHeight; int bytesPerPixel = bIsRGBA ? 4 : 3; bufImageOut.EnsureCapacity( nNewWidth*nNewHeight*bytesPerPixel ); bufImageOut.SeekPut( CUtlBuffer::SEEK_HEAD, nNewWidth*nNewHeight*bytesPerPixel ); // Letterboxing int nPaddingTop = (nNewHeight - nNewContentHeight)/2; int nPaddingBottom = nNewHeight - nNewContentHeight - nPaddingTop; int nPaddingLeft = (nNewWidth - nNewContentWidth)/2; int nPaddingRight = nNewWidth - nNewContentWidth - nPaddingLeft; Assert( nPaddingTop + nPaddingBottom + nNewContentHeight == nNewHeight ); Assert( nPaddingLeft + nPaddingRight + nNewContentWidth == nNewWidth ); if ( nPaddingLeft > 0 || nPaddingRight > 0 || nPaddingTop > 0 || nPaddingBottom > 0 ) { Q_memset( bufImageOut.Base(), 0, nNewWidth*nNewHeight*bytesPerPixel ); } byte *pBits = (byte*)bufImageOut.Base(); int nOriginalStride = nWidth; int nTargetStride = nNewWidth; float flXRatio = (float)(nWidth-1)/(float)nNewContentWidth; float flYRatio = (float)(nHeight-1)/(float)nNewContentHeight; byte *pSrcBits = (byte*)bufImage.Base(); for( int yNew=0; yNew