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

📄 text-overlay.cpp

📁 avisynth-source-0.3.zip,avi edit src
💻 CPP
字号:
// Avisynth v0.3.  Copyright 2000 Ben Rudiak-Gould.  For distribution
// conditions, please see http://www.math.berkeley.edu/~benrg/avisynth.html .

// This file is adapted in part from VirtualDub source code.  VirtualDub is
// Copyright 2000 Avery Lee.


#include "avisynth.h"
#include "internal-filters.h"


class Antialiaser {
  const int w, h;
  HDC hdcAntialias;
  HBITMAP hbmAntialias;
  void* lpAntialiasBits;
  HFONT hfontDefault;
  HBITMAP hbmDefault;
  char* alpha_bits;
  bool dirty;

  void GetAlphaRect();

public:
  Antialiaser(int width, int height, const char fontname[], int size);
  HDC GetDC();
  void Apply(unsigned char* pixel_buf, int textcolor, int halocolor, bool yuv);
  ~Antialiaser();
};


class ShowFrameNumber : public GenericVideoFilter {
  Antialiaser antialiaser;
public:
  ShowFrameNumber(PVideoFilter _child);
  void GetFrame(int n, unsigned char* buf);

  static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
    return new ShowFrameNumber(args[0].clip);
  }
};


class Subtitle : public GenericVideoFilter {
  const int x, y, firstframe, lastframe, size;
  /*const*/ int textcolor, halocolor;
  char* const fontname;
  char* const text;
  Antialiaser* antialiaser;
  void InitAntialiaser();
public:
  Subtitle(const char _text[], int _x, int _y, int _firstframe, int _lastframe, const char _fontname[], int _size,
    int _textcolor, int _halocolor, PVideoFilter _child);
  void GetFrame(int n, unsigned char* buf);
  ~Subtitle();

  static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char* arg_types) {
    int num_args = strlen(arg_types);
    if (num_args == 2) {
      return new Subtitle(args[0].string, 4, 15, 0, 99999999, "Arial", 18, 0xFFFF00, 0, args[1].clip);
    } else {
      return new Subtitle(args[0].string, args[1].integer, args[2].integer,
        args[3].integer, args[4].integer, args[5].string, args[6].integer,
        (num_args >= 9) ? args[7].integer : 0xFFFF00,
        (num_args >= 10) ? args[8].integer : 0, args[num_args-1].clip);
    }
  }
};




static HFONT LoadFont(int size, bool bold, bool italic, const char name[]) {
  return CreateFont(size, 0, 0, 0, bold ? FW_BOLD : FW_NORMAL,
    italic, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
    CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE | DEFAULT_PITCH, name);
}


ShowFrameNumber::ShowFrameNumber(PVideoFilter _child)
 : GenericVideoFilter(_child), antialiaser(vi.width, vi.height, "Arial", 192) {}

void ShowFrameNumber::GetFrame(int n, unsigned char* buf) {
  child->GetFrame(n, buf);
  HDC hdc = antialiaser.GetDC();
  SetTextAlign(hdc, TA_BASELINE|TA_LEFT);
  RECT r = { 0, 0, 32767, 32767 };
  FillRect(hdc, &r, (HBRUSH)GetStockObject(BLACK_BRUSH));
  char text[40];
  wsprintf(text, "%05d", n);
  for (int y=192; y<vi.height*8; y += 192)
    TextOut(hdc, child->GetParity(n) ? 32 : vi.width*8-512, y, text, strlen(text));
  GdiFlush();
  if (vi.IsYUY2())
    antialiaser.Apply(buf, 0xD21092, 0x108080, true);
  else
    antialiaser.Apply(buf, 0xFFFF00, 0, false);
}


Antialiaser::Antialiaser(int width, int height, const char fontname[], int size)
 : w(width), h(height)
{
  struct {
    BITMAPINFOHEADER bih;
    RGBQUAD clr[2];
  } b;

  b.bih.biSize                    = sizeof(BITMAPINFOHEADER);
  b.bih.biWidth                   = width * 8 + 32;
  b.bih.biHeight                  = height * 8 + 32;
  b.bih.biBitCount                = 1;
  b.bih.biPlanes                  = 1;
  b.bih.biCompression             = BI_RGB;
  b.bih.biXPelsPerMeter   = 0;
  b.bih.biYPelsPerMeter   = 0;
  b.bih.biClrUsed                 = 2;
  b.bih.biClrImportant    = 2;
  b.clr[0].rgbBlue = b.clr[0].rgbGreen = b.clr[0].rgbRed = 0;
  b.clr[1].rgbBlue = b.clr[1].rgbGreen = b.clr[1].rgbRed = 255;

  hdcAntialias = CreateCompatibleDC(NULL);
  hbmAntialias = CreateDIBSection(
    hdcAntialias,
    (BITMAPINFO *)&b,
    DIB_RGB_COLORS,
    &lpAntialiasBits,
    NULL,
    0);
  hbmDefault = (HBITMAP)SelectObject(hdcAntialias, hbmAntialias);

  HFONT newfont = LoadFont(size, true, false, fontname);
  hfontDefault = (HFONT)SelectObject(hdcAntialias, newfont);

  SetMapMode(hdcAntialias, MM_TEXT);
  SetTextColor(hdcAntialias, 0xffffff);
  SetBkColor(hdcAntialias, 0);

  alpha_bits = new char[width*height*2];

  dirty = true;
}


