The Gregwar\Image class purpose is to provide a simple object-oriented images handling and caching API

Overview

Gregwar's Image class

Build status paypal

The Gregwar\Image class purpose is to provide a simple object-oriented images handling and caching API.

Installation

With composer :

{
    ...
    "require": {
        "gregwar/image": "2.*"
    }
}

Usage

Basic handling

Using methods chaining, you can open, transform and save a file in a single line:

 use Gregwar\Image\Image;

Image::open('in.png')
     ->resize(100, 100)
     ->negate()
     ->save('out.jpg');

Here are the resize methods:

  • resize($width, $height, $background): resizes the image, will preserve scale and never enlarge it (background is red in order to understand what happens):

resize()

  • scaleResize($width, $height, $background): resizes the image, will preserve scale, can enlarge it (background is red in order to understand what happens):

scaleResize()

  • forceResize($width, $height, $background): resizes the image forcing it to be exactly $width by $height

forceResize()

  • cropResize($width, $height, $background): resizes the image preserving scale (just like resize()) and croping the whitespaces:

cropResize()

  • zoomCrop($width, $height, $background, $xPos, $yPos): resize and crop the image to fit to given dimensions:

zoomCrop()

  • In zoomCrop(), You can change the position of the resized image using the $xPos (center, left or right) and $yPos (center, top or bottom):

zoomCrop() with yPos=top

The other methods available are:

  • crop($x, $y, $w, $h): crops the image to a box located on coordinates $x,y and which size is $w by $h

  • negate(): negates the image colors

  • brighness($b): applies a brightness effect to the image (from -255 to +255)

  • contrast($c): applies a contrast effect to the image (from -100 to +100)

  • grayscale(): converts the image to grayscale

  • emboss(): emboss the image

  • smooth($p): smooth the image

  • sharp(): applies a mean removal filter on the image

  • edge(): applies an edge effect on the image

  • colorize($red, $green, $blue): colorize the image (from -255 to +255 for each color)

  • sepia(): applies a sepia effect

  • merge($image, $x, $y, $width, $height): merges two images

  • fill($color, $x, $y): fills the image with the given color

  • write($font, $text, $x, $y, $size, $angle, $color, $position): writes text over image, $position can be any of 'left', 'right', or 'center'

  • rectangle($x1, $y1, $x2, $y2, $color, $filled=false): draws a rectangle

  • rotate($angle, $background = 0xffffff) : rotate the image to given angle

  • roundedRectangle($x1, $y1, $x2, $y2, $radius, $color, $filled=false): draws a rounded rectangle ($radius can be anything from 0)

  • line($x1, $y1, $x2, $y2, $color): draws a line

  • ellipse($cx, $cy, $width, $height, $color, $filled=false): draws an ellipse

  • circle($cx, $cy, $r, $color, $filled=false): draws a circle

  • fillBackground($bg=0xffffff): fills the background of a transparent image to the 'bg' color

  • fixOrientation(): return the image rotated and flipped using image exif information

  • applyExifOrientation(int $exif_rotation_value): return the image rotated and flipped using an exif rotation value

  • html($title = '', $type = 'jpg'): return the tag with the cache image

  • flip($flipVertical, $flipHorizontal): flips the image in the given directions. Both params are boolean and at least one must be true.

  • inline($type = 'jpg'): returns the HTML inlinable base64 string (see demo/inline.php)

You can also create image from scratch using:


    Image::create(200, 100);

Where 200 is the width and 100 the height

Saving the image

You can save the image to an explicit file using save($file, $type = 'jpg', $quality = 80):


    // ...
    $image->save('output.jpg', 'jpg', 85);

You can also get the contents of the image using get($type = 'jpg', $quality = 80), which will return the binary contents of the image

Using cache

Each operation above is not actually applied on the opened image, but added in an operations array. This operation array, the name, type and modification time of file are hashed using sha1() and the hash is used to look up for a cache file.

