ë¹ëì¤ìì ë¤ìí ìê°ì í¨ê³¼ë¥¼ ë³´ì¬ì£¼ê¸° ìí´,ìºë²ì¤
ì ë¹ëì¤
ì 기ë¥ì ê²°í©íì¬ ì¤ìê°ì¼ë¡ ë¹ëì¤ ë°ì´í°ë¥¼ ì¡°ìí ì ììµëë¤. ì´ íí 리ì¼ììë JavaScript ì½ëë¡ ì´ë»ê² í¬ë¡ë§ í¤ì(chroma-keying, ëí "ë
¹ì ì¤í¬ë¦° í¨ê³¼, green screen effect")ì 구íí ì ìëì§ ë³´ì¬ì¤ëë¤.
ì´ ë´ì©ì ë³´ì¬ì£¼ê¸° ìí XHTML 문ìë ìëì ê°ìµëë¤.
<!doctype html>
<html>
<head>
<style>
body {
background: black;
color: #cccccc;
}
#c2 {
background-image: url(foo.png);
background-repeat: no-repeat;
}
div {
float: left;
border: 1px solid #444444;
padding: 10px;
margin: 10px;
background: #3b3b3b;
}
</style>
<script type="text/javascript" src="main.js"></script>
</head>
<body onload="processor.doLoad()">
<div>
<video id="video" src="video.ogv" controls="true" />
</div>
<div>
<canvas id="c1" width="160" height="96"></canvas>
<canvas id="c2" width="160" height="96"></canvas>
</div>
</body>
</html>
ì¬ê¸°ìì ì¤ìí ììë:
ìºë²ì¤
ê° ììµëë¤. ìºë²ì¤ c1ì ë¹ëì¤ ì본ì íì¬ íë ìì ë³´ì¬ì£¼ê¸° ìí´ ì¬ì©ëê³ , c2ë í¬ë¡ë§ í¤ì í¨ê³¼ë¥¼ ìíí 결과를 ë³´ì¬ì¤ëë¤. c2ìì ë¹ëì¤ì ë
¹ì ë°°ê²½ì ëì²´í ì ì§ ì´ë¯¸ì§ë¥¼ 미리 ë¡ëí©ëë¤.main.jsì ìë JavaScript ì½ëë 3ê°ì ë©ìëë¡ êµ¬ì±ë©ëë¤.
í¬ë¡ë§ í¤ì íë ì´ì´ ì´ê¸°ídoLoad()
ë©ìëë 문ìê° ìµì´ì ë¡ëë ë í¸ì¶ë©ëë¤. ì´ ë©ìëê° íë ì¼ì í¬ë¡ë§ í¤ì ì²ë¦¬ìì ì°ì¼ ë³ì를 ì¤ë¹íê³ , ì´ë²¤í¸ 리ì¤ë를 ë±ë¡í¨ì¼ë¡ì¨ ì¬ì©ìê° ë¹ëì¤ ì¬ìì ììí ë ê°ì§í ì ìëë¡ í´ì¤ëë¤.
var processor;
processor.doLoad = function doLoad() {
this.video = document.getElementById('video');
this.c1 = document.getElementById('c1');
this.ctx1 = this.c1.getContext('2d');
this.c2 = document.getElementById('c2');
this.ctx2 = this.c2.getContext('2d');
let self = this;
this.video.addEventListener('play', function() {
self.width = self.video.videoWidth / 2;
self.height = self.video.videoHeight / 2;
self.timerCallback();
}, false);
},
ì´ì½ëë XHTMLìì ì¤ìí ììì¸ ë¹ëì¤ì ìºë²ì¤ì 참조를 ê°ì ¸ìµëë¤. ë ê°ì ìºë²ì¤ì ëí ê·¸ëí½ ì»¨í ì¤í¸ì 참조ë ê°ì ¸ìµëë¤. ì´ ì°¸ì¡°ë¤ì ë¤ìì í¬ë¡ë§ í¤ì í¨ê³¼ë¥¼ 구íí ë ì¬ì©ë©ëë¤.
ê·¸ë¦¬ê³ addEventListener()
ë ë¹ëì¤ê° ì¬ìì ììí기 ìí´ í¸ì¶ë기 ë문ì ì¬ì©ìê° ì¬ì ë²í¼ì ë를 ë ì림ì ë°ìµëë¤. ì¬ìì´ ììëë©´ ì´ ì½ëë ë¹ëì¤ì ê°ë¡, ì¸ë¡ë¥¼ ì´ë±ë¶ í ê°ì ê°ì ¸ì¤ê³ (í¬ë¡ë§ í¤ì í¨ê³¼ë¥¼ ìíí ë ì´ë±ë¶ í¨), timerCallback()
ë©ìë를 í¸ì¶íì¬ ë¹ëì¤ë¥¼ ë³´ê³ ìê°ì í¨ê³¼ë¥¼ ê³ì°í기 ììí©ëë¤.
íì´ë¨¸ ì½ë°±ì ë¹ëì¤ê° ì¬ìë기 ìì("ì¬ì" ì´ë²¤í¸ê° ë°ì)í ë í¸ì¶ëëë°, 매 íë ìë§ë¤ í¤ì í¨ê³¼ë¥¼ 주기 ìí´ ì£¼ê¸°ì ì¼ë¡ í¸ì¶ ë ì ìëë¡ ì¤ì í´ ì£¼ì´ì¼ í©ëë¤.
processor.timerCallback = function timerCallback() {
if (this.video.paused || this.video.ended) {
return;
}
this.computeFrame();
let self = this;
setTimeout(function() {
self.timerCallback();
}, 0);
},
ì½ë°±ìì íë 첫 ë² ì§¸ ì¼ì ë¹ëì¤ê° ì¬ìëê³ ìëì§ íì¸íë ê²ì¸ë°, ë§ì½ ê·¸ë ì§ ìë¤ë©´ ì½ë°±ì ì무 ì¼ë íì§ ìê³ ì¦ì ë°íë©ëë¤.
ê·¸ íì íì¬ ë¹ëì¤ íë ììì í¬ë¡ë§ í¤ì í¨ê³¼ë¥¼ 주기 ìí computeFrame()
ë©ìë를 í¸ì¶í©ëë¤.
ì½ë°±ìì ë§ì§ë§ì¼ë¡ íë ì¼ì setTimeout()
ì í¸ì¶íì¬ ê°ë¥í í 빨리 timerCallback()
ë©ìë를 ë¤ì í¸ì¶í ì ìëë¡ íë ê²ì
ëë¤. ì¤ì ë¡ë, ë¹ëì¤ íë ì ìëì ëí ê¸°ë° ì§ìì¼ë¡ í¸ì¶í ì ìëë¡ í©ëë¤.
ìëì computeFrame()
ë©ìëë íë ì ë°ì´í°ë¥¼ ê°ì ¸ìì í¬ë¡ë§ í¤ì í¨ê³¼ë¥¼ ìííë ìí ì í©ëë¤.
processor.computeFrame = function computeFrame() {
this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
let frame = this.ctx1.getImageData(0, 0, this.width, this.height);
let l = frame.data.length / 4;
for (let i = 0; i < l; i++) {
let r = frame.data[i * 4 + 0];
let g = frame.data[i * 4 + 1];
let b = frame.data[i * 4 + 2];
if (g > 100 && r > 100 && b < 43) frame.data[i * 4 + 3] = 0;
}
this.ctx2.putImageData(frame, 0, 0);
return;
};
ì ê³¼ì ì´ ê³ì í¸ì¶ ëë©´, ìëì ê°ì´ ë¹ëì¤ ììì ê°ì¥ ìµê·¼ íë ìì ë¹ëì¤ ë°ì´í°ê° íì¶ë©ëë¤.
2ë²ì§¸ ì¤ìì, 첫 ë²ì§¸ ìºë²ì¤ì ê·¸ëí½ ì»¨í
ì¤í¸ ctx1ì ë¹ëì¤ íë ìì´ ë³µì¬ ëëë°, ì본ì ì ë° í¬ê¸°ë¡ íë ìì 그리기 ìí´ ì´ì ì ì ì¥í ê°ë¡, ì¸ë¡ ê°ì¼ë¡ ì§ì í©ëë¤. 컨í
ì¤í¸ì drawImage()
ë©ìëì ë¹ëì¤ ìì를 ì ë¬íê¸°ë§ íë©´ íì¬ ë¹ëì¤ íë ìì 그릴 ì ììµëë¤. ê²°ê³¼ë ìëì ê°ìµëë¤:
3ë²ì§¸ ì¤ììë 첫 ë²ì§¸ 컨í
ì¤í¸ì getImageData()
ë©ìë를 í¸ì¶í´ì íì¬ ë¹ëì¤ íë ìì ìì ê·¸ëí½ ë°ì´í° ë³µì¬ë³¸ì ê°ì ¸ìµëë¤. ì´ê²ì ì¡°ìí ì ìë ìì 32ë¹í¸ í½ì
ì´ë¯¸ì§ ë°ì´í°ë¥¼ ì ê³µí©ëë¤. 4ë²ì§¸ ì¤ììë íë ìì ì´ë¯¸ì§ ë°ì´í° ì ì²´ í¬ê¸°ë¥¼ 4ë¡ ëëì´ ì´ë¯¸ì§ì í½ì
ì를 ê³ì°í©ëë¤.
6ë²ì§¸ ì¤ìì ììíë for
문ì íë ìì í½ì
ì ì¤ìºíì¬, 빨ê°ì, ë
¹ì, íëì ê°ì ì¶ì¶íì¬ ì¬ì ì ì ìë ì«ìì ë¹êµí©ëë¤. ì´ ì«ìë foo.png
ìì ê°ì ¸ì¨ ë°°ê²½ ì´ë¯¸ì§ë¡ ëì²´ë ë
¹ì ì¤í¬ë¦° ììì ê°ì§í©ëë¤.
ë ¹ì ì¤í¬ë¦°ì´ë¼ê³ ê°ì£¼ë 매ê°ë³ì ë´ì íë ì ì´ë¯¸ì§ ë°ì´í°ì 모ë í½ì ì í¬ëª í´ì§ ì ìëë¡ ìíê°ì´ 0ì¼ë¡ ëì²´ë©ëë¤. ê²°ê³¼ì ì¼ë¡ ìµì¢ ì´ë¯¸ì§ë 100% í¬ëª í´ì§ ë ¹ì ì¤í¬ë¦° ììì ê°ê² ëê³ , 13ë²ì§¸ ì¤ìì ëì 컨í ì¤í¸ì ê³ ì ë ë°°ê²½ ìë¡ ì¬ë ¤ì ¸ ê·¸ë ¤ì§ëë¤.
ê²°ê³¼ ì´ë¯¸ì§ë ìëì ê°ìµëë¤:
ì´ ê³¼ì ì ë¹ëì¤ê° ì¬ìë ëë§ë¤ ë°ë³µëë¯ë¡, 매 íë ìë§ë¤ ì²ë¦¬ëì´ í¬ë¡ë§ í¤ì í¨ê³¼ê° ëíëë ê²ì ëë¤.
ë 보기RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4