⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tspuimage.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2005,2006 Milan Cutka
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "stdafx.h"
#include "TspuImage.h"
#include "simd.h"
#include "TffPict.h"
#include "Tlibmplayer.h"
#include "Tconfig.h"
#include "IffdshowBase.h"

//=================================================== TspuImage ===================================================
TspuImage::TspuImage(const TspuPlane src[3],const CRect &rcclip,const CRect &rectReal,const CRect &rectOrig,const TrenderedSubtitleLines::TprintPrefs &prefs):TrenderedSubtitleWordBase(false)
{
 if (rectReal.Width()<0) return;
 Tscaler *scaler=NULL;
 int scale=prefs.dvd?0x100:prefs.vobscale;
 for (int i=0;i<3;i++)
  {
   rect[i]=CRect(roundRshift(rectReal.left,prefs.shiftX[i]),roundRshift(rectReal.top,prefs.shiftY[i]),roundRshift(rectReal.right,prefs.shiftX[i]),roundRshift(rectReal.bottom,prefs.shiftY[i]));
   int dstdx=roundDiv(scale*(rectOrig.Width() ?roundDiv(prefs.dx*rect[i].Width() ,(unsigned int)rectOrig.Width() ):rect[i].Width() ),0x100U);
   int dstdy=roundDiv(scale*(rectOrig.Height()?roundDiv(prefs.dy*rect[i].Height(),(unsigned int)rectOrig.Height()):rect[i].Height()),0x100U);
   plane[i].alloc(CSize(dstdx,dstdy),1);
   if (!scaler || scaler->srcdx!=rect[i].Width() || scaler->srcdy!=rect[i].Height())
    {
     if (scaler) delete scaler;
     scaler=Tscaler::create(prefs,rect[i].Width(),rect[i].Height(),dstdx,dstdy);
    }
   scaler->scale(src[i].c+rect[i].top*src[i].stride+rect[i].left,src[i].r+rect[i].top*src[i].stride+rect[i].left,src[i].stride,plane[i].c,plane[i].r,plane[i].stride);
   rect[i]+=CPoint(roundRshift(rcclip.left,prefs.shiftX[i]),roundRshift(rcclip.top,prefs.shiftY[i]));
   rect[i].left=roundDiv(int(prefs.dx*rect[i].left),rectOrig.Width());rect[i].right=rect[i].left+dstdx;
   rect[i].top=roundDiv(int(prefs.dy*rect[i].top),rectOrig.Height());rect[i].bottom=rect[i].top+dstdy;
   dx[i]=rect[i].Width();dy[i]=rect[i].Height();
   bmp[i]=plane[i].c;msk[i]=plane[i].r;
   bmpmskstride[i]=plane[i].stride;
  }
 dxCharY=dx[0];dyCharY=dy[0];
 if (scaler) delete scaler;
}

//=============================================== TspuImage::Tscaler ==============================================
TspuImage::Tscaler* TspuImage::Tscaler::create(const TrenderedSubtitleLines::TprintPrefs &prefs,int srcdx,int srcdy,int dstdx,int dstdy)
{
 switch (prefs.dvd?0:prefs.vobaamode)
  {
   case 1:return new TscalerApprox(prefs,srcdx,srcdy,dstdx,dstdy);
   case 2:return new TscalerFull(prefs,srcdx,srcdy,dstdx,dstdy);
   case 3:return new TscalerBilin(prefs,srcdx,srcdy,dstdx,dstdy);
   case 4:return new TscalerSw(prefs,srcdx,srcdy,dstdx,dstdy);
   default:
   case 0:return new TscalerPoint(prefs,srcdx,srcdy,dstdx,dstdy);
  }
}

//============================================ TspuImage::TscalerPoint ============================================
TspuImage::TscalerPoint::TscalerPoint(const TrenderedSubtitleLines::TprintPrefs &prefs,int srcdx,int srcdy,int dstdx,int dstdy):Tscaler(srcdx,srcdy,dstdx,dstdy)
{
}
void TspuImage::TscalerPoint::scale(const unsigned char *srci,const unsigned char *srca,stride_t srcStride,unsigned char *dsti,unsigned char *dsta,stride_t dstStride)
{
 if (srcdx==dstdx && srcdy==dstdy)
  {
   TffPict::copy(dsti,dstStride,srci,srcStride,srcdx,srcdy);
   TffPict::copy(dsta,dstStride,srca,srcStride,srcdx,srcdy);
  }
 else
  {
   int scalex=0x100*dstdx/srcdx;
   int scaley=0x100*dstdy/srcdy;
   for (int y=0;y<dstdy;y++)
    {
     int unscaled_y=y*0x100/scaley;
     stride_t strides=srcStride*unscaled_y;
     stride_t scaled_strides=dstStride*y;
     for (int x=0;x<dstdx;x++)
      {
       int unscaled_x=x*0x100/scalex;
       dsti[scaled_strides+x]=srci[strides+unscaled_x];
       dsta[scaled_strides+x]=srca[strides+unscaled_x];
      }
    }
  }
}

