先看视频转换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全部改成了function
Pass 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