[jQuery] 웹상에서 이미지 업로드 하고 자르기[jQuery] 웹상에서 이미지 업로드 하고 자르기

Posted at 2020. 2. 11. 13:29 | Posted in JavaScript & jQuery/jQuery




Jcrop 다운 : http://deepliquid.com/content/Jcrop.html





■ JCROP을 이용한 이미지 업로드하고 크롭하기





웹 사이트 운영중 프로필 사진등을 올리기 위해 이미지를 자르는 것을 크롭( CROP ) 이라고 하는데.


단순히 이미지를 자르기만 하고 끝내는 것은 실제 운영중에 일어날 일이 없다 시피 하기에


이 포스팅에서는 이미지를 업로드하고 올린 이미지를 바로 잘라내는 부분까지


샘플로 제작을 해보려고 한다.




# 파일구조 - Jcrop 샘플에서 다운받은 css, js 파일을 위치시킨다.









# 소스코드 - AJAX 통신을 통한 이미지 업로드 및 JCROP 으로 이미지 자르기

 select_cut.php

<html>

<head>

<title>:: jQuery 이미지 크롭 ::</title>

<link type="text/css" rel="stylesheet" href="./css/jquery.Jcrop.css"/>

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

<script type="text/javascript" src="./js/jquery.Jcrop.js"></script>

<script type="text/javascript">


    // @breif jcrop을 사용하기 위한 변수 선언

    let jcropApi = null;


    // @breif jcrop을 실행한다.

    function jcorpImgStart() {

        jQuery("#thumbnailImg").Jcrop({

              aspectRatio : 0

            , onSelect : updateCoords // @breif 함수 호출

        }, function() {


            // @details 실행한 jcrop을 전역변수 jcropApi에 담는다.

            jcropApi = this;

        });

    }


    // @breif ajax를 통한 파일 업로드 기능 함수

    function ajaxFileUpload() {


        let form = jQuery("#ajaxForm")[0];

        let formData = new FormData(form);

        formData.append("mode", "imageUpload");

        formData.append("file", jQuery("#ajaxFile")[0].files[0]);


        // @breif ajax 이미지 업로드

        jQuery.ajax({

              url : "./upload_image.php"

            , type : "POST"

            , processData : false

            , contentType : false

            , data : formData

            , success:function(json) {

                let obj = JSON.parse(json);

                if(obj.ret == "succ") {


                    // @details 이미지 업로드 경로와 이미지 파일의 이름을 바탕으로 업로드한 이미지를 화면에 띄운다.

                    jQuery("#thumbnailImg").attr("src", obj.imgSrc + "/" + obj.imgFile);

                    jQuery("#thumbnailImg").css("display", "inline");


                    // @details 업로드한 이미지의 정보를 input에 담는다.

                    jQuery("#imgSrc").val(obj.imgSrc);

                    jQuery("#imgFile").val(obj.imgFile);


                    // @breif jcrop을 실행한다.

                    jcorpImgStart();


                } else {

                    alert(obj.message);

                    return false;

                }

            }

        });

    }


    // @breif jcrop 위치값 저장

    function updateCoords(crap) {


        // @detail jcrop 이벤트를 실행할 때마다 좌표 및 높이, 넓이의 값을 input에 담는다.

        jQuery("#xAxis").val(crap.x);

        jQuery("#yAxis").val(crap.y);

        jQuery("#wLength").val(crap.w);

        jQuery("#hLength").val(crap.h);

    }


    // @breif jcrop 위치값 저장

    function checkCoords() {


        // @detail 넓이값이 존재하는지 확인 jcrop 이벤트를 실행하기 위해

        if(parseInt(jQuery("#wLength").val())) {

            jQuery.ajax({

                  url : "./upload_image.php"

                , type : "POST"

                , async : false

                , data : {

                      mode : "cropImage"

                    , imgFile : jQuery("#imgFile").val()

                    , xAxis : jQuery("#xAxis").val()

                    , yAxis : jQuery("#yAxis").val()

                    , wLength : jQuery("#wLength").val()

                    , hLength : jQuery("#hLength").val()

                }

                , success : function(json) {

                    let obj = JSON.parse(json);

                    alert(obj.message);

                    if(obj.ret == "succ") {


                        // @breif jcrop을 종료한다.

                        jcropApi.destroy();

                        jcropApi = null;


                        // @breif 원본 이미지를 자른 이미지로 대체한다.

                        jQuery("#thumbnailImg").removeAttr("style");

                        jQuery("#thumbnailImg").attr("src", obj.imgsrc);

                    }

                }

            });

        } else {

            alert("자르기 영역을 선택한 다음 자르기 버튼을 클릭하세요.");

            return false;

        }

    }


    // @breif 자른 이미지를 원본 이미지로 되돌린다.

    function reloadUploadImg() {


        jQuery("#thumbnailImg").removeAttr("style");

        jQuery("#thumbnailImg").attr("src", jQuery("#imgSrc").val() + "/" + jQuery("#imgFile").val());


        // @details 이미지를 되돌리고 jcrop을 재실행

        jcorpImgStart();

    }

