jcrop:实现EXIF方向

时间:2017-03-07 14:24:31

标签: jquery exif jcrop

我的网站上有一个裁剪工具,用户可以上传图片并裁剪。

每当我上传手机拍摄的图片时,我都会遇到图像方向错误。

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方向,请帮我在我的代码上实现它。

1 个答案:

答案 0 :(得分:0)

我想您所说的是您想要从上传的图片中提取EXIF数据,然后旋转图片以使其始终处于某个位置。 对我而言,目前还不清楚图像会发生什么,例如我上传一张以横向模式制作的图片,而我的手机会将照片颠倒过来?当我上传使用portret模式拍摄的照片时会发生什么?因为我不知道这些信息,所以我无法为您创建完整的代码,但我可以帮助您继续前进。

以下是从客户端的图像中提取EXIF数据的片段。当有人将图像添加到输入文件时,这将触发。此代码段由用户制作:https://stackoverflow.com/users/893432/ali

&#13;
&#13;
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);
  });
}
&#13;
<input id='input' type='file' />
&#13;
&#13;
&#13;

如果图片中包含EXIF数据,则会从图片中提取EXIF数据,您可以获得的响应值如下:

-2: not jpeg
-1: not defined

所以当它不是一个jpeg时,你会得到-2,当没有任何图片时你得到-1。如果它有效,您将获得图像中的一个响应,您必须使用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行代码片段来旋转图像。
  3. 这是另一种解决方案,它要求您稍微更改jCrop代码以允许旋转。 Make Jcrop tracker not rotate when cropping a rotated image