• twitter image
  • facebook image
  • youtube image
  • linkedin image
Language: CMS Made Simple Czech CMS Made Simple France CMS Made Simple Spain CMS Made Simple Hungary CMS Made Simple Russia CMS Made Simple Netherlands

All times are UTC




Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 14 posts ] 
Author Message
 Post subject: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 1:38 am 
Offline
Power Poster
Power Poster

Joined: Sat Nov 25, 2006 3:39 pm
Posts: 356
Location: Copenhagen, Denmark
I've used getimagesize($remoteimagefile) in a template and i works fine. But i've noticed that if i do have more than a couple of images the page slows down a lot.

I then tried to upload a plugin to "lib/plugins" but i can't seem to figure out how to access the output - I only get "Array"!

I have:
\$1:
{$imagesize = "{getjpegsize url=$my_url}"}
<pre>{$imagesize}</pre>

But it's only outputting "Array"!

I've also tried {$imagesize[0]} but then i only get "A".

So i'm clearly missing something but what?

My plugin file:
\$1:
// Retrieve JPEG width and height without downloading/reading entire image.
function smarty_cms_function_getjpegsize($params, &$smarty) {
    $img_loc = $params['url'];
    $handle = fopen($img_loc, "rb") or die("Invalid file stream.");
    $new_block = NULL;
    if(!feof($handle)) {
        $new_block = fread($handle, 32);
        $i = 0;
        if($new_block[$i]=="\xFF" && $new_block[$i+1]=="\xD8" && $new_block[$i+2]=="\xFF" && $new_block[$i+3]=="\xE0") {
            $i += 4;
            if($new_block[$i+2]=="\x4A" && $new_block[$i+3]=="\x46" && $new_block[$i+4]=="\x49" && $new_block[$i+5]=="\x46" && $new_block[$i+6]=="\x00") {
                // Read block size and skip ahead to begin cycling through blocks in search of SOF marker
                $block_size = unpack("H*", $new_block[$i] . $new_block[$i+1]);
                $block_size = hexdec($block_size[1]);
                while(!feof($handle)) {
                    $i += $block_size;
                    $new_block .= fread($handle, $block_size);
                    if($new_block[$i]=="\xFF") {
                        // New block detected, check for SOF marker
                        $sof_marker = array("\xC0", "\xC1", "\xC2", "\xC3", "\xC5", "\xC6", "\xC7", "\xC8", "\xC9", "\xCA", "\xCB", "\xCD", "\xCE", "\xCF");
                        if(in_array($new_block[$i+1], $sof_marker)) {
                            // SOF marker detected. Width and height information is contained in bytes 4-7 after this byte.
                            $size_data = $new_block[$i+2] . $new_block[$i+3] . $new_block[$i+4] . $new_block[$i+5] . $new_block[$i+6] . $new_block[$i+7] . $new_block[$i+8];
                            $unpacked = unpack("H*", $size_data);
                            $unpacked = $unpacked[1];
                            $height = hexdec($unpacked[6] . $unpacked[7] . $unpacked[8] . $unpacked[9]);
                            $width = hexdec($unpacked[10] . $unpacked[11] . $unpacked[12] . $unpacked[13]);
                            return array($width, $height);
                        } else {
                            // Skip block marker and read block size
                            $i += 2;
                            $block_size = unpack("H*", $new_block[$i] . $new_block[$i+1]);
                            $block_size = hexdec($block_size[1]);
                        }
                    } else {
                        return FALSE;
                    }
                }
            }
        }
    }
    return FALSE;
}


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 9:29 am 
Offline
Dev Team Member
Dev Team Member
User avatar

Joined: Wed Apr 23, 2008 7:53 am
Posts: 7719
Location: The Netherlands
https://cmscanbesimple.org/blog/getting ... -in-smarty

_________________
$1

Did my post help you solving a problem at your (customers) website and it saved you many hours of work? Great!! Consider buying me a cup of coffee in return!



Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 9:37 am 
Offline
Power Poster
Power Poster

Joined: Sat Nov 25, 2006 3:39 pm
Posts: 356
Location: Copenhagen, Denmark
Thanks Rolf!

I've already tried that one but i'm fetching remote images and using getimagesize() seems to slow down the page considerably when fetching more than a handfull images.

So i found the above function that only get the image width and height from the remote image. But i'm stuck at getting the width value from the output.

If i do this:
\$1:
 {getjpegsize|print_r url=$my_url}

i get
\$1:
Array ( [0] => 1280 [1] => 720 ) 1

But if i do
\$1:
{$imagesize = "{getjpegsize url=$my_url}"}
{$imagesize[0]}

i get this output
\$1:
A

So how do i access the first value?


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 12:41 pm 
Offline
Dev Team Member
Dev Team Member
User avatar

Joined: Wed Apr 23, 2008 7:53 am
Posts: 7719
Location: The Netherlands
I use this method i.e. in the PhotoSwipe template for the Gallery module:
http://dev.cmsmadesimple.org/project/fi ... ckage-1341

Example with more than 100 photos in this template at:
https://music4allharen.nl/fotoalbum/202 ... smaking/67

_________________
$1

Did my post help you solving a problem at your (customers) website and it saved you many hours of work? Great!! Consider buying me a cup of coffee in return!



Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 1:21 pm 
Offline
Power Poster
Power Poster

Joined: Sat Nov 25, 2006 3:39 pm
Posts: 356
Location: Copenhagen, Denmark
But is the difference not in local and external image files?

I have 6 external image files and load time is ok. But do i increase the gallery to 12 images, then the page takes a long time to load (>10 sec.).

I'm trying to have a portfolio of YouTube videos, where i fetch the YouTube Poster Image depending which size is available (Either Maxresdefault or HQdefault).

And as far i can read on my searches around the web, is that getimagesize() is very slow with external image files, as it has to download the full image data to get width and height.

But maybe it's just in my template there is something wrong to increase load time so much?

My Portfolio template (In LISE):
\$1:
{if $items|@count > 0}{strip}
<!-- Portfolio -->
<div id="portfolio" class="grid-layout portfolio-3-columns" data-margin="0">
{foreach from=$items item=item name=portfolio}
    <!-- portfolio item -->
    <div class="portfolio-item{if $smarty.foreach.portfolio.first || $smarty.foreach.portfolio.iteration is div by 8} large-width{/if} img-zoom">
        <div class="portfolio-item-wrap">
            <div class="portfolio-image">
                <a data-lightbox="iframe" href="https://www.youtube.com/watch?v={$item->fielddefs.video_id.value}">
                   {if $item->fielddefs.poster_image.value}
                   <img src="{CGSmartImage src1=$item->fielddefs.poster_image->GetImagePath(true) src2=$item->fielddefs.poster_image->value filter_croptofit='800,450,c' noauto=1}" alt="">
                  {else}
                  {capture assign=maxresdefault}https://img.youtube.com/vi/{$item->fielddefs.video_id.value}/maxresdefault.jpg{/capture}
                  {capture assign=hqdefault}https://img.youtube.com/vi/{$item->fielddefs.video_id.value}/hqdefault.jpg{/capture}
                  {$imagesize = getimagesize($maxresdefault)}
                  {if $imagesize[0]}
                  {CGSmartImage src=$maxresdefault filter_croptofit='800,450,c' noauto=1}
                  {else}
                  {CGSmartImage src=$hqdefault filter_croptofit='480,270,c' noauto=1}
                  {/if}
                  {/if}
               </a>
            </div>
            <div class="portfolio-description">
                <a class="btn btn-light btn-rounded" title="{$item->title} ({$imagesize[0]})" data-lightbox="iframe" href="https://www.youtube.com/watch?v={$item->fielddefs.video_id.value}">{$item->title}</a>
            </div>
        </div>
    </div>
    <!-- end: portfolio item --> 
{/foreach}
</div>
<!-- end: Portfolio -->
{/strip}{/if}


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 2:28 pm 
Offline
Dev Team Member
Dev Team Member
User avatar

Joined: Mon Jan 29, 2007 4:47 pm
Posts: 1786
webform \webform:
{$imagesize = "{getjpegsize url=$my_url}"}
<pre>{$imagesize}</pre>

But it's only outputting "Array"!
Looking at the source code it easy to get what is wrong: return array($width, $height);
The typical use of a smarty plugin expects the return to be printable and an array is not printable.
There are several options to get around this, one being imploding the var before returning it, other being assigning the return values to one or two smarty variables and then handling the vars on the template.

Also a note: try NOT to use capture on the templates as that is time expensive and probably one of the issues you are experiencing.
Instead of:
\$1:
{capture assign=maxresdefault}https://img.youtube.com/vi/{$item->fielddefs.video_id.value}/maxresdefault.jpg{/capture}
try using
\$1:
{$maxresdefault="https://img.youtube.com/vi/{$item->fielddefs.video_id.value}/maxresdefault.jpg"}

HTH

_________________
"There are 10 types of people in this world, those who understand binary... and those who don't."
* by the way: English is NOT my native language (sorry for any mistakes...).


Code of Conduit | CMSMS Docs
Help Support CMSMS
My developer Page on the Forge | Yet another blog about CMSMS

