📄 vop.cpp
字号:
/*************************************************************************This software module was originally developed by Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation Bruce Lin (blin@microsoft.com), Microsoft Corporation Chuang Gu (chuanggu@microsoft.com), Microsoft Corporation (date: March, 1996)in the course of development of the MPEG-4 Video (ISO/IEC 14496-2). This software module is an implementation of a part of one or more MPEG-4 Video tools as specified by the MPEG-4 Video. ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications thereof for use in hardware or software products claiming conformance to the MPEG-4 Video. Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents. The original developer of this software module and his/her company, the subsequent editors and their companies, and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation. Copyright is not released for non MPEG-4 Video conforming products. Microsoft retains full right to use the code for his/her own purpose, assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products. This copyright notice must be included in all copies or derivative works. Copyright (c) 1996, 1997.Module Name: vop.hppAbstract: class for Video Object Plane Revision History:*************************************************************************/#include <math.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include "basic.hpp"#include "transf.hpp"#include "warp.hpp"#include "vop.hpp"#include "typeapi.h"#ifdef __MFC_#ifdef _DEBUG#undef THIS_FILEstatic char BASED_CODE THIS_FILE[] = __FILE__;#endif#define new DEBUG_NEW #endif // __MFC_Int numPln = 4;CVideoObjectPlane::~CVideoObjectPlane (){ delete [] m_ppxl;}Void CVideoObjectPlane::allocate (CRct r, CPixel pxl) { m_rc = r; delete [] m_ppxl, m_ppxl = NULL; // allocate pixels and initialize if (m_rc.empty()) return; m_ppxl = new CPixel [m_rc.area ()]; for (UInt i = 0; i < m_rc.area (); i++) m_ppxl [i] = pxl;// memset (m_ppxl, pxl, m_rc.area () * sizeof (CPixel));}Void CVideoObjectPlane::copyConstruct (const CVideoObjectPlane& vop, CRct r) { if (!r.valid()) r = vop.where (); if (!vop.valid () || (!vop.m_rc.empty () && vop.m_ppxl == NULL)) assert (FALSE); allocate (r, transpPixel); if (!valid ()) return; // Copy data if (r == vop.where ()) memcpy (m_ppxl, vop.pixels (), m_rc.area () * sizeof (PixelF)); else { r.clip (vop.where ()); // find the intersection CoordI x = r.left; // copy pixels Int cbLine = r.width * numPln; CPixel* ppxl = (CPixel*) pixels (x, r.top); const CPixel* ppxlVop = vop.pixels (x, r.top); Int widthCurr = where ().width; Int widthVop = vop.where ().width; for (CoordI y = r.top; y < r.bottom; y++) { memcpy (ppxl, ppxlVop, cbLine); ppxl += widthCurr; ppxlVop += widthVop; } }}Void CVideoObjectPlane::swap (CVideoObjectPlane& vop) { assert (this && &vop); CRct rcT = vop.m_rc; vop.m_rc = m_rc; m_rc = rcT; CPixel* ppxlT = vop.m_ppxl; vop.m_ppxl = m_ppxl; m_ppxl = ppxlT; }CVideoObjectPlane::CVideoObjectPlane (const CVideoObjectPlane& vop, CRct r) : m_ppxl (NULL){ copyConstruct (vop, r);}CVideoObjectPlane::CVideoObjectPlane (CRct r, CPixel pxl) : m_ppxl (NULL){ allocate (r, pxl);}CVideoObjectPlane::CVideoObjectPlane (const Char* vdlFileName) : m_ppxl (NULL){ FILE* pf = fopen (vdlFileName, "rb"); // write overhead Int c0 = getc (pf); Int c1 = getc (pf); assert (c0 == 'V' && (c1 == 'M' || c1 == 'B') ); CRct rc; if (c1 == 'M'){ fread (&rc.left, sizeof (CoordI), 1, pf); fread (&rc.top, sizeof (CoordI), 1, pf); fread (&rc.right, sizeof (CoordI), 1, pf); fread (&rc.bottom, sizeof (CoordI), 1, pf); rc.width = rc.right - rc.left; } else { U8 byte1, byte2; Int sign; byte1 = getc (pf); byte2 = getc (pf); sign = ((byte1 / 128) == 1) ? 1 : -1; rc.left = byte1 % 128; rc.left = (rc.left * 256) + byte2; rc.left *= sign; byte1 = getc (pf); byte2 = getc (pf); sign = ((byte1 / 128) > 0) ? 1 : -1; rc.top = byte1 % 128; rc.top = (rc.top * 256) + byte2; rc.top *= sign; byte1 = getc (pf); byte2 = getc (pf); sign = ((byte1 / 128) > 0) ? 1 : -1; rc.right = byte1 % 128; rc.right = (rc.right * 256) + byte2; rc.right *= sign; byte1 = getc (pf); byte2 = getc (pf); sign = ((byte1 / 128) > 0) ? 1 : -1; rc.bottom = byte1 % 128; rc.bottom = (rc.bottom * 256) + byte2; rc.bottom *= sign; rc.width = rc.right - rc.left; } allocate (rc); // read the actual data fread (m_ppxl, sizeof (CPixel), where ().area (), pf); fclose (pf);}CVideoObjectPlane::CVideoObjectPlane ( const Char* pchFileName, UInt ifr, const CRct& rct, ChromType chrType, Int nszHeader) : m_ppxl (NULL){ assert (!rct.empty ()); assert (ifr >= 0); assert (nszHeader >= 0); Int iWidth = rct.width, iHeight = rct.height (); UInt area = rct.area (); Int iUVWidth = iWidth, iUVHeight = iHeight; Int uiXSubsample = 1, uiYSubsample = 1; if (chrType == FOUR_TWO_TWO) { uiXSubsample = 2; iUVWidth = (iWidth + 1) / uiXSubsample; } else if (chrType == FOUR_TWO_ZERO) { uiXSubsample = 2; uiYSubsample = 2; iUVWidth = (iWidth + 1) / uiXSubsample; iUVHeight = (iHeight + 1) / uiYSubsample; } UInt iUVArea = iUVWidth * iUVHeight; // allocate mem for buffers U8* pchyBuffer = new U8 [area]; U8* pchuBuffer = new U8 [iUVArea]; U8* pchvBuffer = new U8 [iUVArea]; U8* pchyBuffer0 = pchyBuffer; U8* pchuBuffer0 = pchuBuffer; U8* pchvBuffer0 = pchvBuffer; // read data from a file FILE* fpYuvSrc = fopen (pchFileName, "rb"); assert (fpYuvSrc != NULL); UInt skipSize = (UInt) ((Float) (ifr * sizeof (U8) * (area + 2 * iUVArea))); fseek (fpYuvSrc, nszHeader + skipSize, SEEK_SET); Int size = (Int) fread (pchyBuffer, sizeof (U8), area, fpYuvSrc); assert (size != 0); size = (Int) fread (pchuBuffer, 1, iUVArea, fpYuvSrc); assert (size != 0); size = (Int) fread (pchvBuffer, 1, iUVArea, fpYuvSrc); assert (size != 0); fclose(fpYuvSrc); // assign buffers to a vframe allocate (rct, opaquePixel); CPixel* p = (CPixel*) pixels (); for (CoordI y = 0; y < iHeight; y++) { if ((y % uiYSubsample) == 1) { pchuBuffer -= iUVWidth; pchvBuffer -= iUVWidth; } for (CoordI x = 0; x < iWidth; x++) { p -> pxlU.yuv.y = *pchyBuffer++; p -> pxlU.yuv.u = *pchuBuffer; p -> pxlU.yuv.v = *pchvBuffer; if (chrType == FOUR_FOUR_FOUR || (x % uiXSubsample) != 0) { pchuBuffer++; pchvBuffer++; } p++; } } delete [] pchyBuffer0; delete [] pchuBuffer0; delete [] pchvBuffer0;}Void CVideoObjectPlane::where (const CRct& r) { if (!valid ()) return; if (where () == r) return; CVideoObjectPlane* pvop = new CVideoObjectPlane (*this, r); swap (*pvop); delete pvop;}CRct CVideoObjectPlane::whereVisible() const { if (!valid () || !m_rc.valid ()) return CRct (); CoordI left = where ().right - 1; CoordI top = where ().bottom - 1; CoordI right = where ().left; CoordI bottom = where ().top; const CPixel* ppxlThis = pixels (); for (CoordI y = where ().top; y < where ().bottom; y++) { for (CoordI x = where ().left; x < where ().right; x++) { if (ppxlThis -> pxlU.rgb.a != transpValue) { left = min (left, x); top = min (top, y); right = max (right, x); bottom = max (bottom, y); } ppxlThis++; } } right++; bottom++; return CRct (left, top, right, bottom); if (!valid () || !m_rc.valid ()) return CRct ();}CPixel CVideoObjectPlane::pixel (CoordI x, CoordI y, UInt accuracy_ori) const{ UInt accuracy1 = accuracy_ori + 1; CoordI left = (CoordI) floor ((Double) (x >> accuracy1)); // find the coordinates of the four corners CoordI wLeft = where ().left, wRight1 = where ().right - 1, wTop = where ().top, wBottom1 = where ().bottom - 1; left = checkrange (left, wLeft, wRight1); CoordI right = (CoordI) ceil ((Double) (x >> accuracy1)); right = checkrange (right, wLeft, wRight1); CoordI top = (CoordI) floor ((Double) (y >> accuracy1)); top = checkrange (top, wTop, wBottom1); CoordI bottom = (CoordI) ceil ((Double) (y >> accuracy1)); bottom = checkrange (bottom, wTop, wBottom1); UInt accuracy2 = (accuracy_ori << 1) + 2; const CPixel lt = pixel (left, top); const CPixel rt = pixel (right, top); const CPixel lb = pixel (left, bottom); const CPixel rb = pixel (right, bottom); const Int distX = (x - left) << accuracy1; const Int distY = (y - top) << accuracy1; Int x01 = (distX * (rt.pxlU.rgb.r - lt.pxlU.rgb.r) + (Int) lt.pxlU.rgb.r) << accuracy1; // use p.59's notation (Wolberg, Digital Image Warping) Int x23 = (distX * (rb.pxlU.rgb.r - lb.pxlU.rgb.r) + (Int) lb.pxlU.rgb.r) << accuracy1; Int r = checkrange (((x01 << accuracy1) + (x23 - x01) * distY) >> accuracy2, 0, 255); x01 = (distX * (rt.pxlU.rgb.g - lt.pxlU.rgb.g) + (Int) lt.pxlU.rgb.g) << accuracy1; // use p.59's notation x23 = (distX * (rb.pxlU.rgb.g - lb.pxlU.rgb.g) + (Int) lb.pxlU.rgb.g) << accuracy1; Int g = checkrange (((x01 << accuracy1) + (x23 - x01) * distY) >> accuracy2, 0, 255); x01 = (distX * (rt.pxlU.rgb.b - lt.pxlU.rgb.b) + (Int) lt.pxlU.rgb.b) << accuracy1; // use p.59's notation x23 = (distX * (rb.pxlU.rgb.b - lb.pxlU.rgb.b) + (Int) lb.pxlU.rgb.b) << accuracy1; Int b = checkrange (((x01 << accuracy1) + (x23 - x01) * distY) >> accuracy2, 0, 255); x01 = (distX * (rt.pxlU.rgb.a - lt.pxlU.rgb.a) + (Int) lt.pxlU.rgb.a) << accuracy1; // use p.59's notation x23 = (distX * (rb.pxlU.rgb.a - lb.pxlU.rgb.a) + (Int) lb.pxlU.rgb.a) << accuracy1; Int a = checkrange (((x01 << accuracy1) + (x23 - x01) * distY) >> accuracy2, 0, 255); return CPixel ((U8) r, (U8) g, (U8) b, (U8) a);}CPixel CVideoObjectPlane::pixel (CoordD x, CoordD y) const{ CoordI left = (CoordI) floor (x); // find the coordinates of the four corners CoordI wLeft = where ().left, wRight1 = where ().right - 1, wTop = where ().top, wBottom1 = where ().bottom - 1; left = checkrange (left, wLeft, wRight1); CoordI right = (CoordI) ceil (x); right = checkrange (right, wLeft, wRight1); CoordI top = (CoordI) floor (y); top = checkrange (top, wTop, wBottom1); CoordI bottom = (CoordI) ceil (y); bottom = checkrange (bottom, wTop, wBottom1); const CPixel lt = pixel (left, top); const CPixel rt = pixel (right, top); const CPixel lb = pixel (left, bottom); const CPixel rb = pixel (right, bottom); const Double distX = x - left; const Double distY = y - top; Double x01 = distX * (rt.pxlU.rgb.r - lt.pxlU.rgb.r) + lt.pxlU.rgb.r; // use p.59's notation (Wolberg, Digital Image Warping) Double x23 = distX * (rb.pxlU.rgb.r - lb.pxlU.rgb.r) + lb.pxlU.rgb.r; Int r = checkrange ((Int) (x01 + (x23 - x01) * distY + .5), 0, 255); x01 = distX * (rt.pxlU.rgb.g - lt.pxlU.rgb.g) + lt.pxlU.rgb.g; // use p.59's notation x23 = distX * (rb.pxlU.rgb.g - lb.pxlU.rgb.g) + lb.pxlU.rgb.g; Int g = checkrange ((Int) (x01 + (x23 - x01) * distY + .5), 0, 255); x01 = distX * (rt.pxlU.rgb.b - lt.pxlU.rgb.b) + lt.pxlU.rgb.b; // use p.59's notation x23 = distX * (rb.pxlU.rgb.b - lb.pxlU.rgb.b) + lb.pxlU.rgb.b; Int b = checkrange ((Int) (x01 + (x23 - x01) * distY + .5), 0, 255); x01 = distX * (rt.pxlU.rgb.a - lt.pxlU.rgb.a) + lt.pxlU.rgb.a; // use p.59's notation x23 = distX * (rb.pxlU.rgb.a - lb.pxlU.rgb.a) + lb.pxlU.rgb.a; Int a = checkrange ((Int) (x01 + (x23 - x01) * distY + .5), 0, 255); return CPixel ((U8) r, (U8) g, (U8) b, (U8) a);}own CVideoObjectPlane* CVideoObjectPlane::warp (const CAffine2D& aff) const // affine warp{ CSiteD stdLeftTopWarp = aff * CSiteD (where ().left, where ().top); CSiteD stdRightTopWarp = aff * CSiteD (where ().right, where ().top); CSiteD stdLeftBottomWarp = aff * CSiteD (where ().left, where ().bottom); CSiteD stdRightBottomWarp = aff * CSiteD (where ().right, where ().bottom); CRct rctWarp (stdLeftTopWarp, stdRightTopWarp, stdLeftBottomWarp, stdRightBottomWarp); CVideoObjectPlane* pvopRet = new CVideoObjectPlane (rctWarp); CPixel* ppxlRet = (CPixel*) pvopRet -> pixels (); CAffine2D affInv = aff.inverse (); for (CoordI y = rctWarp.top; y < rctWarp.bottom; y++) { for (CoordI x = rctWarp.left; x < rctWarp.right; x++) { CSiteD src = affInv * CSiteD (x, y); CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation if ( where ().includes (fx, fy) && where ().includes (fx, cy) && where ().includes (cx, fy) && where ().includes (cx, cy) ) *ppxlRet = pixel (src); ppxlRet++; } } return pvopRet;}own CVideoObjectPlane* CVideoObjectPlane::warp (const CAffine2D& aff, const CRct& rctWarp) const // affine warp{ CVideoObjectPlane* pvopRet = new CVideoObjectPlane (rctWarp); CPixel* ppxlRet = (CPixel*) pvopRet -> pixels (); //CAffine2D affInv = aff.inverse (); for (CoordI y = rctWarp.top; y < rctWarp.bottom; y++) { for (CoordI x = rctWarp.left; x < rctWarp.right; x++) { CSiteD src = aff * CSiteD (x, y); CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation if ( where ().includes (fx, fy) && where ().includes (fx, cy) && where ().includes (cx, fy) && where ().includes (cx, cy) ) *ppxlRet = pixel (src); ppxlRet++; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -