Problem
The hard limit width and height in the crop type settings allow to avoid the crop selection being dragged to less width and/or height than the defined hard limits. In an example I combined the ratio setting with a hard limit width.

With these settings, when the crop selection is dragged to be as small as the hard limit width, saving the node results in an error as if the crop selection would already be smaller than the defined hard limit width. But this error should not be displayed as the crop selection can't be dragged below the hard limit sizes (see images for setting and error). The same occurs with a defined hard limit height.

In the case that the uploaded image is exactly as big as the defined hard limit and thus the crop selection cannot be resized at all, the node can't be saved due to the hard limit error after trying to move the crop selection.

Versions
Drupal 8.2.4
Crop API 1.0
Image Widget Crop 1.4

Proposed solution
I've not looked into the code of the crop and image_widget_crop modules, but I assume that there is a slight difference in the javascript code validation (which handles stopping the dragging when it is tried to drag below the hard limit sizes) and the validation of the final crop selection sizes during saving of the node. Maybe something along the use of an 'equal or bigger than' comparison operator for the javascript dragging and a 'bigger than' comparison operator for the validation during the saving of the node. One could also say that the validation during the saving of the node is not necessary at all, as the javascript validation keeps that condition already true.

Thanks for any help with this bug.

Comments

meichr created an issue. See original summary.

woprrr’s picture

Yes, We have an subject here !!

That case need to be specified more because I think that is an case a bit complex. Why ? Because we can solve that easily but with 'N' approach and only one are the BEST.

Differents solution :

1 : Display another Error message to inform user that he upload an image smaller than specified limit in settings.
2 : Add a test in ImageCrop::validateHardLimit() to ensure we don't display these message if image are smaller than setting.
3 : Block upload of Picture smaller than Limit.
4 : Display an warning (not blocker of validate element) to inform user that he upload an image smaller than specified limit in settings and he understand possible distorsion of images avoided by these limite set by Admin.

IMHO the fourth solution are better, inform users, not a blocker of validation and permit user to have more flexibility.

What you think about ?

meichr’s picture

Hi woprrr,
thanks a lot for your quick reply. You have a point with images being uploaded with sizes smaller than the hard limit. I agree to your solution 4 with a short warning displayed directly besides the crop field of the respective image like the soft limit does with its warnings. In my case the field can contain more than one image and the warning thus should point out the problematic image. I also agree to saving not being blocked by one or more images being too small for the hard limit. Though after saving, a common warning on top (mentioned by you) would help, telling that one or more images were smaller than the hard limit, meaning that the quality of these images would be distorted. I'd not block uploading of smaller images as this can be achieved with the field_image itself and should not be duplicated here.

BUT in addition to this solution for images too small for the hard limit
The issue was written, because of an image with both sizes equal to the hard limit! In this case, I assumed, that there would not be any error, as the crop frame cannot be resized smaller than the hard limit, but an error occured despite of my assumption.
Thanks to you mentioning the the method name ImageCrop::validateHardLimit() I could easily add the offending crop frame size information to the error. And I found out that the error can also occur with images much larger than the hard limit, if the crop frame is dragged to its minimum size. See the following screenshots.

Very big image larger than the hard limit, see size on top of the popup window
This original image is much bigger than the hard limit of 1890x700px according to the popup window header

Very big image with smallest crop frame possible with the hard limit
The crop frame is dragged to its minimum width according to the hard limit

The error with the smallest crop frame for the very big image
The Error (with the added crop frame width) after trying to save the node with the smallest crop frame possible

In addition it has to be said that the crop area, on which the crop frame can be resized and moved, is also much smaller than the original image and the hard limit. In the pictured case the crop frame size of 1888 falls 2px short of the 1890 hard limit before the javascript dragging was stopped. In other cases (different original big image size) it falls even 5px short and in some cases (again different original big image size) it doesn't fall short at all. As a result of my tests I assume a rounding problem due to the big difference of hard limit, crop area size and original big image size.

