X-Cart: shopping cart software

X-Cart forums (https://forum.x-cart.com/index.php)
-   Dev Questions (https://forum.x-cart.com/forumdisplay.php?f=20)
-   -   Easy dynamic thumbnail generation (https://forum.x-cart.com/showthread.php?t=22308)

Alltribes 06-06-2006 05:55 AM

Easy dynamic thumbnail generation
 
This isn't a mod for x-cart really. It's a plugin for Smarty: http://www.cerdmann.com/thumb/

See the above link for info on how to use the various paramaters. You'll need to create a images/cache/ directory, or edit the php to point to where you want the thumbnails to be cached.

Save the following code as function.thumb.php and put it in your smarty plugins directory.

Code:

<?php
/*
 * Smarty plugin "Thumb"
 * Purpose: creates cached thumbnails
 * Home: http://www.cerdmann.com/thumb/
 * Copyright (C) 2005 Christoph Erdmann
 *
 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
 * -------------------------------------------------------------
 * Author:  Christoph Erdmann (CE)
 * Internet: http://www.cerdmann.com
 *
 * Author: Benjamin Fleckenstein (BF)
 * Internet: http://www.benjaminfleckenstein.de
 *
 * Author: Marcus Gueldenmeister (MG)
 * Internet: http://www.gueldenmeister.de/marcus/
 *
 * Author: Andreas Bц╤sch (AB)

 * Changelog:
 * 2005-10-31 Fixed some small bugs (CE)
 * 2005-10-09 Rewrote crop-function (CE)
 * 2005-10-08 Decreased processing time by prescaling linear and cleaned code (CE)
 * 2005-07-13 Set crop=true as standard (CE)
 * 2005-07-12 Added crop parameter. Original code by "djneoform at gmail dot com" (AB)
 * 2005-07-02 Found a stupid mistake. Should be faster now (CE)
 * 2005-06-02 Added file_exists(SOURCE)-trigger (CE)
 * 2005-06-02 Added extrapolate parameter (CE)
 * 2005-06-12 Bugfix alt/title (MG)
 * 2005-06-10 Bugfix (MG)
 * 2005-06-02 Added window parameter (MG)
 * 2005-06-02 Made grey banner configurable, added possibility to keep format in thumbs
                          made cache path changeable (BF & MG)
 * 2004-12-01 New link, hint, quality and type parameter (CE)
 * 2004-12-02 Intergrated UnsharpMask (CE)
 * -------------------------------------------------------------
 */
 
function smarty_function_thumb($params, &$smarty)
        {

        // Start time measurement
        if ($params['dev'])
                {
                if (!function_exists('getmicrotime'))
                        {
                        function getmicrotime()
                                {
                                list($usec, $sec) = explode(" ",microtime());
                                return ((float)$usec + (float)$sec);
                                }
                        }
                $time['start'] = getmicrotime();
                }
               
        // Funktion zum Schц╓rfen
        if (!function_exists('UnsharpMask'))
                {
                // Unsharp mask algorithm by Torstein Hц╦nsi 2003 (thoensi_at_netcom_dot_no)
                // Christoph Erdmann: changed it a little, cause i could not reproduce the darker blurred image, now it is up to 15% faster with same results
                function UnsharpMask($img, $amount, $radius, $threshold)
                        {
                        // Attempt to calibrate the parameters to Photoshop:
                        if ($amount > 500) $amount = 500;
                        $amount = $amount * 0.016;
                        if ($radius > 50) $radius = 50;
                        $radius = $radius * 2;
                        if ($threshold > 255) $threshold = 255;
       
                        $radius = abs(round($radius));        // Only integers make sense.
                        if ($radius == 0) {        return $img; imagedestroy($img); break;        }
                        $w = imagesx($img); $h = imagesy($img);
                        $imgCanvas = $img;
                        $imgCanvas2 = $img;
                        $imgBlur = imagecreatetruecolor($w, $h);
       
                        // Gaussian blur matrix:
                        //        1        2        1               
                        //        2        4        2               
                        //        1        2        1               

                        // Move copies of the image around one pixel at the time and merge them with weight
                        // according to the matrix. The same matrix is simply repeated for higher radii.
                        for ($i = 0; $i < $radius; $i++)
                                {
                                imagecopy          ($imgBlur, $imgCanvas, 0, 0, 1, 1, $w - 1, $h - 1); // up left
                                imagecopymerge ($imgBlur, $imgCanvas, 1, 1, 0, 0, $w, $h, 50); // down right
                                imagecopymerge ($imgBlur, $imgCanvas, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left
                                imagecopymerge ($imgBlur, $imgCanvas, 1, 0, 0, 1, $w, $h - 1, 25); // up right
                                imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left
                                imagecopymerge ($imgBlur, $imgCanvas, 1, 0, 0, 0, $w, $h, 25); // right
                                imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 20 ); // up
                                imagecopymerge ($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 16.666667); // down
                                imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 0, 0, $w, $h, 50); // center
                                }
                        $imgCanvas = $imgBlur;       
                               
                        // Calculate the difference between the blurred pixels and the original
                        // and set the pixels
                        for ($x = 0; $x < $w; $x++)
                                { // each row
                                for ($y = 0; $y < $h; $y++)
                                        { // each pixel
                                        $rgbOrig = ImageColorAt($imgCanvas2, $x, $y);
                                        $rOrig = (($rgbOrig >> 16) & 0xFF);
                                        $gOrig = (($rgbOrig >> 8) & 0xFF);
                                        $bOrig = ($rgbOrig & 0xFF);
                                        $rgbBlur = ImageColorAt($imgCanvas, $x, $y);
                                        $rBlur = (($rgbBlur >> 16) & 0xFF);
                                        $gBlur = (($rgbBlur >> 8) & 0xFF);
                                        $bBlur = ($rgbBlur & 0xFF);

                                        // When the masked pixels differ less from the original
                                        // than the threshold specifies, they are set to their original value.
                                        $rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig;
                                        $gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig;
                                        $bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig;
                                       
                                        if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew))
                                                {
                                                $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew);
                                                ImageSetPixel($img, $x, $y, $pixCol);
                                                }
                                        }
                                }
                        return $img;
                        }
                }

        $_CONFIG['types'] = array('','.gif','.jpg','.png');


        ### ц°bergebene Parameter auswerten und verifizieren
        if (empty($params['cache'])) $_CONFIG['cache'] = 'images/cache/';
        else $_CONFIG['cache'] = $params['cache'];
        if (empty($params['file']) OR !file_exists($params['file'])) { $smarty->_trigger_fatal_error("thumb: parameter 'file' cannot be empty and must exist");        return;        }
        if (empty($params['link'])) $params['link'] = true;
        if (empty($params['window'])) $params['window'] = true;
        if (empty($params['hint'])) $params['hint'] = true;
        if (empty($params['extrapolate'])) $params['extrapolate'] = true;
        if (empty($params['dev'])) $params['crop'] = false;
        if (empty($params['crop'])) $params['crop'] = true;
        if (empty($params['width']) AND empty($params['height'])
                AND empty($params['longside']) AND empty($params['shortside'])) $params['width'] = 100;
       
        ### Info ц╪ber Source (SRC) holen
        $temp = getimagesize($params['file']);

        $_SRC['file']                = $params['file'];
        $_SRC['width']                = $temp[0];
        $_SRC['height']                = $temp[1];
        $_SRC['type']                = $temp[2]; // 1=GIF, 2=JPG, 3=PNG, SWF=4
        $_SRC['string']                = $temp[3];
        $_SRC['filename']        = basename($params['file']);
        $_SRC['modified']        = filemtime($params['file']);

        // Hash erstellen
        $_SRC['hash']                = md5($_SRC['file'].$_SRC['modified'].implode('',$params));


        ### Infos ц╪ber Destination (DST) errechnen
        if (is_numeric($params['width'])) $_DST['width'] = $params['width'];
        else $_DST['width'] = round($params['height']/($_SRC['height']/$_SRC['width']));

        if (is_numeric($params['height'])) $_DST['height']        = $params['height'];
        else $_DST['height'] = round($params['width']/($_SRC['width']/$_SRC['height']));
       
        // Das Grц╤ц÷enverhц╓ltnis soll erhalten bleiben egal ob das Bild hoch oder querformatig ist.
        if (is_numeric($params['longside']))
                {
                if ($_SRC['width'] < $_SRC['height'])
                        {
                        $_DST['height']        = $params['longside'];
                        $_DST['width']        = round($params['longside']/($_SRC['height']/$_SRC['width']));
                        }
                else
                        {
                        $_DST['width']        = $params['longside'];
                        $_DST['height']        = round($params['longside']/($_SRC['width']/$_SRC['height']));
                        }
                }
        elseif (is_numeric($params['shortside']))
                {
                if ($_SRC['width'] < $_SRC['height'])
                        {
                        $_DST['width']        = $params['shortside'];
                        $_DST['height']        = round($params['shortside']/($_SRC['width']/$_SRC['height']));
                        }
                else
                        {
                        $_DST['height']        = $params['shortside'];
                        $_DST['width']        = round($params['shortside']/($_SRC['height']/$_SRC['width']));
                        }
                }

        // Soll beschnitten werden? (Standard)
        if($params['crop'])
                {                                                       
                $width_ratio = $_SRC['width']/$_DST['width'];
                $height_ratio = $_SRC['height']/$_DST['height'];
               
                // Es muss an der Breite beschnitten werden
                if ($width_ratio > $height_ratio)
                        {
                        $_DST['offset_w'] = round(($_SRC['width']-$_DST['width']*$height_ratio)/2);
                        $_SRC['width'] = round($_DST['width']*$height_ratio);
                        }
                // es muss an der Hц╤he beschnitten werden
                elseif ($width_ratio < $height_ratio)
                        {
                        $_DST['offset_h'] = round(($_SRC['height']-$_DST['height']*$width_ratio)/2);
                        $_SRC['height'] = round($_DST['height']*$width_ratio);
                        }
                }

        // Wenn das Ursprungsbild kleiner als das Ziel-Bild ist, soll nicht hochskaliert werden und die neu berechneten Werte werden wieder ц╪berschrieben
        if ($params['extrapolate'] == 'false' && $_DST['height'] > $_SRC['height'] && $_DST['width'] > $_SRC['width'])
                {
                $_DST['width'] = $_SRC['width'];
                $_DST['height'] = $_SRC['height'];
                }
               
        if (!empty($params['type'])) $_DST['type']        = $params['type'];
        else $_DST['type']        = $_SRC['type'];

        $_DST['file']                = $_CONFIG['cache'].$_SRC['hash'].$_CONFIG['types'][$_DST['type']];
        $_DST['string']                = 'width="'.$_DST['width'].'" height="'.$_DST['height'].'"';


        ### Rц╪ckgabe-Strings erstellen
        if (empty($params['html'])) $_RETURN['img'] = '[img]'.$_DST['file'].'[/img]';
        else $_RETURN['img'] = '[img]'.$_DST['file'].'[/img]';

        if ($params['link'] == "true")
                {
                if (empty($params['linkurl'])) $params['linkurl'] = $_SRC['file'];
               
                if ($params['window'] == "true") $returner = ''.$_RETURN['img'].'';
                else $returner = ''.$_RETURN['img'].'';
                }
        else
                {
                $returner = $_RETURN['img'];
                }
       
        ### Cache-Datei abfangen
        if (file_exists($_DST['file']) AND !$params['dev']) return $returner;
       
       
        ### ansonsten weitermachen
       
        // SRC einlesen
        if ($_SRC['type'] == 1)        $_SRC['image'] = imagecreatefromgif($_SRC['file']);
        if ($_SRC['type'] == 2)        $_SRC['image'] = imagecreatefromjpeg($_SRC['file']);
        if ($_SRC['type'] == 3)        $_SRC['image'] = imagecreatefrompng($_SRC['file']);

        // Wenn das Bild sehr groц÷ ist, zuerst linear auf vierfache Zielgrц╤ц÷e herunterskalieren und $_SRC ц╪berschreiben
        if ($_DST['width']*4 < $_SRC['width'] AND $_DST['height']*4 < $_SRC['height'])
                {
                // Multiplikator der Zielgrц╤ц÷e
                $_TMP['width'] = round($_DST['width']*4);
                $_TMP['height'] = round($_DST['height']*4);
               
                $_TMP['image'] = imagecreatetruecolor($_TMP['width'], $_TMP['height']);
                imagecopyresized($_TMP['image'], $_SRC['image'], 0, 0, $_DST['offset_w'], $_DST['offset_h'], $_TMP['width'], $_TMP['height'], $_SRC['width'], $_SRC['height']);
                $_SRC['image'] = $_TMP['image'];
                $_SRC['width'] = $_TMP['width'];
                $_SRC['height'] = $_TMP['height'];
               
                // Wenn vorskaliert wird, darf ja nicht nochmal ein bestimmter Bereich ausgeschnitten werden
                $_DST['offset_w'] = 0;
                $_DST['offset_h'] = 0;
                unset($_TMP['image']);
                }

        // DST erstellen
        $_DST['image'] = imagecreatetruecolor($_DST['width'], $_DST['height']);
        imagecopyresampled($_DST['image'], $_SRC['image'], 0, 0, $_DST['offset_w'], $_DST['offset_h'], $_DST['width'], $_DST['height'], $_SRC['width'], $_SRC['height']);
        if ($params['sharpen'] != "false") $_DST['image'] = UnsharpMask($_DST['image'],80,.5,3);

        // Soll eine Lupe eingefц╪gt werden?
        if ($params['hint'] == "true" AND $params['link'] == "true")
                {
                //Soll der weiц÷e Balken wirklich hinzugefц╪gt werden?
                if ($params['addgreytohint'] != 'false')
                        {
                        $trans = imagecolorallocatealpha($_DST['image'], 255, 255, 255, 25);
                        imagefilledrectangle($_DST['image'], 0, $_DST['height']-9, $_DST['width'], $_DST['height'], $trans);
                        }

                $magnifier = imagecreatefromstring(gzuncompress(base64_decode("eJzrDPBz5+WS4mJgYOD19HAJAtLcIMzBBiRXrilXA1IsxU6eIRxAUMOR0gHkcxZ4RBYD1QiBMOOlu3V/gIISJa4RJc5FqYklmfl5CiGZuakMBoZ6hkZ6RgYGJs77ex2BalRBaoLz00rKE4tSGXwTk4vyc1NTMhMV3DKLUsvzi7KLFXwjFEAa2svWnGdgYPTydHEMqZhTOsE++1CAyNHzm2NZjgau+dAmXlAwoatQmOld3t/NPxlLMvY7sovPzXHf7re05BPzjpQTMkZTPjm1HlHkv6clYWK43Zt16rcDjdZ/3j2cd7qD4/HHH3GaprFrw0QZDHicORXl2JsPsveVTDz//L3N+WpxJ5Hff+10Tjdd2/Vi17vea79Om5w9zzyne9GLnWGrN8atby/ayXPOsu2w4quvVtxNCVVz5nAf3nDpZckBCedpqSc28WTOWnT7rZNXZSlPvFybie9EFc6y3bIMCn3JAoJ+kyyfn9qWq+LZ9Las26Jv482cDRE6Ci0B6gVbo2oj9KabzD8vyMK4ZMqMs2kSvW4chz88SXNzmeGjtj1QZK9M3HHL8L7HITX3t19//VVY8CYDg9Kvy2vDXu+6mGGxNOiltMPsjn/t9eJr0ja/FOdi5TyQ9Lz3fOqstOr99/dnro2vZ1jy76D/vYivPsBoYPB09XNZ55TQBAAJjs5s</body>")));
                imagealphablending($_DST['image'], true);
                imagecopy($_DST['image'], $magnifier, $_DST['width']-15, $_DST['height']-14, 0, 0, 11, 11);
                imagedestroy($magnifier);
                }

        // Berechnungszeit hinzufц╪gen
        if ($params['dev'])
                {
                // Zeit anhalten
                $time['end'] = getmicrotime();
                $time = round($time['end'] - $time['start'],2);
               
                // Farben definieren
                $white_trans = imagecolorallocatealpha($_DST['image'], 255, 255, 255, 25);
                $black = ImageColorAllocate ($_DST['image'], 0, 0, 0);

                // Weiц÷er Balken oben
                imagefilledrectangle($_DST['image'], 0, 0, $_DST['width'], 10, $white_trans);

                // Schrift mit Zeitangabe
                imagestring($_DST['image'], 1, 5, 2, 'processing time: '.$time.'s', $black);
                }
       
        // Thumbnail abspeichern
        if ($_DST['type'] == 1)
                {
                imagetruecolortopalette($_DST['image'], false, 256);
                imagegif($_DST['image'], $_DST['file']);
                }
        if ($_DST['type'] == 2)
                {
                if (empty($params['quality'])) $params['quality'] = 80;
                imagejpeg($_DST['image'], $_DST['file'],$params['quality']);
                }
        if ($_DST['type'] == 3)
                {
                imagepng($_DST['image'], $_DST['file']);
                }
       
        imagedestroy($_DST['image']);
        imagedestroy($_SRC['image']);

        // Und Bild ausgeben
        return $returner;
       
        }


