2017-03-07 68 views
1

我在我的網站上有一個裁剪工具,用戶可以上傳圖片並剪裁。jcrop:實現EXIF方向

每當我上傳手機拍攝的圖片時,我都會遇到圖片方​​向錯誤。

HTML

<div class="modal-body"> 

      @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "formAjax", enctype = "multipart/form-data", action = "/ProfilePicture/Crop" })) 
      { 
       @Html.AntiForgeryToken() 

       <label> Upload Photo: </label> 
       <label class="btn btn-default btn-file"> 
        Browse @Html.TextBoxFor(ModelIndex => ModelIndex.ProfilePic.MyFile, new { id = "file", type = "file", style = "display: none;" }) 
       </label> 

       <br /><br /> 
       <div id="crop-image-area" style="display:none;"> 
        <table border="0" cellpadding="0" cellspacing="5"> 
         <tr> 
          <td> 
           <label>Preview: </label> 
           <div class="img-circle" style="width:100px;height:100px;overflow:hidden;margin-left:5px;"> 
            <canvas id="preview"></canvas> 
           </div> 
           <br /> 
          </td> 
         </tr> 
         <tr> 
          <td> 
           <label>Crop Here: </label> 
           <img src="" id="cropbox" style="display: none;"> 
          </td> 
         </tr> 
        </table> 
        <br /> 

        <input type="hidden" id="cropPointX" name="cropPointX" /> 
        <input type="hidden" id="cropPointY" name="cropPointY" /> 
        <input type="hidden" id="imageCropWidth" name="imageCropWidth" /> 
        <input type="hidden" id="imageCropHeight" name="imageCropHeight" /> 
        <span> 
         <input type="submit" id="btnCrop" class="btn btn-success" value="Crop" /> 
         <label> 
          <img id="loader" src="~/Content/images/loading.gif" style="display:none;" /> 
         </label> 
        </span> 
       </div> 

      } 
</div> 

JS

$(function() { 
    var jcrop_api; 

    $("#file").change(function() { 
     var reader = new FileReader(); 
     reader.onload = function(e) { 
      $('#cropbox').show(); 
      $('#cropbox').attr('src', e.target.result); 
      $('#cropbox').Jcrop({ 
       onChange: updatePreview, 
       onSelect: getcroparea, 
       boxWidth: 400, 
       boxHeight: 400, 
       aspectRatio: 1, 
       bgOpacity: .4, 
       setSelect: [80, 45, 100, 100] 
      }, function() { 
       //first attempt 
       if (jcrop_api != null) { 
        jcrop_api.destroy(); 
       } 
       //second attempt - even this does not work 
       $(".jcrop-holder").not(":last").remove(); 
       jcrop_api = this; 
      }); 

      $("#crop-image-area").hide(); 
      $("#crop-image-area").fadeIn("slow"); 

     } 
     reader.readAsDataURL($(this)[0].files[0]); 
     if ($('#cropbox').data('Jcrop')) { 
      $('#cropbox').data('Jcrop').destroy(); 
      $('#cropbox').removeAttr('style'); 
     } 

    }); 

    function updatePreview(c) { 
     if (parseInt(c.w) > 0) { 
      var imageObj = jQuery("#cropbox")[0]; 
      var canvas = jQuery("#preview")[0]; 
      var context = canvas.getContext("2d"); 
      context.beginPath(); 
      context.arc(50, 50, 50, Math.PI * 4, 0, true); 
      context.clip(); 
      context.closePath(); 
      context.drawImage(imageObj, c.x, c.y, c.w, c.h, 0, 0, 100, 100); 
     } 
    }; 

    function getcroparea(c) { 

     imageCropWidth = c.w; 
     imageCropHeight = c.h; 
     cropPointX = c.x; 
     cropPointY = c.y; 

     $('#cropPointX').val(Math.round(cropPointX)) 
     $('#cropPointY').val(Math.round(cropPointY)) 
     $('#imageCropWidth').val(Math.round(imageCropWidth)) 
     $('#imageCropHeight').val(Math.round(imageCropHeight)) 
    } 

    function destroyCrop() { 
     var jcropApi = $('#cropbox').data('Jcrop'); 
     if (jcropApi !== undefined) { 
      jcropApi.destroy(); 
      $('#cropbox').attr('style', "").attr("src", ""); 
     } 
    } 

    function destroyPreview() { 
     $('#preview').removeAttr('src'); 
    } 

    function cropImage() { 

     $("#loader").show(); 
     $('#formAjax').ajaxSubmit({ 
      type: 'POST', 
      success: function(result) { 
       $("#loader").hide(); 
       $('#myProfilePicModal').modal('hide'); 
       $("#crop-image-area").fadeOut("slow"); 
       destroyCrop(); 
       destroyPreview(); 
       $("#alert-success").show(); 
       $('#newImage').attr('src', 'data:image;base64,' + result.Photo); 
       $('.img-avatar').attr('src', 'data:image;base64,' + result.Avatar); 
       setTimeout(function() { 
        $("#alert-success").hide(); 
       }, 5000); 
      }, 
      error: function() { 
       $("#loader").hide(); 
       $('#myProfilePicModal').modal('hide'); 
       $("#crop-image-area").fadeOut("slow"); 
       destroyCrop(); 
       destroyPreview(); 
       $("#alert-fail").show(); 
       setTimeout(function() { 
        $("#alert-fail").hide(); 
       }, 5000); 
      } 
     }); 
    } 
    $("#btnCrop").on("click", function(e) { 
     e.preventDefault(); 
     cropImage(); 
    }); 
}); 

