Yii 1.1: image-displayer

This extension resize images and thumbnail only when they are called and if resized image or his thumbnail not exists.
21 followers

SAImageDisplayer is a Yii Widget providing a better display of images in the views.

Description

This extension resizes images and thumbnail only when they are called and if resized image or his thumbnail does not exist. This means that you can upload images without taking care of dimensions.

This extension is based on justintimeimageresizer extension adding some improvements :

  • We can Specify an unlimited number of sizes, we are no more limited to "Big" or "Thumbs"
  • We can specify a default image to display if the original image doesn't exist
  • we can specify some groups: if we don't want to mix multiple type of image, by specifying the type it will store each image type in a separate folder
  • Add the possiblity to define the class, id and style in image tag
  • We can define where we would like to store the images (inside the webroot folder)
  • We can choose the name of the folder storing the originals images
  • If the folder that should contain the resized image doesn't exist then the widget try to create it before throwing an error
  • Since V1.1: We can display the original file (with the original size)
  • Since V1.2: We can generate the newly sized image whitout displaying it on the screen

Requirements

  • Yii 1.1 or above
  • PHP 5.3
  • image (yii extension)

Installation

To install this extension it's really easy, all you have to do is extract the SAImageDisplayer.php file in your ``extension` folder!

Main Configuration

In this part we are going to configure the extension. This part is optional but I encourage you to do it because later you won't have to put all the variables defined in the config in each of your call to the widget!

There are some params that won't change from one call to the widget to another. This is why I encourage you to use the ability that yii offers to globally configure some widgets option! To do it edit your configuration main file (in general config/main.php) and add the following code:

return array(
    ...
    'components'=>array(
        'widgetFactory'=>array(
            'widgets'=>array(
                ...
                'SAImageDisplayer'=>array(
                    'theOption'=>theValue,
                    'otherOption'=>otherValue,
                ),
            ),
        ),
    ),
);

Params you should put in this configuration file

The options that I encourage you to put in this configuration are:

  • The path to the dir that will contain originals and resized folders. The root of this param will be webroot. Default to images:
'baseDir' => 'images',
  • The name of the folder holding the originals images. default to originals:
'originalFolderName' => 'originals',
  • The different available sizes for the plugin (when you are not using groups):
'sizes' =>array(
    'nameOfTheSize' => array('width' => width, 'height' => height),
   ),
  • The groups and the sizes going with it :
'groups' => array(
    'nameOfTheGroup' => array(
        'nameOfTheSize' => array('width' => width, 'height' => height),
      ),
 ),

Example of params

For the param sizes

The following example:

'sizes' =>array(
    'tiny' => array('width' => 40, 'height' => 30),
    'big' => array('width' => 640, 'height' => 480),
    'thumb' => array('width' => 400, 'height' => 300),
   ),

will give the following structure (if images is defined as baseDir and originals as originalFolderName):

images/ 
  big/
  originals/
  thumb/
  tiny/

For the param groups

The following example:

'groups' => array(
    'news' => array(
        'tiny' => array('width' => 40, 'height' => 30),
        'big' => array('width' => 640, 'height' => 480),
      ),
    'reviews' => array(
        'thumb' => array('width' => 400, 'height' => 300),
     ), 
 ),

will give the following structure (if images is defined as baseDir and originals as originalFolderName):

 images/ 
    news/
       big/
       originals/
       tiny/
    reviews/
       originals/
       thumb/

Complete configuration example

Here is a complete configuration example that you could use:

return array(
    ...
    'components'=>array(
        'widgetFactory'=>array(
            'widgets'=>array(
                ...
                'SAImageDisplayer'=>array(
                    'baseDir' => 'images',
                    'originalFolderName'=> 'originals',
                    'sizes' =>array(
                        'tiny' => array('width' => 40, 'height' => 30),
                        'big' => array('width' => 640, 'height' => 480),
                        'thumb' => array('width' => 400, 'height' => 300),
                    ),
                    'groups' => array(
                        'news' => array(
                            'tiny' => array('width' => 40, 'height' => 30),
                            'big' => array('width' => 640, 'height' => 480),
                          ),
                        'reviews' => array(
                            'thumb' => array('width' => 400, 'height' => 300),
                         ), 
                    ),
                ),
            ),
        ),
    ),
);

Usage