?>


PP 06-06-2006 08:04 AM

Hmm, this looks similiar to Telafirma's mod, have you incorporated this and may we see the output?

Alltribes 06-06-2006 08:50 AM

I haven't incorporated this with anything yet. You could easily replicate the look of Telafirma's mod with this though. Simply define the main image then use the {thumb} function for the detailed images.

I'm in the process of making something similar only using javascript image swapping instead of opening them in a new window.

balinor 06-06-2006 09:11 AM

Moving this to Program Logic, as it really isn't a completed mod.

PP 06-06-2006 09:31 AM

Quote:

Originally Posted by Alltribes
I haven't incorporated this with anything yet. You could easily replicate the look of Telafirma's mod with this though. Simply define the main image then use the {thumb} function for the detailed images.

I'm in the process of making something similar only using javascript image swapping instead of opening them in a new window.



I'd be interested to see the final results, please keep us posted

Alltribes 06-06-2006 09:32 AM

Of course it's a completed mod. The fact it's a smarty plugin instead of a seperate php file shouldn't matter.

Alltribes 06-06-2006 10:47 AM

Here is my modules/Detailed_Product_Images/product_images.tpl

It needs some formatting, and I've only tested it on 4.1x, but I think it should work with 4.0x. This will just change your detailed images to thumbnails with an image popup when you click on it. The default image is displayed normal size. I'll be refining this as I go on.

