서버에 업로드하기 전에 JavaScript로 클라이언트 측 크기 조정


147

JavaScript로 이미지 클라이언트 측의 크기를 조정하는 방법을 찾고 있습니다 (폭과 높이 만 변경하는 것이 아니라 실제로 크기 조정).
플래시에서 할 수 있다는 것을 알고 있지만 가능하면 피하고 싶습니다.

웹 어딘가에 오픈 소스 알고리즘이 있습니까?


아직도 이것에 대한 답을 알고 싶은 분은 할 수 있지만 이미지 처리를 위해 아약스 호출을해야합니다.
다면체

1
'만들어야합니까?' 결국 서버에서 해결할 수 있으며 AJAX 호출을 통해 투명하게 데이터를 얻을 수 있습니다. 그러나 전체 시도는 클라이언트 측에서 수행하는 것이며, Jeremy는 CAN이 수행 할 수 있다고 지적했습니다. 나는이 좋은 예라고 생각합니다 : github.com/rossturner/HTML5-ImageUploader
바트

2
최신 버전 인 Dropzone.js는 업로드 전에 클라이언트 측 이미지 크기 조정을 지원합니다.
user1666456

답변:


111

다음은이 수행하는 요지는 다음과 같습니다 https://gist.github.com/dcollien/312bce1270a5f511bf4a

(es6 버전 및 스크립트 태그에 포함될 수있는 .js 버전)

다음과 같이 사용할 수 있습니다.

<input type="file" id="select">
<img id="preview">
<script>
document.getElementById('select').onchange = function(evt) {
    ImageTools.resize(this.files[0], {
        width: 320, // maximum width
        height: 240 // maximum height
    }, function(blob, didItResize) {
        // didItResize will be true if it managed to resize it, otherwise false (and will return the original file as 'blob')
        document.getElementById('preview').src = window.URL.createObjectURL(blob);
        // you can also now upload this blob using an XHR.
    });
};
</script>

그것은 내가 지원 할 수있는 한 많은 브라우저에서 작동하도록 많은 지원 감지 및 polyfill을 포함합니다.

(또한 애니메이션 이미지 인 경우 GIF 이미지는 무시합니다)


2
나는 당신이 이것에 대해 거의 칭찬을받지 못한 것처럼 느낍니다-나는 그것이 훌륭하게 작동하고 매우 쉽다고 생각합니다. 공유해 주셔서 감사합니다!
Matt

4
흠 .. 나는 이것으로 성공적으로 성공했지만 크기가 조정되는 것 외에도 이미지가 올바른 해상도로 출력되었지만 (화소 픽셀 화의 형태로) 품질이 크게 저하되는 것을 발견했습니다.
Ruben Martinez Jr.

