转换dvd 字幕缩小改进(thinkvd开发日志)

    技术2022-05-20  27

    先看视频转换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


    最新回复(0)