I am finding that on iOS in Safari the image returned by Croppie is rotated by 90 degrees (and sometimes partially cut off). This only seems to happen with photos that are taken on the spot (images from the media library are fine).



Hi Dustin,
I was able to fix this issue by enabling exif as you mentioned in the previous comment. However, if I enable Exif, the images are not displayed on some iPad versions (mostly in versions 8.*). This is happening also in the demo you guys have here: http://foliotek.github.io/Croppie/
Is this a known issue?
Not that I'm aware of. What do you mean the images aren't displaying? They don't display in the cropper? Or when you're trying to get a result?
Thanks for your quick answer. The images are not being displayed in the cropper, but this is only happening with large images.
Nope - not aware of that issue at all. There have been several safari issues popup because of how safari deals with canvas, but I don't have an iPad to test on.
Can you hook up remote debugging and see if you're getting a console error?
We are also having this issue on iPhone where the image gets rotated, in the viewport, after it gets uploaded. Appears to only happen when taking a vertical picture and using the camera. Media Library images are the correct orientation.
I've enabled Exif, but it is still occurring. Is there more code that needs to be added other than just setting enableExif: true? I have the exif.js loaded in before croppie.js.
@technifreak do you know a solution for this problem? I have enabled ExIf but when a photo is taken using the camera of an iPhone, the image is not displayed instead, a white background.
We ended up having to include a rotation button, as it didn't work any other way, in the time we needed to have it done by. Not sure about the white background issue. Our images would turn sideways.
@technifreak I also had the image rotation issue but it was fixed by adding ExIf only for android devices. Not sure why isn't working for ios devices.
@uslperera I fixed the white background issue by reducing the images size. Some apple devices can't process large images because of the their resources. A canvas issue.
@fabrizziosalazar Thanks for the reply. Btw what's the canvas size you have used?
Can we reopen this issue? iOS is still displaying the image in a 90 deg rotation
If anyone is looking for a solution, I found a workaround. It's using the exif.js to get the orientation tag value and then it sets that into the croppie Bind.
image.onload = function() {
// Validate Size
if(image.width < "760" || image.height < "500") {
alert("Your image is a little small. Try a larger image for better quality.");
}
EXIF.getData(image, function() {
var orientation = EXIF.getTag(this, "Orientation");
$uploadCrop.croppie('bind', {
url: e.target.result,
orientation:orientation
});
});
};
I believe you just need to set the enableOrientation bit of Croppie.
Either way, I'm closing this issue. It's too long and too old to follow. If someone's ios rotation issue's persist, feel free to reopen a new issue.
@technifreak I also had the image rotation issue but it was fixed by adding ExIf only for android devices. Not sure why isn't working for ios devices.
I am also facing same rotation issue with iPhone where image rotation is not working! Did you find any solution?
@technifreak, @thedustinsmith I have found the problem that is the cause that when an image is rotated it is saved with a transparent area.
To reproduce ir just rotate an landscape image in a squared viewport, and call to result. Don't drag the image with the mouse or you will loose the error.
The problem is inside _rotate function due you exchange self._originalImageWidth with self._originalImageHeight after calling _updateZoomLimits and this must be done before.
UpdateZoomLimits triggers update event and if you call to result() inside the event listener the getCanvas will get incorrect image dimensions and the fixing of boundaries that is done inside this function is the cause of this final transparent area.
This is the fix:
function _rotate(deg) {
if (!this.options.useCanvas || !this.options.enableOrientation) {
throw 'Croppie: Cannot rotate without enableOrientation && EXIF.js included';
}
var self = this,
canvas = self.elements.canvas;
self.data.orientation = getExifOffset(self.data.orientation, deg);
drawCanvas(canvas, self.elements.img, self.data.orientation);
_updateCenterPoint.call(self, true);
// Reverses image dimensions if the degrees of rotation is not divisible by 180.
if ((Math.abs(deg) / 90) % 2 === 1) {
let oldHeight = self._originalImageHeight;
let oldWidth = self._originalImageWidth;
self._originalImageWidth = oldHeight;
self._originalImageHeight = oldWidth;
}
_updateZoomLimits.call(self);
}
As a contribution, just to maintain the center of the image when rotating, do the following changes:
_rotate function with the previous bug fixed and passing the rotating degrees to _updateCenterPoint:
function _rotate(deg) {
if (!this.options.useCanvas || !this.options.enableOrientation) {
throw 'Croppie: Cannot rotate without enableOrientation && EXIF.js included';
}
var self = this,
canvas = self.elements.canvas;
var scale = self._currentZoom,
pc = new TransformOrigin(self.elements.preview);
self.data.orientation = getExifOffset(self.data.orientation, deg);
drawCanvas(canvas, self.elements.img, self.data.orientation);
_updateCenterPoint.call(self, deg % 360);
// Reverses image dimensions if the degrees of rotation is not divisible by 180.
if ((Math.abs(deg) / 90) % 2 === 1) {
let oldHeight = self._originalImageHeight;
let oldWidth = self._originalImageWidth;
self._originalImageWidth = oldHeight;
self._originalImageHeight = oldWidth;
}
_updateZoomLimits.call(self);
}
and the modified updateCenterPoint:
function _updateCenterPoint(rotate) {
var self = this,
scale = self._currentZoom,
data = self.elements.preview.getBoundingClientRect(),
vpData = self.elements.viewport.getBoundingClientRect(),
transform = Transform.parse(self.elements.preview.style[CSS_TRANSFORM]),
pc = new TransformOrigin(self.elements.preview),
top = (vpData.top - data.top) + (vpData.height / 2),
left = (vpData.left - data.left) + (vpData.width / 2),
center = {},
adj = {};
if (rotate) {
var cx = pc.x;
var cy = pc.y;
var aux;
switch (rotate) {
case 90: // Left 90
case -270:
aux = cx;
cx = cy;
cy = data.height / scale - aux;
break;
case -90: // Right 90
case 270:
aux = cy;
cy = cx;
cx = data.width / scale - aux;
break;
case 180:
case -180:
cx = data.width / scale - cx;
cy = data.height / scale - cy;
break;
}
center.x = cx;
center.y = cy;
transform.x = vpData.width/2 - cx;
transform.y = vpData.height/2 -cy;
}
else {
center.y = top / scale;
center.x = left / scale;
adj.y = (center.y - pc.y) * (1 - scale);
adj.x = (center.x - pc.x) * (1 - scale);
transform.x -= adj.x;
transform.y -= adj.y;
}
var newCss = {};
newCss[CSS_TRANS_ORG] = center.x + 'px ' + center.y + 'px';
newCss[CSS_TRANSFORM] = transform.toString();
css(self.elements.preview, newCss);
}
Hope these changes will be useful for you all
Most helpful comment
If anyone is looking for a solution, I found a workaround. It's using the exif.js to get the orientation tag value and then it sets that into the croppie Bind.