Files
core/ASCImageStudio3/Common/ImageCore.h

671 lines
15 KiB
C++
Raw Blame History

#pragma once
#include "../../Common/ImageStudioUtils.h"
namespace ImageStudio
{
typedef MediaCore::IAVSUncompressedVideoFrame IMediaFrame;
static IMediaFrame* CreateFrame( int nWidth, int nHeight, int nColorSpace, BYTE** pResultBuffer = NULL )
{
if( nWidth <= 0 || nHeight <= 0 )
return NULL;
IMediaFrame* pFrame = NULL;
CoCreateInstance( MediaCore::CLSID_CAVSUncompressedVideoFrame, NULL, CLSCTX_ALL, MediaCore::IID_IAVSUncompressedVideoFrame, (void**)(&pFrame) );
if( !pFrame )
return NULL;
pFrame->put_Width( nWidth );
pFrame->put_Height( nHeight );
pFrame->put_ColorSpace( nColorSpace );
pFrame->SetDefaultStrides();
pFrame->AllocateBuffer( -1 );
BYTE* pBuffer = NULL;
pFrame->get_Buffer( &pBuffer );
if( !pBuffer )
{
pFrame->Release();
return NULL;
}
if( pResultBuffer )
{
*pResultBuffer = pBuffer;
}
long lBufSize;
pFrame->get_BufferSize( &lBufSize );
pFrame->put_DataSize( lBufSize );
pFrame->put_AspectRatioX( nWidth );
pFrame->put_AspectRatioY( nHeight );
return pFrame;
}
static IMediaFrame* CreateFrame( IMediaFrame* pSource, BYTE** pResultBuffer = NULL )
{
if( !pSource )
return NULL;
long lWidth, lHeight, lColorSpace;
pSource->get_Width( &lWidth );
pSource->get_Height( &lHeight );
pSource->get_ColorSpace( &lColorSpace );
IMediaFrame* pResult = CreateFrame( lWidth, lHeight, lColorSpace, pResultBuffer );
if( !pResult )
return NULL;
long lAspectX;
pSource->get_AspectRatioX( &lAspectX );
pResult->put_AspectRatioX( lAspectX );
long lAspectY;
pSource->get_AspectRatioY( &lAspectY );
pResult->put_AspectRatioY( lAspectY );
double dDuration;
pSource->get_Duration( &dDuration );
pResult->put_Duration( dDuration );
double dTimeStamp;
pSource->get_TimeStamp( &dTimeStamp );
pResult->put_TimeStamp( dTimeStamp );
VARIANT_BOOL vbInterlaced;
pSource->get_Interlaced( &vbInterlaced );
pResult->put_Interlaced( vbInterlaced );
VARIANT_BOOL vbDiscontinity;
pSource->get_IsDiscontinuity( &vbDiscontinity );
pResult->put_IsDiscontinuity( vbDiscontinity );
return pResult;
}
static IMediaFrame* CreateFrame( IUnknown* pSource, BYTE** pResultBuffer = NULL )
{
if( !pSource )
return NULL;
IMediaFrame* pFrame = NULL;
pSource->QueryInterface( MediaCore::IID_IAVSUncompressedVideoFrame, (void**)&pFrame );
if( !pFrame )
return NULL;
IMediaFrame* pResult = CreateFrame( pFrame, pResultBuffer );
pFrame->Release();
return pResult;
}
static IMediaFrame* CreateBgraFrame( int nWidth, int nHeight, BYTE** ppResultBuffer = NULL )
{
return CreateFrame( nWidth, nHeight, CSP_BGRA, ppResultBuffer );
}
static BOOL GetBGRAImageData( IMediaFrame* pSource, BYTE*& pBGRA, int& nWidth, int& nHeight, int* pStride = NULL, long* pAspectX = NULL, long* pAspectY = NULL)
{
if (NULL == pSource)
return FALSE;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
long lWidth = 0;
long lHeight = 0;
long lColorSpace = 0;
long lStride = 0;
long lBufferSize = 0;
BYTE* pSourceBuffer = NULL;
pSource->get_Width(&lWidth);
pSource->get_Height(&lHeight);
pSource->get_ColorSpace(&lColorSpace);
pSource->get_Stride(0, &lStride);
pSource->get_BufferSize(&lBufferSize);
pSource->get_Buffer(&pSourceBuffer);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (CSP_BGRA != (CSP_COLOR_MASK & lColorSpace) || lStride < 4*lWidth || lWidth <= 0 || lHeight <= 0 || lBufferSize < 4*lWidth*lHeight || !pSourceBuffer)
{
return FALSE;
}
if( pStride )
*pStride = (lColorSpace & CSP_VFLIP) ? -lStride : lStride;
if( pAspectX ) pSource->get_AspectRatioX( pAspectX );
if( pAspectY ) pSource->get_AspectRatioY( pAspectY );
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pBGRA = pSourceBuffer;
nWidth = lWidth;
nHeight = lHeight;
return TRUE;
}
static BOOL GetBGRAImageData( IUnknown* pSource, BYTE*& pBGRA, int& nWidth, int& nHeight, int* pStride = NULL, long* pAspectX = NULL, long* pAspectY = NULL)
{
if (NULL == pSource)
return FALSE;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> uncompressed frame
IMediaFrame* pFrame = NULL;
pSource->QueryInterface(MediaCore::IID_IAVSUncompressedVideoFrame, (void**)(&pFrame));
if (!pFrame)
return FALSE;
BOOL bSuccess = GetBGRAImageData( pFrame, pBGRA, nWidth, nHeight, pStride, pAspectX, pAspectY );
pFrame->Release();
return bSuccess;
}
namespace Core
{
class MediaData
{
public:
MediaData()
{
m_bAttached = FALSE;
m_pMediaData = NULL;
}
virtual ~MediaData()
{
Destroy();
}
void Destroy()
{
if (m_pMediaData != NULL)
{
if (!m_bAttached)
m_pMediaData->Release();
m_pMediaData = NULL;
}
}
LONG GetWidth()
{
if (!IsValid())
return 0;
LONG lWidth = 0;
m_pMediaData->get_Width(&lWidth);
return lWidth;
}
LONG GetHeight()
{
if (!IsValid())
return 0;
LONG lHeight = 0;
m_pMediaData->get_Height(&lHeight);
return lHeight;
}
LONG GetColorSpace()
{
if (!IsValid())
return 0;
LONG lColorSpace = 0;
m_pMediaData->get_ColorSpace(&lColorSpace);
return lColorSpace;
}
LONG GetStride()
{
if (!IsValid())
return 0;
LONG lStride = 0;
m_pMediaData->get_Stride(0, &lStride);
return lStride;
}
LONG GetBufferSize()
{
if (!IsValid())
return 0;
LONG lBufferSize = 0;
m_pMediaData->get_BufferSize(&lBufferSize);
return lBufferSize;
}
BYTE* GetBuffer()
{
if (!IsValid())
return NULL;
BYTE* pSourceBuffer = 0;
m_pMediaData->get_Buffer(&pSourceBuffer);
return pSourceBuffer;
}
MediaCore::IAVSUncompressedVideoFrame*& GetMediaData(BOOL bAddReference)
{
if (bAddReference)
{
if (m_pMediaData != NULL)
m_pMediaData->AddRef();
}
return m_pMediaData;
}
BOOL IsValid()
{
if (m_pMediaData == NULL)
return FALSE;
return TRUE;
}
BOOL IsValidBGRA()
{
if (!IsValid())
return FALSE;
LONG lWidth = 0; m_pMediaData->get_Width(&lWidth);
LONG lHeight = 0; m_pMediaData->get_Height(&lHeight);
LONG lColorSpace = 0; m_pMediaData->get_ColorSpace(&lColorSpace);
LONG lStride = 0; m_pMediaData->get_Stride(0, &lStride);
LONG lBufferSize = 0; m_pMediaData->get_BufferSize(&lBufferSize);
BYTE* pSourceBuffer = 0; m_pMediaData->get_Buffer(&pSourceBuffer);
if (CSP_BGRA != (CSP_COLOR_MASK & lColorSpace) || 4*lWidth != lStride || lWidth < 1 || lHeight < 1 || lBufferSize != 4*lWidth*lHeight || !pSourceBuffer)
return FALSE;
return TRUE;
}
BOOL Create(IUnknown* pInterface, BOOL bAttach)
{
Destroy();
m_bAttached = bAttach;
return ImageStudioUtils::MediaDataToBGRAMediaData(&pInterface, m_pMediaData, TRUE);
}
protected:
BOOL m_bAttached;
MediaCore::IAVSUncompressedVideoFrame* m_pMediaData; // <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
};
class MediaBuffer
{
public:
MediaBuffer()
{
m_pData = NULL;
m_nSize = 0;
}
virtual ~MediaBuffer()
{
Destroy();
}
void Destroy()
{
if (m_pData != NULL)
{
delete[] m_pData;
m_pData = NULL;
}
m_nSize = 0;
}
LONG GetBufferSize()
{
return m_nSize;
}
BYTE* GetBuffer()
{
return m_pData;
}
BOOL IsValid()
{
if (m_pData == NULL)
return FALSE;
return TRUE;
}
BOOL Create(LONG nSize)
{
if (m_nSize == nSize)
return TRUE;
Destroy();
if (nSize < 1)
return FALSE;
m_pData = new BYTE[nSize];
if (!m_pData)
return FALSE;
m_nSize = nSize;
return TRUE;
}
BOOL Create(BYTE* pData, LONG nSize)
{
if (!pData)
return FALSE;
if (!Create(nSize))
return FALSE;
memcpy(m_pData, pData, nSize);
m_nSize = nSize;
return TRUE;
}
protected:
BYTE* m_pData;
LONG m_nSize;
};
class Mask
{
public:
Mask()
{
m_nWidth = -1;
m_nHeight = -1;
}
virtual ~Mask()
{
Destroy();
}
BOOL IsValid()
{
if (m_nWidth < 1 || m_nHeight < 1 || !m_oPixels.IsValid())
return FALSE;
return TRUE;
}
int GetWidth() const
{
return m_nWidth;
}
int GetHeight() const
{
return m_nHeight;
}
BYTE* GetPixels()
{
return m_oPixels.GetBuffer();
}
BYTE GetPixel(int nX, int nY, BYTE nDefaultValue)
{
if (nX < 0 || nY < 0 || nX >= m_nWidth || nY >= m_nHeight || !m_oPixels.IsValid())
return nDefaultValue;
return *((BYTE*)m_oPixels.GetBuffer() + nY*m_nWidth + nX);
}
void SetPixel(int nX, int nY, BYTE nValue)
{
if (nX < 0 || nY < 0 || nX >= m_nWidth || nY >= m_nHeight || !m_oPixels.IsValid())
return;
*((BYTE*)m_oPixels.GetBuffer() + nY*m_nWidth + nX) = nValue;
}
void Destroy()
{
m_nWidth = -1;
m_nHeight = -1;
m_oPixels.Destroy();
}
BOOL Create(int nWidth, int nHeight)
{
if (m_nWidth == nWidth && m_nHeight == nHeight)
return TRUE;
m_nWidth = nWidth;
m_nHeight = nHeight;
if (m_nWidth < 1 || m_nHeight < 1)
{
m_oPixels.Destroy();
return TRUE;
}
return m_oPixels.Create(nWidth*nHeight);
}
BOOL Fill(BYTE nValue)
{
if (!IsValid())
return FALSE;
BYTE* pPixels = m_oPixels.GetBuffer();
int nSize = m_oPixels.GetBufferSize() - 1;
while (nSize >= 0)
{
*pPixels = nValue;
pPixels++;
nSize--;
}
return TRUE;
}
BOOL FillRegion(Gdiplus::Region& oRegion, BYTE nValue)
{
BYTE* pPixels = m_oPixels.GetBuffer();
if (!pPixels)
return FALSE;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD>
for (int nY = 0; nY < m_nHeight; ++nY)
{
for (int nX = 0; nX < m_nWidth; ++nX, ++pPixels)
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>..<2E><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
if (oRegion.IsVisible(nX, /*m_nHeight - 1 -*/ nY))
*pPixels = nValue;
}
}
return TRUE;
}
BOOL FillGraphicsPath(Gdiplus::GraphicsPath& oPath, BYTE nValue, Gdiplus::Matrix* pTransform = NULL )
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> gdiplus::regions <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Gdiplus::Region oRegion(Gdiplus::RectF(0.0f, 0.0f, (float)m_nWidth, (float)m_nHeight));
oRegion.Intersect(&oPath);
if( pTransform )
{
oRegion.Transform( pTransform );
}
return FillRegion(oRegion, nValue);
}
BOOL FillRectangle(double dLeft, double dTop, double dRight, double dBottom, BYTE nValue, Gdiplus::Matrix* pTransform = NULL)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Gdiplus::GraphicsPath oPath(Gdiplus::FillModeAlternate);
Gdiplus::RectF oRect((float)dLeft, (float)dTop, (float)(dRight - dLeft), (float)(dBottom - dTop));
oPath.AddRectangle(oRect);
return FillGraphicsPath(oPath, nValue, pTransform);
}
BOOL FillEllipse(double dLeft, double dTop, double dRight, double dBottom, BYTE nValue, Gdiplus::Matrix* pTransform = NULL)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Gdiplus::GraphicsPath oPath(Gdiplus::FillModeAlternate);
oPath.AddEllipse((float)dLeft, (float)dTop, (float)(dRight - dLeft), (float)(dBottom - dTop));
return FillGraphicsPath(oPath, nValue, pTransform);
}
BOOL FillPolygon(Gdiplus::PointF* pPoints, int nPointsCount, BYTE nValue, Gdiplus::Matrix* pTransform = NULL)
{
if (!pPoints || nPointsCount < 3)
return FALSE;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Gdiplus::GraphicsPath oPath(Gdiplus::FillModeAlternate);
oPath.AddPolygon(pPoints, nPointsCount);
return FillGraphicsPath(oPath, nValue, pTransform);
}
protected:
int m_nWidth;
int m_nHeight;
ImageStudio::Core::MediaBuffer m_oPixels;
};
class Image
{
public:
Image()
{
m_pPixels = NULL;
}
virtual ~Image()
{
Destroy();
}
virtual void Destroy()
{
m_oImage.Destroy();
m_oMediaData.Destroy();
if (m_pPixels)
{
delete[] m_pPixels;
m_pPixels = NULL;
}
}
virtual BOOL IsValid()
{
return m_oImage.IsValid();
}
virtual int GetWidth()
{
return m_oImage.GetWidth();
}
virtual int GetHeight()
{
return m_oImage.GetHeight();
}
virtual GdiPlusEx::CGdiPlusImage* GetImage()
{
return &m_oImage;
}
virtual Gdiplus::Bitmap* GetBitmap()
{
return (Gdiplus::Bitmap*)m_oImage;
}
virtual ImageStudio::Core::MediaData& GetMediaData()
{
return m_oMediaData;
}
virtual BYTE*& GetBuffer()
{
return m_pPixels;
}
virtual BOOL RotateFlip(int nRotateFlip)
{
return (Gdiplus::Ok == GetBitmap()->RotateFlip((Gdiplus::RotateFlipType)nRotateFlip));
}
virtual BOOL FromByteArray(int nWidth, int nHeight)
{
Destroy();
if (nWidth < 1 || nHeight < 1)
return FALSE;
m_pPixels = new BYTE[4*nWidth*nHeight];
if (NULL == m_pPixels)
return FALSE;
return m_oImage.CreateFromByteArray(m_pPixels, nWidth, nHeight, 4*nWidth, PixelFormat32bppARGB, FALSE);
}
virtual BOOL FromSafeArray(SAFEARRAY** pSafeArray, BOOL CreateCopy)
{
Destroy();
return m_oImage.CreateFromSafeArray(pSafeArray, CreateCopy);
}
virtual BOOL FromMediaData(IUnknown* pInterface, BOOL bCreateCopy)
{
Destroy();
if (!m_oMediaData.Create(pInterface, FALSE))
return FALSE;
int nWidth = m_oMediaData.GetWidth();
int nHeight = m_oMediaData.GetHeight();
BYTE* pPixels = m_oMediaData.GetBuffer();
BOOL bSuccess = m_oImage.CreateFromByteArray(pPixels, nWidth, nHeight, 4*nWidth, PixelFormat32bppARGB, bCreateCopy);
if (bCreateCopy)
m_oMediaData.Destroy();
return bSuccess;
}
virtual BOOL ToSafeArray(SAFEARRAY** pSafeArray)
{
return ImageStudioUtils::GdiPlusImageToSafeArray(&m_oImage, pSafeArray);
}
virtual BOOL ToMediaData(IUnknown** pInterface, BOOL bFlipVertical)
{
return ImageStudioUtils::GdiPlusImageToMediaData(&m_oImage, pInterface, bFlipVertical);
}
protected:
BYTE* m_pPixels; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ImageStudio::Core::MediaData m_oMediaData; // <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
GdiPlusEx::CGdiPlusImage m_oImage; // gdi+ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
};
}
}