The solution to this problem would be not to compare the hard limit with the crop frame size at all, in addition to solution 4 described by you with the modifications I wrote on top of this posting. And also replacing the crop frame size, when saving, with the hard limit size and the other size proportional, if one or both crop frame sizes fall short (due to the rounding problem) of the hard limit.

What do you think?

woprrr’s picture

Issue tags: +D8Media, +DevDays Seville

We need to speak more during Media Sprints DDD Sevilla about this subject.

duaelfr’s picture

Issue tags: -DevDays Seville +DevDaysSeville

Fixing event tag

woprrr’s picture

Status: Active » Postponed (maintainer needs more info)

Hi @meichr,

I need you help on that issue during a big refactor/upcrease of Js integration of module we have solve few problem of that kind. Can we confirm me if current dev branche work better or solve that issue ? Refactoring issue => #2803407: Refactor form element and JS to work with any theme

woprrr’s picture

Status: Postponed (maintainer needs more info) » Fixed
Issue tags: -DevDaysSeville

I have tested all comportements describe previously. All seems good now, I attach a screenshot with a test with my cropType configured to have hard limits to 500 (height & width). When I crop my image with crop maximum close to 500 (501 in my case). I save and all works but if I crop an zone (one of twos zones behind 500 a message are displayed).

Feel free to re-open with more precise details and (2.x version) installed.

woprrr’s picture

Status: Fixed » Closed (fixed)
minnoce’s picture

I found same bug testing latest version (2.0) on simplytest.me

woprrr’s picture

Status: Closed (fixed) » Postponed (maintainer needs more info)

Hii @minnoce thank you for your feedback. Can you describe more the reproduction path of your test ? That can be usefulll to found a solution. Thanks :)

rob230’s picture

StatusFileSize
new1.09 MB
new412.06 KB
new96.97 KB

There seems to be a bug with the module.

For me it works sometimes, but in other cases breaks. I'm not sure, but it might be when you use a very large image (over 2000px for example). Could it be something wrong with the calculations when using the cropper on a large resolution image but the preview is much smaller?

Here is the image I used:

Bilbury

Here you can see I have cropped it to the hard limit:

Bilbury

And finally, you can see when I debug the code that despite the hard limit being 1200x1200, it has allowed it to be 747x747. No crop is saved as a result.

Bilbury

woprrr’s picture

Hii @Rob230

I have tested again with fresh install all functionalities and all seem's good except an error margin of 3 pixels before stop the crop zone.

I attach a video to show you mes usecases.

https://youtu.be/jyU1LGnhdAY

woprrr’s picture

I have more informations about the possible error margin that's is due to ratio vs Hard limit ratio by example if you define a real 16:9 like : (Width : 1024 and Height : 576 ) you can't have a crop zone lower than 1024x576 precisely but if you define hard limits like (576x576) the crop zone stop when width are in 576 and height can be lower than 576px but validation stop submission after because you don't respect hard limits.

Specifically you case with hard limit seem's to be a cache problem I guess :/ I need more information about that.

rob230’s picture

But in your video it fails because it's 3px smaller. This kind of failure is happening to me all the time with large crop sizes and large images. Surely something is not right with it.

woprrr credited markcarver.

woprrr’s picture

Status: Postponed (maintainer needs more info) » Needs work
StatusFileSize
new824.34 KB
new14.3 KB

I have finnaly identify what's the problem !! all of our problems is due to

  /**
   * Sets a single crop value.
   *
   * @param {'applied'|'height'|'width'|'x'|'y'} name
   *   The name of the crop value to set.
   * @param {Number} value
   *   The value to set.
   * @param {Number} [delta]
   *   A delta to modify the value with.
   */
  Drupal.ImageWidgetCropType.prototype.setValue = function (name, value, delta) {
    if (!this.values.hasOwnProperty(name) || !this.values[name][0]) {
      return;
    }
    value = value ? parseInt(value, 10) : 0;
    if (delta && name !== 'applied') {
      value = Math.round(value * delta);
    }
    this.values[name][0].value = value;
    this.values[name].trigger('change.iwc, input.iwc');
  };

