VirtueMart Forum

VirtueMart 2 + 3 + 4 => Product creation => Topic started by: jflash on January 26, 2022, 15:09:45 PM

Title: webp and thumbnail
Post by: jflash on January 26, 2022, 15:09:45 PM
Hello!

Are webp format supported with Virtuemart? It saves webp image to product but does not generate thumbnail. Tried it in hosting and in Xampp (localhost). With png or jpg all works.
VirtueMart 3.8.8 10472
Joomla! 3.10.5

Jüri
Title: Re: webp and thumbnail
Post by: GJC Web Design on January 26, 2022, 17:49:33 PM
VM will use any image but I use https://dj-extensions.com/dj-webp as a system plug to replace them

works out of the box

https://www.stonemania.co.uk/categories/cabochon-gemstones
Title: Re: webp and thumbnail
Post by: jflash on January 26, 2022, 20:38:39 PM
Quote from: GJC Web Design on January 26, 2022, 17:49:33 PM
VM will use any image but I use https://dj-extensions.com/dj-webp as a system plug to replace them
So i use jpg in administration and this plugin generates webp image from the fly and all works? OK, almost works - if i click on image then in lightbox i see some text/code not image.
Title: Re: webp and thumbnail
Post by: pinochico on January 27, 2022, 12:22:33 PM
Quotealmost works - if i click on image then in lightbox i see some text/code not image.

That is right.

https://dj-extensions.com/dj-webp is a 3-page extension and works systemically throughout Joomla.
VirtueMrt uses a non-system fancybox that cannot work with new extensions.