我不熟悉的EXIF方向請幫我實現它在我的代碼。

回答

0

我認爲你的意思是你想從上傳的圖片中提取EXIF數據,然後旋轉圖片,使它始終處於某個位置。 對我而言,圖像會發生什麼變得相當不清楚,比如說我用手機上傳橫向模式下的照片會顛倒照片嗎?當我上傳使用portret模式製作的照片時會發生什麼情況?因爲我不知道這些信息,我無法爲您創建完整的代碼,但我可以幫助您順利完成任務。

這是從客戶端的圖像中提取EXIF數據的代碼片段。這會在有人向輸入文件添加圖像時觸發。這段代碼是由用戶提出:https://stackoverflow.com/users/893432/ali

function getOrientation(file, callback) { 
 
    var reader = new FileReader(); 
 
    reader.onload = function(e) { 
 

 
    var view = new DataView(e.target.result); 
 
    if (view.getUint16(0, false) != 0xFFD8) return callback(-2); 
 
    var length = view.byteLength, offset = 2; 
 
    while (offset < length) { 
 
     var marker = view.getUint16(offset, false); 
 
     offset += 2; 
 
     if (marker == 0xFFE1) { 
 
     if (view.getUint32(offset += 2, false) != 0x45786966) return callback(-1); 
 
     var little = view.getUint16(offset += 6, false) == 0x4949; 
 
     offset += view.getUint32(offset + 4, little); 
 
     var tags = view.getUint16(offset, little); 
 
     offset += 2; 
 
     for (var i = 0; i < tags; i++) 
 
      if (view.getUint16(offset + (i * 12), little) == 0x0112) 
 
      return callback(view.getUint16(offset + (i * 12) + 8, little)); 
 
     } 
 
     else if ((marker & 0xFF00) != 0xFF00) break; 
 
     else offset += view.getUint16(offset, false); 
 
    } 
 
    return callback(-1); 
 
    }; 
 
    reader.readAsArrayBuffer(file); 
 
} 
 

 
// usage: 
 
var input = document.getElementById('input'); 
 
input.onchange = function(e) { 
 
    getOrientation(input.files[0], function(orientation) { 
 
    alert('orientation: ' + orientation); 
 
    }); 
 
}
<input id='input' type='file' />

這個片段會從圖片中提取EXIF數據是否包含了EXIF數據,響應值就可以得到有這些:

-2: not jpeg 
-1: not defined 

因此,當它不是JPEG格式時,如果沒有圖片,您將得到-2。如果它工作,你會得到圖像中的一個響應,你必須用jcrop旋轉圖像。

enter image description here

因此,可以說你得到了代碼爲8,將圖像旋轉45度到右側,你可以使用此代碼來旋轉45度到左側,所以你知道它是直立的。

var jcp = $("#input").Jcrop('api'); 
jcp.ui.stage.setAngle(45).redraw(); 

據我所知,這個片段只有jCrop 2+的作品,你也可以試着這樣做:

$('#cropbox').Jcrop({ 
     onChange: updatePreview, 
     onSelect: getcroparea, 
     boxWidth: 400, 
     boxHeight: 400, 
     setAngle: 45, 
     aspectRatio: 1, 
     bgOpacity: .4, 
     setSelect: [80, 45, 100, 100] 
    } 

但是我沒有測試過了後者。

你最好的選擇是:

  1. 使用我提供的片段,提取圖像的旋轉,根據你回來計算出你需要多少,接通圖像數量/翻轉圖像
  2. 然後使用jCrop 2.0版重建您的jCrop解決方案,並使用我提供的2行代碼片段來旋轉圖像。

這是另一個解決方案,它也需要您更改jCrop代碼以允許旋轉。 Make Jcrop tracker not rotate when cropping a rotated image

+0

嗨,@gertjan謝謝你的回答。對不起,如果我的問題不清楚給你。我想要發生的是每當用戶上傳圖像時,畫布上顯示的圖像將具有正確的方向。因爲現在它輸出錯誤的方向'8'(根據上圖)。 – Terence

+0

嗨@Terence,這意味着你必須用setAngle旋轉圖像270度,或者使用我的回答jcp.ui.stage.setAngle(45).redraw()中描述的重繪函數。 –