티스토리 뷰
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
//전역 변수(*중요*)
var inCanvas, inCtx, outCanvas, outCtx; // 입력 캔버스 관련
var inFile, inImageArray, outImageArray; // 입력 파일 및 배열
var inWidth, inHeight, outWidth, outHeight; // 입력 영상의 폭과 높이
var inPaper,outPaper; // 캔버스에는 한점한점이 안찍힘. 대신 캔버스에 종이를 붙임.
function init(){ // 초기화 함수 (= 생성자 함수 개념)
inCanvas = document.getElementById('inCanvas');
inCtx = inCanvas.getContext('2d');
outCanvas = document.getElementById('outCanvas');
outCtx = outCanvas.getContext('2d');
}
function readRawImage() {
inFile = document.getElementById('selectFile').files[0];
// 중요! 코드 (영상의 크기를 파악)
inWidth = inHeight = Math.sqrt(inFile.size); //폭과 높이가 같을 때 쓰는 로우데이터
// ↓ ★ 입력 2차원 배열을 준비 / 실무에서 쓰는 코드!
inImageArray = new Array(inHeight); // 256짜리 1차원 배열
for(var i=0; i<inHeight; i++)
inImageArray[i] = new Array(inWidth);
// 캔버스 크기를 결정
inCanvas.width = inWidth;
inCanvas.height = inHeight;
// RAW 파일 --> 2차원 배열
var reader = new FileReader();
reader.readAsBinaryString(inFile);
reader.onload = function () {
var bin = reader.result; // 파일을 덩어리(bin)로 읽었음
// 덩어리(bin)에서 한점한점씩 뽑아서, 배열에 넣기
for(var i=0; i<inHeight; i++) {
for(var k=0; k<inWidth; k++) {
// 0,0 0,1 0,2 ...... 0,255
// 1,0 1,1, 1,2 .......1,255
// ....
// 255,0 255,1 ....... 255,255
var sPixel = (i * inHeight + k);
var ePixel = (i * inHeight + k) + 1;
inImageArray[i][k] = bin.slice(sPixel,ePixel); // 1개픽셀-->배열
}
}
// 화면에 출력하기 (사람용)
inPaper = inCtx.createImageData(inHeight, inWidth); //종이 붙였음.
for(var i=0; i<inHeight; i++) {
for (var k=0; k<inWidth; k++) {
var charValue = inImageArray[i][k].charCodeAt(0); // 깨진문자를 숫자로.
inPaper.data[(i*inWidth + k) * 4 + 0] = charValue; // R
inPaper.data[(i*inWidth + k) * 4 + 1] = charValue; // G
inPaper.data[(i*inWidth + k) * 4 + 2] = charValue; // B
inPaper.data[(i*inWidth + k) * 4 + 3] = 255; // Alpha
}
}
inCtx.putImageData(inPaper,0,0);
}
}
//// 영상처리 함수 관련
function printOutImage() {
// 캔버스 크기를 결정
outCanvas.width = outWidth;
outCanvas.height = outHeight;
outPaper = outCtx.createImageData(outHeight, outWidth); //종이 붙였음.
for(var i=0; i<outHeight; i++) {
for (var k=0; k<outWidth; k++) {
var charValue = outImageArray[i][k].charCodeAt(0); // 깨진문자를 숫자로.
outPaper.data[(i*outWidth + k) * 4 + 0] = charValue; // R
outPaper.data[(i*outWidth + k) * 4 + 1] = charValue; // G
outPaper.data[(i*outWidth + k) * 4 + 2] = charValue; // B
outPaper.data[(i*outWidth + k) * 4 + 3] = 255; // Alpha
}
}
outCtx.putImageData(outPaper,0,0);
}
function addImage()/*밝게하기*/ {
//(중요!)출력 영상의 크기를 결정 ... 알고리즘에 따름.
outHeight = inHeight;
outWidth = inWidth;
// 출력 2차원 배열 준비
outImageArray = new Array(outHeight); // 256짜리 1차원 배열
for(var i=0; i<outHeight; i++)
outImageArray[i] = new Array(outWidth);
// ****진짜 영상처리 알고리즘*****
var value = parseInt(prompt("밝게할 값","0"));
for(var i=0; i<inHeight; i++) {
for (var k=0; k<outWidth; k++) {
// 문자 --> 숫자
pixel = inImageArray[i][k].charCodeAt(0);
// ** 요기가 핵심 알고리즘. (밝게하기)
if(pixel + value >255)
pixel = 255;
else
pixel +=value;
// 숫자 --> 문자
outImageArray[i][k] = String.fromCharCode(pixel);
}
}
printOutImage();
}
function subImage()/*어둡게하기*/ {
//(중요!)출력 영상의 크기를 결정 ... 알고리즘에 따름.
outHeight = inHeight;
outWidth = inWidth;
// 출력 2차원 배열 준비
outImageArray = new Array(outHeight); // 256짜리 1차원 배열
for(var i=0; i<outHeight; i++)
outImageArray[i] = new Array(outWidth);
// ****진짜 영상처리 알고리즘*****
var value = parseInt(prompt("어둡게 할 값","0"));
for(var i=0; i<inHeight; i++) {
for (var k=0; k<outWidth; k++) {
// 문자 --> 숫자
pixel = inImageArray[i][k].charCodeAt(0);
// ** 요기가 핵심 알고리즘. (밝게하기)
if(pixel - value < 0)
pixel = 0;
else
pixel -= value;
// 숫자 --> 문자
outImageArray[i][k] = String.fromCharCode(pixel);
}
}
printOutImage();
}
function bwImage() { // 흑백 알고리즘
// (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
outHeight = inHeight;
outWidth = inWidth;
// 출력 2차원 배열을 준비
outImageArray = new Array(outHeight); // 256짜리 1차원 배열
for(var i=0; i<outHeight; i++)
outImageArray[i] = new Array(outWidth);
// ***** 진짜 영상처리 알고리즘 *****
var value = parseInt(prompt("기준 값", "127"));
for(var i=0; i<inHeight; i++) {
for (var k=0; k<inWidth; k++) {
// 문자 --> 숫자
pixel = inImageArray[i][k].charCodeAt(0);
// **** 요기가 핵심 알고리즘. (흑백)
if (pixel > value)
pixel = 255;
else
pixel = 0;
// 숫자 --> 문자
outImageArray[i][k] = String.fromCharCode(pixel);
}
}
printOutImage();
}
function bwAvgImage()/*흑백처리를 평균값으로 하는 알고리즘*/ {
//(중요!)출력 영상의 크기를 결정 ... 알고리즘에 따름.
outHeight = inHeight;
outWidth = inWidth;
// 출력 2차원 배열을 준비
outImageArray = new Array(outHeight); // 256짜리 1차원 배열
for(var i=0; i<outHeight; i++)
outImageArray[i] = new Array(outWidth);
// ***** 진짜 영상처리 알고리즘 *****
var hap = 0;
for(var i=0; i<inHeight; i++)
for (var k=0; k<inWidth; k++)
hap += inImageArray[i][k].charCodeAt(0);
var value = hap / (inHeight*inWidth) ;
for(var i=0; i<inHeight; i++) {
for (var k=0; k<inWidth; k++) {
// 문자 --> 숫자
pixel = inImageArray[i][k].charCodeAt(0);
// **** 요기가 핵심 알고리즘. (흑백)
if (pixel > value)
pixel = 255;
else
pixel = 0;
// 숫자 --> 문자
outImageArray[i][k] = String.fromCharCode(pixel);
}
}
printOutImage();
}
function zoomOutImage()/*축소*/ {
//(중요!)출력 영상의 크기를 결정 ... 알고리즘에 따름.
var scale = parseInt(prompt("축소 배율(짝수)", "2"));
outHeight = parseInt(inHeight/scale);
outWidth = parseInt(inWidth/scale);
// 출력 2차원 배열 준비
outImageArray = new Array(outHeight); // 256짜리 1차원 배열
for(var i=0; i<outHeight; i++)
outImageArray[i] = new Array(outWidth);
// ****진짜 영상처리 알고리즘*****
for(var i=0; i<inHeight; i++) {
for (var k=0; k<inWidth; k++) {
// **** 요기가 핵심 알고리즘. (영상 축소)
outImageArray[parseInt(i/scale)][parseInt(k/scale)] = inImageArray[i][k];
}
}
printOutImage();
}
function zoomInImage()/*확대*/ {
//(중요!)출력 영상의 크기를 결정 ... 알고리즘에 따름.
var scale = parseInt(prompt("확대 배율(짝수)", "2"));
outHeight = parseInt(inHeight*scale);
outWidth = parseInt(inWidth*scale);
// 출력 2차원 배열 준비
outImageArray = new Array(outHeight); // 256짜리 1차원 배열
for(var i=0; i<outHeight; i++)
outImageArray[i] = new Array(outWidth);
//outImageArray를 초기화 시키기(0으로 채우기)
for(var i=0; i<outHeight; i++)
for (var k=0; k<outWidth; k++)
outImageArray[i][k] = String.fromCharCode(0);
// ****진짜 영상처리 알고리즘*****
for(var i=0; i<outHeight; i++) {
for (var k=0; k<outWidth; k++) {
// **** 요기가 핵심 알고리즘. (영상 확대) --> 백워딩 기법 사용하기
outImageArray[i][k] = inImageArray[parseInt(i/scale)][parseInt(k/scale)];
}
}
printOutImage();
}
function reverseImage()/*좌우반전*/ {
// (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
outHeight = inHeight;
outWidth = inWidth;
// 출력 2차원 배열을 준비
outImageArray = new Array(outHeight); // 256짜리 1차원 배열
for(var i=0; i<outHeight; i++)
outImageArray[i] = new Array(outWidth);
// ***** 진짜 영상처리 알고리즘 *****
for(var i=0; i<inHeight; i++) {
for (var k=0; k<inWidth; k++) {
// ** 요기가 핵심 알고리즘.
outImageArray[i][k] = inImageArray[i][inWidth-1-k];
}
}
printOutImage();
}
function udReverseImage()/*상하반전*/ {
// (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
outHeight = inHeight;
outWidth = inWidth;
// 출력 2차원 배열을 준비
outImageArray = new Array(outHeight); // 256짜리 1차원 배열
for(var i=0; i<outHeight; i++)
outImageArray[i] = new Array(outWidth);
// ***** 진짜 영상처리 알고리즘 *****
for(var i=0; i<inHeight; i++) {
for (var k=0; k<inWidth; k++) {
// ** 요기가 핵심 알고리즘.
outImageArray[i][k] = inImageArray[inHeight-1-i][k];
}
}
printOutImage();
}
function posterizingImage()/*포스터라이징*/ {
//(중요!)출력 영상의 크기를 결정 ... 알고리즘에 따름.
outHeight = inHeight;
outWidth = inWidth;
// 출력 2차원 배열 준비
outImageArray = new Array(outHeight); // 256짜리 1차원 배열
for(var i=0; i<outHeight; i++)
outImageArray[i] = new Array(outWidth);
// **** 요기가 핵심 알고리즘.
for(var i=0; i<inHeight; i++) {
for (var k=0; k<inWidth; k++) {
pixel = inImageArray[i][k].charCodeAt(0);
if (pixel >= 231) {
pixel = 255;
} else if (pixel >= 206){
pixel = 230;
} else if (pixel >= 181){
pixel = 205;
} else if (pixel >= 156){
pixel = 180;
} else if (pixel >= 131){
pixel = 155;
} else if (pixel >= 106){
pixel = 130;
} else if (pixel >= 81){
pixel = 105;
} else if (pixel >= 56){
pixel = 80;
} else if (pixel >= 31){
pixel = 55;
}else pixel = 0;
// 숫자 --> 문자
outImageArray[i][k] = String.fromCharCode(pixel);
}
}
printOutImage();
}
// 90도회전(시계)
function rot1Image() {
// (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
outHeight = inHeight;
outWidth = inWidth;
// 출력 2차원 배열을 준비
outImageArray = new Array(outHeight);
for(var i=0; i<outHeight; i++)
outImageArray[i] = new Array(outWidth);
// ***** 진짜 영상처리 알고리즘 *****
for(var i=0; i<inHeight; i++) {
for (var k=0; k<inWidth; k++) {
// ** 요기가 핵심 알고리즘.
outImageArray[i][k] = inImageArray[inWidth-1-i][k];
}
}
for(var i=0; i<outWidth; i++) {
for (var k=i; k<outHeight; k++) {
// ** 요기가 핵심 알고리즘.
tmp = outImageArray[i][k];
outImageArray[i][k] = outImageArray[k][i];
outImageArray[k][i] = tmp;
}
}
printOutImage();
}
// function zoomInImage()/*확대*/ {
// //(중요!)출력 영상의 크기를 결정 ... 알고리즘에 따름.
// var scale = parseInt(prompt("확대 배율(짝수)", "2"));
// outHeight = parseInt(inHeight*scale);
// outWidth = parseInt(inWidth*scale);
// // 출력 2차원 배열 준비
// outImageArray = new Array(outHeight); // 256짜리 1차원 배열
// for(var i=0; i<outHeight; i++)
// outImageArray[i] = new Array(outWidth);
// //outImageArray를 초기화 시키기(0으로 채우기)
// for(var i=0; i<outHeight; i++)
// for (var k=0; k<outWidth; k++)
// outImageArray[i][k] = String.fromCharCode(0);
// // ****진짜 영상처리 알고리즘*****
// for(var i=0; i<inHeight; i++) {
// for (var k=0; k<inWidth; k++) {
// // **** 요기가 핵심 알고리즘. (영상 확대)
// outImageArray[parseInt(i*scale)][parseInt(k*scale)] = inImageArray[i][k];
// }
// }
// printOutImage();
// }
// function colorrevImage()/*색반전*/ {
// //(중요!)출력 영상의 크기를 결정 ... 알고리즘에 따름.
// outHeight = inHeight;
// outWidth = inWidth;
// // 출력 2차원 배열 준비
// outImageArray = new Array(outHeight); // 256짜리 1차원 배열
// for(var i=0; i<outHeight; i++)
// outImageArray[i] = new Array(outWidth);
// // ***** 진짜 영상처리 알고리즘 *****
// for(var i=0; i<inHeight; i++) {
// for (var k=0; k<outWidth; k++) {
// // 문자 --> 숫자
// pixel = inImageArray[i][k].charCodeAt(0);
// // **** 요기가 핵심 알고리즘. (색반전)
// sort(intImageArray.begin(), intImageArray.end());
// if (intImageArray.size() % 2 == 1)
// return intImageArray[intImageArray.size() / 2];
// else
// return (intImageArray[intImageArray.size() / 2] + intImageArray[intImageArray.size() / 2 + 1]) / 2;
// // 숫자 --> 문자
// outImageArray[i][k] = String.fromCharCode(pixel);
// }
// }
// printOutImage();
// }
</script>
</head>
<body onload='init()'>
<button style="background-color: skyblue;border-color: lightpink; color: cornsilk;">
<input type='file' id='selectFile' onchange='readRawImage()'/>
<!-- <input type='button' id='photocolorrev' value='색반전' onclick='colorrevImage()'/> -->
<details>
<summary>이미지 편집</summary>
<input type='button' id='photoAdd' value='밝게하기' onclick='addImage()'/>
<input type='button' id='photoSub' value='어둡게하기' onclick='subImage()'/> <br><br>
<input type='button' id='photoBW' value='흑백처리' onclick='bwImage()'/>
<input type='button' id='photoAvgBW' value='흑백처리(평균)' onclick='bwAvgImage()'/><br><br>
<input type='button' id='photorePosterizing' value='포스터라이징' onclick='posterizingImage()'/>
<input type='button' id='photoreverse' value='좌우반전' onclick='reverseImage()'/><br><br>
<input type='button' id='photoreUpDown' value='상하반전' onclick='udReverseImage()'/>
</details>
<details>
<summary>확대/축소</summary>
<input type='button' id='photoZoomOut' value='축소하기' onclick='zoomOutImage()'/>
<input type='button' id='photoZoomIn' value='확대하기' onclick='zoomInImage()'/>
</details>
</button>
<canvas id='inCanvas' style='background-color:rgb(248, 209, 164)'></canvas>
<canvas id='outCanvas' style='background-color:rgb(136, 182, 196)'></canvas>
</body>
</html>
'공부합시다 > Javascript' 카테고리의 다른 글
[영상처리] 흑백처리 함수 만들기 (0) | 2021.04.01 |
---|---|
[클론코딩] 그림판 만들기 (0) | 2021.03.23 |
[영상처리] 밝기 조절을 하기위한 함수 만들기 (0) | 2021.03.22 |
[영상처리] 밝게 하기 (0) | 2021.03.22 |
[영상처리] 캔버스 크기 지정 (0) | 2021.03.22 |