</script>

</head>

<body>


    <!-- @breif crop 한 이미지의 정보 -->

    <input type="hidden" id="imgSrc" value="" placeholder="업로드된_이미지_파일의_경로"/>

    <input type="hidden" id="imgFile" value="" placeholder="업로드된_이미지_파일의_이름"/>

    <input type="hidden" id="xAxis" value="" placeholder="선택영여역의_x좌표"/>

    <input type="hidden" id="yAxis" value="" placeholder="선택영여역의_y좌표"/>

    <input type="hidden" id="wLength" value="" placeholder="선택영여역의_w넓이"/>

    <input type="hidden" id="hLength" value="" placeholder="선택영여역의_h높이"/>


    <!-- @breif 파일업로드를 위한 Form 지정 -->

    <form id="ajaxForm" method="post">

        <input type="file" id="ajaxFile"/>

        <input type="button" onClick="ajaxFileUpload();" value="업로드"/>

    </form>


    <hr/>

    <img id="thumbnailImg" src="" style="display:none;"/>

    <hr/>


    <input type="button" onClick="checkCoords();" value="자르기"/>

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

</body>

</html>






# 소스코드 - 원본 이미지 및 오려낸 이미지 저장

 upload_image.php

<?php

$RetVal = array("ret"=>"fail", "error"=>"", "error_msg"=>"", "message"=>"");

$backUrl = $_SERVER['HTTP_REFERER'];


// @breif php://input은 내용의 유형에 관계없이 요청 HTTP 헤더 뒤에 모든 원시 데이터를 반환한다.

$data = json_decode(file_get_contents("php://input"), true);


// @breif 업로드할 이미지 경로

$uploadSrc = "./upload";


// @breif 업로드 가능한 확장자 지정

$allowedExe = array("jpg", "JPG", "jpeg", "JPEG", "png", "PNG", "gif", "GIF");


