COverlayController.cpp
上传用户:hhs829
上传日期:2022-06-17
资源大小:586k
文件大小:12k
源码类别:
DirextX编程
开发平台:
Visual C++
- //
- // COverlayController.cpp
- //
- #include <streams.h>
- #include "COverlayController.h"
- #include "CPixelRGB32.h"
- #include "CPixelRGB24.h"
- #include "CPixelRGB565.h"
- #include "CPixelRGB555.h"
- #include "CPixelRGB8.h"
- #include "CAutoFont.h"
- //////////////////////////////////////////////////////////////////////////////
- COverlayController::COverlayController()
- {
- mPixelConverter = 0;
- mCanDoOverlay = FALSE;
- mIsOverlayByCover = TRUE;
- mOverlayCounter = 0;
- mDoubleStartTime = 0;
- mDoubleEndTime = -1;
- mOverlayStartTime = 0;
- mOverlayEndTime = -1; // Means to the end
- mTitle = new char[1];
- *mTitle = ' ';
- mTitleDIBBits = 0;
- mColorRed = 0;
- mColorGreen = 128;
- mColorBlue = 0;
- memset(&mTitleSize, 0, sizeof(SIZE));
- memset(&mStartPos, 0, sizeof(POINT));
- memset(&mTitleFont, 0, sizeof(LOGFONT));
- mIsFontChanged = FALSE;
- mInputColorSpace = FT_NONE;
- mImageWidth = 0;
- mImageHeight = 0;
- mImageWidthInBytes = 0;
- mImageBitCount = 0;
- mIsBottomUpImage = TRUE;
- mDIBWidthInBytes = 0;
- mInputFrameRate = 25;
- }
- COverlayController::~COverlayController()
- {
- ReleasePixelConverter();
- ReleaseTitleBuffer();
- ReleaseTitleDIB();
- }
- void COverlayController::ReleasePixelConverter(void)
- {
- if (mPixelConverter)
- {
- delete mPixelConverter;
- mPixelConverter = 0;
- }
- }
- void COverlayController::ReleaseTitleBuffer(void)
- {
- if (mTitle)
- {
- delete[] mTitle;
- mTitle = 0;
- }
- }
- void COverlayController::ReleaseTitleDIB(void)
- {
- if (mTitleDIBBits)
- {
- delete[] mTitleDIBBits;
- mTitleDIBBits = 0;
- }
- }
- // In order to create the pixel convertor used by overlay working properly,
- // this method must be invoke
- void COverlayController::SetInputColorSpace(RGB_FORMAT inColorSpace)
- {
- if (mInputColorSpace != inColorSpace)
- {
- ReleasePixelConverter();
- mInputColorSpace = inColorSpace;
- SideEffectColorSpaceChanged();
- }
- }
- BOOL COverlayController::CreateTitleDIBBits(void)
- {
- HDC hdc = CreateCompatibleDC(NULL);
- if (hdc)
- {
- HBITMAP hbm = ActualCreateTitleDIB(hdc);
- DeleteDC(hdc);
- if (hbm)
- {
- DeleteObject(hbm);
- return TRUE;
- }
- }
- return FALSE;
- }
- HBITMAP COverlayController::ActualCreateTitleDIB(HDC inDC)
- {
- // DIB info we used to create title pixel-mapping.
- // The system default color policy is:
- // Initial Whole Black, while output area White-background and Black-text.
- struct {
- BITMAPINFOHEADER bmiHeader;
- DWORD rgbEntries[2];
- } bmi =
- {
- {
- sizeof(BITMAPINFOHEADER),
- 0,
- 0,
- 1,
- 1,
- BI_RGB,
- 0,
- 0,
- 0
- },
- {
- 0x00000000,
- 0xFFFFFFFF
- }
- };
- // We change the system default color policy.
- // That is, we use Black-background and White-text.
- // We do so especially for rotation font using.
- // SetBkColor(hdc, RGB(0, 0, 0));
- // SetTextColor(hdc, RGB(255, 255, 255));
- // Set tile font here, so we can get the exact size of the title
- CAutoFont autoFont;
- if (mIsFontChanged)
- {
- // autoFont.CreateFont("Arial"); // Testing
- autoFont.CreateFont(mTitleFont);
- autoFont.SelectToDC(inDC);
- }
- GetTextExtentPoint32(inDC, mTitle, lstrlen(mTitle), &mTitleSize);
- // Overridable to change title DIB size
- if (!ValidateTitleDIBSize())
- {
- return NULL;
- }
- // Set proper DIB size here! Important!
- bmi.bmiHeader.biHeight = mTitleSize.cy;
- bmi.bmiHeader.biWidth = mTitleSize.cx;
- HBITMAP hbm = CreateDIBitmap(inDC, &bmi.bmiHeader, 0, NULL, NULL, 0);
- BOOL pass = (hbm != NULL);
- // Draw title after selecting DIB into the DC
- if (pass)
- {
- HGDIOBJ hobj = SelectObject(inDC, hbm);
- pass = ExtTextOut(inDC, 0, 0, ETO_OPAQUE | ETO_CLIPPED, NULL,
- mTitle, lstrlen(mTitle), NULL);
- SelectObject(inDC, hobj);
- }
- // Get the title-drew DIB bits
- if (pass)
- {
- ReleaseTitleDIB();
- // Attention: To get bitmap data from the DIB object,
- // the scan line must be a multiple of 4 (DWORD)!
- // If the actual bitmap data is not exactly fit for DWORD,
- // The rest of DWORD bits will be filled automatically.
- // So we should expand to bytes and round up to a multiple of 4.
- mDIBWidthInBytes = ((mTitleSize.cx + 31) >> 3) & ~3;
- mTitleDIBBits = new BYTE[mDIBWidthInBytes * mTitleSize.cy];
- memset(mTitleDIBBits, 0, mDIBWidthInBytes * mTitleSize.cy);
- LONG lLines = GetDIBits(inDC, hbm, 0, mTitleSize.cy, (PVOID)mTitleDIBBits,
- (BITMAPINFO *)&bmi, DIB_RGB_COLORS);
- pass = (lLines != 0);
- }
- if (!pass && hbm)
- {
- DeleteObject(hbm);
- hbm = NULL;
- }
- return hbm;
- }
- BOOL COverlayController::ValidateTitleDIBSize(void)
- {
- return TRUE;
- }
- void COverlayController::SideEffectColorSpaceChanged(void)
- {
- switch (mInputColorSpace)
- {
- case FT_RGB8:
- mPixelConverter = new CPixelRGB8();
- mPixelConverter->SetPixelSize(1);
- break;
- case FT_RGB555:
- mPixelConverter = new CPixelRGB555();
- mPixelConverter->SetPixelSize(2);
- break;
- case FT_RGB565:
- mPixelConverter = new CPixelRGB565();
- mPixelConverter->SetPixelSize(2);
- break;
- case FT_RGB24:
- mPixelConverter = new CPixelRGB24();
- mPixelConverter->SetPixelSize(3);
- break;
- case FT_RGB32:
- mPixelConverter = new CPixelRGB32();
- mPixelConverter->SetPixelSize(4);
- break;
- }
- // Set the title color to the pixel converter
- if (mPixelConverter)
- {
- mPixelConverter->SetTargetColor(mColorRed, mColorGreen, mColorBlue);
- }
- }
- // Commonly we don't support rotation font
- // Subclass can override this to support it
- void COverlayController::SideEffectFontChanged(void)
- {
- mTitleFont.lfEscapement = 0;
- mTitleFont.lfOrientation = 0;
- }
- void COverlayController::SetInputVideoInfo(const VIDEOINFOHEADER * inInfoHeader)
- {
- ASSERT(inInfoHeader);
- mImageWidth = inInfoHeader->bmiHeader.biWidth;
- mImageHeight = (DWORD)(abs(inInfoHeader->bmiHeader.biHeight));
- mImageBitCount = inInfoHeader->bmiHeader.biBitCount;
- if (inInfoHeader->AvgTimePerFrame > 0)
- {
- mInputFrameRate = 1.0 * UNITS / inInfoHeader->AvgTimePerFrame;
- SideEffectProgressChanged();
- }
- // biWidth is the stride in pixels for 'normal formats'
- // Expand to bytes and round up to a multiple of 4
- if (mImageBitCount != 0 && 0 == (7 & mImageBitCount))
- {
- mImageWidthInBytes = (mImageWidth * (mImageBitCount / 8) + 3) & ~3;
- }
- else
- {
- mImageWidthInBytes = mImageWidth;
- }
- mIsBottomUpImage = mImageHeight > 0 ? TRUE : FALSE;
- }
- void COverlayController::SetEstimatedFrameRate(double inFrameRate)
- {
- mInputFrameRate = inFrameRate;
- SideEffectProgressChanged();
- }
- void COverlayController::SetOverlayStyle(BOOL inUsingCover)
- {
- mIsOverlayByCover = inUsingCover;
- }
- void COverlayController::GetOverlayStyle(BOOL * outUsingCover)
- {
- *outUsingCover = mIsOverlayByCover;
- }
- void COverlayController::SetTitle(const char * inTitle, int inLength)
- {
- ReleaseTitleBuffer();
- mTitle = new char[inLength + 1];
- if (inTitle && mTitle)
- {
- strcpy(mTitle, inTitle);
- }
- }
- void COverlayController::SetTitleColor(BYTE inR, BYTE inG, BYTE inB)
- {
- mColorRed = inR;
- mColorGreen = inG;
- mColorBlue = inB;
- // Set the title color to the pixel converter
- if (mPixelConverter)
- {
- mPixelConverter->SetTargetColor(mColorRed, mColorGreen, mColorBlue);
- }
- }
- void COverlayController::SetTitleStartPosition(POINT inStartPos)
- {
- mStartPos.x = inStartPos.x;
- mStartPos.y = inStartPos.y;
- }
- void COverlayController::SetTitleFont(LOGFONT inFont)
- {
- mTitleFont = inFont;
- mIsFontChanged = TRUE;
- // Do title font validation
- SideEffectFontChanged();
- }
- void COverlayController::SetTitleDuration(double inStart, double inEnd)
- {
- mDoubleStartTime = inStart;
- mDoubleEndTime = inEnd;
- SideEffectProgressChanged();
- }
- void COverlayController::SideEffectProgressChanged(void)
- {
- mOverlayStartTime = long(mInputFrameRate * mDoubleStartTime);
- mOverlayEndTime = -1;
- if (mDoubleEndTime > 0)
- {
- mOverlayEndTime = long(mInputFrameRate * mDoubleEndTime);
- }
- }
- // Commonly, invoker should get the title length first by passing NULL to outBuffer
- int COverlayController::GetTitle(char * outBuffer)
- {
- int titleLength = 0;
- if (mTitle)
- {
- titleLength = strlen(mTitle) + 1;
- if (outBuffer)
- {
- strcpy(outBuffer, mTitle);
- }
- }
- return titleLength;
- }
- void COverlayController::GetTitleColor(BYTE * outR, BYTE * outG, BYTE * outB)
- {
- *outR = mColorRed;
- *outG = mColorGreen;
- *outB = mColorBlue;
- }
- void COverlayController::GetTitleStartPosition(POINT * outStartPos)
- {
- outStartPos->x = mStartPos.x;
- outStartPos->y = mStartPos.y;
- }
- void COverlayController::GetTitleFont(LOGFONT * outFont)
- {
- *outFont = mTitleFont;
- }
- void COverlayController::GetTitleDuration(double * outStart, double * outEnd)
- {
- *outStart = mDoubleStartTime;
- *outEnd = mDoubleEndTime;
- }
- // This method must be invoked before all actual title overlay work.
- // We can create title DIB map here!
- BOOL COverlayController::StartTitleOverlay(void)
- {
- mCanDoOverlay = (mPixelConverter != 0);
- if (mCanDoOverlay)
- {
- mCanDoOverlay = CreateTitleDIBBits();
- }
- return mCanDoOverlay;
- }
- BOOL COverlayController::StopTitleOverlay(void)
- {
- mCanDoOverlay = FALSE;
- mOverlayCounter = 0;
- return TRUE;
- }
- BOOL COverlayController::DoTitleOverlay(PBYTE inImage)
- {
- if (!mCanDoOverlay)
- {
- return FALSE;
- }
- BOOL pass = BeforeActualOverlay();
- if (pass)
- {
- pass = ActualOverlay(inImage);
- }
- if (pass)
- {
- pass = AfterActualOverlay();
- }
- return pass;
- }
- // Do title duration checking here!
- // Subclass can override this method to ignore tile duration feature
- BOOL COverlayController::BeforeActualOverlay(void)
- {
- // Only keep the title duration here
- if (mOverlayCounter >= mOverlayStartTime)
- {
- if (mOverlayEndTime == -1 || mOverlayCounter <= mOverlayEndTime)
- {
- return TRUE;
- }
- }
- // If not reach the start time, count any way!
- mOverlayCounter++;
- return FALSE;
- }
- BOOL COverlayController::AfterActualOverlay(void)
- {
- mOverlayCounter++;
- return TRUE;
- }
- BOOL COverlayController::ActualOverlay(PBYTE inImage)
- {
- // Now copy the data from the DIB section (which is usually bottom-up)
- // but first check if it's too big
- if (mImageWidth > mStartPos.x && mImageHeight > mStartPos.y &&
- mTitleSize.cx > 0 && mTitleSize.cy > 0)
- {
- long actualOverlayWidth = min((mImageWidth - mStartPos.x), mTitleSize.cx);
- long actualOverlayHeight = min((mImageHeight - mStartPos.y), mTitleSize.cy);
- // Image may be bottom-up, may be top-down.
- // Anyway retrieve the pointer which point to the top line
- PBYTE pTopLine = NULL;
- long strideInBytes = 0;
- if (mIsBottomUpImage)
- {
- strideInBytes = -mImageWidthInBytes;
- pTopLine = inImage + mImageWidthInBytes * (mImageHeight - 1);
- }
- else
- {
- strideInBytes = mImageWidthInBytes;
- pTopLine = inImage;
- }
- PBYTE pStartPos = pTopLine + mStartPos.y * strideInBytes + mStartPos.x * mImageBitCount / 8;
- for (DWORD dwY = 0; dwY < (DWORD)actualOverlayHeight; dwY++)
- {
- PBYTE pbTitle = mTitleDIBBits + mDIBWidthInBytes * ((DWORD)mTitleSize.cy - dwY - 1);
- for (DWORD dwX = 0; dwX < (DWORD)actualOverlayWidth; dwX++)
- {
- // dwX & 7, value from 0 - 7
- // 0x80 >> (dwX & 7), value from 10000000 to 00000001
- // dwX >> 3, value add one every eight
- // If the source bit is 0, the background. If 1, draw the text.
- if ( !((0x80 >> (dwX & 7)) & pbTitle[dwX >> 3]) )
- {
- PBYTE pbPixel = mPixelConverter->NextNPixel(pStartPos, dwX);
- if (mIsOverlayByCover)
- {
- mPixelConverter->ConvertByCover(pbPixel);
- }
- else
- {
- mPixelConverter->ConvertByReverse(pbPixel);
- }
- }
- }
- pStartPos += strideInBytes;
- }
- return TRUE;
- }
- return FALSE;
- }