For the usage, I'll assume that you have followed the configuration step above. If not, each params defined before need to be put in each widget call in your views.

All the originals images have to be in the folder defined by originalFolderName. If you are using the option group then the original image has to be in the folder groupName/originalFolderName

Simplest example

To simply display an image with a given size here is the syntax:

<?php $this->widget('ext.SAImageDisplayer', array(
    'image' => 'yourImage.png',
    'size' => 'thumb',
)); ?>

Display the original sized file (since V1.1)

If you want to display the original file with its original size (for a gallery for example) you can do it by not setting size or setting it to original:

<?php $this->widget('ext.SAImageDisplayer', array(
    'image' => 'yourImage.png',
)); ?>

More info in your image tag

Now you can simply add a title to the image:

<?php $this->widget('ext.SAImageDisplayer', array(
    'image' => 'yourImage.png',
    'size' => 'thumb',
    'title' => 'My super title',
)); ?>

This way you can set:

  • The title by using the param title
  • The alternative text by setting the param alt
  • The class using class
  • The id => id
  • The style => style

And if my image could not exists?

Not sure your image really exists? No need to check it, the plugin do it for you and allow you to define a default image!

This image as to be in your original folder and will be resized to match the size you set.

<?php $this->widget('ext.SAImageDisplayer', array(
    'image' => 'yourImage.png',
    'size' => 'thumb',
    'defaultImage' => 'default.png',
)); ?>

And if I don't want to mix severals types of images?

Let's say you have some images representing the news on your site and some others the reviews. You don't want to mix them because after it's a mess to now what image belongs to what type. I agree with you, everything need to be clean!

This is why you can declare a group for each image you are displaying! The plugin will work in the folder corresponding to the group name.

So to display a new image I'll use:

<?php $this->widget('ext.SAImageDisplayer', array(
    'image' => 'yourImage.png',
    'size' => 'thumb',
    'defaultImage' => 'default.png',
    'group' => 'news',
)); ?>

And for a review:

<?php $this->widget('ext.SAImageDisplayer', array(
    'image' => 'yourImage.png',
    'size' => 'thumb',
    'defaultImage' => 'default.png',
    'group' => 'reviews',
)); ?>

And in your image folder you'll have something clean like:

images/ 
    news/
       big/
       originals/
       thumb/
    reviews/
       originals/
       thumb/

Be careful, since you are using the option group, the original and the default images have to be in the folder groupName/originalFolderName!

If I want to group some images and not some others?

Of course we can use group and size for some images and just specify size for others! This way you'll endup with a structure looking like:

 images/
    big/
    originals/
    news/
       big/
       originals/
       tiny/
    reviews/
       originals/
       thumb/ 
    thumb/
    tiny/

If I want generate a new image size whitout displaying it?

Since v1.2 we can generate a new image size whitout displaying the image on the screen! All we have to do is set the option displayImage to false in the widget. All the other operations will be performed except displaying the image tag.

<?php $this->widget('ext.SAImageDisplayer', array(
    'image' => 'yourImage.png',
    'size' => 'thumb',
    'defaultImage' => 'default.png',
    'displayImage' => false,
)); ?>

List of all the available options

  • image : Name of the image to display (with the extension)
  • size : Name of the size to display. The size has to be declared in sizes or groups if the option group is used
  • defaultImage : Name of the default image to display if image doesn't exist
  • sizes : Array containing all the possible sizes than can be called when group is not defined. The array has to be with the following structure:
'sizes' =>array(
    'nameOfTheSize' => array('width' => width, 'height' => height),
   ),
  • groups : Array containing all the groups and the associated sizes that the widget may use. The array has to be with the following structure:
'groups' => array(
    'nameOfTheGroup' => array(
        'nameOfTheSize' => array('width' => width, 'height' => height),
      ),
 ),
  • baseDir : The path to the dir that will contain originals and resized folders. The root of this param will be webroot. Default to images
  • originalFolderName : The name of the folder holding the originals images. default to originals
  • title : Title of the image tag
  • alt : Alternative name of the image
  • style : Style of the image tag
  • id : Id of the image tag
  • class : Class of the image tag
  • group : Name of the group the image belongs to
  • displayImage : Whether or not we should display the image on the screen. Default to true.
  • resizeMode : How images should be resized by the image extension. Available options are SAImageDisplayer::NONE, SAImageDisplayer::AUTO, SAImageDisplayer::HEIGHT, SAImageDisplayer::WIDTH. Default to AUTO.
  • othersAttributes : An array array('attributeName' => 'value') keeping all the additional attribute we wish to add to the image tag.