Once the cache directory configured, you can call the following methods:

  • jpeg($quality = 80): lookup or create a jpeg cache file on-the-fly

  • gif(): lookup or create a gif cache file on-the-fly

  • png(): lookup or create a png cache file on-the-fly

  • guess($quality = 80): guesses the type (use the same as input) and lookup or create a cache file on-the-fly

  • setPrettyName($prettyName, $prefix = true): sets a "pretty" name suffix for the file, if you want it to be more SEO-friendly. for instance, if you call it "Fancy Image", the cache will look like something/something-fancy-image.jpg. If $prefix is passed to false (default true), the pretty name won't have any hash prefix. If you want to use non-latin1 pretty names, behat/transliterator package must be installed.

For instance:

 use Gregwar\Image\Image;

echo Image::open('test.png')
          ->sepia()
          ->jpeg();

//Outputs: cache/images/1/8/6/9/c/86e4532dbd9c073075ef08e9751fc9bc0f4.jpg

If the original file and operations do not change, the hashed value will be the same and the cache will not be generated again.

You can use this directly in an HTML document:

resize(150, 150)->jpeg(); ?>" /> // ...">
 use Gregwar\Image\Image;

// ...
"resize(150, 150)->jpeg(); ?>" />
// ...

This is powerful since if you change the original image or any of your code the cached hash will change and the file will be regenerated.

Writing image

You can also create your own image on-the-fly using drawing functions:

write('./fonts/CaviarDreams.ttf', 'Hello '.$username.'!', 150, 150, 20, 0, 'white', 'center') ->jpeg(); ?> ">
 
    $img_src = Image::create(300, 300)
                    ->fill(0xffaaaa)    // Filling with a light red
                    ->rectangle(0xff3333, 0, 100, 300, 200, true) // Drawing a red rectangle
                      // Writing "Hello $username !" on the picture using a custom TTF font file
                    ->write('./fonts/CaviarDreams.ttf', 'Hello '.$username.'!', 150, 150, 20, 0, 'white', 'center')
                    ->jpeg();
?>
<img src=" $img_src  ?>" />

Using fallback image

If the image file doesn't exists, you can configurate a fallback image that will be used by the class (note that this require the cache directory to be available).

A default "error" image which is used is in images/error.jpg, you can change it with:


    $img->setFallback('/path/to/my/fallback.jpg');

Garbage Collect

To prevent the cache from growing forever, you can use the provided GarbageCollect class as below:

 use Gregwar\Image\GarbageCollect;

// This could be a cron called each day @3:00AM for instance
// Removes all the files from ../cache that are more than 30 days
// old. A verbose output will explain which files are deleted
GarbageCollect::dropOldFiles(__DIR__.'/../cache', 30, true);

Development

Gregwar\Image is using PHP metaprogramming paradigms that makes it easy to enhance.

Each function that handles the image is implemented in an Adapter, this is where all the specific actions take place.

The Common adapter is design to contain common abstract actions, while the specific adapters (like GD) are designed to contain actions specific to the low level layer.

You can add your own methods by adding it in the corresponding adapter.


    // In the adapter
    private function myFilter()
    {
        $this->negate();
        $this->sepia();
    }

Which could be used on the Image


    $image->myFilter();

You can also write your own adapter which could extend one of this repository and use it by calling setAdapter():


    $image->setAdapter(new MyCustomAdapter);

License

Gregwar\Image is under MIT License, please read the LICENSE file for further details. Do not hesitate to fork this repository and customize it !