GeekMoot 2015 in Ghent, Belgium: I was there!
GeekMoot 2016 in Leicester, UK: I was there!



Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 3:06 pm 
Offline
Dev Team Member
Dev Team Member
User avatar

Joined: Wed Feb 25, 2009 4:25 am
Posts: 961
Location: Victoria, BC
Not an answer to your question, but I think the youtube api provides a method for obtaining the thumbnail dimensions. Might be more efficient, if so.

_________________
Not getting the answer you need? CMSMS support options


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 4:19 pm 
Offline
Dev Team Member
Dev Team Member

Joined: Mon Nov 28, 2011 9:29 am
Posts: 3211
Location: The Netherlands
Also not an answer to your question but can you imagine how inefficient it is to calculate the dimensions of an remote image on every visit of a page?
Especially considering the odds the values change over time.

Further, not sure if I'm right, it seems you're trying to get two remote images for every item. Then get the size of both, if the first fails use the second.
Again the efficiency won't be optimal.

If I were you, I'd consider looking at the LISE api, add some fields if necessary and use a cmsms event - on saving the the LISE item - to trigger your logic and save the results with the LISE item itself.


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 4:40 pm 
Offline
Power Poster
Power Poster

Joined: Sat Nov 25, 2006 3:39 pm
Posts: 356
Location: Copenhagen, Denmark
Thanks all for some very valuable tips and insights.

I've tried something different based on your suggestions:

I've created an UDT for testing if the YouTube URL are available:
\$1:
$url = isset($params['url']) ? $params['url'] : '';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, true);   
curl_setopt($ch, CURLOPT_NOBODY, true);   
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.4");
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $httpcode;

And my portfolio template i've removed "capture" and moved the fetching of the fallback image $hqdefault so it doesn't get fetched unless there is no $maxresdefault image.
I'm already experiencing a vast improvement in load time (although it probably could get better)
\$1:
{if $items|@count > 0}{strip}
<!-- Portfolio -->
<div id="portfolio" class="grid-layout portfolio-3-columns" data-margin="0">
{foreach from=$items item=item name=portfolio}
    <!-- portfolio item -->
    <div class="portfolio-item{if $smarty.foreach.portfolio.first || $smarty.foreach.portfolio.iteration is div by 8} large-width{/if} img-zoom">
        <div class="portfolio-item-wrap">
            <div class="portfolio-image">
                <a data-lightbox="iframe" href="https://www.youtube.com/watch?v={$item->fielddefs.video_id.value}">
                   {if $item->fielddefs.poster_image.value}
                   <img src="{CGSmartImage src1=$item->fielddefs.poster_image->GetImagePath(true) src2=$item->fielddefs.poster_image->value filter_croptofit='800,450,c' noauto=1}" alt="">
                  {else}
                  {$maxresdefault="https://img.youtube.com/vi/{$item->fielddefs.video_id.value}/maxresdefault.jpg"}
                  {$check="{check_404 url=$maxresdefault}"}
                  {if $check == '200'}
                  {CGSmartImage src=$maxresdefault filter_croptofit='800,450,c' noauto=1}
                  {else}
                  {$hqdefault="https://img.youtube.com/vi/{$item->fielddefs.video_id.value}/hqdefault.jpg"}
                  {CGSmartImage src=$hqdefault filter_croptofit='480,270,c' noauto=1}
                  {/if}
                  {/if}
               </a>
            </div>
            <div class="portfolio-description">
                <a class="btn btn-light btn-rounded" title="{$item->title}" data-lightbox="iframe" href="//www.youtube.com/watch?v={$item->fielddefs.video_id.value}">{$item->title}</a>
            </div>
        </div>
    </div>
    <!-- end: portfolio item --> 
{/foreach}
</div>
<!-- end: Portfolio -->
{/strip}{/if}


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin  Topic is solved
PostPosted: Fri Apr 03, 2020 4:50 pm 
Offline
Dev Team Member
Dev Team Member

Joined: Mon Nov 28, 2011 9:29 am
Posts: 3211
Location: The Netherlands
I think if you do the checks for the two images on the saving of the LISE item you will be good.
Then you only need to check once which file to use.

CGSmartImage will do the caching of the cropped image for you.

If you still want to do the check from within the template, I just found this article about checking the existence of a file without actually downloading it.
https://thisinterestsme.com/check-see-h ... xists-php/

I can't see if you're already using this. But remember, it still has to do the request etc. So better would be to do it once, set and forget.


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 5:11 pm 
Offline
Power Poster
Power Poster