You need to contact the VM DEV team to modify the core VM
Title: Re: webp and thumbnail
Post by: Studio 42 on January 28, 2022, 00:28:02 AM
You have allready an answer for this. See https://forum.virtuemart.net/index.php?topic=146852.0
Title: Re: webp and thumbnail
Post by: jflash on January 28, 2022, 08:03:52 AM
Yes! Thank you all!
Solution with DJ-WebP extension and overwriting fancybox works :)
Title: Re: webp and thumbnail
Post by: infyways on October 11, 2023, 22:18:35 PM
We've developed an extension that automates the conversion of PNG and JPG images to the efficient WebP format. This tool is now compatible with Virtuemart 4, enhancing your website's loading speed. https://store.infyways.com/webp-converter-75.html
Title: Re: webp and thumbnail
Post by: alxgan on October 11, 2023, 23:49:48 PM
Hello,
You can "enable" webp files and thumbnail creation but you need to modify some helpers files: /administrator/components/com_virtuemart/helpers/img2thumb.php and /administrator/components/com_virtuemart/helpers/mediahandler.php. Doing this is not recommended but I don't know yet how to override Joomla MCV components. Also you can lose the modification on your next VM update.
In mediahandler.php:
(~line 401)
static private function isImage($file_url){

      $file_extension = strtolower(JFile::getExt($file_url));

      if($file_extension == 'jpg' || $file_extension == 'jpeg' || $file_extension == 'png' || $file_extension == 'gif' || $file_extension == 'webp'){
         $isImage = TRUE;

(~line 477)
function displaySupportedImageTypes() {
      $aSupportedTypes = array();

      $aPossibleImageTypeBits = array();

      if(defined('IMG_GIF')) {
         $aPossibleImageTypeBits[IMG_GIF] = 'GIF';
      }
      if(defined('IMG_JPG')) {
         $aPossibleImageTypeBits[IMG_JPG] = 'JPG';
      }
      if(defined('IMG_PNG')) {
         $aPossibleImageTypeBits[IMG_PNG] = 'PNG';
      }
      if(defined('IMG_WBMP')) {
         $aPossibleImageTypeBits[IMG_WBMP] = 'WBMP';
      }
      if(defined('IMG_WEBP')) {
         $aPossibleImageTypeBits[IMG_WEBP] = 'WEBP';
      }



All img2thumb.php:

<?php

defined 
('_JEXEC') or die();

/**
 * class Image2Thumbnail
 * Thumbnail creation with PHP4 and GDLib (recommended, but not mandatory: 2.0.1 !)
 *
 * @author     Andreas Martens <heyn@plautdietsch.de>
 * @author     Patrick Teague <webdude@veslach.com>
 * @author     Soeren Eberhardt <soeren|at|virtuemart.net>
 * @author      Max Milbers
 *@version   1.0b
 *@date       modified 11/22/2004
 *@modifications
 *   - added support for GDLib < 2.0.1
 *   - added support for reading gif images
 *   - makes jpg thumbnails
 *   - changed several groups of 'if' statements to single 'switch' statements
 *   - commented out original code so modification could be identified.
 * @copyright 2004? The Copyright maybe got lost. So I set now our latest known date (by svn)
 * @copyright 2011 - 2018 The VirtueMart Team
 * @license https://www.gnu.org/licenses/gpl-3.0.html GNU/GPL
 */

class Img2Thumb   {
// New modification
/**
*   private variables - do not use
*
*   @var int $bg_red            0-255 - red color variable for background filler
*   @var int $bg_green            0-255 - green color variable for background filler
*   @var int $bg_blue            0-255 - blue color variable for background filler
*   @var int $maxSize            0-1 - true/false - should thumbnail be filled to max pixels
*/
   
var $bg_red;
   var 
$bg_green;
   var 
$bg_blue;
   var 
$maxSize;
   
/**
    * @var string Filename for the thumbnail
    */
   
var $fileout;

/**
*   Constructor - requires following vars:
*
*   @param string $filename         image path
*
*   These are additional vars:
*
*   @param int $newxsize         new maximum image width
*   @param int $newysize         new maximum image height
*   @param string $fileout         output image path
*   @param int $thumbMaxSize      whether thumbnail should have background fill to make it exactly $newxsize x $newysize
*   @param int $bgred            0-255 - red color variable for background filler
*   @param int $bggreen            0-255 - green color variable for background filler
*   @param int $bgblue            0-255 - blue color variable for background filler
*
*/
   
function __construct($filename$newxsize=60$newysize=60$fileout='',
      
$thumbMaxSize=0$bgred=0$bggreen=0$bgblue=0)
   {

      
//Some big pictures need that
      
VmConfig::ensureMemoryLimit(128);

      
//   New modification - checks color int to be sure within range
      
if($thumbMaxSize)
      {
         
$this->maxSize true;
      }
      else
      {
         
$this->maxSize false;
      }
      if(
$bgred>=|| $bgred<=255)
      {
         
$this->bg_red $bgred;
      }
      else
      {
         
$this->bg_red 0;
      }
      if(
$bggreen>=|| $bggreen<=255)
      {
         
$this->bg_green $bggreen;
      }
      else
      {
         
$this->bg_green 0;
      }
      if(
$bgblue>=|| $bgblue<=255)
      {
         
$this->bg_blue $bgblue;
      }
      else
      {
         
$this->bg_blue 0;
      }

      
$this->NewImgCreate($filename,$newxsize,$newysize,$fileout);
   }

/**
*
*   private function - do not call
*
*/
   
private function NewImgCreate($filename,$newxsize,$newysize,$fileout)
   {

      if(
function_exists('imagecreatefromstring')){

         if( 
substr$filename02) == "//" ) {
            try {
               
$resObj VmConnector::getHttp(array(), array('curl''stream'))->get($filename);
               
//vmdebug('Object per URL',$resObj);
               
if($resObj->code!=200){
                  
vmdebug('URL does not exists',$filename,$resObj);
                  
vmError(vmText::sprintf('COM_VIRTUEMART_FILE_NOT_FOUND',$filename));
               } else {
                  
$content $resObj->body;
               }
            } catch (
RuntimeException $e) {
               
vmError(vmText::sprintf('COM_VIRTUEMART_FILE_NOT_FOUND',$filename));
            }
         } else {
            
$content file_get_contents($filename);
         }

         if(
$content){
            
$gd = @imagecreatefromstring($content);
            if (
$gd === false) {
               
vmError('Img2Thumb NewImgCreate with imagecreatefromstring failed '.$filename.' ');
            } else {
               
$pathinfo pathinfo$fileout );
               
$type = empty($type)? $pathinfo['extension']:$type;
               
$this->fileout $fileout;

               
$orig_size 0;
               if( 
substr$filename02) == "//" ) {
                  if (!empty(
$fileout))
                  {
                     
$this-> NewImgSave($gd,$fileout,$type);
                     
$orig_size getimagesize($fileout);
                  }
               }

               
$new_img =$this->NewImgResize($gd,$newxsize,$newysize,$filename,$orig_size);
               if (!empty(
$fileout))
               {
                  
$this-> NewImgSave($new_img,$fileout,$type);
               }
               else
               {
                  
$this->NewImgShow($new_img,$type);
               }

               
ImageDestroy($new_img);
               
ImageDestroy($gd);
            }
         }

      } else {
         
$type $this->GetImgType($filename);

         
$pathinfo pathinfo$fileout );

         
$type = empty($type)? $pathinfo['extension']:$type;

         if( empty( 
$pathinfo['extension'])) {
            
$fileout .= '.'.$type;
         }
         
$this->fileout $fileout;

         switch(
$type){

            case 
"gif":
               
// unfortunately this function does not work on windows
               // via the precompiled php installation
               // it should work on all other systems however.
               
if( function_exists("imagecreatefromgif") ) {

                  
$orig_img imagecreatefromgif($filename);
               } else {
                  
$app JFactory::getApplication();
                  
$app->enqueueMessage('This server does NOT suppport auto generating Thumbnails by gif');
                  return 
false;
               }
               break;
            case 
"jpg":
               if( 
function_exists("imagecreatefromjpeg") ) {
                  if(
$this->check_jpeg($filename,true)){
                     
$orig_img imagecreatefromjpeg($filename);
                  } else {
                     
vmWarn('Img2Thumb NewImgCreate $orig_img empty, type was not in switch for file '.$filename.' this happens due missing exif data or broken origin file');
                     return 
false;
                  }

               } else {
                  
$app JFactory::getApplication();
                  
$app->enqueueMessage('This server does NOT suppport auto generating Thumbnails by jpg');
                  return 
false;
               }
               break;
            case 
"png":
               if( 
function_exists("imagecreatefrompng") ) {
                  
$orig_img imagecreatefrompng($filename);
               } else {
                  
$app JFactory::getApplication();
                  
$app->enqueueMessage('This server does NOT suppport auto generating Thumbnails by png');
                  return 
false;
               }
               break;
                case 
"webp":
                    if( 
function_exists("imagecreatefromwebp") ) {
                        
$orig_img imagecreatefromwebp($filename);
                    } else {
                        
$app JFactory::getApplication();
                        
$app->enqueueMessage('This server does NOT suppport auto generating Thumbnails by webp');
                        return 
false;
                    }
                    break;

         }

         if(empty(
$orig_img)){
            
vmWarn('Img2Thumb NewImgCreate $orig_img empty, type was not in switch for file '.$filename.' this happens due missing exif data or broken origin file');
            return 
false;
         } else {
            
$new_img =$this->NewImgResize($orig_img,$newxsize,$newysize,$filename);
            if (!empty(
$fileout))
            {
               
$this-> NewImgSave($new_img,$fileout,$type);
            }
            else
            {
               
$this->NewImgShow($new_img,$type);
            }

            
ImageDestroy($new_img);
            
ImageDestroy($orig_img);
         }
      }
   }

   
