php-imagine / imagine Goto Github PK
View Code? Open in Web Editor NEWPHP Object Oriented image manipulation library
Home Page: https://imagine.readthedocs.io
License: Other
PHP Object Oriented image manipulation library
Home Page: https://imagine.readthedocs.io
License: Other
Hopefully, when my PR for phar-util is accepted (see koto/phar-util#14), I see Imagine wanting to take advantage of the new feature; in most of my own tests on working phars, the size has dropped by approximately 40-50% in well-commented code.
The phar-build line in the makefile would likely need to be changed to this (the only change is the addition of the --strip-files
flag and param):
phar-build -s ./lib/Imagine -S ./.stub --phar ./imagine.phar --ns --strip-files ".php$"
I'd appreciate it if this issue were marked as "research" for the time being until the associated pull-request for phar-util is merged, thanks!
I tried cropping a 700x360 image to 100x10 and got the following exception
OutOfBoundsException: Crop coordinates must start at minimum 0, 0 position from top left corner, crop height and width must be positive integers and must not exceed the current image borders.
at Image->thumbnail(object(Box), 'outbound')
Don't have time to investigate right now so if someone else does..
It looks like a little bug hiding there - https://github.com/avalanche123/Imagine/blob/master/lib/Imagine/Gd/Image.php#L196
Instead of $color there should be $background.
private function saveOrOutput($format, array $options, $filename = null, Color $background = null)
.... Image type GIF ....
$color = $background ? $background : new Color('ffffff');
.... Iteration through each pixel ....
imagesetpixel($this->resource, $x, $y, $this->getColor($color));
The problem is that gif image only have 256 colors and when you are trying to allocate more imagecolorallocatealpha returns false and Imagine throws exception.
To fix that you just need to change code like below:
.... Image type GIF ....
$color = $background ? $background : new Color('ffffff');
$gdColor = $this->getColor($color);
.... Iteration through each pixel ....
imagesetpixel($this->resource, $x, $y, $gdColor);
Thank you...
I'm resizing and adding a border to a 1Mb image and the script uses about 80Mb.
Works fine on my local machine with php.ini > memory limit = 128M
But my shared host has it hardcoded to 64M (can't change via .htaccess nor ini_set() )
So I get:
Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 13219521 bytes)
Is there any way to reduce Imagine's memory usage? Thanks!
While using Imagick everything goes fine, and when you attempt to save to a directory without permissions and exception is thrown as expected.
However, while using GD, a warning is thrown along with the return false. Which breaks the flow in developer machines where warnings are errors.
Unfortunately, for you to avoid this the only way to do it is calling the GD function using the '@' operator in order to maintain the proper flow.
I hate using this surpressor, and would much rather see PHP itself fix the GD extension to function as the Imagick does, but what do you think about this?
When i get the phar from master or devel branch and do:
include 'phar://imagine.phar';
var_dump(class_exists('Imagine\Image\ImageInterface'));
var_dump prints false. I'm using php 5.3.3, and Imagick 3.0.0RC1. No errors in the apache log, file is readable.
any idea why this would be happening?
I was working with a Gd adapter in Imagine today and I encountered a problem where an error was triggered because of a bug.
Shouldn't we add a default error handler to catch these errors and throw exceptions?
I've just adapted the error handler from Symfony real quickly. Would you like me to open a pull request?
<?php
namespace Imagine\Error;
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Adapted PHP error handler.
* Original design by Fabien Potencier
*
* @author Fabien Potencier <[email protected]>
*/
class ErrorHandler
{
/**
* @var array
*/
protected $_levels;
/**
* @var string
*/
protected $_level;
/**
* @var string
*/
protected $_previousErrorHandler;
/**
* Instantiate an error handler and tell it to which level of errors it
* should listen to.
*
* If no error level is given it will default to the PHP ini setting.
*
* @param integer $arg_level
*
* @return void
*/
public function __construct ($arg_level = NULL)
{
$this->_level = NULL === $arg_level ? error_reporting() : $arg_level;
$this->_levels = array(E_WARNING => 'Warning'
,E_NOTICE => 'Notice'
,E_USER_ERROR => 'User Error'
,E_USER_WARNING => 'User Warning'
,E_USER_NOTICE => 'User Notice'
,E_STRICT => 'Runtime Notice'
,E_RECOVERABLE_ERROR => 'Catchable Fatal Error'
);
}
/**
* Register the error handler.
*
* @return void
*/
public function register ()
{
$this->_previousErrorHandler = set_error_handler(array($this, 'handle'));
}
/**
* Unegister the error handler and re-register the original error handler.
*
* @return void
*/
public function unregister ()
{
set_error_handler($this->_previousErrorHandler);
}
/**
* Handle a specific error
*
* @param string $arg_level
* @param string $arg_message
* @param string $arg_file
* @param string $arg_line
* @param string $arg_context
*
* @return boolean
*
* @throws ErrorException
*/
public function handle ($arg_level, $arg_message, $arg_file, $arg_line, $arg_context)
{
if (0 === $this->_level)
{
return FALSE;
}
if (error_reporting() & $arg_level && $this->_level & $arg_level)
{
throw new \ErrorException(sprintf('%s: %s in %s line %d', isset($this->_levels[$arg_level]) ? $this->_levels[$arg_level] : $arg_level, $arg_message, $arg_file, $arg_line));
}
return FALSE;
}
}
Imagick has the fantastic ability to load PDFs (and myriad other formats that GD won't support) but for these there has to be a conversion from real world units into pixels. This is as simple as changing:
$imagick = new \Imagick($path);
to (for 72 dpi)
$imagick = new \Imagick();
$imagick->setResolution(72, 72);
$imagick->readImage($path);
in the open method. It would be really nice if this could be incorporate, maybe using an options array similar to the way the options array works for saving.
Many thanks for all your hard work on this and sorry for posting all these irritating requests. It's a really great tool.
It would be nice to have something like ->text(PointInterface $position, $text, $font);
in the drawing API
I would like a method to change an image's saturation (using imagick->modulateImage) but have no clue how to achieve comparable results with gd. Converting the image pixel by pixel to HSV seems not a good idea ...
The master branch is currently the 0.1.5 release which is 4 months old. The library changed a lot since then, including changing the namespace of the interface. This makes the old releases incompatible with the current code using Imagine (in the bundle for instance). You should IMO release a new version of the library as it confuse people to have an outdated version of the library when cloning it.
The default behaviour of Imagick is to draw a line then fill the stroke with the specified colour around it, hence for semi-transparent lines drawn with Imagine, it appears as a 1px line in the middle with the correct colour surrounding it.
http://www.imagemagick.org/Usage/draw/#strokewidth
Adding
$line->setFillColor($pixel);
into the line function solves this.
I'm not sure if this can be already done somehow, the doc page says "More filters and advanced transformations is planned in the nearest future.".
I would like to know if you plan on creating output filters that would allow a user for example to have a custom filter to cache versions of the image and store them in the file system or upload them into a cloud. A filter would be interesting here because we have our own storage abstraction for local FS remote services like cloud services. Similar to http://framework.zend.com/manual/de/zend.cloud.storageservice.html
If you plan on something like that let me know and share your ideas you might already have, I might implement it in a branch.
Edit: I've checked the current code and I do not think what I want is possible because the image manipulations are already applied before I can intercept it somehow and check for a cached version of the file. I might be wrong if so please correct me.
Warning: imagecolorsforindex(): Color index 58 out of range in lib/Imagine/Gd/Image.php line 588
Apparently the 'IMAGETYPE_SWC' constant is not available for all PHP 5.3 builds. I get the following PHP E_NOTICE level error when using Imagine:
Notice: Use of undefined constant IMAGETYPE_SWC - assumed 'IMAGETYPE_SWC'
I commented it out for now in my own copy of the lib, but I know that's not a permanent solution.
Should I create a test case for it? I guess that would involve creating a source image and expected output?
My guess it has something to do with the call_user_func_array
invocation not receiving the arguments in the proper order but I've yet to test that (can't right now).
Subj. Maybe also APNG?
This will make them visible if filter class is extended.
First of all, thumbs up for (finally) building a promising image manipulation library in PHP that's elegant and easy to handle.
And not sure if this is within the scope of Imagine at all but all the inconsistencies and hacks regarding to using non-standard fonts on the web (even now) kind of leave me wishing for a good PHP library that handles some 'advanced' things related to drawing text.
Some things I'd wish Imagine could do beyond basic font drawing are: the already requested word-wrapping (and a way to set the line height), letter spacing (plus maybe word spacing) and probably the most difficult/intense task to implement across all 'drivers': anti-aliasing.
I have been trying to find a suitable library for these things and never found anything that's "good enough" in terms of the output and the usability. (Been a while since I have been looking around, recommendations welcome!)
I think this would be a great step towards making Imagine more complete and as extended charts functions are already targeted, it would be great to have fonts covered as well.
(Also I was hesitant to make this an 'issue' at all but I guess this is the best way to put this up for discussion.)
Hi,
first thing - thanks for that beautiful library. I really appreciate to work with it.
There is one small question left for me:
If i try to make a FilterInterface to manipulate the color of an image like this:
class Color implements FilterInterface { private $color; public function __construct($value) { $ratio = max($value, 255); $this->color = new \Imagine\Image\Color('fff'); $this->color->darken($value); } public function apply(ImageInterface $image) { imagefilter($image->resource, IMG_FILTER_COLORIZE, $this->color->getRed(), $this->color->getGreen(), $this->color->getBlue() ); return $image; } }
there is no way to get receive the resource of the image because it's a private property. I also
haven't found a getter method. So might it make sense to create a getter, or do I only have some heavy knots in my thoughts?
Thanks
I know it is not possible to preserve IPTC headers while using the GD adapter, bug Imagick supports this (I guess Gmagick does as well).
It would be nice if resize() could also resize images like THUMBNAIL_INSET does, but maintain IPTC information. And thumbnail() could get rid of the IPTC headers since you probably do not want to increase file size of your thumbnails.
For a number of reasons I can't use your thumbnail method for creating, well, thumbnails, and so I make a new canvas of known size and then paste a resized version of my original into it.
In Imagick, the resize method uses "adaptiveResizeImage" with rather horrible results. Is there a reason for this rather than a "thumbnailImage" call with known dimensions. It provides much nicer looking images for some reason.
I have got round this by using the Imagine thumbnail method for resizing instead of resize but it is quite a limitation, especially as in GD resize has much higher quality results.
Thanks.
Dom
Hi
First off, great idea and great library.
I use gravity (imagemagick) extensively for draw operations, so have hacked it in in a few places. Wondered if there was any reason you've not supported this? My guess is that its because its imagemagick only so makes the api inconsistent - which seems like a good reason!
Anyhow, I digress, should you be interested in this, I can look at working it in properly and submitting a pull request.
I've also cobbled together a way to wrap text within a box as well - any interest in supporting this? I think this should be possible across all three existing supported image tools.
Ben
Hey There
It's nowhere really explained which one is inset and which one is outbound. Adding that to the documentation would be very helpful.
Thank you.
Pascal Helfenstein
This library is awesome, however I don't know where I can find support, so i hope it's cool if I ask a question here.
Basically I've written this code where i can pass a target width and height and it will scale an image so that it uses the height or the width as ceiling. that is if I have an image of 150_150 and put it in my functio with the params 140_100 it will scale to 100*100.
however now I'd like to place that image centered on a 140*100 white canvas. Is that possible?
Code so far
$imagine = new \Imagine\Gd\Imagine();
try {
$image = $imagine->open($source_path);
} catch (Exception $e) {
return false; // image not present
}
$target_ratio = ($height) ? $width / $height : 0;
$source_ratio = ($image->getSize()->getHeight()) ? $image->getSize()->getWidth() /
$image->getSize()->getHeight() : 1;
//Handle images that have a different aspect ratio than the target ration
if ($target_ratio !== $source_ratio) {
$scale = 0;
if ($source_ratio > $target_ratio) {
if ($image->getSize()->getWidth() > $width) {
$scale = $width / $image->getSize()->getWidth();
}
} else {
if ($image->getSize()->getHeight() > $height) {
$scale = $height / $image->getSize()->getHeight();
}
}
if ($scale !== 0) {
$image->resize(
$image->getSize()
->scale($scale));
}
} else {
// ratio is equal
if ($image->getSize()->getWidth() != $width) {
$image->resize(
$image->getSize()
->scale(
$width / $image->getSize()
->getWidth()));
}
}
$options = array('quality' => $quality);
try {
$image->save($target, $options);
} catch (Exception $e) {
return false;
}
Is there an easy way to grayscale an image while keeping transparencies?
There are 2 main font problems for these libraries;
code>$size *= 72 / 96;
More?
P.S. I used imageftbbox for bbox calculation in GD and queryfontmetrics in Imagick.
P.P.S. Comparing results Imagick/Gmagick with Gd:
Imagick with GD: http://pastie.org/1794355 (save code on your computer by clicking download on left upper corner and open it in your browser)
Gmagick with GD: http://pastie.org/1794360 (same instrucations as above)
PHP code that was used for generation: http://pastie.org/1794364. For proper running you need a webserver with enabled gd with imagick either gmagick (but not both) and fix the path to the font in the beginning of the script.
Hi,
using the quality parameter doesn't affect filesize when the output is png. When outputting for example jpg the parameter is working.
->save($file, array('quality'=>'90'))
I am in the process of adding PDF preview support. I am guessing this feature will not be included as GD doesn't support PDFs. I'm using Imagine together with ImagineBundle.
I did some tests to see whether this is possible at all and it most certainlty seems to be. With a couple of line changes here and there I was able to make Imagine save the filtered preview images without any problems.
I also noticed that Imagine\Imagick\Image::supported()
is not implemented. For me this causes issues when displaying the image for the first time. It's called in Imagine\Imagick\Image::getMimeType
, which itself is used for defining the Content-type
header.
Documentation states that you can resize by:
$image->resize($width, $height) - resizes image to given $height and $width exactly
However, you must use a BoxInterface
$image->resize(BoxInterface $size)
Shouldn't Imagine\Image\ManipulatorInterface::show() be setting the content-type header?
I would submit a pull request, but I cant find the image function that is passed to call_user_func_array() that would be responsible for setting the headers (in Gd/Image.php). Maybe you would want to set the header in the show() method its self..
Gd seems to be rotating the images counter-clockwise while Imagick and Gmagick rotates clockwise. The following code will therefore not generate the same image:
$imagine = new Imagine\Gd\Imagine();
print($imagine->open('/path/to/file.png')->rotate(90));
and
$imagine = new Imagine\Imagick\Imagine();
print($imagine->open('/path/to/file.png')->rotate(90));
Is this intentional behaviour in Imagine or should it be expected that the different drivers produce the same output given the same input?
I can't tell from the docs if this is possible, but I would like to overlay a png with a solid color, while maintaining transparency.
This feature would be useful for changing the color of icons on the fly. Is this currently possible?
it would be nice to support stream resources in the ImagineInterface. right now there is only open (for filesystem paths) and load (for strings). actually maybe there should be one method that can consume all 3 formats (path, string, resource).
Are there plans to bring the namespacing inline with PSR-0? There's no vendor name for this library so the product name clashes with another vendor, and because of the ImageInterface and ImagineInterface being only one-level up on the namespace, separation won't work with most autoloaders.
We store files in a way like /storage/images/jpg/31/5D/K3/ without an extension. By using Imagine as an image processing engine this becomes an issue for us because you have to pass an extension to the output file.
Please make it possible to override the current behavior of mapping the extension to an output format by maybe passing a "format" option to the options array. If the "format" is set in the options the code could ignore the extension and instead use the passed format.
Let me know if my proposed solution is ok for you and I might fix it in my branch.
I'm mostly posting this here as a feature request and reminder: would it be better to use PHP native way to work with hexadecimal notation?
E.g.
$color = new Imagine\Image\Color(0xFFFFFF);
Using Imagine for importing images (with SonataMediaBundle), I've got this error :
Notice: imagecreatefromjpeg() [function.imagecreatefromjpeg]:gd-jpeg, libjpeg: recoverable error: Premature end of JPEG file
Line 157 in Imagine.php
Is it possible to have a try/catch, an exception or else for detecting this problem ?
Thanks !
the idea being that in same cases its just important to ensure a certain width or height, but that the other dimension should just be changed proportionally. this is a feature i am missing in the thumbnail filter of the imagine bundle:
https://github.com/avalanche123/AvalancheImagineBundle/blob/master/Imagine/Filter/Loader/ThumbnailFilterLoader.php
Hello.
How i can set the default background color for a new image?
E.g.: i want make a new image on basics of old image, but with wider canvas. In this case, background in new image will be filled with black color, but i need a way to change it.
In gd2 library i'm using imagefill() function for this.
Thanks.
It's not possible to get a color of point in the image.
It would be nice to have new method:
Image::getColorAt($x, $y);
returning Color object.
Would do you think about this?
When using Image->copy() on the gd implementation on a png image with alpha, the alpha information is lost.
Is there a way to crop to a mask? (that is, a binding box that contains all non-transparent pixels from a grayscale mask)
Hi guys,
Since a recent update of symfony I have this error and Imagine doesnt work anymore:
Catchable Fatal Error: Argument 5 passed to Avalanche\Bundle\ImagineBundle\Controller\ImagineController::__construct() must be an instance of Symfony\Component\Filesystem\Filesystem, instance of Symfony\Component\HttpKernel\Util\Filesystem given, called in /Users/pb/Sites/affilae/www/app/cache/dev/appDevDebugProjectContainer.php on line 911 and defined in /Users/pb/Sites/affilae/www/vendor/bundles/Avalanche/Bundle/ImagineBundle/Controller/ImagineController.php line 60
Thank you for your help,
Regards.
The GD Drawer implementation should be checking for the existence of the following true/free type functions:
They might not be enabled on some platforms...
As far as I can see it is the result of compiling GD without the correct --with-freetype-dir
.
How would you like the test case formatted?
What about supporting ExactImage ?
When using crop the image is cropped starting from the left side of the image,
it would be nice to center the larger side.
For example if you have 150x100 image, want to crop to 100x100
the start position should be 25px using this option, instead 0.
I need this in order to e.g.
Extending Imagine\Imagick\Image is not possible as this is final class.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.