У меня есть виджет обрезки изображения на сайте. Изображение обрезается пользователем с помощью Jcrop перед любой загрузкой.
Однако, когда пользователь загружает фотографию с данными об ориентации (часто с iPhone или аналогичного устройства), фотография отображается с неправильной ориентацией по отношению к нему (по сравнению с тем, когда они открываются в большинстве основных программ просмотра фотографий на своем компьютере).
Что я хотел бы сделать, так это повернуть изображение в ожидаемую ориентацию. Я пытаюсь извлечь данные exif со стороны клиента изображения, а затем использовать это, чтобы добавить класс css к изображению предварительного просмотра перед инициализацией jcrop. Класс css соответствующим образом поворачивает изображение.
На данный момент Jcrop, кажется, создает свой черный ящик (для изображения за изображением) и поле выбора кадрирования, как будто вращение никогда не происходило, но вращение изображения происходит, поэтому все выглядит неправильно.
Некоторый код из виджета, который я пытался изменить, приведен ниже. jsfiddle, включая весь код, находится здесь. Обратите внимание, что setCoords устанавливает другой ввод, который я не включил, так как не считал его уместным.
Любая помощь очень ценится.
HTML
<input type="file" />
<div id="preview-image-holder">
<img id="preview-image" />
</div>
JavaScript
var jcrop_api, ratio=1.3, real_width, real_height;
function setCoords(c) { //function to set value of cropping coords widget to a json string of the cropping coordinates
$('input[id*=cropping_coords]').val(JSON.stringify(c));
}
function base64ToArrayBuffer (base64) {
base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, '');
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array( len );
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
function fixOrientation(image, orientationNum) {
//adds css class to image dependent on orientation number
switch(orientationNum) {
case 2:
image.addClass('flip'); break;
case 3:
image.addClass('rotate-180'); break;
case 4:
image.addClass('flip-and-rotate-180'); break;
case 5:
image.addClass('flip-and-rotate-270'); break;
case 6:
image.addClass('rotate-90'); break;
case 7:
image.addClass('flip-and-rotate-90'); break;
case 8:
image.addClass('rotate-270'); break;
}
}
function initJcrop(selector) {
//intialises jcrop on image
$(selector).Jcrop({
onSelect:setCoords,
onChange:setCoords,
bgColor:'black',
bgOpacity:0.4,
aspectRatio:ratio,
trueSize:[real_width, real_height]
}, function() {
jcrop_api = this;
dim = jcrop_api.getBounds();
var x = 0, y = 0, x_ = dim[0], y_ = dim[1];
var x_r = (x_ / ratio) - y_;
var y_r = (y_ / ratio) - x_;
if (x_r > 0) {
x = x_r / 2;
}
if (y_r > 0) {
y = y_r / 2;
}
jcrop_api.setSelect([x, y, dim[0], dim[1]]);
jcrop_api.setOptions({
allowSelect:false
});
});
}
function readImageURL(input) {
//uses FileReader to change source of #preview-image to
//image from input
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
if(jcrop_api !== undefined) {
jcrop_api.destroy();
$('#preview-image').removeAttr('style');
}
var exif = EXIF.readFromBinaryFile(base64ToArrayBuffer(e.target.result));
console.log(parseInt(exif.Orientation));
var orientation = parseInt(exif.Orientation);
fixOrientation($('#preview-image'), orientation);
$('#preview-image').attr('src', e.target.result);
$('<img />').attr('src', e.target.result).load(function() {
if ([5,6,7,8].indexOf(orientation)) {
real_width = this.height;
real_height = this.width;
} else {
real_width = this.width;
real_height = this.height;
}
initJcrop($('#preview-image'));
});
};
reader.readAsDataURL(input.files[0]);
}
}
$('input').change(function() {
readImageURL(this);
});