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

📄 effects.cpp

📁 avisynth-source-0.3.zip,avi edit src
💻 CPP
📖 第 1 页 / 共 3 页
字号:

/********************************************************************
********************************************************************/


class Levels : public GenericVideoFilter {
  unsigned char map[256], mapchroma[256];
public:
  Levels(int in_min, float gamma, int in_max, int out_min, int out_max, PVideoFilter _child)
   : GenericVideoFilter(_child)
  {
    if (gamma <= 0.0)
      throw FilterChainError(Sprintf("BrightnessContrastGamma: gamma must be positive"));
    gamma = 1/gamma;
    int divisor = in_max - in_min + (in_max == in_min);
    if (vi.IsYUY2()) {
      for (int i=0; i<256; ++i) {
        double p = ((i-16)*(255.0/219.0) - in_min) / divisor;
        p = pow(min(max(p, 0.0), 1.0), gamma);
        p = p * (out_max - out_min) + out_min;
        int pp = int(p*(219.0/255.0)+16.5);
        map[i] = min(max(pp,16),235);

        int q = ((i-128) * (out_max-out_min) + (divisor>>1)) / divisor + 128;
        mapchroma[i] = min(max(q,16),235);
//        mapchroma[i] = i;
      }
    } else {
      for (int i=0; i<256; ++i) {
        double p = (i - in_min) / divisor;
        p = pow(min(max(p, 0.0), 1.0), gamma);
        p = p * (out_max - out_min) + out_min;
        map[i] = PixelClip(int(p+0.5));
      }
    }
  }

  void GetFrame(int n, unsigned char* buf) {
    child->GetFrame(n, buf);
    unsigned char* p = buf;
    if (vi.IsYUY2()) {
      for (int i=vi.ImageSize()>>1; i; --i) {
        p[0] = map[p[0]];
        p[1] = mapchroma[p[1]];
        p += 2;
      }
    } else {
      for (int i=vi.ImageSize()>>1; i; --i) {
        p[0] = map[p[0]];
        ++p;
      }
    }
  }

  static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
    return new Levels(args[0].integer, args[1].floating_pt, args[2].integer, args[3].integer, args[4].integer, args[5].clip);
  }
};


/********************************************************************
********************************************************************/


class AdjustFocus : public GenericVideoFilter {
  const int amount;
  unsigned char* line;
public:
  AdjustFocus(double _amount, PVideoFilter _child)
    : GenericVideoFilter(_child), amount(int(32768*pow(2.0, _amount)+0.5)), line(0) {}

  void GetFrame(int n, unsigned char* buf) {
    if (!line)
      line = new unsigned char[vi.RowSize()];
    child->GetFrame(n, buf);
    const int center_weight = amount*2;
    const int outer_weight = 32768-amount;
    int row_size = vi.RowSize();
    memcpy(line, buf, row_size);
    unsigned char* p = buf + row_size;
    {
      for (int y = vi.height-2; y; --y) {
        for (int x = row_size; x; --x) {
          unsigned char a = ScaledPixelClip(p[0] * center_weight + (line[x] + p[row_size]) * outer_weight);
          line[x] = p[0];
          p[0] = a;
          ++p;
        }
      }
    }
    unsigned char* q = buf;
    for (int y = vi.height; y; --y) {
      if (vi.IsYUY2()) {
        unsigned char uv = q[1];
        unsigned char yy = q[2];
        unsigned char vu = q[3];
        q[2] = ScaledPixelClip(q[2] * center_weight + (q[0] + q[4]) * outer_weight);
        q += 4;
        for (int x = vi.width-4; x; --x) {
          unsigned char w = ScaledPixelClip(q[1] * center_weight + (uv + q[5]) * outer_weight);
          uv = vu; vu = q[1]; q[1] = w;
          unsigned char y = ScaledPixelClip(q[0] * center_weight + (yy + q[2]) * outer_weight);
          yy = q[0]; q[0] = y;
          q += 2;
        }
        q[0] = ScaledPixelClip(q[0] * center_weight + (yy + q[2]) * outer_weight);
        q += 4;
      } else {
        unsigned char bb = q[0];
        unsigned char gg = q[1];
        unsigned char rr = q[2];
        q += 3;
        for (int x = vi.width-2; x; --x) {
          unsigned char b = ScaledPixelClip(q[0] * center_weight + (bb + q[3]) * outer_weight);
          bb = q[0]; q[0] = b;
          unsigned char g = ScaledPixelClip(q[1] * center_weight + (gg + q[4]) * outer_weight);
          gg = q[1]; q[1] = g;
          unsigned char r = ScaledPixelClip(q[2] * center_weight + (rr + q[5]) * outer_weight);
          rr = q[2]; q[2] = r;
          q += 3;
        }
        q += 3;
      }
    }
  }

