title: WordPress convert image to WebP format programmatically with GD image engine
body: <p>There are many PHP solutions and WP plugins, they all come with additional options that I don't want/need, i.e. how the converted files are served, where they are stored, etc.</p>
  <p>I need none of all that and am after pure simple code using GD. I don't want to use a plugin, thank you.</p>
  <ol>
  <li><p>When should the encode happen ? At any time you know it is a good point in the hook routine, could be this <a href="https://make.wordpress.org/core/2019/11/05/use-of-the-wp_update_attachment_metadata-filter-as-upload-is-complete-hook/" rel="nofollow noreferrer">https://make.wordpress.org/core/2019/11/05/use-of-the-wp_update_attachment_metadata-filter-as-upload-is-complete-hook/</a> but if you know better or have another solution then use that and possibly let me know why you choose another hook. I would i.e. also be happy with firing a cron job once new images are uploaded if that is better. Also I don't need to have metadata of the converted images in the WP db, fine with having the original <code>.jpeg</code> files and their metadata in the Media Library, the <code>.webp</code> files are just there to be used inside the <code>picture</code> element.</p>
  </li>
  <li><p>Where should the converted files be stored? <code>wp-content/uploads/</code> default folder structure, <code>.webp</code> files should be next to <code>.jpeg</code> files all in there.</p>
  </li>
  <li><p>GD image engine should be used for the conversion. <a href="https://developer.wordpress.org/reference/classes/wp_image_editor_gd/" rel="nofollow noreferrer">https://developer.wordpress.org/reference/classes/wp_image_editor_gd/</a> Lately I find imagick just crashes or takes ages to do anything. In WP 5.2 things still worked just fine with imagick but there must have been changes introduced that make using imagick in later versions of WP useless. I find GD to me quite stable and fast, it does not matter it creates lossy WebP versions. The methods for the GD image engine from WP do not seem to include conversion/encoding <a href="https://developer.wordpress.org/reference/classes/wp_image_editor_gd/#methods" rel="nofollow noreferrer">https://developer.wordpress.org/reference/classes/wp_image_editor_gd/#methods</a> so I am also happy with any methods using in the GD module <a href="https://www.php.net/manual/en/book.image.php" rel="nofollow noreferrer">https://www.php.net/manual/en/book.image.php</a> concerning encoding to WebP.</p>
  </li>
  <li><p>To get rid of all the extra unneeded image sizes and options WP introduced over time I have these functions/filters in <code>functions.php</code>.</p>
  </li>
  </ol>
  <pre class="lang-php prettyprint-override"><code>function namespace_disable_image_sizes($sizes)
  {
      unset($sizes['thumbnail']);    // disable thumbnail size
      unset($sizes['medium']);       // disable medium size
      unset($sizes['large']);        // disable large size
      unset($sizes['medium_large']); // disable medium-large size
      unset($sizes['1536x1536']);    // disable 2x medium-large size
      unset($sizes['2048x2048']);    // disable 2x large size
  
      return $sizes;
  }
  add_action('intermediate_image_sizes_advanced', 'namespace_disable_image_sizes');
  
  // disable scaled image size
  add_filter('big_image_size_threshold', '__return_false');
  
  // disable rotated image size
  add_filter('wp_image_maybe_exif_rotate', '__return_false');
  
  // disable other image sizes
  function namespace_disable_other_image_sizes()
  {
      remove_image_size('post-thumbnail'); // disable images added via set_post_thumbnail_size()
      remove_image_size('another-size');   // disable any other added image sizes
  }
  add_action('init', 'namespace_disable_other_image_sizes');
  </code></pre>
  <ol start="5">
  <li><p>High resolution and large dimension images are to be converted, see attached image as example, image types can be <code>jpeg</code>, <code>png</code>, etc.</p>
  </li>
  <li><p>The sizes in place are more or less these with possible variations.</p>
  </li>
  </ol>
  <pre class="lang-php prettyprint-override"><code>add_image_size('4096w', 4096, 0);
  add_image_size('3200w', 3200, 0);
  add_image_size('2560w', 2560, 0);
  add_image_size('1920w', 1920, 0);
  add_image_size('1600w', 1600, 0);
  add_image_size('1280w', 1280, 0);
  add_image_size('1140w', 1140, 0);
  add_image_size('1024w', 1024, 0);
  add_image_size('960w', 960, 0);
  add_image_size('800w', 800, 0);
  add_image_size('768w', 768, 0);
  add_image_size('640w', 640, 0);
  add_image_size('425w', 425, 0);
  add_image_size('320w', 320, 0);
  add_image_size('240w', 240, 0);
  </code></pre>
  <ol start="7">
  <li>I use the <code>picture</code> element with more or less the following setup, so I have the browser decide what is needed and hence don't want/need server side <code>.htaccess</code> rules or backend configs. <a href="https://dev.opera.com/articles/responsive-images/" rel="nofollow noreferrer">https://dev.opera.com/articles/responsive-images/</a></li>
  </ol>
  <pre><code>&lt;picture&gt;
      &lt;source
          sizes=&quot;(min-width: 640px) 60vw, 100vw&quot;
          srcset=&quot;opera-200.webp 200w,
                  opera-400.webp 400w,
                  opera-800.webp 800w,
                  opera-1200.webp 1200w,
                  opera-1600.webp 1600w,
                  opera-2000.webp 2000w&quot;
          type=&quot;image/webp&quot;&gt;
      &lt;img
          src=&quot;opera-400.jpg&quot; alt=&quot;The Oslo Opera House&quot;
          sizes=&quot;(min-width: 640px) 60vw, 100vw&quot;
          srcset=&quot;opera-200.jpg 200w,
                  opera-400.jpg 400w,
                  opera-800.jpg 800w,
                  opera-1200.jpg 1200w,
                  opera-1600.jpg 1600w,
                  opera-2000.jpg 2000w&quot;&gt;
  &lt;/picture&gt;
  </code></pre>
  <ol start="8">
  <li>What have I tried?
  a) <a href="https://wordpress.stackexchange.com/questions/256351/hook-after-image-is-uploaded-and-image-sizes-generated/256352">https://wordpress.stackexchange.com/questions/256351/hook-after-image-is-uploaded-and-image-sizes-generated/256352</a>
  b) <a href="https://wordpress.stackexchange.com/questions/38582/hook-to-get-image-filename-when-it-is-uploaded">https://wordpress.stackexchange.com/questions/38582/hook-to-get-image-filename-when-it-is-uploaded</a>
  c) <a href="https://stackoverflow.com/questions/34377231/wordpress-blur-image-on-upload">WordPress - Blur Image on Upload</a>
  d) <a href="https://stackoverflow.com/questions/66815672/convert-images-into-webp">Convert Images into WebP</a>
  e) I have read through and understood <a href="https://kinsta.com/blog/wordpress-hooks/#filters-example-2-insert-content-after-a-post" rel="nofollow noreferrer">https://kinsta.com/blog/wordpress-hooks/#filters-example-2-insert-content-after-a-post</a> - <strong>however</strong> what I am missing is a way to <strong>see/know</strong> what data I am working with, i.e.</li>
  </ol>
  <pre class="lang-php prettyprint-override"><code>add_filter('wp_generate_attachment_metadata', 'gd_webp_encode', 10, 3);
  function gd_webp_encode($metadata, $attachment_id, $context){
      ob_start();
      echo $attachment_id;
      echo $metadata;
      ob_end_clean();
      return $metadata;
  }
  </code></pre>
  <p>will show me nothing, same with trying to log to console or to a file in the plugin folder. Without knowing/seeing the data and what variable names hold what data I am just doing trial and error and guessing, no coding. So given above code, how would it first of all be possible to see/know what variables hold what data at that point in time and make that readable somewhere, i.e. in a log file in the plugin folder?</p>
  <p>Bottom line, given above setup, help me understand what variables hold what data i.e. after upload in a hook and include code where I can make a WebP version of all the sizes and the original created using the GD image engine.</p>
  <p><a href="https://i.stack.imgur.com/DV0Ao.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/DV0Ao.png" alt="JPEG and WebP images next to each other in uploads folder" /></a></p>
  <p><a href="https://i.stack.imgur.com/enbWQ.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/enbWQ.jpg" alt="Example image" /></a></p>