数码相机的照片经常被保存为JPEG格式与EXIF“方向”标签。 要正确显示,图像需要被旋转/镜像的,这取决于方向设置,但浏览器忽略这些信息渲染图像。 即使在大型商用Web应用程序,用于EXIF方向支撑物可以是参差不齐1 。 相同的源还提供了8个不同的方位安装在JPEG可以有一个很好的总结:
样本图像可在4 。
现在的问题是如何旋转/镜像上的客户端侧的图像,以便它显示正确和如果需要,可以进一步处理?
有JS库提供解析EXIF数据,包括定位属性2 。 Flickr的解析大图像时,需要使用webworkers的注意可能的性能问题3 。
控制台工具可以正确地重新定向图像5 。 一个PHP脚本解决这一问题可在6
Answer 1:
GitHub的项目JavaScript的负载图像提供给EXIF定位问题的完整解决方案,正确旋转/所有8个EXIF方向镜像图像。 见的在线演示的javascript EXIF方向
图像被绘制到一个HTML5画布。 其正确的渲染中实现JS /加载图像orientation.js通过帆布操作。
希望这样可以节省别人一段时间,并讲解了这个开源宝石搜索引擎:)
Answer 2:
Mederr的语境转换完美。 如果你需要提取的方向只能使用此功能 -你不需要任何EXIF读库。 下面是重新设定方向为Base64图像的功能。 下面是它的小提琴 。 我还准备了带有定向提取演示小提琴 。
function resetOrientation(srcBase64, srcOrientation, callback) {
var img = new Image();
img.onload = function() {
var width = img.width,
height = img.height,
canvas = document.createElement('canvas'),
ctx = canvas.getContext("2d");
// set proper canvas dimensions before transform & export
if (4 < srcOrientation && srcOrientation < 9) {
canvas.width = height;
canvas.height = width;
} else {
canvas.width = width;
canvas.height = height;
}
// transform context before drawing image
switch (srcOrientation) {
case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
case 7: ctx.transform(0, -1, -1, 0, height, width); break;
case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
default: break;
}
// draw image
ctx.drawImage(img, 0, 0);
// export base64
callback(canvas.toDataURL());
};
img.src = srcBase64;
};
Answer 3:
如果
width = img.width;
height = img.height;
var ctx = canvas.getContext('2d');
然后你可以使用这些变换的图像转向方向1
从方向:
-
ctx.transform(1, 0, 0, 1, 0, 0);
-
ctx.transform(-1, 0, 0, 1, width, 0);
-
ctx.transform(-1, 0, 0, -1, width, height);
-
ctx.transform(1, 0, 0, -1, 0, height);
-
ctx.transform(0, 1, 1, 0, 0, 0);
-
ctx.transform(0, 1, -1, 0, height, 0);
-
ctx.transform(0, -1, -1, 0, height, width);
-
ctx.transform(0, -1, 1, 0, 0, width);
之前CTX绘制图像
Answer 4:
确定除了@ user3096626答案我认为这将是,如果有人提供的代码示例更有帮助,下面的例子将告诉你如何解决图像方向来自URL(远程图像):
解决方案1:使用JavaScript(推荐)
因为负载图像库不提供从URL仅适用于图像(文件/ BLOB)提取EXIF标签,我们将同时使用EXIF-JS和加载图像的javascript库,所以先添加这些库到您的网页为如下:
<script src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.1.0/exif.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image-scale.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image-orientation.min.js"></script>
注意版本EXIF-JS的2.2似乎有问题,所以我们用2.1
那么基本上就是我们要做的就是
一个-加载使用图像window.loadImage()
b -读取使用EXIF标签window.EXIF.getData()
c -接收图像转换为画布,用固定的图像方向window.loadImage.scale()
d - 在画布到文档
干得好 :)
window.loadImage("/your-image.jpg", function (img) {
if (img.type === "error") {
console.log("couldn't load image:", img);
} else {
window.EXIF.getData(img, function () {
var orientation = EXIF.getTag(this, "Orientation");
var canvas = window.loadImage.scale(img, {orientation: orientation || 0, canvas: true});
document.getElementById("container").appendChild(canvas);
// or using jquery $("#container").append(canvas);
});
}
});
当然,你也可以得到图像从画布对象Base64和放置在IMG SRC属性,因此使用jQuery你可以做;)
$("#my-image").attr("src",canvas.toDataURL());
这里是完整的代码:github上: https://github.com/digital-flowers/loadimage-exif-example
方案2:使用HTML(浏览器黑客)
有一个非常快速和容易破解,大多数浏览器显示,如果图像被打开一个新的标签内的正确方向图像的情况下直接任意HTML(LOL我不知道为什么),所以基本上你可以使用iframe的显示图像通过将IFRAME SRC属性作为直接的图片网址:
<iframe src="/my-image.jpg"></iframe>
解决方案3:使用CSS(IOS上仅Firefox和Safari浏览器)
有CSS3属性来修复形象定位,但它仅在Firefox和Safari的工作问题/ IOS它仍然是值得一提,因为它很快将可用于所有的浏览器(从浏览器支持信息caniuse )
img {
image-orientation: from-image;
}
Answer 5:
WunderBart的回答是最适合我。 请注意,您可以加快步伐了很多,如果你的图片往往是围绕正确的方式,只需先试的方位,如果不需要旋转绕过代码的其余部分。
把所有从wunderbart的信息结合在一起,这样的事情;
var handleTakePhoto = function () {
let fileInput: HTMLInputElement = <HTMLInputElement>document.getElementById('photoInput');
fileInput.addEventListener('change', (e: any) => handleInputUpdated(fileInput, e.target.files));
fileInput.click();
}
var handleInputUpdated = function (fileInput: HTMLInputElement, fileList) {
let file = null;
if (fileList.length > 0 && fileList[0].type.match(/^image\//)) {
isLoading(true);
file = fileList[0];
getOrientation(file, function (orientation) {
if (orientation == 1) {
imageBinary(URL.createObjectURL(file));
isLoading(false);
}
else
{
resetOrientation(URL.createObjectURL(file), orientation, function (resetBase64Image) {
imageBinary(resetBase64Image);
isLoading(false);
});
}
});
}
fileInput.removeEventListener('change');
}
// from http://stackoverflow.com/a/32490603
export function getOrientation(file, callback) {
var reader = new FileReader();
reader.onload = function (event: any) {
var view = new DataView(event.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.slice(0, 64 * 1024));
};
export function resetOrientation(srcBase64, srcOrientation, callback) {
var img = new Image();
img.onload = function () {
var width = img.width,
height = img.height,
canvas = document.createElement('canvas'),
ctx = canvas.getContext("2d");
// set proper canvas dimensions before transform & export
if (4 < srcOrientation && srcOrientation < 9) {
canvas.width = height;
canvas.height = width;
} else {
canvas.width = width;
canvas.height = height;
}
// transform context before drawing image
switch (srcOrientation) {
case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
case 7: ctx.transform(0, -1, -1, 0, height, width); break;
case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
default: break;
}
// draw image
ctx.drawImage(img, 0, 0);
// export base64
callback(canvas.toDataURL());
};
img.src = srcBase64;
}
Answer 6:
对于那些谁拥有从输入控制文件,不知道它的方向是什么,都有点懒,不想包括下面一个大图书馆是他联系到了答案通过融合在一起提供@WunderBart代码( https://stackoverflow.com/a/32490603 )是找到方向。
function getDataUrl(file, callback2) {
var callback = function (srcOrientation) {
var reader2 = new FileReader();
reader2.onload = function (e) {
var srcBase64 = e.target.result;
var img = new Image();
img.onload = function () {
var width = img.width,
height = img.height,
canvas = document.createElement('canvas'),
ctx = canvas.getContext("2d");
// set proper canvas dimensions before transform & export
if (4 < srcOrientation && srcOrientation < 9) {
canvas.width = height;
canvas.height = width;
} else {
canvas.width = width;
canvas.height = height;
}
// transform context before drawing image
switch (srcOrientation) {
case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
case 7: ctx.transform(0, -1, -1, 0, height, width); break;
case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
default: break;
}
// draw image
ctx.drawImage(img, 0, 0);
// export base64
callback2(canvas.toDataURL());
};
img.src = srcBase64;
}
reader2.readAsDataURL(file);
}
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);
}
它可以很容易被称为像这样
getDataUrl(input.files[0], function (imgBase64) {
vm.user.BioPhoto = imgBase64;
});
Answer 7:
除了@fareed namrouti的回答,
这应该被使用,如果图像已从文件输入元件来浏览
<input type="file" name="file" id="file-input"><br/>
image after transform: <br/>
<div id="container"></div>
<script>
document.getElementById('file-input').onchange = function (e) {
var image = e.target.files[0];
window.loadImage(image, function (img) {
if (img.type === "error") {
console.log("couldn't load image:", img);
} else {
window.EXIF.getData(image, function () {
console.log("load image done!");
var orientation = window.EXIF.getTag(this, "Orientation");
var canvas = window.loadImage.scale(img,
{orientation: orientation || 0, canvas: true, maxWidth: 200});
document.getElementById("container").appendChild(canvas);
// or using jquery $("#container").append(canvas);
});
}
});
};
</script>
Answer 8:
我使用的混合溶液(PHP + CSS)。
需要集装箱:
-
div.imgCont2
旋转所需的容器中; -
div.imgCont1
需要缩小(ZoomOut)容器- width:150%
; -
div.imgCont
容器所需的滚动条,当图像是缩小(ZoomOut)。
。
<?php
$image_url = 'your image url.jpg';
$exif = @exif_read_data($image_url,0,true);
$orientation = @$exif['IFD0']['Orientation'];
?>
<style>
.imgCont{
width:100%;
overflow:auto;
}
.imgCont2[data-orientation="8"]{
transform:rotate(270deg);
margin:15% 0;
}
.imgCont2[data-orientation="6"]{
transform:rotate(90deg);
margin:15% 0;
}
.imgCont2[data-orientation="3"]{
transform:rotate(180deg);
}
img{
width:100%;
}
</style>
<div class="imgCont">
<div class="imgCont1">
<div class="imgCont2" data-orientation="<?php echo($orientation) ?>">
<img src="<?php echo($image_url) ?>">
</div>
</div>
</div>
Answer 9:
我写了一个小PHP脚本,旋转图像。 请务必将图像存储在赞成只是重新计算每个请求。
<?php
header("Content-type: image/jpeg");
$img = 'IMG URL';
$exif = @exif_read_data($img,0,true);
$orientation = @$exif['IFD0']['Orientation'];
if($orientation == 7 || $orientation == 8) {
$degrees = 90;
} elseif($orientation == 5 || $orientation == 6) {
$degrees = 270;
} elseif($orientation == 3 || $orientation == 4) {
$degrees = 180;
} else {
$degrees = 0;
}
$rotate = imagerotate(imagecreatefromjpeg($img), $degrees, 0);
imagejpeg($rotate);
imagedestroy($rotate);
?>
干杯
文章来源: JS Client-Side Exif Orientation: Rotate and Mirror JPEG Images