  static PVideoFilter __cdecl CreateSharpen(const FilterInfo*, const Arg* args, const char*) {
    const float amount = args[0].floating_pt;
    if (amount < -1.5849625 || amount > 1.0)
      throw FilterChainError(Sprintf("Sharpen: argument must be in the range -1.58 to 1.0"));
    return new AdjustFocus(amount, args[1].clip);
  }
  static PVideoFilter __cdecl CreateBlur(const FilterInfo*, const Arg* args, const char*) {
    const float amount = args[0].floating_pt;
    if (amount < -1.0 || amount > 1.5849625)
      throw FilterChainError(Sprintf("Blur: argument must be in the range -1.0 to 1.58"));
    return new AdjustFocus(-amount, args[1].clip);
  }
};


/********************************************************************
********************************************************************/


class TemporalSoften : public GenericVideoFilter {
  const unsigned luma_threshold, chroma_threshold;
  const int radius;
  unsigned char** source_buffers;
  int cur_frame;

  void NextFrame();
  void PrevFrame();

public:
  TemporalSoften(int _radius, unsigned _luma_threshold, unsigned _chroma_threshold, PVideoFilter _child);
  void GetFrame(int n, unsigned char* buf);
  ~TemporalSoften();

  static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
    return new TemporalSoften(args[0].integer, args[1].integer, args[2].integer, args[3].clip);
  }
};


class SpatialSoften : public GenericVideoFilter {
  const unsigned luma_threshold, chroma_threshold;
  const int diameter;
  unsigned char* source_buffer;

public:
  SpatialSoften(int _radius, unsigned _luma_threshold, unsigned _chroma_threshold, PVideoFilter _child);
  void GetFrame(int n, unsigned char* buf);
  ~SpatialSoften();

  static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
    return new SpatialSoften(args[0].integer, args[1].integer, args[2].integer, args[3].clip);
  }
};


static inline IsClose(int a, int b, unsigned threshold) { return (unsigned(a-b+threshold) <= threshold*2); }


void TemporalSoften::NextFrame() {
  unsigned char* temp = source_buffers[0];
  if (!temp) temp = new unsigned char[vi.ImageSize()];
  for (int i=0; i<radius*2; ++i)
    source_buffers[i] = source_buffers[i+1];
  ++cur_frame;
  child->GetFrame(cur_frame+radius, source_buffers[radius*2] = temp);
}

void TemporalSoften::PrevFrame() {
  unsigned char* temp = source_buffers[radius*2];
  if (!temp) temp = new unsigned char[vi.ImageSize()];
  for (int i=radius*2; i>0; --i)
    source_buffers[i] = source_buffers[i-1];
  --cur_frame;
  child->GetFrame(cur_frame-radius, source_buffers[0] = temp);
}

TemporalSoften::TemporalSoften(int _radius, unsigned _luma_threshold, unsigned _chroma_threshold, PVideoFilter _child)
 : GenericVideoFilter(_child), radius(_radius), luma_threshold(_luma_threshold), chroma_threshold(_chroma_threshold), cur_frame(-32768)
{
  if (!vi.IsYUY2())
    throw FilterChainError("TemporalSoften: requires YUY2 input");

  source_buffers = new unsigned char*[radius*2+1];
  memset(source_buffers, 0, (radius*2+1)*sizeof(unsigned char*));
}

TemporalSoften::~TemporalSoften() {
  if (source_buffers) {
    for (int i=0; i<radius*2+1; ++i)
      if (source_buffers[i])
        delete[] source_buffers[i];
    delete[] source_buffers;
  }
}

void TemporalSoften::GetFrame(int n, unsigned char* buf) {
  if (n < cur_frame - (radius*2+1) || n > cur_frame + (radius*2+1))
    cur_frame = n - (radius*2+1);   // this is safe because all buffered frames will be replaced in a moment
  if (cur_frame < n) {
    while (cur_frame < n)
      NextFrame();
  } else {
    while (cur_frame > n)
      PrevFrame();
  }

  for (int y = 0; y < vi.height; ++y) {
    int line = y * vi.RowSize();
#ifdef OLD_TEMPORAL_SOFTEN_METHOD
    for (int x = 0; x < vi.width*2; x += 4) {
      int cnt1=0, cnt2=0, y1=0, u=0, y2=0, v=0;
      int Y1=source_buffers[radius][line+x], U=source_buffers[radius][line+x+1], Y2=source_buffers[radius][line+x+2], V=source_buffers[radius][line+x+3];
      for (int a = 0; a <= radius*2; ++a) {
        if (IsClose(source_buffers[a][line+x+1], U, chroma_threshold) && IsClose(source_buffers[a][line+x+3], V, chroma_threshold)) {
          if (IsClose(source_buffers[a][line+x], Y1, luma_threshold)) {
            ++cnt1; y1 += source_buffers[a][line+x]; u += source_buffers[a][line+x+1]; v += source_buffers[a][line+x+3];
          }
          if (IsClose(source_buffers[a][line+x+2], Y2, luma_threshold)) {
            ++cnt2; y2 += source_buffers[a][line+x+2]; u += source_buffers[a][line+x+1]; v += source_buffers[a][line+x+3];
          }
        }
      }
      buf[line+x+0] = (y1+(cnt1>>1)) / cnt1;
      buf[line+x+2] = (y2+(cnt2>>1)) / cnt2;
      buf[line+x+1] = (u+((cnt1+cnt2)>>1)) / (cnt1+cnt2);
      buf[line+x+3] = (v+((cnt1+cnt2)>>1)) / (cnt1+cnt2);
    }
#else
    for (int x = 0; x < vi.width*2; x += 2) {
      int cnt1=0, cnt2=0, yy=0, uv=0;
      int YY=source_buffers[radius][line+x], UV=source_buffers[radius][line+x+1];
      for (int a = 0; a <= radius*2; ++a) {
        if (IsClose(source_buffers[a][line+x], YY, luma_threshold)) {
          ++cnt1; yy += source_buffers[a][line+x];
        }
        if (IsClose(source_buffers[a][line+x+1], UV, chroma_threshold)) {
          ++cnt2; uv += source_buffers[a][line+x+1];
        }
      }
      buf[line+x+0] = (yy+(cnt1>>1)) / cnt1;
      buf[line+x+1] = (uv+(cnt2>>1)) / cnt2;
    }
#endif
  }
}