/**
    * check for jpeg file header and footer - also try to fix it
    * @author willertan1980 at yahoo dot com http://www.php.net/manual/de/function.imagecreatefromjpeg.php
    * @param $f
    * @param bool $fix
    * @return bool
    */
   
function check_jpeg($f$fix=false ){

      if ( 
false !== (@$fd fopen($f'r+b' )) ){
         if ( 
fread($fd,2)==chr(255).chr(216) ){
            
fseek $fd, -2SEEK_END );
            if ( 
fread($fd,2)==chr(255).chr(217) ){
               
fclose($fd);
               return 
true;
            }else{
               if ( 
$fix && fwrite($fd,chr(255).chr(217)) ){vmdebug('corrected jpg '.$f);return true;}
               
fclose($fd);
               
vmInfo('broken jpg, cannot create thumb '.$f);
               return 
false;
            }
         }else{
fclose($fd); return false;}
      }else{
         
vmWarn('check_jpeg could not open file '.$f);
         return 
false;
      }
   }

   
/**

   /**
*   Maybe adding sharpening with
*            $sharpenMatrix = array
            (
                array(-1.2, -1, -1.2),
                array(-1, 20, -1),
                array(-1.2, -1, -1.2)
            );

            // calculate the sharpen divisor
            $divisor = array_sum(array_map('array_sum', $sharpenMatrix));

            $offset = 0;

            // apply the matrix
            imageconvolution($img, $sharpenMatrix, $divisor, $offset);
*
*   private function - do not call
*   includes function ImageCreateTrueColor and ImageCopyResampled which are available only under GD 2.0.1 or higher !
*/
   
