Problem/Motivation
Cropped images are not generated / shown
Steps to reproduce
- Have: Drupal 10.2.2 with drupal/crop_image:2.0.2, drupal/media_contextual_crop:2.0.3, drupal/media_contextual_crop_field_formatter:2.0.2, drupal/media_contextual_crop_fp_adapter:2.0.0, drupal/media_contextual_crop_iwc_adapter:dev-2.0.x
- Create a '16:9' Crop type
- Create a 'Cropped - 16:9' Image Style that uses the 16:9 Crop type
- Add a 'Media with contextual modifications' field to a Node type referencing the Image media type
- Set Form Display to Media Library Extra for that field. Form mode: default
- Edit the Image media type: Form Display: Default: Use the Contextual Crop Image widget
- Set Manage Display of the 'Media with contextual modifications' field to Rendered Entity: Default
- Edit the Image media type: Manage Display: Default: Use Contextual Crop Image. Image style: Cropped - 16:9
- Create / Edit a Node
- Observe that you can select an image from the Media Library
- Observe that you can click the edit button
- Observe that you see a working cropping widget and you can adjust / set the crop
- Save the node
- The crop is not displayed
- In sites/default/files there is no 'contextual' folder. There is no generated cropped image to be found anywhere
- Inspect the URL of the missing / broken image: /sites/default/files/contextual/styles/crop_16_9/279/public/uploads/crop-duplicate-1-for-adobestock_599962628%20%281%29.jpeg?itok=jjTbP3cM
- Manually opening that url into a new window redirects to: https://mywebsite.com/nl/sites/default/files/contextual/styles/crop_16_9/279/public?itok=jjTbP3cM which is a 404 page not found
Proposed resolution
I observe that in media_contextual_crop/src/PathProcessor/PathProcessorImageStyles.php inside the processInbound function 'file' and 'contextual_crop' are set to the request object:
$request->query->set('file', $file);
$request->query->set('contextual_crop', $context);But I see that in media_contextual_crop/src/Controller/ContextualImageStyleDownloadController.php inside the process function, those are missing from that Request object. I can see this if I add a line at line 50 like: dpm($request);.
If, as a test, I manually add these parameters here to the Request like this:
$request->query->set('file', 'uploads/crop-duplicate-1-for-adobestock_599962628 (1).jpeg');
$request->query->set('contextual_crop', '279');Then I see a working cropped image. And then I see that the sites/default/files/contextual folder now exists, and a cropped image is placed inside that folder: sites/default/files/contextual/styles/crop_hero/279/public/uploads/crop-duplicate-1-for-adobestock_599962628 (1).jpeg
So the problem seems to boil down to missing file and contextual crop query parameters inside the process() function.
Remaining tasks
Fix it.
| Comment | File | Size | Author |
|---|---|---|---|
| #48 | working different crops.png | 1.15 MB | flyke |
| #45 | 04 - crop entity.png | 69.81 KB | flyke |
| #45 | 03 - broken image after cropping.png | 869.4 KB | flyke |
| #45 | 02 - cropping only 1 image.png | 296.45 KB | flyke |
| #45 | 01 - before cropping.png | 788.76 KB | flyke |
Comments
Comment #2
drdam commentedIt seems the bug is caused by the end of the image name " (1)" which are encoded to "%20%281%29".
Did you have the same effect on all images ?
Comment #3
flyke commentedYes, If I upload a new image to the Media library with a simple filename like 'Naamloos.png' and use that, still the same problem.
Broken image src =
https://mywebsite.com/sites/default/files/contextual/styles/crop_hero/public/uploads/Naamloos.png?itok=zbqO4E0bmanually opening that in browser redirects to:
https://mywebsite.com/nl/sites/default/files/contextual/styles/crop_hero/public/uploads?itok=zbqO4E0bbut thats a 404 page not found. No image is generated. There is a sites/default/files/contextual folder now (from the previous test where I forced the parameters inside the Controller) but its empty.Comment #4
drdam commentedYou have a multilanguage site ? (i see the /nl/ )
Comment #5
flyke commentedYes, it is a multilingual website.
Comment #6
drdam commentedCan you confirm me Images URL ? (as they are written in sources)
because :
are broken due the fact there is no "contextual id" in URL.
A good URL would be :
=> if it's the case, the bug are in the formater
In the first message, the error may are in the PathProcessor ...
so i'm confused...
Comment #7
flyke commentedI can confirm that the Image URLs I pasted here are real and unmodified exept for the 'mywebsite.com' part.
If you check to proposed resolution part of the issue, you will see that I already noticed that 'file' and 'contextual_crop' query parameters are missing inside the process() function, and that if I manually set something there for those parameters, then everything works.
So the problem is that the 'file' and 'contextual_crop' parameters are missing inside the process() function. They are available inside the processInbound() function, but they are missing from the process() function of the Controller.
Comment #8
flyke commentedI think images might make it clearer.
Comment #9
flyke commentedExtra screenshots.
Comment #10
drdam commentedOk, I does not understand why the parameters in the request not passe to the controller...
Can you make a dsm on other parameters of the controller ?
Comment #11
flyke commentedHere you go.
Comment #12
flyke commentedMore info from that first request object if you need it.
Comment #13
drdam commentedThat seem logic.
So, in the PathProcessorImageStyles, can you put some dsm :
Comment #14
flyke commentedHere you go.
Comment #15
flyke commentedI refreshed the page, and then you see the expected number of output / dpms. That is probably less confusing.
Comment #16
drdam commentedThere is the problem, the "rest" url will be "styles/[style_name]/[context_id]/[scheme]/[file path] and in your case, the context_id are absent.
can you add another dsm at the line 33
Comment #17
flyke commentedHere you go.
Comment #18
drdam commentedcan you confirme that is the URL in the HTML source ?
If it's the case, the error are in the URL generation
Comment #19
flyke commentedYes, looks the same to me. Where might the URL generation be wrong ? any way to trouble shoot that further ?
Comment #20
flyke commentedTesting around, I find this. Will try to investigate more.
Comment #21
flyke commentedIt seems that inside generateContextualizedImage() function, $plugin->saveCrop returns NULL.
Comment #22
drdam commentedSo, can you add dsm in
Drupal\media_contextual_crop_iwc_adapter\Plugin\MediaContextualCrop/ImageWidgetCrop::save_cropComment #23
flyke commentedI will in a moment. I am now debugging
media_contextual_crop_iwc_adapter/src/Plugin/MediaContextualCrop/ImageWidgetCrop.php.I can see there that $croptype gets the value 'hero' (which is indeed the applied crop style).
But inside $crop_settings['crop_wrapper'], there is only the '16_9' crop type, which is the first of the available crop types, but not the correct one.
So the code never passes this part:
because 'hero' is never equal to '16_9'.
That causes the code to never retrieve or create a crop, and thus returning NULL instead of a crop ID.
EDIT: I see now that we were looking at the same code at the same time, I just didn't realise it.
Comment #24
flyke commentedadded screenshot with arrow in image 1 for the part that we want to reach but never reach.
Comment #25
drdam commentedIn fact, the
$crop_settings['crop_wrapper']contain only the 16_9 and no hero here. (see #21)ok, so go to the media_contextual_crop.mode in the "template_preprocess_image_contextual_formatter" function, Line 241
Sorry for the "debuging method"
Comment #26
flyke commentedNo problem at all, I am actually glad I can be of assistance and that you are willing to help troubleshoot this.
Comment #27
drdam commentedOk, and in the
dsm($variables['item']['values']['image_crop']['crop_wrapper'])Comment #28
flyke commentedAnd here is the more detailed output from
dpm($variables['item']->image_crop);So yes, that has the wrong crop type inside crop_wrapper or its at least missing the correct one
Comment #29
drdam commentedAnd if you modifiy this crop, and resave the content ? the missing value are added ? (I imagine not ... )
Comment #30
drdam commentedThe bug may came from
Drupal\media_contextual_crop_iwc_adapter\Plugin\MediaContextualCrop\ImageWidgetCrop::processFieldDataCan you add a
dsmLine 114 & 158Comment #31
flyke commentedHere you go. I had to adjust the crop then resave my node to trigger that function.
Comment #32
flyke commentedI offer you my apologies, It seems that I have in all that testing switched from applying a hero crop to actually applying a 16_9 crop.
So the crop_applied = 1 is correct for the 16_9 crop at the moment. Still no working image unfortunatly.
Comment #33
drdam commentedCan you test, to be sure the crop is applied. I don't know how IWC really work...
And, if it's the case (no crop applied), an image must be processed and provide by the formater (from global crop settings, or not a not cropped image)
Comment #34
flyke commentedI can edit the image, set a crop, save the page.
The image is not shown as we already saw in numerous previous screenshots.
I can then edit the page and the image again, and I can see while editing that the crop is in exactly the same place as when I previously saved it. So on the Edit side, eveything works ?
But on the page itself, the image is not working because in media_contextual_crop_iwc_adapter/src/Plugin/MediaContextualCrop/ImageWidgetCrop.php in saveCrop it compare $croptype ('hero') to $crop_type (16_9);
Maybe because of some old crop data or something ? Can I clear all existing crops somehow to test this ?
Comment #35
drdam commentednow, in Drupal\media_contextual_crop_iwc_adapter\Plugin\MediaContextualCrop\ImageWidgetCrop::processFieldData
the "crop_values['crop_applied']" for the "hero" crop still have 0 as value ?
Comment #36
flyke commentedI found the reason why it did not work, where the 'hero' comes from and so also how to fix it.
I am sorry for your time. The frustrating thing about current implementation of cropping is that while you can select multiple possible cropping types on the Form Display, you are still required to set a single crop image style in the Manage display settings of the 'Contextual Crop Image' widget.
And apparently the crop I was trying to apply did not match the crop image style of the Manage display settings of the 'Contextual Crop Image' widget.
So everything works now, cropped image is generated and visible. A thousand times thank you for your time.
I have a way around this problem in other projects, I just removed it because it did no longer apply for Drupal 10. But I will try to refactor it for D10.
- Create a new 'Automatic crop' image style. It is empty without any operations.
- use preprocessing for this image style, get the crop type and hardwire a corresponding crop image style for each crop type
- apply that image style. this means that applying 'automatic_crop' image style for a 16_9 crop will actually apply the '16_9_crop' image style, while applying 'automatic_crop' image style for a 'hero' crop will actually apply the 'hero_crop' image style.
Comment #37
drdam commentedNo worry, there is this kind of "issues" that show something is really broken.
I don't understand the use_case here ...
In the media, you have a view_mode, and for the field_image you want have multiple style to be applied on the image ? Did you tried to use a Responsive_Image_Style instead of an "image_style" ?
Comment #38
drdam commentedComment #39
flyke commentedHi DrDam: Please look at the screenshot about what the use case is:
- User can apply a 16:9 crop
- OR user can apply a 16:9 small image crop
- OR user can apply a 80:39 crop
- OR user can apply a Hero crop
- OR user can apply a square crop
BUT
only when he applies the 16:9 crop it will work, because that is the image style that is selected for the Contextual Crop Image in Manage Display. It is that fact that you have to choose an image style there that screws up the possibility of giving the user the choice of what crop type he applies to the image. It would be better if there was no image style setting there and that the code would automatically figure it out, like: Is the applied crop a 16_9 crop, then get image style that uses 16_9 crop. If the applied crop is a hero crop, then get the image style that uses the hero crop. The manual option to set a fixed image style there should be removed in favor of code that auto detects and selects the correct image style based on the selected crop.
Comment #40
drdam commentedIf I understood correctly, you use CROP to impose some "image formats" (and the user is free to select the area), but the user "in addition" has the ability to choose which format he wants. want for its image (from the node form)?
Something like this module but applied to media with crop ?
Comment #41
flyke commentedHi, what I mean is: make the screenshot 'multiple possible crops.png' work, so user can choose any of the crops on the left side of that screenshot. But thats not possible because of screenshot 'manage display - set contextual crop image style.png' because we are forced to set a crop image style there. In this example, the 'Crop 16:9' image style is selected.
Only if the user chooses to use the 16:9 crop it will work because of that image style.
But if the user chooses to use any other crop (see the left side with possible crop options available to him), the image will be broken because it does not match that 'Crop 16:9' image style.
Therefor, I would like that that the manage display - Contextual Crop Image - Image style option is removed completely. So we dont need to set it. Instead the code from the Contextual Crop Image widget could figer out which image style to apply based on the selected crop type.
Comment #42
drdam commentedOK,
The scenario you want for the use case :
Step 1 : Insert Media in content
Step 2 : crop the media "what ever you want"
Step 3 : the image are display "as she is croped"
In fact, you don't even care about the type of crop : "display image as the user crop her"
Comment #43
flyke commentedYes, I think thats what I mean :-). So If the user crops a Media with a 1:1 crop or a 16:9 crop or a 4:3 crop, It will work and the crop will be generated and displayed without me having to bother to set an image style in the Manage Display.
Of course, If I have a 1:1 crop type, a 1:1 crop image style needs to exist. And if I have a 16:9 crop type, a 16:9 image style needs to exist. But I should not have to explicitly set a crop image style in Manage Display. It should automatically choose the correct one.
Comment #44
drdam commentedOk, It's definitly out of the media_contextual_crop feature...
You may create an "crop_as_you_want" plugin, which don't care the crop type will be used.
With this plugin, you create a "crop_as_you_want" image style and use it in your image formater.
Comment #45
flyke commentedSorry to bother again, Its not working on a fresh try :-(
I tried to crop from a clean start, So I deleted all existing crops:
drush php-eval '$crops = \Drupal::entityTypeManager()->getStorage("crop")->loadMultiple(); foreach ($crops as $crop) { $crop->delete(); }'I went to sites/default/files and deleted all cropped and crop duplicate images I could find.
I deleted the existing image blocks. I added 2 image blocks next to each other, both showing the same Media image, no cropping applied.
See 01 - before cropping.png
I then edited image 1 and added cropping to that image, see:
02 - cropping only 1 image.png
The cropped image is broken unfortunatly, see image:
03 - broken image after cropping.png
But, the image src now does contain a contextual id I think (289): https://mywebsite.com/sites/default/files/contextual/styles/crop_16_9/28...
Also, it passes the
if ($croptype != $crop_type) {statement (because '16_9' == '16_9') which is also good.A Crop entity is created and the function does return a valid crop ID.
I can DPM the Crop entity, see 04 - crop entity.png
So I think more is working than at the beginning of this issue, but somehow still no working image on this fresh try. Like in the description of this issue, '
file' and 'contextual_crop' parameters are still missing from the$request->queryinsidemedia_contextual_crop/src/Controller/ContextualImageStyleDownloadController.phpComment #46
drdam commentedDid you have any error in drupal watchdog ?
The URL in 03 are correct, so can you make a dsm for parameters of
MediaContextualCropService::createContextualizedDerivativePathComment #47
flyke commentedI will look further into this tomorrow if I find the time, new urgent stuff for other clients have came up.
But in the meantime I created a fix for the process function for when the necessary request query parameters are missing:
Comment #48
flyke commentedIt might not be pretty code but it's working for now with this code so I can focus on other urgent assignments.
I do hope to find the actual cause and I do hope I find the time to check
MediaContextualCropService::createContextualizedDerivativePathfor you.Will report back if I do.
Comment #49
drdam commentedIn fact, you are right, if I have the context, the file are not mandatory...
Comment #52
drdam commentedReleased in 2.0.4