SpatialSoften::SpatialSoften(int _radius, unsigned _luma_threshold, unsigned _chroma_threshold, PVideoFilter _child)
  : GenericVideoFilter(_child), diameter(_radius*2+1), luma_threshold(_luma_threshold),
    chroma_threshold(_chroma_threshold), source_buffer(0)
{
  if (!vi.IsYUY2())
    throw FilterChainError("SpatialSoften: requires YUY2 input");
}


SpatialSoften::~SpatialSoften() {
  if (source_buffer)
    delete[] source_buffer;
}


void SpatialSoften::GetFrame(int n, unsigned char* buf) {
  if (!source_buffer)
    source_buffer = new unsigned char[vi.ImageSize()];
  child->GetFrame(n, source_buffer);

  int row_size = vi.RowSize();
  for (int y=0; y<vi.height; ++y) {
    const unsigned char* line[65];    // better not make diameter bigger than this...
    for (int h=0; h<diameter; ++h)
      line[h] = &source_buffer[row_size * min(max(y+h-(diameter>>1), 0), vi.height-1)];
    int x;

    int edge = (diameter+1) & -4;
    for (x=0; x<edge; ++x)  // diameter-1 == (diameter>>1) * 2
      buf[y*row_size + x] = source_buffer[y*row_size + x];
    for (; x < row_size - edge; x+=2) {
      int cnt=0, _y=0, _u=0, _v=0;
      int xx = x | 3;
      int Y = source_buffer[y*row_size + x], U = source_buffer[y*row_size + (x | 3) - 2], V = source_buffer[y*row_size + (x | 3)];
      for (int h=0; h<diameter; ++h) {
        for (int w = -diameter+1; w < diameter; w += 2) {
          int xw = (x+w) | 3;
          if (IsClose(line[h][x+w], Y, luma_threshold) && IsClose(line[h][xw-2], U, chroma_threshold) && IsClose(line[h][xw], V, chroma_threshold)) {
            ++cnt; _y += line[h][x+w]; _u += line[h][xw-2]; _v += line[h][xw];
          }
        }
      }
      buf[y*row_size + x] = (_y + (cnt>>1)) / cnt;
      if (!(x&3)) {
        buf[y*row_size + x+1] = (_u + (cnt>>1)) / cnt;
        buf[y*row_size + x+3] = (_v + (cnt>>1)) / cnt;
      }
    }
    for (; x<row_size; ++x)
      buf[y*row_size + x] = source_buffer[y*row_size + x];
  }
}


FilterInfo effects_filters[] = {
  { "VerticalReduceBy2", "c", VerticalReduceBy2::Create },
  { "HorizontalReduceBy2", "c", HorizontalReduceBy2::Create },
  { "ReduceBy2", "c", Create_ReduceBy2 },
  { "Levels", "ifiiic", Levels::Create },
  { "Blur", "fc", AdjustFocus::CreateBlur },
  { "Sharpen", "fc", AdjustFocus::CreateSharpen },
  { "BilinearResize", "iic", Create_BilinearResize },
  { "BilinearResize", "ffffiic", Create_BilinearResize },
  { "BicubicResize", "iic", Create_BicubicResize },
  { "BicubicResize", "ffiic", Create_BicubicResizeBC },
  { "BicubicResize", "ffffiic", Create_BicubicResize },
  { "BicubicResize", "ffffffiic", Create_BicubicResizeBC },
  { "Bob", "c", Create_Bob },
  { "Bob", "ffc", Create_Bob },
  { "Crop", "iiiic", Crop::Create },
  { "CropBottom", "ic", CropBottom::Create },
  { "AddBorders", "iiiic", AddBorders::Create },
  { "Letterbox", "iic", Letterbox::Create },
  { "FixLuminance", "ifc", FixLuminance::Create },
  { "PeculiarBlend", "ic", PeculiarBlend::Create },
  { "TemporalSoften", "iiic", TemporalSoften::Create },
  { "SpatialSoften", "iiic", SpatialSoften::Create },
  { 0,0,0 }
};

⌨️ 快捷键说明

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