Answers.Body: <p>By default, Craft will defer creating image transforms to avoid slowing down page loads. Instead, transforms are queued and executed asynchronously. You can change this behaviour to always generate transforms directly using the  <a href="https://craftcms.com/docs/3.x/config/config-settings.html#generatetransformsbeforepageload" rel="nofollow noreferrer">generateTransformsBeforePageLoad config setting</a>.</p>
  <p>Of course, you don't have control over the config if you're working on a plugin. In this case, you will have to find a way to force Craft to create the  transform immediately. Without the config setting, I haven't actually found a straightforward way of doing that. <a href="https://docs.craftcms.com/api/v3/craft-elements-asset.html#method-geturl" rel="nofollow noreferrer">Asset::getUrl()</a> has an optional second parameter for that behaviour – but <a href="https://docs.craftcms.com/api/v3/craft-elements-asset.html#method-copywithtransform" rel="nofollow noreferrer">Asset::copyWithTransform()</a> does not, and <a href="https://docs.craftcms.com/api/v3/craft-elements-asset.html#method-getcontents" rel="nofollow noreferrer">Asset::getContents()</a> does not accept a transform argument at all.</p>
  <p>If you check the <a href="https://github.com/craftcms/cms/blob/87c6e788af4d463285d5cfd82f143596e4407ee3/src/services/Assets.php#L644" rel="nofollow noreferrer">source code for Asset::getUrl()</a>, it uses <a href="https://docs.craftcms.com/api/v3/craft-services-assettransforms.html#method-ensuretransformurlbyindexmodel" rel="nofollow noreferrer">craft\Services\AssetTransforms:: ensureTransformUrlByIndexModel()</a> to get execute transforms. That returns an asset URL, but under the hood it uses <a href="http://%20%20%20%20private%20function%20_createTransformForAsset(Asset%20$asset,%20AssetTransformIndex%20$index)" rel="nofollow noreferrer">AssetTransforms::_createTransformForAsset</a> which executes the actual image transformation. This method is private unfortunately, so you can't use it directly. But using <code>Asset::getUrl()</code> with <code>$generateNow</code> set to <code>true</code> should suffice to force Craft to generate the transform synchronously. Though you might need to query the asset from the database again to get the actual transformed content.</p>
  <p>Sorry this answer isn't complete, but it should point you in the right direction. Maybe also post this as a discussion / feature request to Github, as arguably this is a pretty common requirement.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-08-03T13:50:22.360Z
Answers.Text: Thanks so much for explaining! 
Answers.UserDisplayName: tomkiss
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-08-03T14:16:31.500Z
Answers.Text: @tomkiss You're welcome! If the approach outlined here works, I'd be interested in seeing some working examples for this as well, or hearing about points you got stuck on. Craft could definitely use a utility function for generating transforms immediately ...
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-08-08T17:49:06.587Z
Answers.Text: Thanks! Yes, as a bit of background - this was for my first plugin. I was finding multiple related issues using assets and so in the end opted to resize directly in PHP. You can see my plugin over here: https://github.com/dodecastudio/craft-blurhash It's my first plugin so I'm not quite sure how "correct" I've achieved the result with, but hopefully it's all improvements from here on out.
Answers.UserDisplayName: tomkiss
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-08-09T07:35:32.157Z
Answers.Text: @tomkiss Yeah that's probably the easier approach … cool plugin! One thing I noticed is that it's difficult to call the functions provided by the module from PHP since they're tightly coupled to the Twig extension. One use-case I can think of would be to compute blurhashes in the entries save hook and store them for later use in a template. Right now that's difficult because of that coupling. I'd move all functions to a [service class](https://craftcms.com/docs/3.x/extend/services.html) and call those from the Twig plugin, allowing users to call the service class functions directly from PHP.
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-11-29T14:47:33.820Z
Answers.Text: Hey @MoritzLost, just wanted to say thanks for your suggestion back in the summer. I moved all the functionality to Service classes, which then made a GraphQL feature request much easier to implement  Credited you, cheers https://github.com/dodecastudio/craft-blurhash/releases/tag/v1.1.0
Answers.UserDisplayName: tomkiss
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-11-29T14:55:09.780Z
Answers.Text: @tomkiss Glad the suggestion helped! The plugin looks great, I might give it a try as well :)
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-08-03T13:40:42.080Z
Answers.LastActivityDate: 2021-08-03T13:40:42.080Z
Answers.UserDisplayName: MoritzLost
Body: <p>I'm working with images in a plugin but getting a bit stuck reading a transformed image.</p>
  <p>Given the following code:</p>
  <pre><code>$assetTransform = new AssetTransform([
      'mode' =&gt; 'stretch',
      'width' =&gt;  64, 
      'height' =&gt; 64,
  ]);
  $transformedAsset = $asset-&gt;copyWithTransform($assetTransform);
  $image = imagecreatefromstring($transformedAsset-&gt;getContents());
  $width = imagesx($image);
  </code></pre>
  <p>...I would expect the value of <code>$width;</code> to be <code>64</code>. But it returns the width of the original untransformed image.</p>
  <p>Incidentally, the width of <code>$transformedAsset-&gt;width</code> returns <code>64</code>.</p>
  <p>Does anyone understand why this occurs?</p>
  
