Foliotek / Croppie

A Javascript Image Cropper
http://foliotek.github.io/Croppie
MIT License
2.58k stars 884 forks source link

Result image gets distorted #515

Closed AlexanderLyon closed 5 years ago

AlexanderLyon commented 6 years ago

When uploading an image that's zoomed all the way out (or close to it), the result image sometimes becomes stretched and distorted. The further out I zoom, the more distorted the image becomes. Not sure what's causing it or how exactly to recreate the issue since it only happens with certain images.

As far as I can tell it happens on Chrome, Firefox, and IE. Has anyone else experienced this? Any ideas?

Max zoomed out (with distorted result)

1 result1

Zoomed in, working normally

2 result2

thedustinsmith commented 6 years ago

We need more information:

AlexanderLyon commented 6 years ago

The result base64 image is being rendered in an img tag with the same dimensions as what I set for Croppie's viewport. It appears that this distortion issue only occurs (at least in my experience) after rotating a rectangular image from landscape to portrait, then getting the result.

This leads me to believe there is some confusion in keeping track of the original image's height and width. In my commit, all I did was swap _originalImageWidth and _originalImageHeight after a rotation, which fixed the issue for me.

key60529 commented 6 years ago

I have the same issue as you, I'm using croppie 2.6.2, so it happen when I zoomed all the way out and drag until viewport exist the bottom of the image, then it will happen.

Update:: Sorry for missing some step for creating that issue, so I think it only happen if you rotate the image first and then do that step above then it will happen.

Update 2:: After trying to add the code wrote by @AlexanderLyon , it works fine for me, so I'm guessing he's right, the original image's height and width is not tracked after rotate.

And here are some of the code:

var resultWidth = 900, resultHeight = 1200;
var imageSource = 'https://www.w3schools.com/w3css/img_lights.jpg';

// init the croppie with setting
uploadCrop = $('#photo-edit-holder').croppie({
  viewport: {
    width: resultWidth / 5,
    height: resultHeight / 5
  },
  boundary: {
    width: resultWidth / 5 + 80,
    height: resultHeight / 5 + 80
  },
  enableOrientation: true;
});

// bind the image
uploadCrop.croppie('bind', {
  url: imageSource,
  points: [0,0,0,0],
  zoom: 0.5
})

// rotate the image if user click on the rotate button
$('.rotate-btn').on('click', function() {
  if ($(this).attr('data-toggle') === 'cw') {
    uploadCrop.croppie('rotate', -90)
  } else {
    uploadCrop.croppie('rotate', 90)
  }
})

// render the result to base64 type and return the preview of cropped image
uploadCrop.croppie('result', {
  type: 'base64',
  format: 'jpg',
  size: {
    width: resultWidth,
    height: resultHeight
  }
}).then(function (resp) {
  $('#image-preview').attr('src', resp);
});

It seems like the result is not getting the correct width and height of the setting maybe? not so sure.

trevorlangston commented 6 years ago

I'm having a similar experience. @AlexanderLyon How exactly are you swapping these variables?

AlexanderLyon commented 6 years ago

@trevorlangston at the bottom of the _rotate() function, I created temp variables to store the old orientations, then just reassigned them to each other:

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,
    ornt;

  self.data.orientation = getExifOffset(self.data.orientation, deg);
  drawCanvas(canvas, self.elements.img, self.data.orientation);
  _updateZoomLimits.call(self);
  _onZoom.call(self);
  copy = null;

  // Reverses image dimensions:
  let oldHeight = self._originalImageHeight;
  let oldWidth = self._originalImageWidth;
  self._originalImageWidth = oldHeight;
  self._originalImageHeight = oldWidth;
}
aamiguet commented 5 years ago

After applying the fix, I had some issues dragging the picture after a rotation. Moving the following two lines :

_updateCenterPoint.call(self, true);  
_updateZoomLimits.call(self); 

After updating self._originalImageWidth & self._originalImageHeight seems to fix them.

bwakabats commented 5 years ago

Do you need an extra check that the "deg" is divisible by 90/270/-90 etc? Something like

if ((Math.abs(deg) / 90) % 2 === 1) {
   ...
}