ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JS] 모자이크 처리
    기초/자바스크립트 2022. 3. 4. 09:39

    테스트 페이지

    https://eaststar1129.github.io/mozaic.html

     

    구성도

     

    마우스를 올렸을때 그림에 마우스 영역이 나타나며 모자이크를 클릭시 모자이크 / 되돌리기를 구현

     

    코드 

    Canvas 활용 

    Canvas 3개

     - 원본

     - 마우스 영역

     - 수정되는 영역

     

    페이지 로드시 원본, 모자이크영역에 이미지 삽입, hover영역 초기화

     

    마우스 move시 hover 영역에서 사각형을 계속 표시

    마우스 out시 hover 영역 초기화

    마우스 click시 원본데이터를 가져와 모자이크 / 원본그대로 수정데이터에 삽입

     

    Canvas의 index는 원본 < 수정본 < hover 순

    [css]

    html, body{
            margin:0;
            padding:0;
        }
    
        #divCanvas {
            position:relative;
            padding: 5rem;
            display:inline-block;
            width:70%; 
            height: 400px;
        }
    
        #divCanvas canvas{
            position: absolute;
            left:0px;
            width:400;
            height: 400;
        }
    
        #divCanvas #canvas{
            z-index:1;
        }
        #divCanvas #mosaic{
            z-index:2;
        }
        #divCanvas #hover{
            z-index:3;
        }

     

    [body]

    <section>
            <div id="divCanvas"> 
                <canvas id="canvas"></canvas> <!--원본-->
                <canvas id="mosaic"></canvas> <!--모자이크 영역-->
                <canvas id="hover"></canvas> <!--마우스영역-->
            </div>
            <button type="button" id="btnMosaic">모자이크</button>
            <button type="button" id="btnEraser">지우개</button>
            <button type="button" id="btnSave">저장하기</button>
        </section>

    [스크립트]

    		let isMozaic = false;
    
            /* canvas setting*/
            const canvas = document.getElementById('canvas');    
            const ctx = canvas.getContext('2d');
    
            /* 이미지 가져오기 */
            let img = new Image()
            img.src = "../images/test.jpg"
            img.onload = function(){
                ctx.clearRect(0,0, canvas.width, canvas.height);
                ctx.drawImage(img, 0 , 0, canvas.width, canvas.height);
                
                mosaicCtx = document.getElementById('mosaic').getContext('2d');
                mosaicCtx.clearRect(0,0, canvas.width, canvas.height);
                mosaicCtx.drawImage(img, 0 , 0, canvas.width, canvas.height);
            };
    
            /* event */
            document.getElementById('hover').addEventListener('mousemove', function (e) {  
            	/* 사각형 영역 만들기 */
                var x = event.clientX - ctx.canvas.offsetLeft - 15; 
                var y = event.clientY - ctx.canvas.offsetTop - 15; 
    
                x = x < 0 ? 0 : x;
                y = y < 0 ? 0 : y;
    
                ctxHover = this.getContext('2d');
                ctxHover.clearRect(0,0, this.width, this.height)
    
                ctxHover.strokeStyle = 'black';
                ctxHover.strokeWidth= 3;
                ctxHover.fillStyle = 'rgba(255, 255, 255, 0.5)';
    
                ctxHover.fillRect(x, y, 30, 30);
            });
            
            document.getElementById('hover').addEventListener('mouseout', function (e) {  
            	/* 사각형 지우기 */          
                ctxHover = this.getContext('2d');
                ctxHover.clearRect(0,0, this.width, this.height);
            });
            
            document.getElementById('hover').addEventListener('click', function (e) { 
            	/* 사각형 영역만큼 처리 */                    
                var x = event.clientX - ctx.canvas.offsetLeft - 15; 
                var y = event.clientY - ctx.canvas.offsetTop - 15; 
    
                x = x < 0 ? 0 : x;
                y = y < 0 ? 0 : y;
                
    
                mosaic = document.getElementById('mosaic');
                mosaicCtx = mosaic.getContext('2d');
                var imageData = ctx.getImageData(x, y, 30, 30);
                if(isMozaic){
    	            /* 모자이크 */
    	            for(var i=0;i<imageData.data.length;i=i+4){
    	            	r = imageData.data[i];
    	            	g = imageData.data[i+1];
    	            	b = imageData.data[i+2];
    	            	a = imageData.data[i+3];
    	               	for(var j=1;j<=9;j++){
    	            		imageData.data[i+4] = r;
    	            		imageData.data[i+5] = g;
    	            		imageData.data[i+6] = b;
    	            		imageData.data[i+7] = a;
    	            		i=i+4;
    	            	}
    	        	}
    	            
                }
                mosaicCtx.putImageData(imageData, x , y);
            })
            
            /* btn */
            document.getElementById("btnMosaic").onclick = function(){
            	isMozaic = true;
            };
            
            document.getElementById("btnEraser").onclick = function(){
            	isMozaic = false;
            };
    
            document.getElementById("btnSave").onclick = function(e){
                mosaic = document.getElementById('mosaic');
                image = mosaic.toDataURL("image/png", 1.0).replace("image/png", "image/octet-stream");
                var link = document.createElement('a');
                link.download = "mozaic.png";
                link.href = image;
                link.click();
           	};

     

     

    ##모자이크 로직변경

    기존에는 모자이크 사이즈가 고정이였지만 

    현재는 모자이크 크기를 지정하여 자연스럽게 처리가능

    function mosaic(imageData){	
    	const mosaicXY = {x:15, y:15};
    	for(var x = 0, w = imageData.width; x < w; x=x+mosaicXY.x) {
    		for(var y = 0, h =  imageData.height; y < h; y=y+mosaicXY.y) {
    			const pixIndex = (y * w + x) * 4;
    			const r = imageData.data[pixIndex];
    			const g = imageData.data[pixIndex + 1];
    			const b = imageData.data[pixIndex + 2];
    			const a = imageData.data[pixIndex + 3];
    			
    			for(xx = x; xx < x+mosaicXY.x && xx < w;++xx){
    				for( yy = y; yy < y+mosaicXY.y && yy < h; ++yy){
    					const pixIndex2 = (yy * w + xx) * 4;
    					imageData.data[pixIndex2] = r;
    					imageData.data[pixIndex2 + 1] = g;
    					imageData.data[pixIndex2 + 2] = b;
    					imageData.data[pixIndex2 + 3] = a;
    				}
    			}
    		}
    	}
    	return imageData;
    }

    '기초 > 자바스크립트' 카테고리의 다른 글

    [JS] 일급 함수와 고차함수  (0) 2022.12.14
    GridSatck (Test.html)  (0) 2022.03.16
    [Javascript] OpenLayers + GeoServer + PostGIS + VWORLD + WFS,WMS  (6) 2020.11.11
    [JS] 기초 훈련(내장함수)  (0) 2017.04.26
    [JS] 시작  (0) 2017.04.26

    댓글

Designed by Tistory.