Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for #46: Implementation of Image helper based on Imagine library #1669

Merged
merged 19 commits into from
Dec 31, 2013

Conversation

tonydspaniard
Copy link
Contributor

Closes #46

Implements common used methods for Image manipulation:

  • crop
    Yii::$app->image->crop('/path/to/image.jpg', 200, 200, 720, 450);
  • thumb (keeping aspect ratio)
    Yii::$app->image->thumb('/path/to/image.jpg',120, 120);
  • text
    Yii::$app->image->text('/path/to/image.jpg', 'Yii-2 Image', ['font' => 'path/to/font.otf', 'size' => 12, 'color' =>'000']);
  • watermark
    Yii::$app->image->crop('/path/to/image.jpg', /path/to/watermark.jpg' );
  • frame
    Yii::$app->image->frame('/path/to/image.jpg', 5 );

It uses Imagine library. It also contains a method to access Imagine methods directly (ie when used for simple image manipulations):

Yii::$app->image->getImagine()
   ->open('/path/to/image.jpg')
   ->save('/path/to/image.jpg', array('quality' => 50));

Edit: This extension is on WIP, methods are proven to work, if accepted. Then will write the tests

tonydspaniard and others added 8 commits December 20, 2013 14:02
Conflicts:
	extensions/yii/jui/CHANGELOG.md
* origin/master:
  Update change log
  Add active id to options if input widget has a model fixes yiisoft#1550
* upstream:
  Fixed CSRF token masking issue.
  improved error message of calling invalid scope method.
  Fixed repo URL
  Fixes yiisoft#1650: Added Connection::pdoClass.
  code style fix.
  added changelog
  codestyle fix
  improved checkIntegrity method
  Modified extension guidlines
  fix sphinx command signature
  fixed bug with forgotten param, fixed behavior for one table integrity
  fixed sequence reset
  added postgresql features to reset seq/check integrity
* upstream:
  Fixed CSRF token masking issue.
  improved error message of calling invalid scope method.
  Fixed repo URL
  Fixes yiisoft#1650: Added Connection::pdoClass.
  code style fix.
  added changelog
  codestyle fix
  improved checkIntegrity method
  Modified extension guidlines
  fix sphinx command signature
  fixed bug with forgotten param, fixed behavior for one table integrity
  fixed sequence reset
  added postgresql features to reset seq/check integrity
@qiangxue
Copy link
Member

Looks good to me. @yiisoft/core-developers What's your opinion?

Do you plan to implement more commonly used methods?

@tonydspaniard
Copy link
Contributor Author

@qiangxue the ones included are the most common used. If @yiisoft/core-developers have any suggestions that cannot be easily handled with Imagine would be great to hear it.

/**
* @return array of available drivers.
*/
public function getAvailableDrivers()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tonydspaniard About this method implementation. Why not just:

return [static::DRIVER_GD2, static::DRIVER_GMAGICK, static::DRIVER_IMAGICK];

For which goals you use excess/static variable ❓

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@creocoder fast typing... fixing

Any other methods to implement?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tonydspaniard

Any other methods to implement?

Will think about that.

* @return ManipulatorInterface
*/
public function watermark($filename, $watermarkFilename, Point $pos = null)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Different methods interface looks inconstant: here you pass coordinates as an object, while in “crop()” you are using separated $startX, $startY.

@klimov-paul
Copy link
Member

Any other methods to implement?

Maybe “rotate()”.

@qiangxue
Copy link
Member

What about resize()? Does thumbnail() do the same thing?

@tonydspaniard
Copy link
Contributor Author

@qiangxue resize() is something very simple to do with access to getImagine(), not worth a method here.

Maybe “rotate()”.

Same goes with rotation. Check results of the following code (frame it and then rotate -8 degrees):

Yii::$app->image->frame($imgPath, 5, '666', 0)
    ->rotate(-8)
    ->save($runtime . '/123456789.jpg', ['quality' => 50]);

123456789

private $_imagine;
/**
* @var string the driver to use. These can be:
* - gd2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to provide constants in example or people will use strings directly.

@samdark
Copy link
Member

samdark commented Dec 28, 2013

Looks OK to me overall.

* - imagick
* - gmagick
*/
private $_driver = "gd2";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"gd" => 'gd'

@kmergen
Copy link

kmergen commented Dec 29, 2013

How can I implement extension in my project. Can not find extension in extensions directory

@creocoder
Copy link
Contributor

@kmergen This is not merget yet.

* @param integer $y position on image to apply watermark. Defaults to null
* @return ManipulatorInterface
*/
public function watermark($filename, $watermarkFilename, $x = null, $y = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is better to pass coordinates as an array. Single argument will simplify the interface as well as cover possible pass of “Point” object:

public function watermark($filename, $watermarkFilename, $point = null)
{
    if (is_array($point)) {
        list($x, $y) = $point;
        $point = new Point($x, $y);
    } elseif ($point instanceof Point) {
        // do nothing  
    }
}

Same strategy can be applied for all methods.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

* upstream: (35 commits)
  Fixes yiisoft#1691: added “viewport” meta tag to layout views.
  Fixed the issue that query cache returns the same data for the same SQL but different query methods
  moved section
  subsection added
  typo [skip ci]
  docs about response
  Fixes yiisoft#1586: `QueryBuilder::buildLikeCondition()` will now escape special characters and use percentage characters by default
  docs improved
  csrf docs added
  Fixes yiisoft#1685: UrlManager::showScriptName should be set true for tests.
  Fixes yiisoft#1688: ActiveForm is creating duplicated messages in error summary
  change back the visibility of findTableNames to protected.
  Typo fix.
  Fixes yiisoft#1681: Added support for automatically adjusting the "for" attribute of label generated by `ActiveField::label()`
  Simplified tests.
  Fixes yiisoft#1631: Charset is now explicitly set to UTF-8 when serving JSON
  Fixed typo
  added html layout for mail component in basic app
  CS fixes.
  Merge branch 'debug_module_improvements' of github.com:Ragazzo/yii2 into Ragazzo-debug_module_improvements
  ...
@qiangxue qiangxue merged commit 52ad66e into yiisoft:master Dec 31, 2013
@qiangxue
Copy link
Member

merged 2df7d0a

@qiangxue
Copy link
Member

I just review the code. It seems to me the only configurable option is which driver to use. For this reason, how about we turn this into a static helper instead of an application component? The helper can automatically choose which driver to use based on the installed PHP extensions.

@cebe
Copy link
Member

cebe commented Jan 1, 2014

Sounds good to me. We can have a static property for the driver that is null for autodetect and may be set explicitly.

@creocoder
Copy link
Contributor

@cebe Which order for autodetection:

1) Gmagick
2) Imagick
3) Gd2

