![]() |
<!DOCTYPE HTML> <HTML LANG="ja"> <HEAD> <META CHARSET="Shift_JIS"> <TITLE>特殊効果ビデオ</TITLE> </HEAD> <BODY onLoad="init()" STYLE="background-color:#CCFFFF"> <DIV STYLE="text-align:center"> <BR> <B>特殊効果ビデオ</B> <BR><BR> <FORM> <SELECT ID="sel" DISABLED onChange="sel_chg(this.selectedIndex)"> <OPTION SELECTED>ソラリゼーション <OPTION>レリーフ <OPTION>ラプラシアン 1 <OPTION>ラプラシアン 2 <OPTION>ポスタリゼーション 1 <OPTION>ポスタリゼーション 2 <OPTION>ポスタリゼーション 3 <OPTION>ガラス <OPTION>スケッチ <OPTION>ディザ 1 <OPTION>ディザ 2 <OPTION>ディザ 3 <OPTION>網点 <OPTION>波紋 <OPTION>回転 </SELECT> </FORM> <BR> <CANVAS ID="view" WIDTH=1 HEIGHT=1></CANVAS> </DIV> <SCRIPT TYPE="text/javascript"> <!-- function init() { if(navigator.mozGetUserMedia == undefined) { if(navigator.webkitGetUserMedia == undefined) navigator.getUserMedia({video:true, audio:false}, success, error); else navigator.webkitGetUserMedia({video:true, audio:false}, success, error); } else { navigator.mozGetUserMedia({video:true, audio:false}, success, error); } } function success(stream) { elem_video = document.createElement("VIDEO"); elem_video.autoplay = true; elem_video.addEventListener("canplay", wait, false); if(elem_video.mozSrcObject === undefined) { if(elem_video.srcObject === undefined) elem_video.src = (window.URL == undefined || window.URL.createObjectURL == undefined) ? stream : window.URL.createObjectURL(stream); else elem_video.srcObject = stream; } else { elem_video.mozSrcObject = stream; } elem_video.play(); } function error(err) { alert("カメラが使用できません"); } function wait() { if(elem_video.videoWidth) { video_width_h = (video_width = elem_video.videoWidth) >> 1; video_height_h = (video_height = elem_video.videoHeight) >> 1; with(elem_view = document.getElementById("view")) { width = video_width; height = video_height; style.width = String(video_width) + "px"; style.height = String(video_height) + "px"; ctx_view = getContext("2d"); } with(work_imgdat = ctx_view.getImageData(0, 0, video_width, video_height)) { dev_width_h = (dev_width = width) >> 1; dev_height_h = (dev_height = height) >> 1; } data_len = (dev_size = dev_width * dev_height) << 2; // ガラス,波紋 用 glass_rnd = new Uint32Array(dev_size); ripple_pha = new Uint8Array(dev_size); ripple_att = new Float32Array(dev_size); var i = 0; for(var y = 0; y < dev_height; y++) { var dist_y = y - dev_height_h; dist_y *= dist_y; for(var x = 0; x < dev_width; x++) { var rnd_x = x + (Math.floor(Math.random() * 41) - 20); if(rnd_x < 0) rnd_x = 0; else if(rnd_x >= dev_width) rnd_x = dev_width - 1; var rnd_y = y + (Math.floor(Math.random() * 41) - 20); if(rnd_y < 0) rnd_y = 0; else if(rnd_y >= dev_height) rnd_y = dev_height - 1; glass_rnd[i] = (rnd_y * (dev_width + 6) + rnd_x) << 2; var dist = x - dev_width_h; dist = Math.sqrt(dist * dist + dist_y); ripple_pha[i] = Math.round(dist * 8) & 0xff; ripple_att[i] = (dist < 32) ? dist : dist * Math.sqrt(dist / 32); i++; } } // 回転 用 ctx_view.beginPath(); ctx_view.arc(video_width_h, video_height_h, ((video_width < video_height) ? video_width_h : video_height_h) - 10, 0, PI2, false); ctx_view.closePath(); work_data = new Uint8Array(work_imgdat.data.buffer, 0, data_len); work_data32 = new Uint32Array(work_imgdat.data.buffer, 0, dev_size); work1 = new Uint8Array(work_imgdat.data.buffer, 0, dev_size); work2 = new Uint8Array(work_imgdat.data.buffer, dev_size, dev_size); work3 = new Uint8Array(work_imgdat.data.buffer, dev_size << 1, dev_size); var size = dev_width_h * dev_height_h; work1d = new Int16Array(work_imgdat.data.buffer, 0, size); work2d = new Int16Array(work_imgdat.data.buffer, size << 1, size); work3d = new Int16Array(work_imgdat.data.buffer, size << 2, size); with(elem_work = document.createElement("CANVAS")) { width = video_width + 6; height = video_height + 6; ctx_work = getContext("2d"); } document.getElementById("sel").disabled = false; frame(); return; } setTimeout(wait, 50); } function sel_chg(index) { proc = proc_tbl[index]; interval = (proc == rotate/* 回転 */) ? 50 : 200; if(proc == glass) { // ガラス // αを非透過に初期化する for(var i = 3; i < data_len; i += 4) work_data[i] = 255; } } function frame() { setTimeout(frame, interval); if(proc == glass) { // ガラス glass(); } else { ctx_view.drawImage(elem_video, 0, 0); if(proc == rotate) { // 回転 rotate(); } else { var imgdat = ctx_view.getImageData(0, 0, video_width, video_height); if(proc == ripple) { // 波紋 ripple(imgdat); } else { // クランプされないように(高速化のため),ただの配列にする proc(new Uint8Array(imgdat.data.buffer)); ctx_view.putImageData(imgdat, 0, 0); } } } } // ソラリゼーション function solar(data) { for(var i_data = 0; i_data < data_len; i_data += 4) data[i_data] = data[i_data + 1] = data[i_data + 2] = solar_map[(360 * data[i_data] + 707 * data[i_data + 1] + 137 * data[i_data + 2]) >> 8]; } // レリーフ function relief(data) { var i_data = 0; var off = (dev_width << 3) + 8; for(var y = dev_height - 2; y; y--) { for(var x = dev_width - 2; x; x--) { var i_data2 = i_data + off; var val = (((306 * data[i_data] + 601 * data[i_data + 1] + 117 * data[i_data + 2]) + 0x3fc00 - (306 * data[i_data2] + 601 * data[i_data2 + 1] + 117 * data[i_data2 + 2])) >> 10) - 128; data[i_data] = data[i_data + 1] = data[i_data + 2] = (val > 255) ? 255 : ((val < 0) ? 0 : val); i_data += 4; } data[i_data] = data[i_data + 1] = data[i_data + 2] = data[i_data + 4] = data[i_data + 5] = data[i_data + 6] = 128; i_data += 8; } for(; i_data < data_len; i_data += 4) data[i_data] = data[i_data + 1] = data[i_data + 2] = 128; } // ラプラシアン 1 function laplacian_1(data) { var stride = dev_width << 2; var i_data = stride + 4; var i_work = 0; for(var y = dev_height - 2; y; y--) { for(var x = dev_width - 2; x; x--) { var i_data2 = i_data - stride; var i_data3 = i_data + stride; var val = ((data[i_data] << 3) - data[i_data2 - 4] - data[i_data2] - data[i_data2 + 4] - data[i_data - 4] - data[i_data + 4] - data[i_data3 - 4] - data[i_data3] - data[i_data3 + 4]) + ((data[i_data + 1] << 3) - data[i_data2 - 3] - data[i_data2 + 1] - data[i_data2 + 5] - data[i_data - 3] - data[i_data + 5] - data[i_data3 - 3] - data[i_data3 + 1] - data[i_data3 + 5]) + ((data[i_data + 2] << 3) - data[i_data2 - 2] - data[i_data2 + 2] - data[i_data2 + 6] - data[i_data - 2] - data[i_data + 6] - data[i_data3 - 2] - data[i_data3 + 2] - data[i_data3 + 6]); work1[i_work++] = (val > 255) ? 0 : ((val < 0) ? 255 : 255 - val) i_data += 4; } i_data += 8; } var off = (dev_height - 1) * stride; for(i_data = 0; i_data < stride; i_data += 4) { var i_data2 = i_data + off; data[i_data] = data[i_data + 1] = data[i_data + 2] = data[i_data2] = data[i_data2 + 1] = data[i_data2 + 2] = 255; } i_work = 0; for(var y = dev_height - 2; y; y--) { data[i_data] = data[i_data + 1] = data[i_data + 2] = 255; i_data += 4; for(var x = dev_width - 2; x; x--) { data[i_data] = data[i_data + 1] = data[i_data + 2] = work1[i_work++]; i_data += 4; } data[i_data] = data[i_data + 1] = data[i_data + 2] = 255; i_data += 4; } } // ラプラシアン 2 function laplacian_2(data) { var stride = dev_width << 2; var i_data = stride + 4; var i_work = 0; for(var y = dev_height - 2; y; y--) { for(var x = dev_width - 2; x; x--) { var i_data2 = i_data - stride; var i_data3 = i_data + stride; var r = (data[i_data] << 3) - data[i_data2 - 4] - data[i_data2] - data[i_data2 + 4] - data[i_data - 4] - data[i_data + 4] - data[i_data3 - 4] - data[i_data3] - data[i_data3 + 4]; var g = (data[i_data + 1] << 3) - data[i_data2 - 3] - data[i_data2 + 1] - data[i_data2 + 5] - data[i_data - 3] - data[i_data + 5] - data[i_data3 - 3] - data[i_data3 + 1] - data[i_data3 + 5]; var b = (data[i_data + 2] << 3) - data[i_data2 - 2] - data[i_data2 + 2] - data[i_data2 + 6] - data[i_data - 2] - data[i_data + 6] - data[i_data3 - 2] - data[i_data3 + 2] - data[i_data3 + 6]; work1[i_work++] = (r > 50 || g > 50 || b > 50) ? 0 : 255; i_data += 4; } i_data += 8; } var off = (dev_height - 1) * stride; for(i_data = 0; i_data < stride; i_data += 4) { var i_data2 = i_data + off; data[i_data] = data[i_data + 1] = data[i_data + 2] = data[i_data2] = data[i_data2 + 1] = data[i_data2 + 2] = 255; } i_work = 0; for(var y = dev_height - 2; y; y--) { data[i_data] = data[i_data + 1] = data[i_data + 2] = 255; i_data += 4; for(var x = dev_width - 2; x; x--) { data[i_data] = data[i_data + 1] = data[i_data + 2] = work1[i_work++]; i_data += 4; } data[i_data] = data[i_data + 1] = data[i_data + 2] = 255; i_data += 4; } } // ポスタリゼーション 1 function poster_1(data) { for(var i_data = 0; i_data < data_len; i_data += 4) { var val; val = data[i_data] & 0xc0; data[i_data] = val | (val >> 2) | (val >> 4) | (val >> 6); val = data[i_data + 1] & 0xc0; data[i_data + 1] = val | (val >> 2) | (val >> 4) | (val >> 6); val = data[i_data + 2] & 0xc0; data[i_data + 2] = val | (val >> 2) | (val >> 4) | (val >> 6); } } // ポスタリゼーション 2 function poster_2(data) { for(var i_data = 0; i_data < data_len; i_data += 4) { data[i_data] = (data[i_data] & 0x80) ? 0xd0 : 0x30; data[i_data + 1] = (data[i_data + 1] & 0x80) ? 0xd0 : 0x30; data[i_data + 2] = (data[i_data + 2] & 0x80) ? 0xd0 : 0x30; } } // ポスタリゼーション 3 function poster_3(data) { // 16色に減色 var i_data; var i; poster_leaves = 0; for(i = 0; i < 4680; i++) poster_pixels[i] = 0x80000000; poster_internal_cnt[0] = poster_internal_cnt[1] = poster_internal_cnt[2] = 0; for(i_data = 0; i_data < data_len; i_data += 4) { poster_add_color(data[i_data], data[i_data + 1], data[i_data + 2], 0, 0); while(poster_leaves > 16) { // 葉の数が 16 より多い // 葉を減らす var level; for(level = 2; ; level--) { if(poster_internal_cnt[level]) break; } var i_store = poster_internal[level * 17 + --poster_internal_cnt[level]]; var index = (i_store - poster_off[level]) << 3; level++; var pixels = 0; var r_sum = 0; var g_sum = 0; var b_sum = 0; for(i = 0; i < 8; i++) { var i_store_child = poster_off[level] + (index | i); if(!(poster_pixels[i_store_child] & 0x80000000)) { // ノードあり pixels += poster_pixels[i_store_child]; r_sum += poster_r_sum[i_store_child]; g_sum += poster_g_sum[i_store_child]; b_sum += poster_b_sum[i_store_child]; poster_leaves--; } } poster_leaves++; poster_pixels[i_store] = pixels; poster_r_sum[i_store] = r_sum; poster_g_sum[i_store] = g_sum; poster_b_sum[i_store] = b_sum; } } poster_i_color = 0; poster_get_colors(-1, 0); for(i_data = 0; i_data < data_len; i_data += 4) { var r = data[i_data]; var g = data[i_data + 1]; var b = data[i_data + 2]; var min = 0x7fffffff; var i_min; for(i = 0; i < poster_leaves; i++) { var dr = r - poster_r[i]; var dg = g - poster_g[i]; var db = b - poster_b[i]; var d2 = dr * dr + dg * dg + db * db; if(d2 < min) { min = d2; i_min = i; } } data[i_data] = poster_r[i_min]; data[i_data + 1] = poster_g[i_min]; data[i_data + 2] = poster_b[i_min]; } } function poster_add_color(r, g, b, level, index) { index = (index << 3) | ((r >> (5 - level)) & 0x4) | ((g >> (6 - level)) & 0x2) | ((b >> (7 - level)) & 0x1); var i_store = poster_off[level] + index; if(poster_pixels[i_store] & 0x80000000) { // ノードなし // ノード追加 poster_pixels[i_store] = 0; if(level == 3) { // 葉 poster_r_sum[i_store] = 0; poster_g_sum[i_store] = 0; poster_b_sum[i_store] = 0; poster_leaves++; } else { poster_internal[level * 17 + poster_internal_cnt[level]++] = i_store; } } if(poster_pixels[i_store] || level == 3) { // 葉 poster_pixels[i_store]++; poster_r_sum[i_store] += r; poster_g_sum[i_store] += g; poster_b_sum[i_store] += b; } else { poster_add_color(r, g, b, level + 1, index); } } function poster_get_colors(level, index) { var i_store; var pixels = (level < 0) ? 0 : poster_pixels[i_store = poster_off[level] + index]; if(pixels) { // 葉 poster_r[poster_i_color] = Math.floor(poster_r_sum[i_store] / pixels); poster_g[poster_i_color] = Math.floor(poster_g_sum[i_store] / pixels); poster_b[poster_i_color] = Math.floor(poster_b_sum[i_store] / pixels); poster_i_color++; } else { index <<= 3; level++; for(var i = 0; i < 8; i++) { if(!(poster_pixels[poster_off[level] + (index | i)] & 0x80000000)) { // ノードあり poster_get_colors(level, index | i); if(poster_i_color == poster_leaves) break; } } } } // ガラス function glass() { ctx_work.drawImage(elem_video, 3, 3); ctx_work.drawImage(elem_work, 3, 3, 1, video_height, 0, 3, 3, video_height); ctx_work.drawImage(elem_work, 2 + video_width, 3, 1, video_height, 3 + video_width, 3, 3, video_height); ctx_work.drawImage(elem_work, 0, 3, video_width + 6, 1, 0, 0, video_width + 6, 3); ctx_work.drawImage(elem_work, 0, 2 + video_height, video_width + 6, 1, 0, 3 + video_height, video_width + 6, 3); var data = ctx_work.getImageData(0, 0, video_width + 6, video_height + 6).data; var y_l6 = (dev_width + 6) * 24; var off = dev_width << 2; for(var i_rnd = dev_size; i_rnd; ) { var i_data; var sum_r, sum_g, sum_b; sum_r = sum_g = sum_b = 0; i_data = glass_rnd[--i_rnd]; var i_kernel = 0; for(var y_end = i_data + y_l6; ; ) { for(var x_end = i_data + 24; ; ) { var k = blur_kernel[i_kernel++]; sum_r += data[i_data] * k; sum_g += data[i_data + 1] * k; sum_b += data[i_data + 2] * k; if(i_data == x_end) break; i_data += 4; } if(i_data > y_end) break; i_data += off; } i_data = i_rnd << 2; work_data[i_data] = sum_r >> 12; work_data[i_data + 1] = sum_g >> 12; work_data[i_data + 2] = sum_b >> 12; } ctx_view.putImageData(work_imgdat, 0, 0); } // スケッチ function sketch(data) { var i_data; for(i_data = 0; i_data < data_len; i_data += 4) data[i_data] = (306 * data[i_data] + 601 * data[i_data + 1] + 117 * data[i_data + 2]) >> 10; var off1 = (dev_width + 1) * 12; var off2 = (dev_width - 6) << 2; i_data = 0; for(var y = 0; y < dev_height; y++) { for(var x = 0; x < dev_width; x++) { var sum = 0; var i_data2 = i_data - off1; var i_kernel = 0; for(var dy = -3; ; ) { var y_ob = (y + dy < 0 || y + dy >= dev_height); for(var dx = -3; ; ) { sum += data[(y_ob || x + dx < 0 || x + dx >= dev_width) ? i_data : i_data2] * blur_kernel[i_kernel++]; if(dx == 3) break; dx++; i_data2 += 4; } if(dy == 3) break; dy++; i_data2 += off2; } data[i_data + 1] = sum >> 12; i_data += 4; } } for(i_data = 0; i_data < data_len; i_data += 4) { var val = (data[i_data + 1]) ? Math.floor(data[i_data] * 510 / data[i_data + 1]) - 255 : 255; data[i_data] = data[i_data + 1] = data[i_data + 2] = (val > 255) ? 255 : ((val < 0) ? 0 : val); } } // ディザ 1 function dither_1(data) { var i_data = 0; var i, i_end; for(i = 0, i_end = dev_width << 1; i < i_end; i++) { work1d[i] = data[i_data] work2d[i] = data[i_data + 1] work3d[i] = data[i_data + 2] i_data += 4; } i_data = 0; var i_work1 = 0; var i_work2 = dev_width; for(var y = dev_height; ; ) { for(var x = dev_width; x; x--) { // R var r = work1d[i_work1]; data[i_data] = (r >= 128) ? (r -= 255, 255) : 0; // G var g = work2d[i_work1]; data[i_data + 1] = (g >= 128) ? (g -= 255, 255) : 0; // B var b = work3d[i_work1]; data[i_data + 2] = (b >= 128) ? (b -= 255, 255) : 0; if(x > 1) { work1d[i_work1 + 1] += (r * 7) >> 4; work2d[i_work1 + 1] += (g * 7) >> 4; work3d[i_work1 + 1] += (b * 7) >> 4; } if(y > 1) { if(x < dev_width) { work1d[i_work2 - 1] += (r * 3) >> 4; work2d[i_work2 - 1] += (g * 3) >> 4; work3d[i_work2 - 1] += (b * 3) >> 4; } work1d[i_work2] += (r * 5) >> 4; work2d[i_work2] += (g * 5) >> 4; work3d[i_work2] += (b * 5) >> 4; if(x > 1) { work1d[i_work2 + 1] += r >> 4; work2d[i_work2 + 1] += g >> 4; work3d[i_work2 + 1] += b >> 4; } } i_data += 4; i_work1++; i_work2++; } if(y == 1) break; if(i_work1 == dev_width) i_work2 = 0; else i_work1 = 0; var i_data2 = i_data + (dev_width << 2); for(i = i_work2, i_end = i_work2 + dev_width; i < i_end; i++) { work1d[i] = data[i_data2] work2d[i] = data[i_data2 + 1] work3d[i] = data[i_data2 + 2] i_data2 += 4; } y--; } } // ディザ 2 function dither_2(data) { var stride = dev_width << 2; var i_data = 0; var i_work = 0; var x, y; for(y = dev_height_h; y; y--) { for(x = dev_width_h; x; x--) { var i_data2 = i_data + stride; work1d[i_work] = (data[i_data] + data[i_data + 4] + data[i_data2] + data[i_data2 + 4]) >> 2; work2d[i_work] = (data[i_data + 1] + data[i_data + 5] + data[i_data2 + 1] + data[i_data2 + 5]) >> 2; work3d[i_work] = (data[i_data + 2] + data[i_data + 6] + data[i_data2 + 2] + data[i_data2 + 6]) >> 2; i_data += 8; i_work++; } if(dev_width & 0x1) { data[i_data] = data[i_data + 1] = data[i_data + 2] = data[i_data + stride] = data[i_data + stride + 1] = data[i_data + stride + 2] = 0; i_data += 4; } i_data += stride; } if(dev_height & 0x1) { for(x = dev_width; x; x--) { data[i_data] = data[i_data + 1] = data[i_data + 2] = 0; i_data += 4; } } i_data = 0; i_work = 0; for(y = dev_height_h; y; y--) { for(x = dev_width_h; x; x--) { var i_data2 = i_data + stride; // R var r = work1d[i_work]; data[i_data] = data[i_data + 4] = data[i_data2] = data[i_data2 + 4] = (r >= 128) ? (r -= 255, 255) : 0; // G var g = work2d[i_work]; data[i_data + 1] = data[i_data + 5] = data[i_data2 + 1] = data[i_data2 + 5] = (g >= 128) ? (g -= 255, 255) : 0; // B var b = work3d[i_work]; data[i_data + 2] = data[i_data + 6] = data[i_data2 + 2] = data[i_data2 + 6] = (b >= 128) ? (b -= 255, 255) : 0; if(x > 1) { work1d[i_work + 1] += (r * 7) >> 4; work2d[i_work + 1] += (g * 7) >> 4; work3d[i_work + 1] += (b * 7) >> 4; } if(y > 1) { var i_work2 = i_work + dev_width_h; if(x < dev_width_h) { work1d[i_work2 - 1] += (r * 3) >> 4; work2d[i_work2 - 1] += (g * 3) >> 4; work3d[i_work2 - 1] += (b * 3) >> 4; } work1d[i_work2] += (r * 5) >> 4; work2d[i_work2] += (g * 5) >> 4; work3d[i_work2] += (b * 5) >> 4; if(x > 1) { work1d[i_work2 + 1] += r >> 4; work2d[i_work2 + 1] += g >> 4; work3d[i_work2 + 1] += b >> 4; } } i_data += 8; i_work++; } if(dev_width & 0x1) i_data += 4; i_data += stride; } } // ディザ 3 function dither_3(data) { var i_data = 0; for(var y = 0; y < dev_height; y++) { var y2 = (y & 0x3) << 2; for(var x = 0; x < dev_width; x++) { var thresh = dither_thresh[y2 | (x & 0x3)]; data[i_data] = (data[i_data] >= thresh) ? 255 : 0; data[i_data + 1] = (data[i_data + 1] >= thresh) ? 255 : 0; data[i_data + 2] = (data[i_data + 2] >= thresh) ? 255 : 0; i_data += 4; } } } // 網点 function halftone(data) { var x_adj; var y_rem; var i; // 3 ピクセル単位の余りの部分をクリア var data32 = new Uint32Array(data.buffer); switch(x_adj = dev_width % 3) { case 1: for(i = dev_size - 1; i > 0; i -= dev_width) data32[i] = 0xffffffff; break; case 2: for(i = dev_size - 1; i > 0; i -= dev_width) data32[i - 1] = data32[i] = 0xffffffff; break; } x_adj <<= 2; if(y_rem = dev_height % 3) { for(i = dev_width * (dev_height - y_rem); i < dev_size; i++) data32[i] = 0xffffffff; } var stride = dev_width << 2; var wt = Math.floor(dev_width / 3); var ht = Math.floor(dev_height / 3); var i_data1 = data_len - (y_rem + 2) * stride - x_adj; for(var y = ht; y; y--) { for(var x = wt; x; x--) { i_data1 -= 12; var i_data2, i_data3; i_data3 = (i_data2 = i_data1 + stride) + stride; var g_b2, g_b3, b_b2, b_b3; // R(C) i = Math.floor((data[i_data1] + data[i_data1 + 4] + data[i_data1 + 8] + data[i_data2] + data[i_data2 + 4] + data[i_data2 + 8] + data[i_data3] + data[i_data3 + 4] + data[i_data3 + 8]) / 9) >> 4; data[i_data2 + 4] = halftone_b1[i]; data[i_data1 + 4] = data[i_data2] = data[i_data2 + 8] = data[i_data3 + 4] = halftone_b2[i]; data[i_data1] = data[i_data1 + 8] = data[i_data3] = data[i_data3 + 8] = halftone_b3[i]; // G(M) // 1 ピクセル右にずらす i = Math.floor((data[i_data1 + 1] + data[i_data1 + 5] + data[i_data1 + 9] + data[i_data2 + 1] + data[i_data2 + 5] + data[i_data2 + 9] + data[i_data3 + 1] + data[i_data3 + 5] + data[i_data3 + 9]) / 9) >> 4; data[i_data2 + 9] = halftone_b1[i]; data[i_data1 + 9] = data[i_data2 + 5] = data[i_data3 + 9] = g_b2 = halftone_b2[i]; data[i_data1 + 5] = data[i_data3 + 5] = g_b3 = halftone_b3[i]; // B(Y) // 1 ピクセル下にずらす i = Math.floor((data[i_data1 + 2] + data[i_data1 + 6] + data[i_data1 + 10] + data[i_data2 + 2] + data[i_data2 + 6] + data[i_data2 + 10] + data[i_data3 + 2] + data[i_data3 + 6] + data[i_data3 + 10]) / 9) >> 4; data[i_data3 + 6] = halftone_b1[i]; data[i_data2 + 6] = data[i_data3 + 2] = data[i_data3 + 10] = b_b2 = halftone_b2[i]; data[i_data2 + 2] = data[i_data2 + 10] = b_b3 = halftone_b3[i]; if(x < wt || x_adj) { // G(M) data[i_data2 + 13] = g_b2; data[i_data1 + 13] = data[i_data3 + 13] = g_b3; } if(y < ht || y_rem) { // B(Y) i = i_data3 + stride; data[i + 6] = b_b2; data[i + 2] = data[i + 10] = b_b3; } } i_data1 -= x_adj + (stride << 1); } for(i = data_len - y_rem * stride + 1; ; ) { if((i -= stride) < 0) break; data[i] = 255; } for(i = stride - x_adj + 2; ; ) { if((i -= 4) < 0) break; data[i] = 255; } } // 波紋 function ripple(imgdat) { var data = new Uint32Array(imgdat.data.buffer); var x_end = (dev_width & 0x1) ? dev_width_h + 1 : dev_width_h; var y_end = (dev_height & 0x1) ? dev_height_h + 1 : dev_height_h; var i = 0; for(var y = - dev_height_h; y < y_end; y++) { for(var x = - dev_width_h; x < x_end; x++) { if(x | y) { var disp = ripple_sin[(ripple_pha[i] + ripple_time) & 0xff] / ripple_att[i]; var x2 = x + Math.round(x * disp); var y2 = y + Math.round(y * disp); if(x >= 0) { if (x2 < 0) x2 = 0; else if(x2 >= x_end) x2 = x_end - 1; } else { if (x2 >= 0) x2 = -1; else if(x2 < - dev_width_h) x2 = - dev_width_h; } if(y >= 0) { if (y2 < 0) y2 = 0; else if(y2 >= y_end) y2 = y_end - 1; } else { if (y2 >= 0) y2 = -1; else if(y2 < - dev_height_h) y2 = - dev_height_h; } work_data32[i] = data[(y2 + dev_height_h) * dev_width + (x2 + dev_width_h)]; } else { work_data32[i] = data[i]; } i++; } } ctx_view.putImageData(work_imgdat, 0, 0); ripple_time = (ripple_time - 40) & 0xff; } // 回転 function rotate() { ctx_work.drawImage(elem_view, 0, 0); ctx_view.save(); ctx_view.clip(); ctx_view.translate(video_width_h, video_height_h); ctx_view.rotate(rotate_angle); ctx_view.translate(- video_width_h, - video_height_h); ctx_view.drawImage(elem_work, 0, 0, video_width, video_height); ctx_view.restore(); if((rotate_angle += 0.05) >= PI2) rotate_angle -= PI2; } proc_tbl = [solar, relief, laplacian_1, laplacian_2, poster_1, poster_2, poster_3, glass, sketch, dither_1, dither_2, dither_3, halftone, ripple, rotate]; proc = solar; interval = 200; // ソラリゼーション用変換マップ solar_map = new Uint8Array(1200); for(i = 0; i < 200; i++) solar_map[i + 1000] = (solar_map[i] = Math.floor(i * 128 / 200)) + 128; for(; i < 600; i++) { var sin = Math.sin((i - 200) * Math.PI / 400) * 256 / Math.PI; solar_map[i] = Math.floor(128 + sin); solar_map[i + 400] = Math.floor(128 - sin); } // ポスタリゼーション用減色処理ワーク // 8 + 8*8 + 8*8*8 + 8*8*8*8 = 4680 poster_pixels = new Uint32Array(4680); poster_r_sum = new Uint32Array(4680); poster_g_sum = new Uint32Array(4680); poster_b_sum = new Uint32Array(4680); poster_off = new Uint16Array([0, 8, 72, 584]); poster_internal = new Uint16Array(51); poster_internal_cnt = new Uint8Array(3); poster_r = new Uint8Array(16); poster_g = new Uint8Array(16); poster_b = new Uint8Array(16); // ぼかしフィルター blur_kernel = new Uint16Array([ 21, 38, 55, 63, 55, 38, 21, 38, 71, 102, 116, 102, 71, 38, 55, 102, 148, 167, 148, 102, 55, 63, 116, 167, 192, 167, 116, 63, 55, 102, 148, 167, 148, 102, 55, 38, 71, 102, 116, 102, 71, 38, 21, 38, 55, 63, 55, 38, 21]); // ディザ用しきい値 dither_thresh = new Uint8Array([ 15, 136, 45, 166, 196, 75, 226, 105, 60, 181, 30, 151, 241, 120, 211, 90]); // 網点用明度 halftone_b1 = new Uint8Array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 29, 135, 255]); halftone_b2 = new Uint8Array([ 7, 20, 34, 48, 63, 79, 96, 113, 132, 152, 175, 200, 228, 251, 255, 255]); halftone_b3 = new Uint8Array([116, 133, 149, 165, 180, 194, 208, 220, 231, 241, 249, 254, 255, 255, 255, 255]); // 波紋用 sin テーブル ripple_sin = new Float32Array(256); for(i = 0; i < 256; i++) ripple_sin[i] = Math.sin(i * Math.PI / 128) * 40; ripple_time = 0; rotate_angle = 0; PI2 = 2 * Math.PI; // ページを再ロードしたときのため document.forms[0].reset(); document.getElementById("sel").disabled = true; //--> </SCRIPT> </BODY> </HTML> |