private function NewImgResize($orig_img,$newxsize,$newysize,$filename$orig_size 0)
   {
      
//getimagesize returns array
      // [0] = width in pixels
      // [1] = height in pixels
      // [2] = type
      // [3] = img tag "width=xx height=xx" values

      
if(empty($orig_size))$orig_size getimagesize($filename);

      
$newxsize = (int)$newxsize;
      
$newysize = (int)$newysize;
      if(empty(
$newxsize) and empty($newysize)){
         
vmWarn('NewImgResize failed x,y = 0','NewImgResize failed x,y = 0');
         return 
false;
      } else {
         if(empty(
$newxsize)){
            
//Recalculate newxsize
            
$newxsize $newysize/$orig_size[1] * $orig_size[0];
         } else if(empty(
$newysize)){
            
$newysize $newxsize/$orig_size[0] * $orig_size[1];
         }
      }
      
$maxX $newxsize;
      
$maxY $newysize;

      if (
$orig_size[0]<$orig_size[1])
      {
         
$newxsize = (int)$newysize * ($orig_size[0]/$orig_size[1]);
         
$adjustX = (int)($maxX $newxsize)/2;
         
$adjustY 0;
      }
      else
      {
         
$newysize = (int) $newxsize / ($orig_size[0]/$orig_size[1]);
         
$adjustX 0;
         
$adjustY = (int)($maxY $newysize)/2;
      }

      
/* Original code removed to allow for maxSize thumbnails
      $im_out = ImageCreateTrueColor($newxsize,$newysize);
      ImageCopyResampled($im_out, $orig_img, 0, 0, 0, 0,
         $newxsize, $newysize,$orig_size[0], $orig_size[1]);
      */

      //   New modification - creates new image at maxSize
      
if( $this->maxSize )
      {
         if( 
function_exists("imagecreatetruecolor") )
           
$im_out imagecreatetruecolor($maxX,$maxY);
         else
           
$im_out imagecreate($maxX,$maxY);

         
// Need to image fill just in case image is transparent, don't always want black background
         
$bgfill imagecolorallocate$im_out$this->bg_red$this->bg_green$this->bg_blue );

         if( 
function_exists"imageAntiAlias" )) {
            
imageAntiAlias($im_out,true);
         }
           
imagealphablending($im_outfalse);
          if( 
function_exists"imagesavealpha")) {
             
imagesavealpha($im_out,true);
          }
          if( 
function_exists"imagecolorallocatealpha")) {
             
$transparent imagecolorallocatealpha($im_out255255255127);
          }

         
//imagefill( $im_out, 0,0, $bgfill );
         
if( function_exists("imagecopyresampled") ){
            
ImageCopyResampled($im_out$orig_img$adjustX$adjustY00$newxsize$newysize,$orig_size[0], $orig_size[1]);
         }
         else {
            
ImageCopyResized($im_out$orig_img$adjustX$adjustY00$newxsize$newysize,$orig_size[0], $orig_size[1]);
         }

      }
      else
      {

         if( 
function_exists("imagecreatetruecolor") )
           
$im_out ImageCreateTrueColor($newxsize,$newysize);
         else
           
$im_out imagecreate($newxsize,$newysize);

         if( 
function_exists"imageAntiAlias" ))
           
imageAntiAlias($im_out,true);
           
imagealphablending($im_outfalse);
          if( 
function_exists"imagesavealpha"))
           
imagesavealpha($im_out,true);
          if( 
function_exists"imagecolorallocatealpha"))
           
$transparent imagecolorallocatealpha($im_out255255255127);

         if( 
function_exists("imagecopyresampled") )
           
ImageCopyResampled($im_out$orig_img0000$newxsize$newysize,$orig_size[0], $orig_size[1]);
         else
           
ImageCopyResized($im_out$orig_img0000$newxsize$newysize,$orig_size[0], $orig_size[1]);
      }


      return 
$im_out;
   }

   
/**
*
*   private function - do not call
*
*/
   