1
안녕하세요, 이처럼 사용할 수있는 스 니펫이 필요합니다. 매우 훌륭하다고 생각합니다 .. function (blob, didItResize) {// 크기를 조정할 수 있으면 didItResize가 true이고 그렇지 않으면 false입니다 (원본을 반환합니다) 파일을 'blob') document.getElementById ( 'preview'). src = window.URL.createObjectURL (blob); // 이제 XHR을 사용하여이 Blob을 업로드 할 수도 있습니다. 여기에 문제가 있습니다. 양식을 제출하여이 이미지를 양식으로 보내려면 어떻게해야합니까? 제출 버튼으로 트리거 된 게시물 요청과 같습니다. 알다시피, 일반적인 방법입니다. 요점 감사합니다!
iedmrc

3
품질 (리샘플링)의 손실이 누군가를 위해, 세트에 캔버스 컨텍스트 업데이트 imageSmoothingEnabledTRUE '같은과 imageSmoothingQuality에를 high. 타입 스크립트에서 블록은 다음과 같습니다 : const ctx = canvas.getContext('2d'); ctx.imageSmoothingEnabled = true; (ctx as any).imageSmoothingQuality = 'high'; ctx.drawImage(image, 0, 0, width, height);
Sean Perkins

1
이 패키지를 npm 패키지로 만들 가능성이 있습니까? 슈퍼 대단 할 것입니다!
erksch

62

이에 대한 대답은 예입니다. HTML 5에서는 canvas 요소를 사용하여 클라이언트 쪽 이미지의 크기를 조정할 수 있습니다. 새 데이터를 가져 와서 서버로 보낼 수도 있습니다. 이 튜토리얼을 참조하십시오 :

http://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/


28
이것은 링크 전용 답변 이므로 의견이어야합니다.
Jimbo

2
canvas.mozGetAsFile ( "foo.png"); 더 이상 사용되지 않는 함수입니다
mili

12

업로드하기 전에 크기를 조정 한 경우 http://www.plupload.com/을 발견했습니다 .

상상할 수있는 방법으로 모든 마법을 수행합니다.

불행히도 HTML5 크기 조정은 Mozilla 브라우저에서만 지원되지만 다른 브라우저를 Flash 및 Silverlight로 리디렉션 할 수 있습니다.

방금 시도해 보았고 안드로이드로 작동했습니다!

플래시에서 http://swfupload.org/ 를 사용 하고 있었지만 작업이 잘 수행되지만 크기 조정 크기는 매우 작습니다. (한도를 기억할 수 없음) 플래시를 사용할 수없는 경우 html4로 돌아 가지 않습니다.


44
사용자가 훨씬 작은 사진으로 만 저장 될 10MB 사진을 업로드하려고 할 때 클라이언트 측 크기 조정을 수행하는 것이 좋습니다. 이 방법으로 훨씬 빠르게 업로드됩니다.
Kyle

파일 입력이 있고 사용자가 스마트 폰을 사용하고 카메라를 사용하여 이미지를 스냅하자마자 동일한 시나리오는 최신 스마트 폰에서 약 10MB가됩니다. 어쨌든 서버 쪽에서 크기를 조정하고 훨씬 작은 버전 만 저장하는 경우 클라이언트에서 미리 크기 조정을 수행 할 때 많은 셀룰러 데이터와로드 시간을 절약 할 수 있습니다.
Alex

1
plupload는 AGPL이므로주의하십시오.
Alex

11

http://nodeca.github.io/pica/demo/

최신 브라우저에서는 캔버스를 사용하여 이미지 데이터를로드 / 저장할 수 있습니다. 그러나 클라이언트에서 이미지 크기를 조정하는 경우 몇 가지 사항을 명심해야합니다.

  1. 채널당 8 비트 만 있습니다 (jpeg는 약 12 ​​비트의 더 나은 동적 범위를 가질 수 있음). 전문적인 사진을 업로드하지 않아도 문제가되지 않습니다.
  2. 크기 조정 알고리즘에주의하십시오. 대부분의 클라이언트 측 리사이 저는 사소한 수학을 사용하므로 결과가 예상보다 나쁩니다.
  3. 축소 된 이미지를 선명하게해야 할 수도 있습니다.
  4. 원본의 메타 데이터 (exif 및 기타)를 재사용하려면 색상 프로파일 정보를 제거해야합니다. 이미지를 캔버스에로드 할 때 적용되기 때문입니다.

6

아마도 canvas 태그를 사용했을 것입니다 (휴대용이 아니지만). 캔버스로 이미지를 회전시키는 방법에 대한 블로그가 있습니다. , 당신이 그것을 회전 수 있다면, 당신은 크기를 조정할 수 있다고 생각. 아마도 시작점이 될 수 있습니다.

이 라이브러리 도 참조하십시오 .


2
매우 유용한 예. 링크가 끊어 질 경우 답변에 스 니펫을 추가 할 수도 있습니다.
Trevor

4

이미지를 서버에 업로드하기 전에 클라이언트 측 이미지 처리에 자바 스크립트 이미지 처리 프레임 워크를 사용할 수 있습니다.

아래에서 MarvinJ 를 사용하여 다음 페이지의 예제를 기반으로 실행 가능한 코드를 만들었습니다. "이미지를 서버에 업로드하기 전에 클라이언트 측에서 이미지 처리"

기본적으로 Marvin.scale (...) 메서드 를 사용하여 이미지 크기를 조정합니다. 그런 다음 image.toBlob () 메소드를 사용하여 이미지를 blob으로 업로드합니다 . 서버는 수신 된 이미지의 URL을 제공하여 응답합니다.

/***********************************************
 * GLOBAL VARS
 **********************************************/
var image = new MarvinImage();

/***********************************************
 * FILE CHOOSER AND UPLOAD
 **********************************************/
 $('#fileUpload').change(function (event) {
	form = new FormData();
	form.append('name', event.target.files[0].name);
	
	reader = new FileReader();
	reader.readAsDataURL(event.target.files[0]);
	
	reader.onload = function(){
		image.load(reader.result, imageLoaded);
	};
	
});

function resizeAndSendToServer(){
  $("#divServerResponse").html("uploading...");
	$.ajax({
		method: 'POST',
		url: 'https://www.marvinj.org/backoffice/imageUpload.php',
		data: form,
		enctype: 'multipart/form-data',
		contentType: false,
		processData: false,
		
	   
		success: function (resp) {
       $("#divServerResponse").html("SERVER RESPONSE (NEW IMAGE):<br/><img src='"+resp+"' style='max-width:400px'></img>");
		},
		error: function (data) {
			console.log("error:"+error);
			console.log(data);
		},
		
	});
};

/***********************************************
 * IMAGE MANIPULATION
 **********************************************/
function imageLoaded(){
  Marvin.scale(image.clone(), image, 120);
  form.append("blob", image.toBlob());
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.marvinj.org/releases/marvinj-0.8.js"></script>
<form id="form" action='/backoffice/imageUpload.php' style='margin:auto;' method='post' enctype='multipart/form-data'>
				<input type='file' id='fileUpload' class='upload' name='userfile'/>
</form><br/>
<button type="button" onclick="resizeAndSendToServer()">Resize and Send to Server</button><br/><br/>
<div id="divServerResponse">
</div>


이것은 굉장해 보인다!
pimbrouwers

2

예, 최신 브라우저에서는 완전히 가능합니다. 캔버스를 여러 번 변경하여 파일을 바이너리 파일로 업로드하는 시점까지 가능합니다.

http://jsfiddle.net/bo40drmv/

(이 답변은 여기 에서 허용되는 답변의 개선입니다 )

PHP에서 다음과 유사한 결과 제출 프로세스를 잡는 것을 명심하십시오.

//File destination
$destination = "/folder/cropped_image.png";
//Get uploaded image file it's temporary name
$image_tmp_name = $_FILES["cropped_image"]["tmp_name"][0];
//Move temporary file to final destination
move_uploaded_file($image_tmp_name, $destination);

Vitaly의 요점이 걱정된다면 작동하는 jfiddle에서 자르기 및 크기 조정을 시도해 볼 수 있습니다.


0

내 경험에 따르면이 예제는 크기가 조정 된 사진을 업로드하는 가장 좋은 솔루션입니다. https://zocada.com/compress-resize-images-javascript-browser/

HTML5 Canvas 기능을 사용합니다.

코드는 다음과 같이 '단순'합니다.

compress(e) {
    const fileName = e.target.files[0].name;
    const reader = new FileReader();
    reader.readAsDataURL(e.target.files[0]);
    reader.onload = event => {
        const img = new Image();
        img.src = event.target.result;
        img.onload = () => {
                const elem = document.createElement('canvas');
                const width = Math.min(800, img.width);
                const scaleFactor = width / img.width;
                elem.width = width;
                elem.height = img.height * scaleFactor;

                const ctx = elem.getContext('2d');
                // img.width and img.height will contain the original dimensions
                ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);
                ctx.canvas.toBlob((blob) => {
                    const file = new File([blob], fileName, {
                        type: 'image/jpeg',
                        lastModified: Date.now()
                    });
                }, 'image/jpeg', 1);
            },
            reader.onerror = error => console.log(error);
    };
}

이 옵션에는 단점이 하나 있으며 EXIF ​​데이터를 무시하기 때문에 이미지 회전과 관련이 있습니다. 내가 지금하고있는 중입니다. 완료되면 업데이트됩니다.

또 다른 단점은 IE / Edge 지원이 부족하다는 것입니다. 위의 링크에 정보가 있지만. 두 가지 문제 모두.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.