Please Note

Don't hesitate to ask for help or tell me any issue you could meet while using the plugin! If you see som typo errors in this extension page please tell me, English is not my mother tongue so there might have plenty of them.

Feel free to provide some ideas of improvment and if you provide some pull request on github I'll most definitely examinate your code and add it to the widget if I thin it adds something!

Links

Updates

  • 1.1: Add the ability to display the image with its original size
  • 1.2: Add the ability to not display the generated image (it will only resize the original one in the right folder)
  • 1.3 Add the base url to the image path when displaying it
  • 1.4: Adding "width" and "height" tags to the generated image since it's a good practice: PageSpeed best practices
  • 1.5: Now Image extension can use ImageMagick or GD library to resize images. (Before it was only GD no matter what was the user configuration).
  • 1.6: Add the ability to choose which resize mode to use (NONE, AUTO, WIDTH, HEIGHT), add the ability to add other attributes to the image tag.
  • 1.7 Thanks to Oreolek the exceptions are now handled internally if not in debug mode.

Total 20 comments

#16913 report it
gb5256 at 2014/04/13 09:12am
Another hack: add image as Square

To allow the user to ask for a squared image, do this:

in setWidthAndHeight()

$this->width = $size['width'];
$this->height = $size['height'];
if($size['square'] == 1) {
    $this->square = $size['square'];
}

in createImagesIfNotExists()

if ($this->square == 1) {
    if ($image->__get('height')>$image->__get('width')){
        //throw new CHttpException(404,'sqare');
        $image->resize($this->width, NULL)->crop($this->width, $this->height);            
    } else {
        $image->resize(NULL,$this->width)->crop($this->width, $this->height);
 
    }
 
} else {
    $image->resize($this->width, $this->height);
}
#16912 report it
gb5256 at 2014/04/13 09:08am
Another hack for your extension

Hello, I have another idea for your extension: Allow the user the ask for a "square" images:

in createImagesIfNotExists()

if ($this->square == 1) {
if ($image->__get('height')>$image->__get('width')){
                            //throw new CHttpException(404,'sqare');
                            $image->resize($this->width, NULL)->crop($this->width, $this->height);            
                        } else {
                            $image->resize(NULL,$this->width)->crop($this->width, $this->height);
 
                        }
 
} else {
                        $image->resize($this->width, $this->height);
}

And in setWidthAndHeight()

$this->width = $size['width'];
$this->height = $size['height'];
if($size['square'] == 1) {
       $this->square = $size['square'];
}

gb5256

#14584 report it
zanscath at 2013/08/25 10:03am
file_exists error

I just uploaded my local project (that works really well btw on xammp) on my HostGator server. I get errors on line 181: 180 if (!file_exists($this->_originalFile)) { 181 throw new Exception($this->image . ' do not exists!');

I have no idea why this is happening. The filename in the error points to the exact filename i get on the server.

#13315 report it
kicoe at 2013/05/22 06:10am
RE: Love it, juste a problem with heavy images

Actually I meant before uploading, resizing the original image to a more suitable size. I'll look into it but I'm also exploring the ImageMagick solution!

BTW, thank a lot!

#13314 report it
darkheir at 2013/05/22 06:00am
RE: Love it, juste a problem with heavy images

But I think it must be possible to find something to use client side memory to resize before uploading, no?

The widget can't handle it on the client side since all the php is executed on the server side (only javascript can be executed int he client browser). If you don't want to change to imagemagick or give more memory to php your best bet is to limit the size of the uploaded image and force the users to give smaller images in the upload form!

#13310 report it
kicoe at 2013/05/22 04:55am
RE: Love it, juste a problem with heavy images

Hi,

Thank you for your help, I will try it out. But I think it must be possible to find something to use client side memory to resize before uploading, no?

Nevertheless, I'll look up ImageMagick!

#13283 report it
rhigel at 2013/05/20 12:00pm
How To Display Image Orderly

hi again darkheir :D

i wonder how to display image orderly. at the moment im thinking about using dynamicdrive css as the style. i have been trying it but somehow, i think im doing it the wrong way.

if you have spare time, please drop by to forum : How To Display Image Orderly. i already post question, code, and the displayed picture there.

thank you. :)

