视频转字符动画c语言,HTML5视频转字符动画

什么是视频转字符动画?大至就是

b8a3ea0d22ffb1e4cca218ec86e14d5c.png

1e16875913435154a3b27168a2bda656.png

一. 实现原理将视频拆分成独立的帧(等同于每换一个画面截一张图)

将图转换成黑白图(如何将图片转成黑白自行百度)后,拿到每个像素点的颜色,点的rgb是相同的,是一个0~255的整数,0表示完全黑,255表示完全白

准备一组字符,比如@#&!:,. 这些字符同字号时的表面积应该是递增的且越多越好,对应2中的rgb数值,比如 @对应0,表示黑,  .对应255表示白

将2中的黑白图片每个像素点换成3中对应的字符

重复1-4步到视频结束

二. 代码实现

最下面有完整源码,实现部分能理清思路就好。

准备cnavas容器,用来播放字符动画。准备input文件上传入口

创建一个视频转动画的Dv类,构造中初始化画布function Dv(){

this.textCanvas = $('textCanvas');

this.textCanvas.width = window.innerWidth;

this.textCanvas.height = window.innerHeight;

this.textCtx = this.textCanvas.getContext('2d');

}

创建一个离屏video容器,用来播放原视频,是字符画的数据来源Dv.prototype.initVideo = function(src) {

if(!this.video){

this.video = document.createElement('video');

}

if(src){

this.video.src = src;

}

};

获取并使用FileReader对象做为Blob对象载入Dv.prototype.initFile = function() {

var file = $('file').files[0];

if(!file){

alert("请选择一个MP4视频文件");

return false;

}

var reader = new FileReader();

var buffer = [];

var that = this;

reader.onload = function(){

var blob = new Blob([reader.result], { type: 'video/mp4'});

that.playFile(reader.result,blob);

}

reader.readAsArrayBuffer(file);

};

将载入的Blob对象做为ObjectURL赋值给video的src属性,video可以播放视频文件了,下面开始抓取视频帧来生成字符画Dv.prototype.playFile = function(arrayBuffer,blob) {

var mediaSource = new MediaSource();

src = URL.createObjectURL(blob);

this.initVideo(src);

this.interval();

this.video.play();

};

使用requestAnimationFrame动画API开始定时抓取视频单帧图像转换成黑白。ctx是离屏画布的上下文用于临时存放图像,ctx将图像缩小一定比列来减少要处理的像素点。Dv.prototype.interval = function() {

var that = this;

requestAnimationFrame(function(){

if(!that.video.paused){

that.ctx.drawImage(that.video,0,0,that.width,that.height);

var data = that.loadData();

that.reDraw(data);

that.drawText();

}

that.interval();

});

};

将图像像素点数据,按黑白程度映射成相应的字符,并输出在画布上Dv.prototype.drawText = function() {

this.textCtx.clearRect(0,0,window.innerWidth,window.innerHeight);

var data = this.data.data;

var points = '.,`":!^|*ITDXUHB%@NM'.split('');

for(var i=0,len=data.length;i

this.textCtx.fillStyle = '#333';

var xl = (i/4|0)%this.width;

var yl = Math.ceil(i/4/this.width);

var x = xl * this.space;

var y = yl * this.space;

var newData = data[i] | 0;

var plen = Math.ceil(255/points.length);

var point = points[newData/plen  | 0]

this.textCtx.font="12px courier";

this.textCtx.fillText(point,x,y);

}

};

三. 完整示例,(控制台开启手机模式效果最好)html>

chars video

html,body{ height: 100%; }

html,body,.ctrl{margin: 0;padding: 0;}

#textCanvas{ font-family: 'courier';}

#videoScreen{ height: 100vh;width: 100vw;}

