摘要:[Canvas]依據EXIF旋轉照片
之前有介紹過使用Canvas來將照片加上濾鏡的效果,可以讓照片有不同的樂趣。另一個會遇到的場景,則是使用Canvas來將橫的或上下顛倒的照片旋轉成正確的方向。
之前有介紹過使用Canvas來將照片加上濾鏡的效果-使用Canvas處理濾鏡效果,可以讓照片有不同的樂趣。另一個會遇到的場景,則是使用Canvas來將橫的或上下顛倒的照片旋轉成正確的方向。
會有這種需求,是因為在隨手使用智慧型手機拍照時,大家都會隨手地以各種方向拍照。大多數的智慧型手機中有陀螺儀,所以也就會把照片的轉置角度資訊記錄在照片的EXIF中。
而一般的照片檢視器會依據EXIF將照片轉正,但是,透過HTML的img
來顯示照片時,卻無法自動轉正。透過Canvas的rotate
功能,就可以讓我們依據需求對照片進行旋轉。
取得照片的EXIF資訊
要取得照片的EXIF,可以透過這一個套件-Github-exif-js,它也可以透過npm下載-exif-js on npm。使用方式很簡單,在網頁的Head
區塊先載入exif.js,然後就可以使用EXIF.getData()
取得照片的EXIF資訊,或是使用EXIF.getTag()
取得EXIF中某個屬性,例如Orientation的資訊。
EXIF.getData(document.getElementById('imgElement'), function(){
EXIF.getAllTags(this);
EXIF.getTag(this, 'Orientation');
});
Orientation總共有8個值:1~8,在JPEGClud的網頁-Exif Orientation中詳細的說明。
其中有四個值是鏡像翻轉,所以不需要處理。Orientation為1的話,就是沒有翻轉,所以也不需要處理。因此,只需要處理3,6,8這三個狀況就可以了。
使用Canvas旋轉照片
在Canvas上要旋轉圖片,只要執行Context.rotate()
這個function就可以了。不過要注意到,因為圖片的旋轉是依據座標的原點進行旋轉。預設的旋轉座標原點是在畫布的(0,0)的位置,所以旋轉之後,整個圖片的位置會跑掉。所以在旋轉之前,先要把座標圓點設定在圖片的中央,再進行rotate()
。使用Context.drawImage()
時,還要注意到座標原點要設定回去。
var x = canvas.width / 2;
var y = canvas.height / 2;
var width = image.width;
var height = image.height;
context.translate(x, y);
context.rotate(angleInRadians);
context.drawImage(image, -width / 2, -height / 2, width, height);
完整的Example列出如下:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://raw.githubusercontent.com/exif-js/exif-js/master/exif.js"></script>
<script>
var ImageHelper = {
resizeAndRotateImage: function(inImageSource,inMaxLength,inSuccessCallback){
var reader = new FileReader();
reader.readAsDataURL(inImageSource);
reader.onload = function(e){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
var img = new Image();
img.onload = function () {
//設定長邊上限值
var max_Length = inMaxLength;
var imgWidth = img.width;
var imgHeight = img.height;
if (imgWidth > imgHeight) {
if (imgWidth > max_Length) {
imgHeight = Math.round(imgHeight *= max_Length / imgWidth);
imgWidth = max_Length;
}
} else {
if (imgHeight > max_Length) {
imgWidth = Math.round(imgWidth *= max_Length / imgHeight);
imgHeight = max_Length;
}
}
canvas.width = imgWidth;
canvas.height = imgHeight;
var that = this;
EXIF.getData(img, function(){
var orientation = EXIF.getTag(that, 'Orientation');
alert(orientation);
if(orientation == 6 || orientation == 8|| orientation == 3)
{
var rotateAngle = 0;
switch(orientation){
case 3:
rotateAngle = 180;
break;
case 6:
rotateAngle = 90;
canvas.width = imgHeight;
canvas.height = imgWidth;
break;
case 8:
rotateAngle = -90;
canvas.width = imgHeight;
canvas.height = imgWidth;
break;
}
var x = canvas.width / 2;
var y = canvas.height / 2;
ctx.translate(x, y);
ctx.rotate(rotateAngle*Math.PI/180);
ctx.drawImage(img, (-imgWidth / 2), (-imgHeight / 2), imgWidth, imgHeight);
}
else
{
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
}
});
var res = canvas.toDataURL("image/jpeg", 1.0);
inSuccessCallback(res);
};
img.src = e.target.result;
};
}
};
function previewImage() {
var file = document.getElementById("uploadImage").files[0];
ImageHelper.resizeAndRotateImage(file,400,function(resizeImageObj){
$("#preview").attr("src",resizeImageObj);
});
}
</script>
</head>
<body>
<input type="file" id="uploadImage" onchange="previewImage()">
<hr/>
<img id="preview" />
</body>
</html>