Tags: <assets><gd>
Title: Reading transformed image data in plugin
ThreadText: # Reading transformed image data in plugin
  
  (Asked by: username_0 on 2021-08-03)
  
  I'm working with images in a plugin but getting a bit stuck reading a transformed image.
  
  Given the following code:
  
  ```
  $assetTransform = new AssetTransform([
      'mode' => 'stretch',
      'width' =>  64, 
      'height' => 64,
  ]);
  $transformedAsset = $asset->copyWithTransform($assetTransform);
  $image = imagecreatefromstring($transformedAsset->getContents());
  $width = imagesx($image);
  
  ```
  
  ...I would expect the value of `$width;` to be `64`. But it returns the width of the original untransformed image.
  
  Incidentally, the width of `$transformedAsset->width` returns `64`.
  
  Does anyone understand why this occurs?
  
  **Tags:** assets, gd
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-08-03. Score: 2
  
  By default, Craft will defer creating image transforms to avoid slowing down page loads. Instead, transforms are queued and executed asynchronously. You can change this behaviour to always generate transforms directly using the [generateTransformsBeforePageLoad config setting](https://craftcms.com/docs/3.x/config/config-settings.html#generatetransformsbeforepageload).
  
  Of course, you don't have control over the config if you're working on a plugin. In this case, you will have to find a way to force Craft to create the transform immediately. Without the config setting, I haven't actually found a straightforward way of doing that. [Asset::getUrl()](https://docs.craftcms.com/api/v3/craft-elements-asset.html#method-geturl) has an optional second parameter for that behaviour – but [Asset::copyWithTransform()](https://docs.craftcms.com/api/v3/craft-elements-asset.html#method-copywithtransform) does not, and [Asset::getContents()](https://docs.craftcms.com/api/v3/craft-elements-asset.html#method-getcontents) does not accept a transform argument at all.
  
  If you check the [source code for Asset::getUrl()](https://github.com/craftcms/cms/blob/87c6e788af4d463285d5cfd82f143596e4407ee3/src/services/Assets.php#L644), it uses [craft\Services\AssetTransforms:: ensureTransformUrlByIndexModel()](https://docs.craftcms.com/api/v3/craft-services-assettransforms.html#method-ensuretransformurlbyindexmodel) to get execute transforms. That returns an asset URL, but under the hood it uses [AssetTransforms::\_createTransformForAsset](http://%20%20%20%20private%20function%20_createTransformForAsset(Asset%20$asset,%20AssetTransformIndex%20$index)) which executes the actual image transformation. This method is private unfortunately, so you can't use it directly. But using `Asset::getUrl()` with `$generateNow` set to `true` should suffice to force Craft to generate the transform synchronously. Though you might need to query the asset from the database again to get the actual transformed content.
  
  Sorry this answer isn't complete, but it should point you in the right direction. Maybe also post this as a discussion / feature request to Github, as arguably this is a pretty common requirement.
  
  > **Comments:**
  > **username_0**: Thanks so much for explaining!   
  > **username_1**: @username_0 You're welcome! If the approach outlined here works, I'd be interested in seeing some working examples for this as well, or hearing about points you got stuck on. Craft could definitely use a utility function for generating transforms immediately ...  
  > **username_0**: Thanks! Yes, as a bit of background - this was for my first plugin. I was finding multiple related issues using assets and so in the end opted to resize directly in PHP. You can see my plugin over here: https://github.com/dodecastudio/craft-blurhash It's my first plugin so I'm not quite sure how "correct" I've achieved the result with, but hopefully it's all improvements from here on out.  
  > **username_1**: @username_0 Yeah that's probably the easier approach … cool plugin! One thing I noticed is that it's difficult to call the functions provided by the module from PHP since they're tightly coupled to the Twig extension. One use-case I can think of would be to compute blurhashes in the entries save hook and store them for later use in a template. Right now that's difficult because of that coupling. I'd move all functions to a [service class](https://craftcms.com/docs/3.x/extend/services.html) and call those from the Twig plugin, allowing users to call the service class functions directly from PHP.  
  > **username_0**: Hey @username_1, just wanted to say thanks for your suggestion back in the summer. I moved all the functionality to Service classes, which then made a GraphQL feature request much easier to implement  Credited you, cheers https://github.com/dodecastudio/craft-blurhash/releases/tag/v1.1.0  
  > **username_1**: @username_0 Glad the suggestion helped! The plugin looks great, I might give it a try as well :)  
  
  ---
  
  