#13278 report it
darkheir at 2013/05/20 06:24am
RE: Love it, juste a problem with heavy images

Okay, I tried with a big image and I have an error! The error is:

PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 29180 bytes) in protected/extensions/image/drivers/Image_GD_Driver.php on line 77

My memory limit was 32M. I tried to change it to 512M (just for testing purpose) and then the image is resized and displayed! So the problem is that php needs a lot of memory to resize a big sized image.

For me the solution would be one of the following:

  1. Allocate more memory to php: In your php.ini file change the memory_limit var to something more important.
  2. Use ImageMagick instead of GD to manipulate images. Imagemagick is not impacted by php memory limit, so you will be able to leave the same amount of memory for php. The drawback is that ImageMagick needs to be installed on your server.
#13270 report it
kicoe at 2013/05/19 04:59pm
RE: Love it, juste a problem with heavy images

Thank you for helping, Actually, this did not work, my image is uploaded but not resized... :-/

#13268 report it
darkheir at 2013/05/19 02:19pm
RE: Love it, juste a problem with heavy images

Hi,

Thank for your kind comment, I'm glad that you like this extension!

For your problem with big Images I have to admit that I never tried it. I will look into that, but chances are that php hasn't enough memory to handle big sized images or that it's a problem coming from the image extension.

To know if this is a problem coming from php or the image extension you could try the following code for one of the images causing problem:

Yii::import('application.extensions.image.Image');
$image = new Image('path/to/your/original/image.png');
$image->resize($width, $height);
$image->save('path/to/your/new/image.png');
#13267 report it
kicoe at 2013/05/19 01:36pm
Love it, juste a problem with heavy images

Hi,

First, thank you for this work, it takes a huge place in my project and you are reponsible of its success :-)

I just had an issue with large images when trying to show the resized version of them, e.g. >5Mb for this exemple. I don't have any error code to show, my app just crashes. Do you have any suggestion ?

#13168 report it
darkheir at 2013/05/10 05:43am
RE: Image Does Not Show

The version 1.3 fixes rhigel problem (see forum thread for more informations)

#13151 report it
rhigel at 2013/05/08 01:20pm
Image Does Not Show

the image only show the title as picture. can you give me advice where i do wrong in my code.

_view.php

<?php $this->widget('saimagedisplayer', array(
            'image' => '21.png',
            'size' => 'tiny',
            'displayImage' => true,
            'title' => 'My super title',
        )); ?>

it show the name/title "21.png" as picture. it doesnot show the real picture. i wonder why is that happen. below is my main code.

main.php

'import'=>array(
                ...
 
                'application.helpers.*', // yii image
                'ext.saimagedisplayer.*',// SAImageDisplayer        
    ),
 
    'components'=>array(
                ...
                'widgetFactory'=>array(
                    'widgets'=>array(
                        'saimagedisplayer'=>array(
                            'baseDir' => 'images',
                            'originalFolderName'=> 'originals',
                            'sizes' =>array(
                                'tiny' => array('width' => 40, 'height' => 30),
                                'big' => array('width' => 640, 'height' => 480),
                                'thumb' => array('width' => 400, 'height' => 300),
                            ),
                        ),
                    ),
                ),
 
                'image'=>array(
                  'class'=>'application.extensions.image.CImageComponent',
                    // GD or ImageMagick
                    'driver'=>'GD',
                    // ImageMagick setup path
                    //'params'=>array('directory'=>'/opt/local/bin'),
                    'params'=>array('directory'=>'C:/Program Files (x86)/ImageMagick-6.8.5-Q16'),
                ),  
    ),

i also put same question in yii forum. Image Does Not Show. if know the answer of my problem, you can either answer here or in the forum.

thank you.

#12861 report it
darkheir at 2013/04/16 09:03am
Re: Proposal for addition to your extension

This is actually a great idea!

I will update the extension and the documentation when I have some spare time!

#12833 report it
gb5256 at 2013/04/15 05:53am
Proposal for addition to your extension