And specially ==> value = value ? parseInt(value, 10) : 0; When value arrived by recover cropper values we have a string "1200" and when parseInt("1200", 10) recover integer we have (int) 1997 ... All of next calculations are based on 1997 and not 1200...

We have two approach possible understand why parseInt() not works as excepted (My skill are limited in JS) or understand why we need to use parseInt() and not using this if not necessary ?! I add marcarver to have more specialist opinion about this.

With following debug :

  /**
   * Sets a single crop value.
   *
   * @param {'applied'|'height'|'width'|'x'|'y'} name
   *   The name of the crop value to set.
   * @param {Number} value
   *   The value to set.
   * @param {Number} [delta]
   *   A delta to modify the value with.
   */
  Drupal.ImageWidgetCropType.prototype.setValue = function (name, value, delta) {
    if (!this.values.hasOwnProperty(name) || !this.values[name][0]) {
      return;
    }
    console.log('before : ' + value);
    value = value ? parseInt(value, 10) : 0;
      console.log('after : ' + value);
      if (delta && name !== 'applied') {
      value = value * delta;
          console.log('before Math : ' + value);
          value = Math.round(value);
          console.log('after Math : ' + value);

      }
    this.values[name][0].value = value;
    this.values[name].trigger('change.iwc, input.iwc');
  };

Result :


(X value)
before : 0
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:803 after : 0
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:806 before Math : 0
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:808 after Math : 0

(Y value)
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:801 before : 12
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:803 after : 12
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:806 before Math : 76.80000000000001
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:808 after Math : 77

(Width value)
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:801 before : 187.5
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:803 after : 187
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:806 before Math : 1196.8
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:808 after Math : 1197

(Height value)
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:801 before : 105.46875
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:803 after : 105
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:806 before Math : 672
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:808 after Math : 672

(Is Applied value)
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:801 before : 1
js_XrKVvRZzXs5i6HkiFeBJOIDdStZa9pk8QmGKYImCmvc.js:803 after : 1

we can see parseInt() convert string with float to interger that convert introduce ~3px errors.

markhalliwell’s picture

The problem isn't parseInt, that behaves as expected.

The reason the value is changing is due to:

    if (delta && name !== 'applied') {
      value = Math.round(value * delta);
    }

Just did some quick math and it seems the delta is roughly .9975 (1200 * .9975 = 1197).

IIRC, delta has something to do with the ratio of the original image dimensions vs. the real container size (e.g. picture is bigger than the space allotted for the screen/container).

I cannot attest to what that actually means, however. I know you tagged me on this issue, but I never really fully understood the full math behind this module and how exactly delta was properly calculated (think it's provided by the cropper).

Regardless, I only rearranged the existing code into a better JS structure. I didn't alter the logic behind the existing code.

woprrr’s picture

Regardless, I only rearranged the existing code into a better JS structure. I didn't alter the logic behind the existing code.

Yes, and again Thank you for that !! I add you to this issue because I'm really disappointed by this errors and I have added more precisions about parseInt() that seems convers string 187.5 to 187 systematically and with that we can explain the problem EG

with correct values : with : 187.5 * 6.4 = 1200 (Ok !)
with parseInt() value : 187 * 6.4 = 1996.8 (and Math convert this to 1997)

woprrr’s picture

Status: Needs work » Needs review
StatusFileSize
new2.14 KB

This patch does solve the problems. Anyone can review that to tell me if we have better way to do that ?

Status: Needs review » Needs work

The last submitted patch, 19: dragging_the_crop-2855081-19.patch, failed testing. View results

woprrr’s picture

Version: 8.x-1.4 » 8.x-2.0
Component: User interface » Code
Status: Needs work » Needs review
StatusFileSize
new2.14 KB

Only available for 2.x branch.

markhalliwell’s picture

Status: Needs review » Needs work

Hm. I guess there could be floats. No need to check for either or, you can just use parseFloat instead.

Also, the above patch unnecessarily increased the indentation of the method block.

woprrr’s picture

StatusFileSize
new1.05 KB

You right @markcarver :) ! Changes applied Thanks

