先看视频转换320x240的效果比较图:采用的是:Two Pass Scaling using Filters图片缩放算法http://www.codeproject.com/KB/graphics/2_pass_scaling.aspx把它改到mingw c语言下,用gcc编译时遇到了许多问题,开始总出现异常,尽管在vc下测试是正常的。目前还存在字幕显示有点模糊,缩小情况下不能调整字幕颜色了,这个与视频合并时有关,合并前字幕截图是正常的。由于字幕颜色格式采用的是rgba,而转换出来的视频颜色格式采用的可能是其它格式,如YUV420P, YV12等,如何有效地转换成一致,这个暂时不太清楚,尽管可用sws_scale转换,但效果如何有待确认。编译异常主要遇到的情况:1。声明变量类型分配空间大小问题。由于原来用的是c++中的new,不用考虑int8, int32等大小,但用malloc则需要。2。由于vc下有采用的变量类型在c语言下可能没有,需要自己定义并替换原来的。3。语法问题,如for (int i=0; i<10; i++){....}, i在后面就不能直接用了等。有关Pass Scaling源代码,里面函数Filter,其实就是它原来的CBilinearFilter, 把原来的class全部改成了functionPass Scaling的设计思路还是相当不错的.#ifndef _2_PASS_SCALE_H_#define _2_PASS_SCALE_H_
#include <math.h>
typedef struct { double *Weights; // Normalized weights of neighboring pixels int Left,Right; // Bounds of source pixels window} ContributionType; // Contirbution information for a single pixel
typedef struct { ContributionType *ContribRow; // Row (or column) of contribution weights UINT WindowSize, // Filter window size (of affecting source pixels) LineLength; // Length of line (no. or rows / cols) } LineContribType; // Contribution information for an entire line (row or column)
COLORREF * AllocAndScale ( COLORREF *pOrigImage, UINT uOrigWidth, UINT uOrigHeight, UINT uNewWidth, UINT uNewHeight);
COLORREF * Scale ( COLORREF *pOrigImage, UINT uOrigWidth, UINT uOrigHeight, COLORREF *pDstImage, UINT uNewWidth, UINT uNewHeight);
LineContribType *AllocContributions (UINT uLineLength, UINT uWindowSize){ LineContribType *res = (LineContribType *) malloc(sizeof(LineContribType)); // Init structure header res->WindowSize = uWindowSize; res->LineLength = uLineLength; // Allocate list of contributions res->ContribRow = (ContributionType *) malloc(uLineLength * sizeof(ContributionType)); for (UINT u = 0 ; u < uLineLength ; u++) { // Allocate contributions for every pixel res->ContribRow[u].Weights = (double *)malloc(uWindowSize * sizeof(double)); } return res; } void FreeContributions (LineContribType * p){ for (UINT u = 0; u < p->LineLength; u++) { // Free contribs for every pixel free(p->ContribRow[u].Weights); } free(p->ContribRow); // Free list of pixels contribs free(p); // Free contribs header} double Filter (double dVal) { dVal = fabs(dVal); return (dVal < 1.0 ? 1.0 - dVal : 0.0); }
LineContribType *CalcContributions (UINT uLineSize, UINT uSrcSize, double dScale){ double dWidth; double dFScale = 1.0; double dFilterWidth = 1.0;
if (dScale < 1.0) { // Minification dWidth = dFilterWidth / dScale; dFScale = dScale; } else { // Magnification dWidth= dFilterWidth; } // Window size is the number of sampled pixels int iWindowSize = 2 * (int)ceil(dWidth) + 1; // Allocate a new line contributions strucutre LineContribType *res = AllocContributions (uLineSize, iWindowSize); for (UINT u = 0; u < uLineSize; u++) { // Scan through line of contributions double dCenter = (double)u / dScale; // Reverse mapping // Find the significant edge points that affect the pixel int iLeft = max (0, (int)floor (dCenter - dWidth)); res->ContribRow[u].Left = iLeft; int iRight = min (ceil (dCenter + dWidth), uSrcSize - 1); res->ContribRow[u].Right = iRight; // Cut edge points to fit in filter window in case of spill-off if (iRight - iLeft + 1 > iWindowSize) { if (iLeft < (uSrcSize - 1 / 2)) { iLeft++; } else { iRight--; } } int iSrc; double dTotalWeight = 0.0; // Zero sum of weights for (iSrc = iLeft; iSrc <= iRight; iSrc++) { // Calculate weights dTotalWeight += (res->ContribRow[u].Weights[iSrc-iLeft] = dFScale * Filter (dFScale * (dCenter - (double)iSrc))); } //assert (dTotalWeight >= 0.0); // An error in the filter function can cause this if (dTotalWeight > 0.0) { // Normalize weight of neighbouring points for (iSrc = iLeft; iSrc <= iRight; iSrc++) { // Normalize point res->ContribRow[u].Weights[iSrc-iLeft] /= dTotalWeight; } } } return res; } void ScaleRow(COLORREF *pSrc, UINT uSrcWidth, COLORREF *pRes, UINT uResWidth, UINT uRow, LineContribType *Contrib){ COLORREF *pSrcRow = &(pSrc[uRow * uSrcWidth]); COLORREF *pDstRow = &(pRes[uRow * uResWidth]); for (UINT x = 0; x < uResWidth; x++) { // Loop through row BYTE r = 0; BYTE g = 0; BYTE b = 0; int iLeft = Contrib->ContribRow[x].Left; // Retrieve left boundries int iRight = Contrib->ContribRow[x].Right; // Retrieve right boundries //printf("%d, left=%d, right=%d/n", x,iLeft, iRight); if (iRight - iLeft >= 5) { // printf("%d, left=%d, right=%d===============================/n", x,iLeft, iRight); } for (int i = iLeft; i <= iRight; i++) { // Scan between boundries // Accumulate weighted effect of each neighboring pixel r += (BYTE)(Contrib->ContribRow[x].Weights[i-iLeft] * (double)(GetRValue(pSrcRow[i]))); g += (BYTE)(Contrib->ContribRow[x].Weights[i-iLeft] * (double)(GetGValue(pSrcRow[i]))); b += (BYTE)(Contrib->ContribRow[x].Weights[i-iLeft] * (double)(GetBValue(pSrcRow[i]))); } pDstRow[x] = RGB(r,g,b); // Place result in destination pixel } }
void HorizScale (COLORREF *pSrc, UINT uSrcWidth, UINT uSrcHeight, COLORREF *pDst, UINT uResWidth, UINT uResHeight){ if (uResWidth == uSrcWidth) { // No scaling required, just copy memcpy (pDst, pSrc, sizeof (COLORREF) * uSrcHeight * uSrcWidth); } // Allocate and calculate the contributions LineContribType * Contrib = CalcContributions (uResWidth, uSrcWidth, (double)uResWidth/uSrcWidth); for (UINT u = 0; u < uResHeight; u++) { printf("noRow=%d, w=%d/n", u, uResWidth); ScaleRow ( pSrc, uSrcWidth, pDst, uResWidth, u, Contrib); // Scale each row } FreeContributions (Contrib); // Free contributions structure} void ScaleCol (COLORREF *pSrc, UINT uSrcWidth, COLORREF *pRes, UINT uResWidth, UINT uResHeight, UINT uCol, LineContribType *Contrib){ for (UINT y = 0; y < uResHeight; y++) { // Loop through column BYTE r = 0; BYTE g = 0; BYTE b = 0; int iLeft = Contrib->ContribRow[y].Left; // Retrieve left boundries int iRight = Contrib->ContribRow[y].Right; // Retrieve right boundries //printf("%d, left=%d, right=%d/n", y,iLeft, iRight); for (int i = iLeft; i <= iRight; i++) { // Scan between boundries // Accumulate weighted effect of each neighboring pixel COLORREF pCurSrc = pSrc[i * uSrcWidth + uCol]; r += BYTE(Contrib->ContribRow[y].Weights[i-iLeft] * (double)(GetRValue(pCurSrc))); g += BYTE(Contrib->ContribRow[y].Weights[i-iLeft] * (double)(GetGValue(pCurSrc))); b += BYTE(Contrib->ContribRow[y].Weights[i-iLeft] * (double)(GetBValue(pCurSrc))); } pRes[(uResHeight-1-y) * uResWidth + uCol] = RGB (r,g,b); // Place result in destination pixel }} void VertScale (COLORREF *pSrc, UINT uSrcWidth, UINT uSrcHeight, COLORREF *pDst, UINT uResWidth, UINT uResHeight){ if (uSrcHeight == uResHeight) { // No scaling required, just copy memcpy (pDst, pSrc, sizeof (COLORREF) * uSrcHeight * uSrcWidth); } // Allocate and calculate the contributions LineContribType * Contrib = CalcContributions (uResHeight, uSrcHeight, (double)uResHeight/uSrcHeight); for (UINT u = 0; u < uResWidth; u++) { // Step through columns printf("noCol=%d, w=%d/n", u, uResWidth); ScaleCol ( pSrc, uSrcWidth, pDst, uResWidth, uResHeight, u, Contrib); // Scale each column } FreeContributions (Contrib); // Free contributions structure}
COLORREF *AllocAndScale ( COLORREF *pOrigImage, UINT uOrigWidth, UINT uOrigHeight, UINT uNewWidth, UINT uNewHeight){ // Scale source image horizontally into temporary image COLORREF *pTemp = (COLORREF*)malloc(uNewWidth * uOrigHeight * sizeof(COLORREF)); HorizScale (pOrigImage, uOrigWidth, uOrigHeight, pTemp, uNewWidth, uOrigHeight);
// Scale temporary image vertically into result image COLORREF *pRes = (COLORREF*)malloc(uNewWidth * uNewHeight * sizeof(COLORREF)); VertScale ( pTemp, uNewWidth, uOrigHeight, pRes, uNewWidth, uNewHeight); free(pTemp); return pRes;}
COLORREF *Scale ( COLORREF *pOrigImage, UINT uOrigWidth, UINT uOrigHeight, COLORREF *pDstImage, UINT uNewWidth, UINT uNewHeight){ // Scale source image horizontally into temporary image COLORREF *pTemp = (COLORREF*)malloc(uNewWidth * uOrigHeight * sizeof(COLORREF)); HorizScale (pOrigImage, uOrigWidth, uOrigHeight, pTemp, uNewWidth, uOrigHeight); // Scale temporary image vertically into result image VertScale ( pTemp, uNewWidth, uOrigHeight, pDstImage, uNewWidth, uNewHeight); free(pTemp); return pDstImage;}
#endif // _2_PASS_SCALE_H_参考文档:http://www.compuphase.com/graphic/scale2.htm