//============================================ TspuImage::TscalerApprox ===========================================
TspuImage::TscalerApprox::TscalerApprox(const TrenderedSubtitleLines::TprintPrefs &prefs,int srcdx,int srcdy,int dstdx,int dstdy):Tscaler(srcdx,srcdy,dstdx,dstdy)
{
 scalex=0x100*dstdx/srcdx;
 scaley=0x100*dstdy/srcdy;
}
void TspuImage::TscalerApprox::scale(const unsigned char *srci,const unsigned char *srca,stride_t srcStride,unsigned char *dsti,unsigned char *dsta,stride_t dstStride)
{
 unsigned int height=srcdy;
 for (int y=0;y<dstdy;y++,dsti+=dstStride,dsta+=dstStride)
  {
   const unsigned int unscaled_top=y*0x100/scaley;
   unsigned int unscaled_bottom=(y+1)*0x100/scaley;
   if (unscaled_bottom>=height)
    unscaled_bottom=height-1;
   unsigned char *dstiLn=dsti,*dstaLn=dsta;
   for (int x=0;x<dstdx;x++,dstiLn++,dstaLn++)
    {
     const unsigned int unscaled_left=x*0x100/scalex;
     unsigned int unscaled_right=(x+1)*0x100/scalex;
     unsigned int width=srcdx;
     if (unscaled_right>=width)
      unscaled_right=width-1;
     unsigned int alpha=0,color=0;
     int cnt=0;
     for (unsigned int walky=unscaled_top;walky<=unscaled_bottom;walky++)
      for (unsigned int walkx=unscaled_left;walkx<=unscaled_right;walkx++)
       {
        cnt++;
        stride_t base=walky*srcStride+walkx;
        unsigned int tmp=srca[base];
        alpha+=tmp;
        color+=tmp*srci[base];
       }
     *dstiLn=(unsigned char)(alpha?color/alpha:0);
     *dstaLn=(unsigned char)(cnt?alpha/cnt:0);
    }
  }
}

//============================================ TspuImage::TscalerFull =============================================
TspuImage::TscalerFull::TscalerFull(const TrenderedSubtitleLines::TprintPrefs &prefs,int srcdx,int srcdy,int dstdx,int dstdy):Tscaler(srcdx,srcdy,dstdx,dstdy)
{
}
void TspuImage::TscalerFull::scale(const unsigned char *srci,const unsigned char *srca,stride_t srcStride,unsigned char *dsti,unsigned char *dsta,stride_t dstStride)
{
 const double scalex=(double)0x100*dstdx/srcdx;
 const double scaley=(double)0x100*dstdy/srcdy;
 /* Best antialiasing.  Very slow. */
 /* Any pixel (x, y) represents pixels from the original
    rectangular region comprised between the columns
    unscaled_y and unscaled_y + 0x100 / scaley and the rows
    unscaled_x and unscaled_x + 0x100 / scalex

    The original rectangular region that the scaled pixel
    represents is cut in 9 rectangular areas like this:

    +---+-----------------+---+
    | 1 |        2        | 3 |
    +---+-----------------+---+
    |   |                 |   |
    | 4 |        5        | 6 |
    |   |                 |   |
    +---+-----------------+---+
    | 7 |        8        | 9 |
    +---+-----------------+---+

    The width of the left column is at most one pixel and
    it is never null and its right column is at a pixel
    boundary.  The height of the top row is at most one
    pixel it is never null and its bottom row is at a
    pixel boundary. The width and height of region 5 are
    integral values.  The width of the right column is
    what remains and is less than one pixel.  The height
    of the bottom row is what remains and is less than
    one pixel.

    The row above 1, 2, 3 is unscaled_y.  The row between
    1, 2, 3 and 4, 5, 6 is top_low_row.  The row between 4,
    5, 6 and 7, 8, 9 is (unsigned int)unscaled_y_bottom.
    The row beneath 7, 8, 9 is unscaled_y_bottom.

    The column left of 1, 4, 7 is unscaled_x.  The column
    between 1, 4, 7 and 2, 5, 8 is left_right_column.  The
    column between 2, 5, 8 and 3, 6, 9 is (unsigned
    int)unscaled_x_right.  The column right of 3, 6, 9 is
    unscaled_x_right. */
 const double inv_scalex = (double) 0x100 / scalex;
 const double inv_scaley = (double) 0x100 / scaley;
 for (int y = 0; y < dstdy; ++y,dsti+=dstStride,dsta+=dstStride)
  {
   const double unscaled_y = y * inv_scaley;
   const double unscaled_y_bottom = unscaled_y + inv_scaley;
   const unsigned int top_low_row = (unsigned int)std::min(unscaled_y_bottom, unscaled_y + 1.0);
   const double top = top_low_row - unscaled_y;
   const unsigned int height = unscaled_y_bottom > top_low_row
     ? (unsigned int) unscaled_y_bottom - top_low_row
     : 0;
   const double bottom = unscaled_y_bottom > top_low_row
     ? unscaled_y_bottom - floor(unscaled_y_bottom)
     : 0.0;
   unsigned char *dstiLn=dsti,*dstaLn=dsta;
   for (int x = 0; x < dstdx; ++x,dstiLn++,dstaLn++)
    {
     const double unscaled_x = x * inv_scalex;
     const double unscaled_x_right = unscaled_x + inv_scalex;
     const unsigned int left_right_column = (unsigned int)std::min(unscaled_x_right, unscaled_x + 1.0);
     const double left = left_right_column - unscaled_x;
     const unsigned int width = unscaled_x_right > left_right_column
       ? (unsigned int) unscaled_x_right - left_right_column
       : 0;
     const double right = unscaled_x_right > left_right_column
       ? unscaled_x_right - floor(unscaled_x_right)
       : 0.0;
     double color = 0.0;
     double alpha = 0.0;
     double tmp;
     stride_t base;
     /* Now use these informations to compute a good alpha,
        and lightness.  The sum is on each of the 9
        region's surface and alpha and lightness.

       transformed alpha = sum(surface * alpha) / sum(surface)
       transformed color = sum(surface * alpha * color) / sum(surface * alpha)
     */
     /* 1: top left part */
     base = srcStride * (unsigned int) unscaled_y;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -