DPlayer for WordPress

中秋节还是稍前一些的时候,看完了《四月是你的谎言》,真的太棒了,后来还去coursera上看了古典音乐导论ww

然后昨天晚上在逛DIYGod的博客时,发现了这篇post,DPlayer – 最好看的弹幕播放器送给最好看的宫园薰,于是去看了github上的这个项目,DIYGod/DPlayer,又是有不少扩展,但是没有我用的WordPress的QAQ

袖子卷起来(明明穿的是短袖好么!),代码写起来~

先给你们看看最好看的弹幕播放器的效果吧~

继续阅读DPlayer for WordPress

在macOS Sierra及以上系统中为bilibili启用画中画功能

最新的macOS Sierra支持画中画播放了,虽然用的时候不多,现在也还不算特别好用,不过偶尔还是挺方便的,比如写代码的时候开着B站在后面放演唱会之类的,但是遇到精彩的部分却必须要跳回网页,稍微有点不爽呢……

B站最近也开始了HTML5播放器的公测,实现大概是一个video标签,再加上外面一个相同大小的div,div内应该是个svg,弹幕由js解析,并通过svg画出来。那么理论上来讲,使用了video标签的话,就是系统可以自行解码的视频,比如mp4,mov这类。B站上绝大多数要么是mp4,要么就是flv。如果某个视频只有flv的话,就没办法了。不过只要是mp4的话,就可以使用macOS Sierra的画中画播放。

继续阅读在macOS Sierra及以上系统中为bilibili启用画中画功能

Magic Image(2)——Mathematical Model

上次试着用threshold的方式写(Magic image——Alpha Channel),虽然有那么些感觉了,但是最终的图像是二值化的,效果不好。

于是今天特意找了Alpha Blending的资料,根据wiki页面给出的公式:

$$\left\{\begin{aligned}
out_A &= src_A + dst_A(1-src_A)\\
out_{RGB} &= \frac{(src_{RGB}src_A + dst_{RGB}dst_A(1-src_A))}{out_A}\\
out_A &= 0 \implies out_{RGB} = 0
\end{aligned}\right.
$$

当我们的destination background不透明时,\(dst_A = 1\),于是有

$$\left\{\begin{aligned}
out_A &= 1\\
out_{RGB} &= src_{RGB}src_A + dst_{RGB}(1-src_A)
\end{aligned}\right.
$$

于是,根据我们的实际情况,对于合并后的图像I,给定背景B时,有如下等式:
$$\left\{\begin{aligned}
out_A &= 1\\
out_{G} &= I_{G}I_A + B_{G}(1-I_A)
\end{aligned}\right.
$$

继续阅读Magic Image(2)——Mathematical Model

Standard A* Search Algorithm in C++

在看了NTU的AI课程之后,试着用C++来实现了A*搜索算法。它的思想就是Avoid expanding paths that are already expensive.。标准的A*搜索算法描述如下:

给出带权无向图,初始顶点,目标顶点,以及evaulation function。Evalutaion function包括

  • g(n):为到达顶点n,当前已有的花费(cost so far to reach n)
  • h(n):一个 从任意顶点 到 目标顶点 的估计花费(estimated cost to goal from n)
  • f(n):从 初始顶点 到 目标顶点 的估计花费(estimated total cost from the starting node to goal through n)

f(n) = h(n) + g(n)

 

例如有三个地点A, B, C,它们之间的图如下

A —— B —— C

A —— B权重为30,B —— C权重为40,

A —— C的直线距离为50,但是并没有A——C这条边(即不能直接从A开始,只经过一条边就到达C)

现在,给出初始顶点为A,目标顶点为C,h(n)如下

h(A) = 50

h(B) = 40

h(C) = 0

在一开始,我们将A放入名为froniter的优先队列中,froniter按照f(n)的值升序排序。

那么我们有f(A) = h(A) + g(A)。h(A)是由用户直接给出的,等于50。g(A)是我们为了到达C,已有的花费,在这个例子中,可以理解为已经走过的路程,因为我们是一开始就在A,还没有开始走,所以g(A)为0。于是f(A) = h(A) + g(A) = 50 + 0 = 50

froniter中的数据如下:

current from g(current) h(current)
A A 0 50

继续阅读Standard A* Search Algorithm in C++

A simple EventEmitter in C++

EventEmitter coming with node.js is handy most of the time, and I implement this useful utility in C++ after finishing writing Functor. Yes, we need Functor to make it much more easier to write this fabulous utility. (Why don't you use lamdba? I'll talk about that later in this post)

It's extremely simple to use EventEmitter in node.js

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
    console.log('an event occurred!');
});
myEmitter.emit('event');

——https://nodejs.org/api/events.html

And the C++ version of EventEmitter need to be as easy as it is in node.js. As a matter of fact, this class made it.

#include <iostream>
#include <sstream>
#include <thread>
#include <vector>
#include "EventEmitter.hpp"

using namespace std;

class emitter : public EventEmitter {
};

int main(int argc, const char * argv[]) {
    emitter emitter;
    emitter.on("event", [&emitter](int data) {
        ostringstream osstream;
        osstream << "data: " << data << '\n';
        std::cout << osstream.str();
    });

    vector<thread> threads;
    for (int i = 0; i < 10; i++) {
        threads.emplace_back([&emitter, i]() {
            emitter.emit("event", i);
        });
    }

    for (auto &t : threads) t.join();
}

继续阅读A simple EventEmitter in C++

A simple EventEmitter in C++

node.js里面的EventEmitter非常好用,于是上次写完Functor之后,就顺理成章的写了这个EventEmitter,或者说,就是为了实现这个EventEmitter才写的Functor(后文会提到为什么要Functor,毕竟如果只看Functor本身的话,还不如直接用lamdba方便)。

在node.js中,使用EventEmitter非常简单,

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
    console.log('an event occurred!');
});
myEmitter.emit('event');

——https://nodejs.org/api/events.html

那么现在这个C++版的EventEmitter也必须做到这样简单易用,事实上,它也的确和node.js的使用方式类似。

#include <iostream>
#include <sstream>
#include <thread>
#include <vector>
#include "EventEmitter.hpp"

using namespace std;

class emitter : public EventEmitter {
};

int main(int argc, const char * argv[]) {
    emitter emitter;
    emitter.on("event", [&emitter](int data) {
        ostringstream osstream;
        osstream << "data: " << data << '\n';
        std::cout << osstream.str();
    });

    vector<thread> threads;
    for (int i = 0; i < 10; i++) {
        threads.emplace_back([&emitter, i]() {
            emitter.emit("event", i);
        });
    }

    for (auto &t : threads) t.join();
}

继续阅读A simple EventEmitter in C++

Module Check——Usage of std::enable_if

最近写代码的时候,总能在不少STL的函数声明里看见可爱的std::enable_if,虽然自己偶尔用过,不过也只是直接用STL库里的std::is_arithmetic之类。

于是就去Google了std::enable_if,然后参考了如下几篇post,写了一个较为通用的Module Check。

所以还是先从一个小的问题开始讲起吧~

假设我们做了一个中间类作为接口,这个中间类有一个模版构造函数,它接受一个类实例和一个double类型的参数,并且总是调用一个固定的实例方法。

class Intermediate {
public:
    template <typename T>
    Intermediate(const T& object, double value) {
        object.method(value);
    }
};

现在我们有如下的类,

class A {
public:
    void method(double d) const {
        std::cout<<d<<'\n';
    }
};

class B {
public:
    void method(int i) const {
        std::cout<<i<<'\n';
    }
};

虽然如下代码可以编译运行,但是假如我们希望只有类A被这样调用才有效呢?

Intermediate inter_a_1(a, 2.33); // print 2.33
Intermediate inter_b_1(b, 2.33); // print 2

继续阅读Module Check——Usage of std::enable_if