Comments
  • Error during generate non-existing file

    Error during generate non-existing file

    This is part of my template.

    {{ image('image_uploads/' ~ program.id ~ '.jpg').resize(118,88) }}

    When file don't exist occurs error.

    <img src="/ Fatal error: Method Gregwar\ImageBundle\ImageHandler::__toString() must not throw an exception in /home/pchludzinski/www/d3/Symfony/app/cache/dev/classes.php on line 7063

    opened by piotrchludzinski 15
  • Set Cache Dir

    Set Cache Dir

    Hi, I was wondering if its possible to set the cache dir on the fly, without creating an instance. Actually, I don't know how to create a cache dir to activate it.

    opened by Surt 13
  • added powerful sharpen() filter / added extended zoomCrop()

    added powerful sharpen() filter / added extended zoomCrop()

    Hi,

    this is one of the best image classes I've found. Really clean code and nice work! There was just one thing I didn't like: sharp()

    It just runs the MEAN_REMOVAL and causes ugly images. I've implemented some more powerful method which also can receive parameters.

    public function sharpen($amount = 80, $radius = 0.5, $threshold = 3);
    

    The default settings are similar to photshop and the maximum values are also like photoshop. In most cases it should be good to just call ->sharpen() in your chain. If you want to be more or less aggressive, you can change the params.

    I hope you merge this PR and this fits to your coding standards.

    Important To prevent ugly or slow rendering problems, always use this filter at the end. Really, just do it. ->resize()->crop().....->sharpen($optional, $with, $parameters)->save() as described below

    This filter works also on PHP < 5, I guess we could/should remove this parts (I used this filter long time ago also with PHP4, but it's even fine with PHP 5.5+). It's up to you, as this Image-Class don't work with < 5.3

    Maybe we should add also something like this: (pseudocode)

    if imagetype == gif
    return $this
    

    Crop without ->sharpen() 145f12f0a61dcd9f84ba09ac7a67877b766cbca3

    Crop with ->sharpen() (default settings) 9a5eb7793597a0d0dd0f01463248bb77d8ece814

    Btw, I'm that pretty guy on the left :smile:

    opened by hirbod 11
  • Bug: resize() enlarges images without keeping original ratio. Fix provided.

    Bug: resize() enlarges images without keeping original ratio. Fix provided.

    Hi there! I found a (possible) bug using the image-bundle:

    The Readme tells that resize() should not enlarge images, preserving original ratio. If I ask the library to resize a 350x50 image specifying only one dimension, eg.

    ->resize(500, 0)

    I expect the library not to rescale it. The library, instead, outputs a 500x50 image, with padded pixels at both sides.

    This is not a correct behaviour, I think.

    I may have found the issue and fixed it.

    In Adapter/Common.js, lines 190:196

            if ($width == null || $crop) {
                $width = $new_width;
            }
    
            if ($height == null || $crop) {
                $height = $new_height;
            }
    

    should become:

            if ($width == null || $crop || $scale == 1) {
                $width = $new_width;
            }
    
            if ($height == null || $crop || $scale == 1) {
                $height = $new_height;
            }
    

    to prevent raw target values being passed to doResize() function.

    Thank you!

    opened by bozma88 8
  • Proposal: Adding image size difference in generation mobile platform, tablet or desktop

    Proposal: Adding image size difference in generation mobile platform, tablet or desktop

    It would be nice to go to resize a size chart to choose the size according to detected by the header sent by the client browser platform.

    The functionality would be neutral detection device, is another component that is recommeded in the documentation for it.

    Why I joined a switchable option parameter can be used on any action images.

    Simply append an action Switch case sensitive and use the action as shown. eg

    resizeSwitch( array( "phone" => array(150, 150), "tablet" => array(300, 300), "other" => array(450, 450), ), "phone");

    opened by jean-pasqualini 8
  • Add ability to specify custom cropping values for zoomCrop

    Add ability to specify custom cropping values for zoomCrop

    Currently, when you use zoomCrop() you cannot set custom cropping position other than basic left / right, top / bottom, center.

    With this PR, you can set a target cropping "zone" as it were (based on the original dimensions of the image) and it will try to crop from that area. It also handles if the given cropping position will result in a crop outside the bounds by forcing it stay within the bounds of the image (maybe that could be configured, if people really want it to crop outside for some reason?)

    My use case: I use a library to do face detection which returns a X, Y coords of the face. I want to zoomCrop around that area but currently that is not easily possible, this PR allows such a use case and others.

    opened by garygreen 6
  • Add test by Github Actions

    Add test by Github Actions

    Travis does not offer an easy free tier for open source, so I replaced it by the new Github Action service. I did not got the end of life php versions running properly, so dropped them. Before the usual complains: people with eol php can still use the older lib versions. Best wishes

    Changes:

    • Remove travis
    • Use current phpunit 9
    • Bump min php to 7.3
    • Test php 7.3, 7.4, 8.0, 8.1
    • Fix link to gregware.com
    opened by Rotzbua 5
  • Correcting required: gregwar/cache dependency version for composer insta...

    Correcting required: gregwar/cache dependency version for composer insta...

    Corrected the composer version attribute for "gregwar/cache", was "v1.0.7" which did not follow the composer configuration rules (https://getcomposer.org/doc/04-schema.md#version) and caused automatic installation with composer to stop with error.

    opened by born2discover 5
  • Default type for save should always be original

    Default type for save should always be original

    Right now the default type for a save is "jpeg" which in the case of certain images might not be desired.

    The library should use the value it gets from guessType() during __construct() as a default when saving the image.

    opened by atrauzzi 5
  • Function guess() not working

    Function guess() not working

    I'm having an issue with the function guess() The saved image is always a .jpeg.

    From the demo cache.php :

    echo Image::open('img/test.png')->sepia()->guess();
    result in: cache/images/1/2/3/7/f/1bdb743fb85b8445cf12a0a58a25e3edaa0.jpeg
    

    I found a solution with the following work around :

    $img = Image::open('img/test.png');
    $type = $img->guessType();
    $img->sepia()->cacheFile($type);
    
    opened by 10257 5
  • Undefined constant 'IMG_JPG'

    Undefined constant 'IMG_JPG'

    Undefined constant 'IMG_JPG' FILE: vendor/gregwar/image/Gregwar/Image/Image.php  LINE: 285

    when php uninstall "GD" extension , but "Imagick" installed

    opened by hizt 4
  • Deprecated: Implicit conversion from float 768.1159420289855 to int loses precision

    Deprecated: Implicit conversion from float 768.1159420289855 to int loses precision

    I'm using gregwar/image "2.1.0" in a Symfony PHP 8.1 app and I'm getting the following exception...

    Deprecated: Implicit conversion from float 768.1159420289855 to int loses precision

    In my code I'm calling..

    $img->save($absoluteDir . $outputDirectory . '/' . $newName, 'jpg', 90);

    And I believe the exception is being thrown in "/vendor/gregwar/image/Gregwar/Image/Adapter/GD.php" on line 90...

    imagecopyresampled($n, $this->resource, ($target_width - $new_width) / 2, ($target_height - $new_height) / 2, 0, 0, $new_width, $new_height, $width, $height);

    Thanks

    opened by WelshDev 0
  • How to change default dir cache folder?

    How to change default dir cache folder?

    use Gregwar\Image\Image;
    $img = new Image();
    $img->setCacheDir('customDir')->create($width, $height)->fill($faker->hexcolor)->save($path, config('mime.service'));
    # expected customDir/a/b/3....
    

    keeps creating cache/images folder

    opened by hebertlima 0
  • Centre Merged Images?

    Centre Merged Images?

    I am Implementing code as such:

    Image::open($target_path . '/' . $imageName)->merge(Image::open($source_path)->scaleResize('',$h_o))->save($target_path . '/' . $imageName, 'jpg');

    In this scenario I am taking a 16:9 image (already Created) $target_path, taking a 1:1 image $source_path and merging them. The images merge, but, I would like to center the 1:1 to the 16:9 image. Currently when I run this code, the 1:1 image is attached to the left of the image. Is there a way of centering the image instead?

    opened by AndrewMarkUK 0
  • AVIF support

    AVIF support

    Starting with php8.1 GD supports avif which is a new image format. It is the successor of webp.

    Playground

    • https://squoosh.app/

    Reference

    • https://en.wikipedia.org/wiki/AVIF
    • https://www.php.net/manual/en/function.imageavif.php
    • https://www.php.net/manual/en/function.imagetypes.php
    opened by Rotzbua 1
Owner
Grégoire Passault
Don't send me e-mail to advertise for your new products or services, thanks :)
Grégoire Passault
PHP 5.3 Object Oriented image manipulation library

Imagine Tweet about it using the #php_imagine hashtag. Image manipulation library for PHP 5.3 inspired by Python's PIL and other image libraries. Requ

Bulat Shakirzyanov 4.3k Jan 6, 2023
GifCreator is a PHP class that creates animated GIF from multiple images

================================ GifCreator ================================ GifCreator is a PHP class to create animated GIF from multiple images For

Clément Guillemain 320 Dec 15, 2022
The Tinify API allows you to compress and optimize WebP, JPEG and PNG images.

The Tinify API allows you to compress and optimize WebP, JPEG and PNG images. It is designed as a REST service. The client libraries in various languages make it very easy to interact with the Tinify API.

Devscast 10 May 13, 2022
A PHP GD + TwitterOAuth demo to dynamically generate Twitter header images and upload them via the API.

A PHP GD + TwitterOAuth demo to dynamically generate Twitter header images and upload them via the API. This enables you to build cool little tricks, like showing your latest followers or sponsors, latest content creted, a qrcode to something, a progress bar for some goal, and whathever you can think of.

Erika Heidi 172 Jan 5, 2023
Simple, fast and secure archive for images

Slim Image Archive Simple*, fast and secure archive for images: Create multiple categories with multiple albums with multiple images! Manage multiple

KS 24 Oct 23, 2021
Image Cache is a very simple PHP class that accepts an image source and will compress and cache the file, move it to a new directory, and returns the new source for the image.

NO LONGER MAINTAINED!!! Image Cache v. 1.0.0 Image Cache is a very simple PHP class that accepts an image source and will compress and cache the file,

Erik Nielsen 455 Dec 30, 2022
PHP library to resize, scale and crop images.

PHP library to resize, scale and crop images.

Gumlet 1.1k Jan 3, 2023
ImageWorkshop is a PHP5.3+ library that helps you to manage images based on GD library

================================ ImageWorkshop class ================================ Summary and features Really flexible and easy-to-use PHP class t

Clément Guillemain 853 Dec 27, 2022
Create images with embedded text using advanced typography

Image with Text This class makes it super easy to render images with multiple, independently styled text blocks. You can control each text block's ali

New Media Campaigns 144 Sep 7, 2022
Easily convert images with Glide

Easily convert images with Glide This package provides an easy to use class to manipulate images. Under the hood it leverages Glide to perform the man

Spatie 374 Dec 30, 2022
Optimize your images on the fly with Glide for Laravel.

Glide for Laravel Optimize your images on the fly with Glide for Laravel. Support us Like our work? You can support us by purchasing one of our produc

Flowframe 53 Oct 17, 2022
Upload SVG images in Magento 2.x

Upload SVG images in Magento 2.x This extension for Magento 2 allows uploading SVG images in the following sections: wysiwyg editor in static blocks a

Magegadgets 6 Dec 23, 2022
Inline Images Protocol implementation for PHP.

Imgecho Echo the image on iTerm App using Inline Images Protocol. Installation Use Composer to install. composer require mileschou/imgecho Usage Use

MilesChou 4 May 30, 2022
The image server plugin allows you to add responsive images via config without extra elements

Grav image server plugin adds picture tag with loading, responsive, high density images

catchIT 7 Dec 30, 2022
Create beautiful generative background images from a string. Based on jasonlong/geo_pattern

GeoPattern This is a PHP port of jasonlong/geo_pattern. Generate beautiful tiling SVG patterns from a string. The string is converted into a SHA and a

Redeye Group 106 Aug 17, 2022
GifFrameExtractor is a PHP class that separates all the frames (and their duration) of an animated GIF

================================ GifFrameExtractor ================================ GifFrameExtractor is a PHP class that separates all the frames (an

Clément Guillemain 173 Dec 12, 2022
This is a class of php QR Code, This library helps you generate QR codes in a jiffy.

This is a class of php QR Code, This library helps you generate QR codes in a jiffy.

null 59 Oct 5, 2022
Laragram is a simple instagram "clone" built with Laravel and Tailwind CSS

Laragram is a simple instagram "clone" built with Laravel and Tailwind CSS that gives to the users the ability to create or edit their own profiles (including profile image and description), upload images and share them among friends

null 0 Jul 24, 2021
A simple page view counter that store data as text and shows data as a PNG image

Image Counter A simple page view counter that store data as text and shows the counter as a PNG image.

Victor Ribeiro 10 Apr 19, 2022