Author Topic: webp and thumbnail  (Read 3057 times)

jflash

  • 3rd party VirtueMart Developer
  • Jr. Member
  • *
  • Posts: 70
webp and thumbnail
« 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

GJC Web Design

  • 3rd party VirtueMart Developer
  • Super Hero
  • *
  • Posts: 10882
  • Virtuemart, Joomla & php developer
    • GJC Web Design
  • VirtueMart Version: 3.8.8
Re: webp and thumbnail
« Reply #1 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
GJC Web Design
VirtueMart and Joomla Developers - php developers https://www.gjcwebdesign.com
VM3 AusPost Shipping Plugin - e-go Shipping Plugin - VM3 Postcode Shipping Plugin - Radius Shipping Plugin - VM3 NZ Post Shipping Plugin - AusPost Estimator
Samport Payment Plugin - EcomMerchant Payment Plugin - ccBill payment Plugin
VM2 Product Lock Extension - VM2 Preconfig Adresses Extension - TaxCloud USA Taxes Plugin - Virtuemart  Product Review Component
https://extensions.joomla.org/profile/profile/details/67210
Contact for any VirtueMart or Joomla development & customisation

jflash

  • 3rd party VirtueMart Developer
  • Jr. Member
  • *
  • Posts: 70
Re: webp and thumbnail
« Reply #2 on: January 26, 2022, 20:38:39 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.

pinochico

  • 3rd party VirtueMart Developer
  • Full Member
  • *
  • Posts: 1707
    • MiniJoomla
  • Skype Name: support-easysoftware
  • VirtueMart Version: 3
Re: webp and thumbnail
« Reply #3 on: January 27, 2022, 12:22:33 PM »
Quote
almost 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
www.minijoomla.org  - new portal for Joomla!, Virtuemart and other extensions
XML Easy Feeder - feeds for FB, GMC,.. from products, categories, orders, users, articles, acymailing subscribers and database table
Virtuemart Email Manager - customs email templates
Import products for Virtuemart - from CSV and XML
Rich Snippets - Google Structured Data
VirtueMart Products Extended - Slider with products, show Others bought, Products by CF ID and others filtering products

Studio 42

  • Contributing Developer
  • Sr. Member
  • *
  • Posts: 4728
  • Joomla & Virtuemart developper
    • Studio 42 - Virtuemart & Joomla extentions
  • VirtueMart Version: 2.6 & 3
Re: webp and thumbnail
« Reply #4 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

jflash

  • 3rd party VirtueMart Developer
  • Jr. Member
  • *
  • Posts: 70
Re: webp and thumbnail
« Reply #5 on: January 28, 2022, 08:03:52 AM »
Yes! Thank you all!
Solution with DJ-WebP extension and overwriting fancybox works :)

infyways

  • Beginner
  • *
  • Posts: 1
    • Infyways
  • Skype Name: infyways.solutions
Re: webp and thumbnail
« Reply #6 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

alxgan

  • Beginner
  • *
  • Posts: 2
  • A beginner
Re: webp and thumbnail
« Reply #7 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:
Code: [Select]
<?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