[JavaScript] Canvas를 통한 이미지 회전[JavaScript] Canvas를 통한 이미지 회전

Posted at 2020. 3. 4. 11:06 | Posted in JavaScript & jQuery/JavaScript
반응형




■ 휴대폰 사진 업로드시 이미지가 가로, 세로가 변경되는 이유





휴대폰, 스마트폰의 카메라로 찍은 사진을 웹 브라우저를 통해 업로드 할경우,


이미지의 가로, 세로가 변경되어 등록되는 경우가 존재한다.


이러한 이유는 EXIF( Exchangeable Image File Format ) 의


회전값 변경이 반영되지 않기에 생기는 이유인데.



아래 이미지는 초기 스마트 폰에서 자주 볼 수 있었던 문제이다.

( 자이로 센서( Gyro Sensor ) 등의 기술 발전으로 이런 문제는 많이 해결 되었지만, 이미지의 편집등 다른 작업 과정으로 현재에도 이런 문제를 맏닥드릴 수 있다. )









가로로 찍은 이미지의 경우 스마트폰 상에서는 분명 정상적으로 보여주지만.


실제 이미지의 EXIF 값을 보면 회전정보( Orientation )가 90° CW 가 적용되어 있는것을 알 수 있다.


이를 회전정보 값을 브라우저에서는 인식하지 않고 보여지는 문제이다.







   # EXIF( Exchangeable Image File Format ) 란?



   디지털 카메라 등에서 사용되는 이미지 파일 메타데이터 포맷으로,


   카메라가 촬영한 사진, 녹음파일에 시간 등의 각종 정보를 담기 위해 개발되었다. 즉, 


   JPEG, TIFF 6.0과 RIFF, WAV 포맷에 이미지나 소리에 대한 정보를 추가로 기록할 수 있다.


   디지털카메라의 보급으로 널리 활성화되었고 이미지 메타데이터의 사실상 표준 지위에 있다.


   EXIF 데이터는 이미지 파일의 일부로 저장되며,


   EXIF 데이터를 지원하는 소프트웨어 사용 시 이미지를 변경해도 데이터를 보존한다.



   출처 : 나무위키( https://namu.wiki/w/EXIF )






간단하게 이미지 파일 하나를 선택하여 마우스 오른쪽 버튼을 클릭하고


오른쪽으로 회전( T ) 을 선택해 보자.





회전 정보 : 90° CW 로 반영된 것을 확인할 수 있다.


이 렇게 회전된 파일을 <img src="스토브리그.jpg">로 올려서 브라우저로 확인을 해 본다면.



# 소스코드

<html>

<head>

<title>:: 스토브리그 ::</title>

<style type="text/css">

/* image-orientation:from-image; */

</style>

</head>

<body>

<img src="stoveleague.jpg"/>

</body>

</html> 



# 출력결과




회전 정보 : 90° CW가 반영이 <img> 태그를 사용한 경우


브라우저에서 다시 정방향으로 돌려서 출력하는 모습을 확인 할 수 있다.




현재 파이어 폭스 브라우저의경우 CSS에 image-orientation:from-image; 를 넣어주는 것만으로도


회전정보 값을 읽어들여 반영하여 이미지가 돌아가는 것을 막아주어서 해결할 수 있지만.


아직까지 크롬등의 다른 브라우저에서는 CSS4의 실험적 기능이기에 적용되어 있지 않다고 한다.


결국 자동으로 이러한 상황을 해결 할 수는 없는 상황이기에


사용자의 폰, 찍은 각도에 따라 업로드시 문제가 발생할 수 있다.











■ 캔버스를 통한 업로드 이미지 각도 조정




그래서 필자는 이에대한 해결책으로


자동으로 이미지를 보정하는 것이 아닌,


사용자가 직접 수동으로 이미지를 수정하는 방향으로 가닥을 잡고,


다 완성된 정보만을 서버로 전달하는 형태로 취하는 방식을 택하게 되었다.




# 소스코드

<html>

<head>

<title>:: JavaScript 캔버스 - 회전 ::</title>

<script type="text/javascript">


    function uploadImgPreview() {


     // @breif 업로드 파일 읽기

     let fileInfo = document.getElementById("upImgFile").files[0];

     let reader = new FileReader();


     reader.addEventListener("load", function() {


          console.log("INDEX #02");


          // @details 업로드한 파일의 URL을 가져온다.

          document.getElementById("thumbnail").src = reader.result;


     }, false);


     if(fileInfo) {


          console.log("INDEX #01");


          // @details readAsDataURL을 통해 업로드한 파일의 URL을 읽어 들인다.

          reader.readAsDataURL(fileInfo);

        }

    }


    function rotateCanvasImg( angle ) {


     // @breif 썸네일 이미지 생성

    let tempImage = new Image();                         // @details drawImage 메서드에 넣기 위해 이미지 객체화

        tempImage.src = document.getElementById("thumbnail").src; // @details 업로드 완료된 이미지를 객체에 주입


     tempImage.onload = function() {


          // @breif 캔버스 위에 이미지 그리기

          let canvas = document.getElementById("canvas");

          let canvasContext = canvas.getContext("2d");


          // @breif 왼쪽( 270° ) 회전의 경우

          if( angle == '270' ) {


               // @details 270° 회전의 경우 이미지의 높이와 넓이를 서로 바꿔준다.

               canvas.width = tempImage.height;

canvas.height = tempImage.width;


               canvasContext.rotate((270) * Math.PI / 180);


               // @details 이미지가 270° 회전 했을 경우 x축의 값을 업로드 이미지의 넓이를 음수로 변경한다.

               canvasContext.drawImage(this, (tempImage.width * -1), 0);


          }


// @breif 오른쪽( 90° ) 회전의 경우

          else if( angle == '90' ) {


               // @details 90° 회전의 경우 이미지의 높이와 넓이를 서로 바꿔준다.

               canvas.width = tempImage.height;

canvas.height = tempImage.width;


               // canvasContext.rotate((90) * Math.PI / 180);

               canvasContext.rotate(Math.PI / 2);


               // @details 이미지가 90° 회전 했을 경우 y축의 값을 업로드 이미지의 높이 음수로 변경한다.

canvasContext.drawImage(this, 0, (tempImage.height * -1));


          }


          // @breif 거꾸로( 180° ) 회전의 경우

          else if( angle == '180' ) {


               canvas.width = tempImage.width;

               canvas.height = tempImage.height;


               // canvasContext.rotate((180) * Math.PI / 180);

               canvasContext.rotate(Math.PI);


               // @details 이미지가 180° 회전 했을 경우 x, y축의 값을 업로드 이미지의 넓이와 높이 음수로 변경한다.

               canvasContext.drawImage(this, (tempImage.width * -1), (tempImage.height * -1));


          }


          // @breif 정방향

          else {


               canvas.width = tempImage.width;

               canvas.height = tempImage.height;

               canvasContext.drawImage(this, 0, 0);

          }


          // @breif 캔버스의 이미지

          let dataURI = canvas.toDataURL("image/jpeg");

          document.querySelector("#thumbnail").src = dataURI;


     };

    }

</script>

</head>

<body>

    <!-- @breif accept 태그는 파일 업로드시 그것을 이미지 파일로 제한한다. -->

    <input type="file" id="upImgFile" onChange="uploadImgPreview();" accept="image/*">

    &nbsp;|&nbsp;

    <input type="button" onClick="rotateCanvasImg('270');" value="왼쪽(270°)"/>

    &nbsp;|&nbsp;

    <input type="button" onClick="rotateCanvasImg('90');" value="오른쪽(90°)"/>

    &nbsp;|&nbsp;

    <input type="button" onClick="rotateCanvasImg('180');" value="거꾸로(180°)"/>

    &nbsp;|&nbsp;

    <input type="button" onClick="uploadImgPreview();" value="되돌리기"/>

    <hr/>

    <img id="thumbnail" src="">

    <!-- @breif 캔버스는 화면에 노출시키지 않는다. -->

    <canvas id="canvas" style="display:none;"></canvas>

</body>

</html>




# 출력결과




이렇게 이미지 조작이 완료되었다면.


해당 미지를 마우스 우클릭으로 다운받아 보자.








다운받은 이미지는 index.jpg 라는 이름으로 생성되며


회전 정보가 표기되지 않는 0° CW 임을 알 수 있다.


그렇기에 해당 이미지를 <img> TAG를 사용해도 원하는 각도 조절이 가능하기에




사용자의 업로드한 사진의 이미지 축 보정 작업이 끝나고 사진 등록( 파일 업로드 )을 실행하면


편집된 캔버스의 작업내용을 서버에 전송하는 형태로 진행을 하면 된다.






관련포스팅#01 : [JavaScript] 이미지 파일 썸네일 생성하기

관련포스팅#02 : [JavaScript] Canvas를 통한 이미지 회전

관련포스팅#03 : [JavaScript] Canvas로 이미지 서버에 전송하기 - Sample

관련포스팅#04 : [jQuery] JCROP을 이용한 이미지 자르기 - Sample







반응형
//

[JavaScript] 업로드한 파일 Resizer 하여 화면에 출력시키기[JavaScript] 업로드한 파일 Resizer 하여 화면에 출력시키기

Posted at 2020. 3. 4. 07:34 | Posted in JavaScript & jQuery/JavaScript
반응형




업로드한 파일 리사이즈 하여 화면에 출력시키기




<html>

<head>

<title>:: JavaScript 캔버스 - 뷰 ::</title>

<style type="text/css">

table {

            border:1px solid #444444;

            border-collapse:collapse;

  }

table th {

            border:1px solid #444444;

            padding:5px 10px 5px 10px;

            text-align:center;

            font-weight:bold;

}

table td {

            border:1px solid #444444;

            padding:10px;

            text-align:center;

  }

</style>

<script type="text/javascript">


    function uploadImgPreview() {


        // @breif 업로드 파일 읽기

        let fileInfo = document.getElementById("upImgFile").files[0];

        let reader = new FileReader();


        // @details INDEX #01 실행 이후, 파일의 업로드( onload )가 확인되고 나서 실행된다.

        reader.onload = function() {


            console.log( "INDEX #02" );


            // @details 업로드한 파일의 URL을 가져온다.

            document.getElementById("preview").src = reader.result;


            // @breif 썸네일 이미지 생성

            let tempImage = new Image();    // @details drawImage 메서드에 넣기 위해 이미지 객체화

            tempImage.src = reader.result;    // @details data-uri를 이미지 객체에 주입


            tempImage.addEventListener("load", function() {


                // @breif 캔버스 위에 이미지 그리기

                let canvas = document.getElementById( "canvas" );

                let canvasContext = canvas.getContext( "2d" );

                // @breif 캔버스 크기 셋팅

                canvas.width = 240;

                canvas.height = 300;

                // @breif 캔버스 위에 이미지 그리기

                canvasContext.drawImage(

                  this // @details 업로드한 이미지 파일의 정보

                , -10 // @details X좌표

                , -10 // @details Y좌표

                , 270 // @details 넣을 이미지의 가로 사이즈( 해당 예제는 변화를 보기위해 살짝 크게 다. )

                , 330 // @details 넣을 이미지의 세로 사이즈( 해당 예제는 변화를 보기위해 살짝 크게 했다. )

                );

                

                // @breif 캔버스 위에 이미지 그리기

                canvasContext.stroke();

                

                // @breif 캔버스의 이미지 URL 정보를 받아 썸네일 출력

                let dataURI = canvas.toDataURL("image/jpeg");

                document.querySelector("#thumbnail").src = dataURI;

            });

        };


        if( fileInfo) {


            console.log( "INDEX #01" );


            // @details readAsDataURL을 통해 업로드한 파일의 URL을 읽어 들인다.

            reader.readAsDataURL(fileInfo);

        }

    }


</script>

</head>

<body>

     <!-- @breif accept 태그는 파일 업로드시 그것을 이미지 파일로 제한한다. -->

    <input type="file" id="upImgFile" onChange="uploadImgPreview();" accept="image/*">

    <hr/>

    <table>

<tr>

<th>업로드 이미지 출력</th>

<th>이미지 캔버스 출력</th>

</tr>

<tr>

<td rowspan="3"><img id="preview" src=""></td>

<td><canvas id="canvas"></canvas></td>

</tr>

<tr>

<th>캔버스 이미지 변환</th>

</tr>

<tr>

<td><img id="thumbnail" src=""></td>

</tr>

    </table>

</body>

</html> 







① 이미지 파일을 업로드 한다.


② 업로드한 이미지를 화면에 출력한다.


③ 지정한 캔버스 영역에 해당 이미지를 그대로 리사이징 하여 따라 그리는 작업을 수행한다.

    ( 이때 기본적으로 이미지는 *.png 파일로 생성된다. )


④ 마지막으로 캔버스의 이미지 파일을 그대로 다시 이미지로 출력시키는 작업을 수행한다.







사실 필자가 해당 글을 작성하게 된 경위는


[JavaScript] Canvas를 통한 이미지 회전 포스팅의 사전 준비 과정이었다.


캔버스를 통해 프론트 개발의 좀더 넓은 시각을 바라보고.


HTML5의 가능성에 대해서 좀더 알아봐야 겠다는 생각을 하고 있다.











반응형
//

[jQuery] load( ) 메소드를 이용한 외부 데이터의 페이지 반영[jQuery] load( ) 메소드를 이용한 외부 데이터의 페이지 반영

Posted at 2020. 3. 2. 19:03 | Posted in JavaScript & jQuery/jQuery
반응형



■ 새로고침 없이변경된 데이터 조회하기




Ajax 통신을 사용한 비동기 통신으로


웹 브라우저의 새로고침 없이 데이터를 조회하거나, 변경 및 이벤트를 실행하는 경우는 많이 보아 왔을 것이다.


또한 iframe을 통해 작업되어져 있는 다른 페이지의 정보를 가져오는 방식으로도


새로고침 없이 작업을 진행 할 수 있지만.



여기서 설명할 .load( ) 메소드는 Ajax와 iframe은 비슷한 기능을 수행하면서도, 좀 하위 호한의 느낌이 강하지만.


사용여부와 방법에따라서 직관적이고 단순한 사용의 장점이 있다.


단순히 가져올 데이터가 명확하다면 .load( ) 메소드는 큰 힘을 발휘 하게 된다.



 load_front.php

<html>

<head>

<title>:: jQuery load() 함수 ::</title>

<script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>

<script type="text/javascript">

jQuery(document).ready(function() {

backLoadAgainCall();

});


function backLoadAgainCall() {

jQuery(".output").load("load_back.php");

}

</script>

</head>

<body>

<input type="button" onClick="backLoadAgainCall();" value="재호출">

<hr/>

<div class="output"></div>

</body>

</html>




 load_back.php

<html>

<head>

<title>:: jQuery load() 함수 ::</title>

<style type="text/css">

#turnImg { transform:rotate(0deg); }

/* #turnImg { transform:rotate(90deg); } */

/* #turnImg { transform:rotate(180deg); } */

/* #turnImg { transform:rotate(270deg); } */

</style>

</head>

<body>

<img id="turnImg" src="joker.jpg"/>

</body>

</html>




코드를 다 작성했다면.


load_front.php 를 실행한다.


이후 load_back.php에서 #turnImg { transform : rotate ( 0deg ); } 를 


0 → 90 → 180 → 270 순서로 한번씩 변경하면서


브라우저의 재호출 버튼을 클릭해 보자.






load_front.php를 새로고침 하지 않고 load_back.php의 변경된 사항을 반영하여


이미지가 계속 회전하는 것을 확인 할 수 있다.


위와같이 jQuery의 .load( ) 를 사용하면


이미 만들어진 결과를 페이지의 새로고침 없이 가져올 수 있어.


경우의 따라서는 Ajax 호출과 구분하여 사용할 수 있다.













반응형
//

[Kotlin] Eclipse를 이용한 Kotlin 작업환경 구성[Kotlin] Eclipse를 이용한 Kotlin 작업환경 구성

Posted at 2020. 3. 1. 17:29 | Posted in Kotlin
반응형




■ 이클립스에서 코틀린 실행하기




01. https://www.eclipse.org/ 페이지에 접속하여 이클립스를 다운로드 받는다.





02. Eclipse Installer 화면이 나타나면 최 상단의 가장 기본이 되는

     Eclipse IDE for Java Developers 를 선택한다.





03. Eclipse를 설치하기에 앞서 컴퓨터에 JAVA가 먼저 설치되어 있어야 한다.

     설치한 JAVA의 JRE경로와 이클립스를 설치할 경로를 지정해 준다.





04. 설치가 진행되는중 License 관련 화면이 나타난다. Accept 버튼을 클릭하여 설치를 계속 진행한다.





05. Eclipse의 설치가 완료 되었다면 LAUNCH 버튼을 클릭한다.





06. 설치가 완료되면 작업을 진행할 프로젝트가 생성될 디렉토리를 지정한다.





07. Eclipse IDE의 설치가 완료되고 프로젝트를 생성했다면.

    이제 설치한 Eclipse에서 Kotlin을 사용할 수 있게 셋팅을 해보자.

※ 순서 : Help → Eclipse User Storage → Open Marketplace Favorites





08. Eclipse Marketplace가 실행되면 Kotlin을 검색하고 설치를 진행한다.





09. Kotlin 설치를 유무를 묻는다.

    I accept the terms of the license agreements 를 선택하고

    Finish 버튼을 클릭하여 설치를 진행한다.





10. 설치 진행중 Eclipse에서 정식으로 지원하는 소프트웨어가 아니라는 경고 문구가 나타난다.

    Install anyway를 눌러 설치를 계속 진행한다.





11. 설치가 완료되면 Eclipse를 재시작하라는 팝업창이 나타난다.

     Restart Now 버튼을 클릭하여 Eclipse를 재실행 한다.







※ 참고로 설치가 끝까지 안되거나, 재실행 여부를 묻지않는경우

   12번, 13번의 Kotline 퍼스펙티브 기능을 사용할 수 없다.

   이 경우 Eclipse를 강제로 종료하고 다시 7번부터 시작하여 작업을 진행해 보자.






12. Kotlin 작업을 위한 플러그인의 설치가 완료되었다면

     Eclipse에서 Kotlin 코드 작성 및 실행 작업이 가능해 진다.

     Kotlin 퍼스펙티브를 불러와서 작업환경 구성을 마무리 하자.

※ 순서 : Window → Perspective → Open Perspective → Other





13. Open Perspective 창이 팝업되면, Kotlin항목을 선택하고, 작업환경을 Open한다.





14. 작업을 진행할 준비가 모두 마무리 되었다면, 본격적으로 Kotlin 프로젝트를 생성해 보자.

※ 순서 : File → New Kotlin → Project





15. 시작할 프로젝트 명을 입력하고 Finish 버튼을 클릭하여, 프로젝트를 생성한다.





16. 프로젝트가 정상적으로 생성 되었다면, 아래 화면과 같은 프로젝트명과 

     그안에 관련 내용들이 카테고리 형태로 나타나는 것을 알 수 있다.





17. 이제 코틀린 ( *.kf ) 파일을 생성하고, 그 위에 코드를 작성해 보자.

 순서 : src → New Kotlin → File





18. Kotlin Source File 생성 팝업창이 나타나면

     생성할 코틀린 ( *.kf ) 파일의 이름 지정하고 Finish 버튼을 클릭한다.





19. 코드 입력창에 아래와 같이 입력을 해보자.

  fun main( args : Array < string > ) {

        println( "Hello Kotlin~!!" );

  }





20. 이제 작성한 코틀린 코드를 컴파일 해보자.

※ 순서 : Run → Run As → Kotlin Application






21. 컴파일 수행할 자바 런처의 실행과 그 결과의 저장 여부를 묻는다.

     OK 버튼을 클릭하여 작업을 계속 진행한다.






22. 그럼 Eclipse 화면 하단에 Console 영역에서 Println( ) 함수에 기입한 문구가 출력되는 것을 직접 확인 할 수 있다.











■ 사용 목적에 따른 이클립스 구분하기




한대의 컴퓨터에 Eclipse IDE는 한개 이상 n개로 컴퓨터가 허용하는한 구분하여 설치가 가능하다.


필자의 경우 자바 프로젝트와의 구분을 위해 Eclipse의 *.icon 파일을 변경하여 Kotlin 전용으로 따로 구분하여 사용하고 있다.





윈도우 환경에서 자바용 이클립스와 코틀린용 이클립스를 구분하여 사용하는건


Kotline.ico 파일을 첨부하여 두었으니 사용유무는 사용자의 센스에 맞긴다.





첨부파일 : kotlin.ico








반응형

'Kotlin' 카테고리의 다른 글

[Kotlin] 코틀린 프로젝트 시작하기  (0) 2020.04.27
[Kotlin] 코틀린이란?  (0) 2020.02.12
//