switch($_POST['mode']) {


    // @breif ajax 이미지 업로드

    case "imageUpload" :


        // @breif 파일명과 확장자를 분리 하여 담는다.

        $fileName = array_shift(explode(".", $_FILES['file']['name'])); // @details 이미지 파일 이름

        $fileExe = array_pop(explode(".", $_FILES['file']['name']));    // @details 이미지 파일 확장자


        // @breif 업로드 가능한 확장자 인지 확인한다.

        if(in_array($fileExe, $allowedExe)) {


            // @breif 업로드할 파일의 경로 지정하고, 파일명을 변경한다.

            $uploadFile = $fileName."_".time().".".$fileExe;


            // @breif 임시파일을 지정한 경로에 업로드 한다.

            if(move_uploaded_file($_FILES['file']['tmp_name'], $uploadSrc."/".$uploadFile)) {

                $RetVal['imgSrc'] = $uploadSrc;

                $RetVal['imgFile'] = $uploadFile;

                $RetVal['ret'] = "succ";

            } else {

                $RetVal['message'] = "업로드시 문제가 발생하였습니다.\n다시 시도하여 주시기 바랍니다.";

            }

        } else {

            $RetVal['message'] = "허용되지 않는 확장자입니다.";

        }


        print json_encode($RetVal);

        return;

    break;


    case "cropImage" :


        $targ_w = "150";              // @details 변환할 이미지의 넓이 ( px )

        $targ_h = "150";              // @details 변환할 이미지의 높이 ( px )

        $img_quality = "100";        // @details 변환할 이미지의 품질을 지정 ( % 퍼센트 )


        // @breif 업로드된 원본 이미지의 경로

        $uploadSrc = $uploadSrc."/".$_POST['imgFile'];


        // @breif 새로 저장할 이미지의 경로

        // @details 파일은 해당 예제는 jpg로 저장 한다.

        $imageSrc = "./img/".array_shift(explode(".", $_POST['imgFile'])).".jpg";


        $img_r = null;


        // @breif 이미지 파일의 확장자를 바탕으로 switch문을 실행한다.

        switch(array_pop(explode(".", $_POST['imgFile']))) {


            // @details 이미지 파일이 jpg, jpeg 인경우

            case "jpg" : case "JPG" : case "jpeg" : case "JPEG" :

                $img_r = imagecreatefromjpeg($uploadSrc);

            break;


            // @details 이미지 파일이 png 인경우

            case "png" : case "PNG" :

                $img_r = imagecreatefrompng($uploadSrc);

            break;


            // @details 이미지 파일이 gif 인경우

            case "gif" : case "GIF" :

                $img_r = imagecreatefromgif($uploadSrc);

            break;

        }


        $dst_r = imageCreateTrueColor($targ_w, $targ_h);


        imagecopyresampled(

              $dst_r                   // @details 이미지의 높이와 너비를 인자로 받아서 캔버스 생성

            , $img_r                  // @details 원본 이미지 파일의 위치

            , 0                         // @details 대상 점의 x좌표 ( 최상단 좌측을 지정 )

            , 0                         // @details 대상 점의 y좌표 ( 최상단 좌측을 지정 )

            , $_POST['xAxis']       // @details 크롭한 이미지의 x좌표

            , $_POST['yAxis']       // @details 크롭한 이미지의 y좌표

            , $targ_w                // @details 변환할 이미지의 넓이

            , $targ_h                 // @details 변환할 이미지의 높이

            , $_POST['wLength']   // @details 크롭한 이미지 영역의 넓이

            , $_POST['hLength']   // @details 크롭한 이미지 영역의 높이

        );


        // @breif 업로드된 이미지를 확인하려면

        // header("Content-Type:image/jpeg");

        // imagejpeg($dst_r, null, $jpeg_quality);


        imagejpeg($dst_r, $imageSrc, $jpeg_quality);

        // @details imagejpeg() 대신 imagepng(), imagegif() 사용 가능


        // @breif 이미지가 업로드 되어 있다면 실행

        if(file_exists($imageSrc) == true) {


            // @breif 이미지를 삭제한다.

            // imagedestroy($uploadSrc);


            $RetVal['imgsrc'] = $imageSrc;

            $RetVal['message'] = "자른 이미지를 저장하였습니다.";

            $RetVal['ret'] = "succ";


        } else {

            $RetVal['message'] = "이미지를 크롭하는데 실패하였습니다.\n다시 시도하여 주시기 바랍니다.";

        }


        print json_encode($RetVal);

        return;


    break;


    default :

    $RetVal['message'] = "데이터 조회 실패";

    print json_encode($RetVal);

        return;


    break;

}


header("location:".$backUrl);

?>





# 출력결과




위와같이 원하는 이미지를 하나 자르고,


올린 이미지에서 원한는 영역을 클릭해서 잘라내는 것을 확인 할 수 있다.


해당 예제에서 신경써야 하는 부분은.


CSS의 Style을 통한 width, height를 통해 이미지를 노출시키고


노출 시킨 이미지를 오려내면 원하는 위치가 잘리지 않는다는 것이다.


실제 사용을 하려면 업로드 하는 이미지의 크기를 Style롤 지정하는 것이 아니기에


해결하이기 위해서는 업로드를 하면서 resizing을 같이 진행을 해야 한다는는것이다.






Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기