Code:

{if $images ne ""}
{capture name=dialog}
<table>
<tr>
<td>
<table>
{section name=image loop=$images}
{if $images[image].image_path}
<tr><td>{thumb file=`$images[image].image_path` longside="100" link="true"}</td></tr>

 
{/if}
{/section}
</table>
</td>
<td>
[img]{$product.image_path_P}[/img]
</td>
</tr>
</table>
{/capture}
{include file="dialog.tpl" title=$lng.lbl_detailed_images content=$smarty.capture.dialog extra='width="100%"'}
{/if}


*edit*

Here is another modules/Detailed_Product_Images/product_images.tpl
This one uses javascript mouseover image swapping. It ignores the main product image and just uses the detailed images. As in the above example I've only tested in in 4.1x, but it should work on 4.0x. My next task is to preload the detailed images.

Code:

{if $images ne ""}
{capture name=dialog}
<table width=100%>
<tr>
<td>
<table>
{section name=image loop=$images}
{if $images[image].image_path}
<tr><td>{thumb file=`$images[image].image_path` longside="100" link="false"}</td></tr>

 
{/if}
{/section}
</table>
</td>
<td>
<img src={$images[0].image_path} name="main_image"/>
</td>
</tr>
</table>
{/capture}
{include file="dialog.tpl" title=$lng.lbl_detailed_images content=$smarty.capture.dialog extra='width="100%"'}
{/if}