or

1) Imagick
2) Gmagick
3) Gd2

?

@samdark
Copy link
Member

samdark commented Jan 1, 2014

Gmagick, Imagick, Gd2 according to performance and efficiency.

@qiangxue
Copy link
Member

qiangxue commented Jan 1, 2014

Finished refactoring.

@qiangxue
Copy link
Member

qiangxue commented Jan 1, 2014

@tonydspaniard The frame() method doesn't look quite right to me. Currently, the frame is added to the outside of the original image. The $alpha value doesn't make much sense then. IMO, the frame should be added to the inside of the image with alpha value indicating the transparency of the frame. By doing so, we also keep the image size unchanged, which is probably preferable in practice. What do you think?

@cebe
Copy link
Member

cebe commented Jan 1, 2014

margin could be positive for inside frame or negative for outside frame. alpha should have no effect on outside frame then.

For the text() method I think we should add a position parameter that can be a point or array as it is in the other methods. it is quite uncommon that the position will be default.

@cebe
Copy link
Member

cebe commented Jan 1, 2014

rest of the code looks really cool to me :)

@qiangxue
Copy link
Member

qiangxue commented Jan 2, 2014

I have refactored the text() method as you suggested.

I like your suggestion about the frame margin. I don't know how to implement the inside frame though. @tonydspaniard Do you have any idea?

@tonydspaniard tonydspaniard deleted the 46-image-helper branch February 5, 2014 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement ImageHelper
7 participants