Antialiaser::~Antialiaser() {
  DeleteObject(SelectObject(hdcAntialias, hbmDefault));
  DeleteObject(SelectObject(hdcAntialias, hfontDefault));
  DeleteDC(hdcAntialias);
  if (alpha_bits) delete[] alpha_bits;
}


HDC Antialiaser::GetDC() {
  dirty = true;
  return hdcAntialias;
}


char* MyStrdup(const char* s) {
  return lstrcpy(new char[(lstrlen(s)+1)], s);
}


Subtitle::Subtitle(const char _text[], int _x, int _y, int _firstframe, int _lastframe, const char _fontname[], int _size, int _textcolor, int _halocolor, PVideoFilter _child)
 : GenericVideoFilter(_child), antialiaser(0), text(MyStrdup(_text)), x(_x), y(_y), firstframe(_firstframe), lastframe(_lastframe), fontname(MyStrdup(_fontname)), size(_size*8)
{
  if (vi.IsYUY2()) {
    textcolor = RGB2YUV(_textcolor);
    halocolor = RGB2YUV(_halocolor);
  } else {
    textcolor = _textcolor;
    halocolor = _halocolor;
  }
}


Subtitle::~Subtitle() {
  if (antialiaser)
    delete antialiaser;
  if (text)
    delete[] text;
  if (fontname)
    delete[] fontname;
}


void Subtitle::InitAntialiaser() {
  antialiaser = new Antialiaser(vi.width, vi.height, fontname, size);

  HDC hdcAntialias = antialiaser->GetDC();

  int real_x;
  if (x == -1) {
    SetTextAlign(hdcAntialias, TA_BASELINE|TA_CENTER);
    real_x = vi.width>>1;
  } else {
    SetTextAlign(hdcAntialias, TA_BASELINE|TA_LEFT);
    real_x = x;
  }

  RECT r;
  r.left = 0;
  r.top = 0;
  r.right = vi.width * 8 + 32;
  r.bottom = vi.height * 8 + 32;
//  FillRect(hdcAntialias, &r, (HBRUSH)GetStockObject(WHITE_BRUSH));
  TextOut(hdcAntialias, real_x*8+16, y*8+16, text, strlen(text));
  GdiFlush();
}


void Subtitle::GetFrame(int n, unsigned char* buf) {
  child->GetFrame(n, buf);
  if (n >= firstframe && n <= lastframe) {
    if (!antialiaser)
      InitAntialiaser();
    antialiaser->Apply(buf, textcolor, halocolor, vi.IsYUY2());
  } else {
    // if we get far enough away from the frames we're supposed to
    // subtitle, then junk the buffered drawing information
    if (antialiaser && (n < firstframe-10 || n > lastframe+10)) {
      delete antialiaser;
      antialiaser = 0;
    }
  }
}


void Antialiaser::Apply(unsigned char* pixel_buf, int textcolor, int halocolor, bool yuv) {
  if (dirty) GetAlphaRect();
  if (yuv) {
    int Ytext = ((textcolor>>16)&255), Utext = ((textcolor>>8)&255), Vtext = (textcolor&255);
    int Yhalo = ((halocolor>>16)&255), Uhalo = ((halocolor>>8)&255), Vhalo = (halocolor&255);
    for (int i=0; i<w*h*2; i+=4) {
      if (*(long*)&alpha_bits[i]) {
        pixel_buf[i] = (pixel_buf[i] * (64-alpha_bits[i]-alpha_bits[i+1]) + Ytext * alpha_bits[i] + Yhalo * alpha_bits[i+1]) >> 6;
        pixel_buf[i+2] = (pixel_buf[i+2] * (64-alpha_bits[i+2]-alpha_bits[i+3]) + Ytext * alpha_bits[i+2] + Yhalo * alpha_bits[i+3]) >> 6;
        int auv1 = alpha_bits[i]+alpha_bits[i+2];
        int auv2 = alpha_bits[i+1]+alpha_bits[i+3];
        pixel_buf[i+1] = (pixel_buf[i+1] * (128-auv1-auv2) + Utext * auv1 + Uhalo * auv2) >> 7;
        pixel_buf[i+3] = (pixel_buf[i+3] * (128-auv1-auv2) + Vtext * auv1 + Vhalo * auv2) >> 7;
      }
    }
  } else {
    int Rtext = ((textcolor>>16)&255), Gtext = ((textcolor>>8)&255), Btext = (textcolor&255);
    int Rhalo = ((halocolor>>16)&255), Ghalo = ((halocolor>>8)&255), Bhalo = (halocolor&255);
    for (int y=0; y<h; ++y) {
      unsigned char* pixel_buf_line = pixel_buf + y*w*3;
      char* alpha_bits_line = alpha_bits + (h-y-1)*w*2;
      for (int x=0; x<w; ++x) {
        int textalpha = alpha_bits_line[0];
        int haloalpha = alpha_bits_line[1];
        if (textalpha | haloalpha) {
          pixel_buf_line[0] = (pixel_buf_line[0] * (64-textalpha-haloalpha) + Btext * textalpha + Bhalo * haloalpha) >> 6;
          pixel_buf_line[1] = (pixel_buf_line[1] * (64-textalpha-haloalpha) + Gtext * textalpha + Ghalo * haloalpha) >> 6;
          pixel_buf_line[2] = (pixel_buf_line[2] * (64-textalpha-haloalpha) + Rtext * textalpha + Rhalo * haloalpha) >> 6;
        }
        pixel_buf_line += 3;
        alpha_bits_line += 2;
      }
    }
  }
}