*edit2*

Here is the above code, now with image preloading and now using imageid instead of orderby.

*fixed

Code:

{if $images ne ""}
{capture name=dialog}
<script language="JavaScript" type="text/javascript">
{section name=image loop=$images}
{if {$images[image].image_path}
Image{$images[image].imageid} = new Image();
Image{$images[image].imageid}.src = "{$images[image].image_path}";
{/if}
{/section}
</script>
<table width="100%">
<tr>
<td>
<table>
{section name=image loop=$images}
{if {$images[image].image_path neq ""}
<tr>
<td>
<a href="#" onmouseover="document.main_image.src=Image{$images[image].imageid}.src;">{thumb file=`$images[image].image_path` longside="100" link="false" html="alt='`$product.product`' border='0'"}</a>
</td>
</tr>
{/if}
{/section}
</table>
</td>
<td>
<img src="{$images[0].image_path}" name="main_image" alt="{$product.product}" />
</td>
</tr>
</table>
{/capture}
{include file="dialog.tpl" content=$smarty.capture.dialog extra='width="100%"'}
{/if}


*edit*

Here is the preloading script for 4.0x, now using imageid instead of orderby:

Code:

{if $images ne ""}
{capture name=dialog}
<script language="JavaScript" type="text/javascript">
{section name=image loop=$images}
{if {$images[image].image_path}
Image{$images[image].imageid} = new Image();
Image{$images[image].imageid}.src = "{$images[image].image_path|replace:"server path to replace":""}";
{/if}
{/section}
</script>
<table width="100%">
<tr>
<td>
<table>
{section name=image loop=$images}
{if {$images[image].image_path}
<tr>
<td>
{thumb file=`$images[image].image_path` longside="100" link="false" html="alt='`$product.product` '"}
</td>
</tr>
{/if}
{/section}
</table>
</td>
<td>
[img]{$images[0].image_path|replace:[/img]
</td>
</tr>
</table>
{/capture}
{include file="dialog.tpl" content=$smarty.capture.dialog extra='width="100%"'}
{/if}


gfiebich 06-09-2006 11:30 AM

Cool mod! I'm trying it on 4.0.18 and the problem I run into is that
Code:

{$images[0].image_path}
returns the full server path of the image - which of course won't display properlly in the browser. Any ideas?
thanks,
Glen

Alltribes 06-09-2006 12:03 PM

Quote:

Originally Posted by gfiebich
Cool mod! I'm trying it on 4.0.18 and the problem I run into is that
Code:

{$images[0].image_path}
returns the full server path of the image - which of course won't display properlly in the browser. Any ideas?
thanks,
Glen


Try using smarty's replace function to strip off the unneeded part of the image path.
Code:

{$images[0].image_path|replace:'server path to remove':''}

nfc5382 06-09-2006 12:12 PM

what exactly does this do?


All times are GMT -8. The time now is 09:06 AM.

Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.