.ctrl{ position: fixed;right: 0px;bottom: 0px;left: 0;z-index: 3;  padding: 10px; border-radius: 4px;background-color: #fff;}

input[type=button]{background-color: #1aa988;color: #fff;border-width: 0;padding: 4px 8px;border-radius: 4px;cursor: pointer;}

select{padding : 4px 8px;border-radius: 4px;}

#file{position : absolute;left:-99999px;}

.file{background-color: #1aa988;color: #fff;border-width: 0;padding: 12px 8px;border-radius: 96px;cursor: pointer;display: block;text-align: center;}

#info{position: absolute;text-align: center;padding: 20px;left: 0;right: 0; top: 20%;color: #999;line-height: 2;}

浏览

点击浏览,选择一个mp4视频文件即可开始
点击空白处可隐藏底部按钮

function $(id){ return document.getElementById(id); }

function Dv(){

this.space = 10;

this.width = Math.ceil(window.innerWidth/this.space);

this.height = Math.ceil(window.innerHeight/this.space);

this.data = {};

this.cav = {};

this.ctx = {};

this.playing = false;

this.init();

this.scaleX = window.innerWidth/this.width;

this.textCanvas = $('textCanvas');

this.textCanvas.width = window.innerWidth;

this.textCanvas.height = window.innerHeight;

this.textCtx = this.textCanvas.getContext('2d');

}

Dv.prototype.init = function() {

this.initVideo();

this.initCanvas();

this.cav.width = this.width;

this.cav.height = this.height;

this.initEvent();

};

Dv.prototype.initVideo = function(src) {

if(!this.video){

this.video = document.createElement('video');

//document.body.appendChild(this.video);

}

if(src){

this.video.src = src;

}

};

Dv.prototype.initCanvas = function(video) {

this.cav = document.createElement('canvas');

this.ctx = this.cav.getContext('2d');

};

Dv.prototype.loadData = function() {

return this.ctx.getImageData(0,0,this.width,this.height);

};

Dv.prototype.reDraw = function(data) {

for(var i=0,len=data.data.length;i

var r = data.data[i],

g = data.data[i+1],

b = data.data[i+2];

data.data[i] = data.data[i+1] = data.data[i+2] = 255-(r+g+b)/3 | 0;

}

this.data = data

this.ctx.putImageData(data,0,0,0,0,this.width,this.height);

};

Dv.prototype.drawText = function() {

this.textCtx.clearRect(0,0,window.innerWidth,window.innerHeight);

var data = this.data.data;

var points = '.,`":!^|*ITDXUHB%@NM'.split('');

for(var i=0,len=data.length;i

this.textCtx.fillStyle = '#333';

var xl = (i/4|0)%this.width;

var yl = Math.ceil(i/4/this.width);

var x = xl * this.space;

var y = yl * this.space;

var newData = data[i] | 0;

var plen = Math.ceil(255/points.length);

var point = points[newData/plen  | 0]

this.textCtx.font="12px courier";

this.textCtx.fillText(point,x,y);

}

};

Dv.prototype.interval = function() {

var that = this;

requestAnimationFrame(function(){

if(!that.video.paused){

that.ctx.drawImage(that.video,0,0,that.width,that.height);

var data = that.loadData();

that.reDraw(data);

that.drawText();

}

that.interval();

});

};

//以下方法用于本地视频

Dv.prototype.initEvent = function() {

var that = this;

$('file').onchange = function(){

var filename = this.value;

var index = filename.lastIndexOf(".");

var ext = filename.substr(index+1);

if(ext == "mp4"){

that.initFile();

$('info').style.display = 'none';

$('ctrl').style.display = 'none';

}else{

alert("仅支持MP4格式");

}

}

$('videoScreen').onclick = function(){

if($('ctrl').style.display == 'none'){

$('ctrl').style.display = 'block';

}else{

$('ctrl').style.display = 'none';

}

}

};

Dv.prototype.initFile = function() {

var file = $('file').files[0];

if(!file){

alert("请选择一个MP4视频文件");

return false;

}

var reader = new FileReader();

var buffer = [];

var that = this;

reader.onload = function(){

var blob = new Blob([reader.result], { type: 'video/mp4'});

that.playFile(reader.result,blob);

}

reader.readAsArrayBuffer(file);

};

Dv.prototype.playFile = function(arrayBuffer,blob) {

var mediaSource = new MediaSource();

src = URL.createObjectURL(blob);

this.initVideo(src);

this.interval();

this.video.play();

};

var d = new Dv();

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值