HTML5+ CSS3+ Javascript

5일차

구자룡 2021. 3. 22. 17:32


<!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>
    <style>
        div {
            font: normal 24px verdana;
            background-color: rgb(189, 22, 22);
        }

        .wordArtEffectText {
            color: rgb(251, 255, 192);
            text-shadow: 3px 3px rgb(135, 235, 157);
        }

        body {
            background-image: url(rea.png);
            background-repeat: repeat-x;
            background-size: cover;

        }
    </style>

    <script> // 전역 변수(*중요*)
        var inCanvas,
            inCtx,
            outCanvas,
            outCtx,
            GRCanvas,
            GRCtx; // 입력 캔버스 관련
        var inFile,
            inImageArray,
            outImageArray,
            GRlmageArray; // 입력 파일 및 배열
        var inWidth,
            inHeight,
            outWidth,
            outHeight,
            GRWidth,
            GRHeight; // 입력 영상의 폭과 높이
        var inPaper,
            outPaper,
            GRPaper; // 캔버스에는 한점한점이 안찍힘. 대신 캔버스에 종이를 붙임.

        function init() {
            inCanvas = document.getElementById('inCanvas');
            inCtx = inCanvas.getContext('2d');
            outCanvas = document.getElementById('outCanvas');
            outCtx = outCanvas.getContext('2d');
            GRCanvas = document.getElementById('GRCanvas');
            GRCtx = GRCanvas.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 ImageProcessing(selectNum) {

            // 선택번호를 받음.
            switch (selectNum.value) {
                case "1": // 동일 영상
                    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 < inWidth; k++) {
                            outImageArray[i][k] = inImageArray[i][k];
                        }
                    }

                    printOutImage();
                    break;
                case "2": // 밝게 하기
                    // (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
                    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 < inWidth; k++) {
                            // 문자 --> 숫자
                            pixel = inImageArray[i][k].charCodeAt(0);
                            // **** 요기가 핵심 알고리즘. (밝게하기)
                            if (pixel + value > 255) pixel = 255;
                            else pixel += value;
                            // 숫자 --> 문자
                            outImageArray[i][k] = String.fromCharCode(pixel);
                        }
                    }

                    printOutImage();
                    break;
                case "4": // (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
                    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();
                    break;
                case "5": // (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
                    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();
                    break;
                case "6": 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 < inHeight; k++) {
                            //문자를 숫자로 바꿈
                            pixel = inImageArray[i][k].charCodeAt(0);
                            //(색변환)
                            pixel = 255 - pixel;
                            inImageArray[i][k] = String.fromCharCode(pixel);
                        }
                    }

                    for (var i = 0; i < inHeight; i++) {
                        for (var k = 0; k < inWidth; k++) {
                            outImageArray[i][k] = inImageArray[i][k];
                        }
                    }

                    printOutImage();
                    break;
            }
        }
        function ImageProcessing1(selectNum) {

            // 선택번호를 받음.
            switch (selectNum.value) {
                case "21": // (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
                    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();
                    break;
                case "22": // (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
                    var scale = parseInt(prompt("확대 배율(짝수)", "2"));
                    outHeight = inHeight * scale;
                    outWidth = 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();
                    break;
                case "23": outHeight = inHeight;
                    outWidth = inWidth;
                    // 출력 2차원 배열을 준비
                    outImageArray = new Array(outHeight); // 256짜리 1차원 배열
                    for (var i = 0; i < outHeight; i++) outImageArray[i] = new Array(outWidth);
                    var aaa;

                    for (var i = 0; i < inHeight; i++) {
                        for (var k = 0; k < inWidth / 2; k++) {
                            aaa = inImageArray[i][k];
                            inImageArray[i][k] = inImageArray[i][inWidth - k - 1];
                            inImageArray[i][inWidth - k - 1] = aaa;

                            //문자를 숫자로 바꿈
                        }
                    }

                    for (var i = 0; i < inHeight; i++) {
                        for (var k = 0; k < inWidth; k++) {
                            outImageArray[i][k] = inImageArray[i][k];
                        }
                    }

                    printOutImage();
                    break;
                case "24": outHeight = inHeight;
                    outWidth = inWidth;
                    // 출력 2차원 배열을 준비
                    outImageArray = new Array(outHeight); // 256짜리 1차원 배열
                    for (var i = 0; i < outHeight; i++) outImageArray[i] = new Array(outWidth);
                    var bbb;

                    for (var i = 0; i < inHeight / 2; i++) {
                        for (var k = 0; k < inWidth; k++) {
                            bbb = inImageArray[i][k];
                            inImageArray[i][k] = inImageArray[inHeight - i - 1][k];
                            inImageArray[inHeight - i - 1][k] = bbb;

                            //문자를 숫자로 바꿈
                        }
                    }

                    for (var i = 0; i < inHeight; i++) {
                        for (var k = 0; k < inWidth; k++) {
                            outImageArray[i][k] = inImageArray[i][k];
                        }
                    }

                    printOutImage();
                    break;
            }
        }
        function ImageProcessing2(selectNum) {

            // 선택번호를 받음.
            switch (selectNum.value) {
                case "41": // (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
                    outHeight = inHeight;
                    outWidth = inWidth;
                    // 출력 2차원 배열을 준비
                    outImageArray = new Array(outHeight); // 256짜리 1차원 배열
                    for (var i = 0; i < outHeight; i++) outImageArray[i] = new Array(outWidth);

                    // ***** 진짜 영상처리 알고리즘 *****
                    // out = (in - low ) / (high - low) * 255
                    var low = inImageArray[0][0].charCodeAt(0);
                    var high = inImageArray[0][0].charCodeAt(0);

                    for (var i = 0; i < inHeight; i++) {
                        for (var k = 0; k < inWidth; k++) {
                            pixel = inImageArray[i][k].charCodeAt(0);
                            if (pixel < low) low = pixel;
                            if (pixel > high) high = pixel
                        }
                    }

                    for (var i = 0; i < inHeight; i++) {
                        for (var k = 0; k < inWidth; k++) {
                            // 문자 --> 숫자
                            inVal = inImageArray[i][k].charCodeAt(0);
                            // **** 요기가 핵심 알고리즘. (흑백)
                            outVal = (inVal - low) / (high - low) * 255 // 숫자 --> 문자
                            outImageArray[i][k] = String.fromCharCode(outVal);
                        }
                    }

                    printOutImage();
                    break;
                case "42": // (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
                    outHeight = inHeight;
                    outWidth = inWidth;
                    // 출력 2차원 배열을 준비
                    outImageArray = new Array(outHeight); // 256짜리 1차원 배열
                    for (var i = 0; i < outHeight; i++) outImageArray[i] = new Array(outWidth);

                    // ***** 진짜 영상처리 알고리즘 *****
                    // out = (in - low ) / (high - low) * 255
                    var low = inImageArray[0][0].charCodeAt(0);
                    var high = inImageArray[0][0].charCodeAt(0);

                    for (var i = 0; i < inHeight; i++) {
                        for (var k = 0; k < inWidth; k++) {
                            pixel = inImageArray[i][k].charCodeAt(0);
                            if (pixel < low) low = pixel;
                            if (pixel > high) high = pixel
                        }
                    }

                    low += 50;
                    high -= 50;

                    for (var i = 0; i < inHeight; i++) {
                        for (var k = 0; k < inWidth; k++) {
                            // 문자 --> 숫자
                            inVal = inImageArray[i][k].charCodeAt(0);
                            // **** 요기가 핵심 알고리즘. (흑백)
                            outVal = (inVal - low) / (high - low) * 255
                            if (outVal > 255) outVal = 255;
                            else if (outVal < 0) out = 0;
                            // 숫자 --> 문자
                            outImageArray[i][k] = String.fromCharCode(outVal);
                        }
                    }

                    printOutImage();
                    break;
                case "43": // (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
                    outHeight = inHeight;
                    outWidth = inWidth;
                    // 출력 2차원 배열을 준비
                    outImageArray = new Array(outHeight); // 256짜리 1차원 배열
                    for (var i = 0; i < outHeight; i++) outImageArray[i] = new Array(outWidth);

                    // ***** 진짜 영상처리 알고리즘 *****
                    // 1단계 : 히스토그램 생성
                    histo = new Array(256);
                    for (var i = 0; i < 256; i++) histo[i] = 0;

                    for (var i = 0; i < inHeight; i++) for (var k = 0; k < inWidth; k++) {
                        value = inImageArray[i][k].charCodeAt(0);
                        histo[value]++;
                    }

                    // 2단계 : 누적 히스토그램 생성
                    sumHisto = new Array(256);
                    for (var i = 0; i < 256; i++) sumHisto[i] = 0;
                    sumVal = 0;

                    for (var i = 0; i < 256; i++) {
                        sumVal += histo[i];
                        sumHisto[i] = sumVal;
                    }

                    // 3단계 : 정규화된 누적히스토그램
                    // ns = s * (1/픽셀총수) * 화소최대밝기
                    normalHisto = new Array(256);
                    for (var i = 0; i < 256; i++) normalHisto[i] = 0.0;
                    for (var i = 0; i < 256; i++) normalHisto[i] = sumHisto[i] * (1 / (inWidth * inHeight)) * 255;

                    for (var i = 0; i < inHeight; i++) {
                        for (var k = 0; k < inWidth; k++) {
                            // 문자 --> 숫자
                            inVal = inImageArray[i][k].charCodeAt(0);
                            // **** 요기가 핵심 알고리즘. (흑백)
                            outVal = normalHisto[inVal];
                            if (outVal > 255) outVal = 255;
                            else if (outVal < 0) outVal = 0;
                            else outVal = parseInt(outVal);
                            // 숫자 --> 문자
                            outImageArray[i][k] = String.fromCharCode(outVal);
                        }
                    }

                    printOutImage();
                    break;
                case "44":
                    var histo = new Array(256);

                    for (var i = 0; i < 256; i++)

                        histo[i] = 0;

                    for (var i = 0; i < GRHeight; i++) {

                        for (var k = 0; k < GRWidth; k++) {

                            // 문자 --> 숫자

                            value = inImageArray[i][k].charCodeAt(0);

                            // **** 요기가 핵심 알고리즘.

                            histo[value]++;

                        }

                    }

                    var max = 0;

                    var min = GRHeight * GRWidth;



                    for (var i = 0; i < 256; i++) {

                        if (histo[i] < min)

                            min = histo[i];

                        if (histo[i] > max)

                            max = histo[i];

                    }





                    var dif = max - min

                    var normalHisto = new Array(256);

                    for (var i = 0; i < 256; i++) {

                        normalHisto[i] = (histo[i] - min) * 255 / dif;

                    }



                    // (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.

                    GRHeight = inHeight;

                    GRWidth = inWidth;

                    // 출력 2차원 배열을 준비

                    GRImageArray = new Array(GRHeight);

                    for (var i = 0; i < GRHeight; i++)

                        GRImageArray[i] = new Array(GRWidth);

                    for (var i = 0; i < GRHeight; i++) {

                        for (var k = 0; k < GRWidth; k++) {

                            GRImageArray[i][k] = 255;

                        }

                    }

                    for (var i = 0; i < GRHeight; i++) {

                        for (var k = 0; k < normalHisto[i]; k++) {

                            GRImageArray[GRHeight - 1 - k][i] = 0;



                        }

                    }

                    for (var i = 0; i < GRHeight; i++) {

                        for (var k = 0; k < GRWidth; k++) {

                            // 숫자 --> 문자

                            GRImageArray[i][k] = String.fromCharCode(GRImageArray[i][k]);

                        }

                    }
                    printGRImage();
                    break;

            }
        }


    </script>