void Antialiaser::GetAlphaRect() {

	dirty = false;

	static unsigned char	bitcnt[256],		// bit count
							bitexl[256],		// expand to left bit
							bitexr[256];		// expand to right bit
	static bool fInited = false;

	if (!fInited) {
		int i;

		for(i=0; i<256; i++) {
			unsigned char b=0, l=0, r=0;

			if (i&  1) { b=1; l|=0x01; r|=0xFF; }
			if (i&  2) { ++b; l|=0x03; r|=0xFE; }
			if (i&  4) { ++b; l|=0x07; r|=0xFC; }
			if (i&  8) { ++b; l|=0x0F; r|=0xF8; }
			if (i& 16) { ++b; l|=0x1F; r|=0xF0; }
			if (i& 32) { ++b; l|=0x3F; r|=0xE0; }
			if (i& 64) { ++b; l|=0x7F; r|=0xC0; }
			if (i&128) { ++b; l|=0xFF; r|=0x80; }

			bitcnt[i] = b;
			bitexl[i] = l;
			bitexr[i] = r;
		}

		fInited = true;
	}

	int srcpitch = (w+4+3) & -4;

	char* dst = alpha_bits;

	for (int y=0; y<h; ++y) {
		unsigned char* src = (unsigned char*)lpAntialiasBits + ((h-y-1)*8 + 20) * srcpitch + 2;
		int wt = w;
		do {
			int alpha1, alpha2;
			int i;
			unsigned char bmasks[8], tmasks[8];

			alpha1  = bitcnt[src[srcpitch*0]];
			alpha1 += bitcnt[src[srcpitch*1]];
			alpha1 += bitcnt[src[srcpitch*2]];
			alpha1 += bitcnt[src[srcpitch*3]];
			alpha1 += bitcnt[src[srcpitch*4]];
			alpha1 += bitcnt[src[srcpitch*5]];
			alpha1 += bitcnt[src[srcpitch*6]];
			alpha1 += bitcnt[src[srcpitch*7]];

			alpha2 = 0;

			unsigned char cenmask = 0, mask1, mask2;

			for(i=0; i<=8; i++) {
				cenmask |= (unsigned char)(((long)-src[srcpitch*i  ])>>31);
				cenmask |= bitexl[src[srcpitch*i-1]];
				cenmask |= bitexr[src[srcpitch*i+1]];
			}

			mask1 = mask2 = cenmask;

			for(i=0; i<8; i++) {
				mask1 |= (unsigned char)(((long)-src[srcpitch*(-i)])>>31);
				mask1 |= bitexl[src[srcpitch*(-i)-1]];
				mask1 |= bitexr[src[srcpitch*(-i)+1]];
				mask2 |= (unsigned char)(((long)-src[srcpitch*(8+i)])>>31);
				mask2 |= bitexl[src[srcpitch*(8+i)-1]];
				mask2 |= bitexr[src[srcpitch*(8+i)+1]];

				tmasks[i] = mask1;
				bmasks[i] = mask2;
			}

			for(i=0; i<8; i++) {
				alpha2 += bitcnt[cenmask | tmasks[7-i] | bmasks[i]];
			}

			dst[0] = alpha1;
			dst[1] = alpha2-alpha1;
			dst += 2;
			++src;
		} while(--wt);
	}
}



FilterInfo text_filters[] = {
  { "ShowFrameNumber", "c", ShowFrameNumber::Create },
  { "Subtitle", "siiiisiiic", Subtitle::Create },
  { "Subtitle", "siiiisiic", Subtitle::Create },
  { "Subtitle", "siiiisic", Subtitle::Create },
  { "Subtitle", "sc", Subtitle::Create },
  { 0,0,0 }
};


PVideoFilter new_Subtitle(const char _text[], int _x, int _y, int _firstframe, int _lastframe, const char _fontname[], int _size, int _YUVtext, int _YUVhalo, PVideoFilter _child) {
  return new Subtitle(_text, _x, _y, _firstframe, _lastframe, _fontname, _size, _YUVtext, _YUVhalo, _child);
}

⌨️ 快捷键说明

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