Hi, I am using this extension quite often, works perfect. Thanks for this. I have made one addition to your script, which actually makes the usage of it even broader. My case is: Sometimes, I do want to display an image inside another widget. Or within a cell of the grid. To call a widget from within another widget can be very difficult or whith huge workarounds. I created a simple solution for it. I defined a new paramter called "precheck". So the widget calls this:

<?php $this->widget('ext.SAImageDisplayer', array(
    'image' => 'yourImage.png',
    'size' => 'thumb',
    'defaultImage' => 'default.png',
    'group' => 'reviews',
    'precheck' => true,
)); ?>

Within your extension, I define that this variable, set it default to be false and edited the run-Function so that it only returns the image-tag, if precheck is false. This way your whole script is running, checking if image exist,storing it correctly without showing it inside the view, as nothing is returned. I can then inside the view use the image in fancybox, knowing that your script has created everything needed on the page.

Hope it helps others, gb5256

#12519 report it
Tikisman at 2013/03/25 12:30pm
im a noob

OMG i forgot image extension! testing if it works now..

EDIT: Ok, it works now. Great support, thank you very much and sorry, im yii noob :P

#12518 report it
darkheir at 2013/03/25 12:28pm
re: error

Just a question: have you installed the "image" extension (http://www.yiiframework.com/extension/image)?

It's indicated in the requirements that this extension needs Image's extension to work.

If it's not it then I'm going to watch it at home and I'll get back to you! Keep me informed.

#12517 report it
Tikisman at 2013/03/25 12:16pm
error

Yes.

My config:

'widgetFactory'=>array(
            'widgets'=>array(
                    'class'=>'CWidgetFactory',
                    'SAImageDisplayer'=>array(
                        'baseDir'=>'anexos/imagenesCT',
                        'originalFolderName' => 'centro_trabajo',
                        'sizes' =>array(
                            'centro_trabajo_thumbnails' => array('width' => 40, 'height' => 30),
                        ),
                    ),
            ),
    ),

And in my view:

$this->widget('ext.SAImageDisplayer', array(
                    'image' => 'a.jpg',
                    'size' => 'centro_trabajo_thumbnails',
));

And the error: Stack Trace

0

+ C:\xampp\htdocs\yii-1.1.13\framework\YiiBase.php(395): YiiBase::autoload()

1

unknown(0): YiiBase::autoload("Image")

2

+ C:\xampp\htdocs\WorkPro\protected\extensions\SAImageDisplayer.php(170): spl_autoload_call("Image")

3

+ C:\xampp\htdocs\WorkPro\protected\extensions\SAImageDisplayer.php(125): SAImageDisplayer->createImagesIfNotExists()

4

+ C:\xampp\htdocs\yii-1.1.13\framework\web\CBaseController.php(147): SAImageDisplayer->init()

5

+ C:\xampp\htdocs\yii-1.1.13\framework\web\CBaseController.php(172): CBaseController->createWidget("ext.SAImageDisplayer", array("image" => "a.jpg", "size" => "centro_trabajo_thumbnails"))

6

+ C:\xampp\htdocs\WorkPro\protected\modules\centrotrabajo\views\centrotrabajo_form.php(120): CBaseController->widget("ext.SAImageDisplayer", array("image" => "a.jpg", "size" => "centro_trabajo_thumbnails"))

7

+ C:\xampp\htdocs\yii-1.1.13\framework\web\CBaseController.php(126): require("C:\xampp\htdocs\WorkPro\protected\modules\centrotrabajo\views\ce...")

8

+ C:\xampp\htdocs\yii-1.1.13\framework\web\CBaseController.php(95): CBaseController->renderInternal("C:\xampp\htdocs\WorkPro\protected\modules\centrotrabajo\views\ce...", array("model" => Centrotrabajo), true)

9

+ C:\xampp\htdocs\yii-1.1.13\framework\web\CController.php(869): CBaseController->renderFile("C:\xampp\htdocs\WorkPro\protected\modules\centrotrabajo\views\ce...", array("model" => Centrotrabajo), true)

Thanks.

#12515 report it
darkheir at 2013/03/25 12:08pm
re: installation failed

@Tikisman : Could you show me what did you put in your configuration file and how did you call the plugin?

#12514 report it
Tikisman at 2013/03/25 12:03pm
bad

bad installation instructions, plugin fails

Leave a comment

Please to leave your comment.

Create extension