</head>

<body onload='init()'>
    <h1>
        <div class="wordArtEffectText">PHOTO@@</div>
    </h1>
    <hr>
    <form><input style="border: 5px groove rgb(255, 0, 0);" type='file' id='selectFile' onchange='readRawImage()' />
        <br>
        <label p style="border: 5px groove rgb(255, 153, 0)">화소점 처리</label>
        <select name='imageAlgo' onchange="ImageProcessing(this.form.imageAlgo)"
            style="border: 7px groove rgb(238, 255, 0);">
            <option value=0>선택 하세요 </option>
            <option value="1">동일 영상 처리</option>
            <option value="2">영상 밝게 하기</option>
            <option value="4">흑백 처리</option>
            <option value="5">흑백 처리(평균)</option>
            <option value="6">반대의 색</option>
        </select>
        <label p style="border: 5px groove rgb(0, 255, 21)">기하학 처리</label>
        <select name='imageAlgo1' onchange="ImageProcessing1(this.form.imageAlgo1)"
            style="border: 7px groove rgb(0, 17, 255);">
            <option value="20">선택 하세요 </option>
            <option value="21">축소 하기</option>
            <option value="22">확대 하기</option>
            <option value="23">좌/우 변경</option>
            <option value="24">상/하 변경</option>
        </select>
        <br>
        <label p style="border: 5px groove rgb(47, 0, 255)">히스토그램</label>
        <select name='imageAlgo2' onchange="ImageProcessing2(this.form.imageAlgo2)"
            style="border: 7px groove rgb(140, 0, 255);">
            <option value="40">선택 하세요 </option>
            <option value="41">히스토그램 스트래칭</option>
            <option value="42">엔드-인 탐색</option>
            <option value="43">평활화 </option>
            <option value="44">히스토그램 차트 </option>
        </select>
        <br>
        <canvas id='inCanvas' style='background-color:rgb(248, 209, 164)'></canvas>
        <canvas id='outCanvas' style='background-color:rgb(164, 248, 192)'></canvas>
        <br>
        <canvas id='GRCanvas' style='background-color:rgb(164, 248, 192)'></canvas>
    </form>
</body>

</html>

'HTML5+ CSS3+ Javascript' 카테고리의 다른 글

7일차  (0) 2021.03.26
6일차  (0) 2021.03.23
4일차  (0) 2021.03.19
3일차  (0) 2021.03.18
2일차  (0) 2021.03.17