woprrr’s picture

Status: Needs work » Needs review
markhalliwell’s picture

Status: Needs review » Needs work
+++ b/js/ImageWidgetCropType.js
@@ -647,12 +647,15 @@
-      return;
+        return;
...
+
...
+
...
-      value = Math.round(value * delta);
+        value = Math.round(value * delta);

Still some unnecessary whitespace additions and indentations.

This should only be a one-line two line patch.

Edit: forgot the version bump.

woprrr’s picture

Status: Needs work » Needs review
StatusFileSize
new811 bytes

Oops ! Sorry markcarver I change that now that's good.

markhalliwell’s picture

Status: Needs review » Reviewed & tested by the community

LGTM

rob230’s picture

Unfortunately that patch has not fixed it for me. With the 1200x1200 crop it still fails.

I think you fixed the 3px problem, but not the problem where it's the wrong size by hundreds of pixels.

woprrr’s picture

Hii @Rob230 Thank you for tests :)

The validation fails are normal because cropper block the crop zone only when width are smaller than your fixed hard limit.

By example : If you set 1200 x 1200 for Hard limits and you use a crop with 16:9 ratio. In that case cropper block crop zone only when width are in 1200 but you should have a validation warning because in 16:9 aspect ratio your crop area are (1200x~675) the height 675 not pass the validation and that's is normal and excepted.

If you define a crop limits not respect your aspect ratio cropper choose to fixed width only and not height. This is why I consider this issue as fixed because before patch we can have a width smaller than hard crop limits and that's is bad because we can have width AND height not valid.

If you define a crop ratio 1:1 and try hard limits with 1200 x 1200 all works to you.

This respond to your problematic ?

rob230’s picture

StatusFileSize
new38.22 KB
new17.54 KB
new437.3 KB

I agree that you have fixed the original problem reported, but I am still having a similar but different problem. I don't know why.

Here you can see the crop type:

Crop type

Here you can see the image style using the crop type:

Image style

Here is me cropping the image I gave before (which is 2560x1600):

Crop image

It is letting me choose an area which looks much smaller than 1200x1200.

And then it doesn't save the crop, because the crop size is smaller than 1200x1200. I have gone over these settings again and again. I'm not sure if there is some mistake, but I don't see one.

woprrr’s picture

@Rob230 Ok for original problem solved by patch ;) Thank for your feedback !

Specially for your problem I think this is a missConfiguration problem. I just tried to reproduce and configure all in video to show you my trying to reproduce your issue.

In my test I have my Image style using 1:1 crop Type with aspect ratio 1:1 and hard limit set as 1200 x 1200.

I configure a basic Node 'article' using image field provided by standard edition.

I go add an Article to my new site and upload an image.

My crop 1:1 appear and I select the minimum crop zone as possible 1200 x 1200 I save and all works as excepted.

@see my tests https://youtu.be/U6RDBn4R9Z0

Your preview crop thumbnail it's module provided style or you have customized it ? Can you show me all your configuration of Image Style / Crop type / field Widget ?

markhalliwell’s picture

I think it is misconfiguration (and an entirely separate issue) on @Rob230's part.

The patch in #26 is good to go as it fixes the OP.

  • woprrr committed f2eae2b on 8.x-2.x
    Issue #2855081 by woprrr, Rob230, meichr, markcarver: Dragging the crop...
woprrr’s picture

Status: Reviewed & tested by the community » Fixed

Merged :) Thanks all ! Special thank @markcarver for your following :)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

andreyks’s picture

andreyks’s picture

patch for version 8.x-2.1
previous one was for current 8.x-2.x