Joined: Sat Nov 25, 2006 3:39 pm
Posts: 356
Location: Copenhagen, Denmark
Thanks!

Yes, i'm doing a http header check, to see if the image exist and load the correct image accordingly.

You saying i could do this already at the creation of the LISE item?


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 5:26 pm 
Offline
Dev Team Member
Dev Team Member

Joined: Mon Nov 28, 2011 9:29 am
Posts: 3211
Location: The Netherlands
I think it's possible yes.

LISE has a useful API and you can connect a UDT which does the checks to a LISE event (Extensions > Event Manager).

You will need some php knowledge and some knowledge of the LISE api.

But check the help of the LISE PreItemSave event

\$1:
//use for pre-save item event

$item = $params['item_object'];

...do your logic here---

$item->YourFieldAliasHere = 'YourValueHere';


Think that shoud do it.


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Fri Apr 03, 2020 5:29 pm 
Offline
Power Poster
Power Poster

Joined: Sat Nov 25, 2006 3:39 pm
Posts: 356
Location: Copenhagen, Denmark
Thanks! I'll look into it as it maybe also could help some more on the load speed of the page.


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
 Post subject: Re: Get image dimensions with a plugin
PostPosted: Sat Apr 04, 2020 8:04 pm 
Offline
Power Poster
Power Poster

Joined: Sat Nov 25, 2006 3:39 pm
Posts: 356
Location: Copenhagen, Denmark
Thanks for all the suggestions, feedback and help.

I've got a working solution now with only a 1/3 of previous load time.

Here is what i did (if it's to any use of others):

My UDT (remote_youtube_poster_image):
\$1:
$item = $params['item_object'];

// Remote image URL
$url = 'https://img.youtube.com/vi/'.$item->video_id.'/maxresdefault.jpg';
// Remote fallback image URL
$fallbackurl = 'https://img.youtube.com/vi/'.$item->video_id.'/hqdefault.jpg';

// Save path to uploads folder
$path = $_SERVER['DOCUMENT_ROOT'].'/uploads/images/portfolio/img-'.$item->video_id.'.jpg';

// Image path to LISE field
$img = '/uploads/images/portfolio/img-'.$item->video_id.'.jpg';

//Check Availability
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, true);   
curl_setopt($ch, CURLOPT_NOBODY, true);   
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.4");
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpcode == '200') {

// Save maxresdefault image
$ch = curl_init($url);
$fp = fopen($path, 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($fp);

} else {

// Save hqdefault image
$ch = curl_init($fallbackurl);
$fp = fopen($path, 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($fp);

}

$item->poster_image_youtube = $img;

The UDT i connected to my LISE PreItemSave in Event Manager.

My LISE Summary Template:
\$1:
{if $items|@count > 0}{strip}
<!-- Portfolio -->
<div id="portfolio" class="grid-layout portfolio-3-columns" data-margin="0">
{foreach from=$items item=item name=portfolio}
    <!-- portfolio item -->
    <div class="portfolio-item{if $smarty.foreach.portfolio.first || $smarty.foreach.portfolio.iteration is div by 8} large-width{/if} img-zoom">
        <div class="portfolio-item-wrap">
            <div class="portfolio-image">
                <a data-lightbox="iframe" href="https://www.youtube.com/watch?v={$item->fielddefs.video_id.value}">
                   {if $item->fielddefs.poster_image.value}
                   <img src="{CGSmartImage src1=$item->fielddefs.poster_image->GetImagePath(true) src2=$item->fielddefs.poster_image->value filter_croptofit='800,450,c' noauto=1}" alt="">
                  {else}
                  {$posterimg = $item->fielddefs.poster_image_youtube.value}
                  {$imagesize = getimagesize("{root_url}{$posterimg}")}
                  {if $imagesize[0] > '720'}
                  {CGSmartImage src=$posterimg filter_croptofit='800,450,c' noauto=1}
                  {else}
                  {CGSmartImage src=$posterimg filter_croptofit='480,270,c' noauto=1}
                  {/if}
                  {/if}
               </a>
            </div>
            <div class="portfolio-description">
                <a class="btn btn-light btn-rounded" title="{$item->title}" data-lightbox="iframe" href="//www.youtube.com/watch?v={$item->fielddefs.video_id.value}">{$item->title}</a>
            </div>
        </div>
    </div>
    <!-- end: portfolio item --> 
{/foreach}
</div>
<!-- end: Portfolio -->
{/strip}{/if}


Top
  Profile  
 
Share On:
Share on Facebook Share on Twitter Share on Google+
Display posts from previous:  Sort by  
Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 14 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
A2 Hosting