private function NewImgSave($new_img,$fileout,$type)
   {
      if( !@
is_dirdirname($fileout))) {
         @
mkdirdirname($fileout) );
      }
      switch(
$type)
      {
         case 
"gif":
            if( !
function_exists("imagegif") )
            {
               if (
strtolower(substr($fileout,strlen($fileout)-4,4))!=".gif") {
                  
$fileout .= ".png";
               }
               return 
imagepng($new_img,$fileout);

            }
            else {
               if (
strtolower(substr($fileout,strlen($fileout)-4,4))!=".gif") {
                  
$fileout .= '.gif';
               }
               return 
imagegif$new_img$fileout );

            }
            break;
         case 
"jpg":
            if (
strtolower(substr($fileout,strlen($fileout)-4,4))!=".jpg")
               
$fileout .= ".jpg";
            
$quality VmConfig::get('img_quality'89);
            return 
imagejpeg($new_img$fileout$quality);
            break;
         case 
"png":
            if (
strtolower(substr($fileout,strlen($fileout)-4,4))!=".png")
               
$fileout .= ".png";
            return 
imagepng($new_img,$fileout);
            break;
            case 
"webp":
                if (
strtolower(substr($fileout,strlen($fileout)-5,5))!=".webp")
                    
$fileout .= ".webp";
                return 
imagewebp($new_img,$fileout);
                break;
      }
   }

   
/**
*
*   private function - do not call
*
*/
   
private function NewImgShow($new_img,$type)
   {
      
/* Original code removed in favor of 'switch' statement
      if ($type=="png")
      {
         header ("Content-type: image/png");
          return imagepng($new_img);
      }
      if ($type=="jpg")
      {
         header ("Content-type: image/jpeg");
          return imagejpeg($new_img);
      }
      */
      
switch($type)
      {
         case 
"gif":
            if( 
function_exists("imagegif") )
            {
               
header ("Content-type: image/gif");
               return 
imagegif($new_img);
               break;
            }
            
//either there is missing a break or the else $this->NewImgShow is unecessary
            
else
               
$this->NewImgShow$new_img"jpg" );

         case 
"jpg":
            
header ("Content-type: image/jpeg");
            return 
imagejpeg($new_img);
            break;
         case 
"png":
            
header ("Content-type: image/png");
            return 
imagepng($new_img);
            break;
            case 
"webp":
                
header ("Content-type: image/webp");
                return 
imagewebp($new_img);
                break;
      }
   }

   
/**
*
*   private function - do not call
*
*   1 = GIF, 2 = JPG, 3 = PNG, 4 = SWF,
*   5 = PSD, 6 = BMP,
*   7 = TIFF(intel byte order),
*   8 = TIFF(motorola byte order),
*   9 = JPC, 10 = JP2, 11 = JPX,
*   12 = JB2, 13 = SWC, 14 = IFF
*/
   
private function GetImgType($filename)
   {
        
$imageExtensionsArray = array(
            
IMAGETYPE_GIF => 'gif',
            
IMAGETYPE_JPEG => 'jpg',
            
IMAGETYPE_PNG => 'png',
            
IMAGETYPE_SWF => 'swf',
            
IMAGETYPE_PSD => 'psd',
            
IMAGETYPE_BMP => 'bmp',
            
IMAGETYPE_TIFF_II => 'tiff',
            
IMAGETYPE_TIFF_MM => 'tiff',
            
IMAGETYPE_JPC => 'jpc',
            
IMAGETYPE_JP2 => 'jp2',
            
IMAGETYPE_JPX => 'jpx',
            
IMAGETYPE_JB2 => 'jb2',
            
IMAGETYPE_SWC => 'swc',
            
IMAGETYPE_IFF => 'iff',
            
IMAGETYPE_WBMP => 'wbmp',
            
IMAGETYPE_XBM => 'xbm',
            
IMAGETYPE_ICO => 'ico',
            
IMAGETYPE_WEBP => 'webp',
            
IMAGETYPE_AVIF => 'avif'
        
);

      
$info getimagesize($filename);
        if (isset(
$imageExtensionsArray[$info[2]])){
            return 
$imageExtensionsArray[$info[2]];
        }
        else return 
false;

   }

}


Don't know if it's required but I also added image/webp mimetype in Joomla settings, Media, to allow them to be uploded.

This modification works for me on J4, VM4.20, PHP8