$30 off During Our Annual Pro Sale. View Details »

Introduction to Imagine

Introduction to Imagine

Imagine is a image processing library for PHP 5.3, which changes the way image processing is done

Bulat Shakirzyanov

October 16, 2011
Tweet

More Decks by Bulat Shakirzyanov

Other Decks in Programming

Transcript

  1. Introduction to Imagine
    image processing for PHP 5.3+
    Sunday, October 16, 11

    View Slide

  2. Image processing in PHP
    is hard
    Sunday, October 16, 11

    View Slide

  3. There are many existing
    tools
    • GD
    • Imagick (ImageMagick extension)
    • Gmagick (GraphicsMagick extension)
    • Cairo
    http://www.imagemagick.org/
    http://www.graphicsmagick.org/
    Sunday, October 16, 11

    View Slide

  4. • not testable
    • inconsistent
    • have cluttered apis
    • not intuitive
    Existing tools
    Sunday, October 16, 11

    View Slide

  5. Resize in GD
    // open original and memorize dimensions
    $src = imagecreatefrompng('/path/to/image.png');
    $srcWidth = imagesx($src);
    $srcHeight = imagesy($src);
    // desclare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // create target canvas
    $dest = imagecreatetruecolor($destWidth, $destHeight);
    // keep transparency
    imagealphablending($dest, false);
    imagesavealpha($dest, true);
    // stretch image to fit target size
    // and put it on target canvas
    imagecopyresampled(
    $dest, $src,
    0, 0, 0, 0,
    $width, $height, $srcWidth, $srcHeight
    );
    // save image on filesystem as png
    imagepng($dest,'/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  6. Resize in GD
    // open original and memorize dimensions
    $src = imagecreatefrompng('/path/to/image.png');
    $srcWidth = imagesx($src);
    $srcHeight = imagesy($src);
    // desclare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // create target canvas
    $dest = imagecreatetruecolor($destWidth, $destHeight);
    // keep transparency
    imagealphablending($dest, false);
    imagesavealpha($dest, true);
    // stretch image to fit target size
    // and put it on target canvas
    imagecopyresampled(
    $dest, $src,
    0, 0, 0, 0,
    $width, $height, $srcWidth, $srcHeight
    );
    // save image on filesystem as png
    imagepng($dest,'/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  7. Resize in GD
    // open original and memorize dimensions
    $src = imagecreatefrompng('/path/to/image.png');
    $srcWidth = imagesx($src);
    $srcHeight = imagesy($src);
    // desclare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // create target canvas
    $dest = imagecreatetruecolor($destWidth, $destHeight);
    // keep transparency
    imagealphablending($dest, false);
    imagesavealpha($dest, true);
    // stretch image to fit target size
    // and put it on target canvas
    imagecopyresampled(
    $dest, $src,
    0, 0, 0, 0,
    $width, $height, $srcWidth, $srcHeight
    );
    // save image on filesystem as png
    imagepng($dest,'/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  8. Resize in GD
    // open original and memorize dimensions
    $src = imagecreatefrompng('/path/to/image.png');
    $srcWidth = imagesx($src);
    $srcHeight = imagesy($src);
    // desclare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // create target canvas
    $dest = imagecreatetruecolor($destWidth, $destHeight);
    // keep transparency
    imagealphablending($dest, false);
    imagesavealpha($dest, true);
    // stretch image to fit target size
    // and put it on target canvas
    imagecopyresampled(
    $dest, $src,
    0, 0, 0, 0,
    $width, $height, $srcWidth, $srcHeight
    );
    // save image on filesystem as png
    imagepng($dest,'/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  9. Resize in GD
    // open original and memorize dimensions
    $src = imagecreatefrompng('/path/to/image.png');
    $srcWidth = imagesx($src);
    $srcHeight = imagesy($src);
    // desclare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // create target canvas
    $dest = imagecreatetruecolor($destWidth, $destHeight);
    // keep transparency
    imagealphablending($dest, false);
    imagesavealpha($dest, true);
    // stretch image to fit target size
    // and put it on target canvas
    imagecopyresampled(
    $dest, $src,
    0, 0, 0, 0,
    $width, $height, $srcWidth, $srcHeight
    );
    // save image on filesystem as png
    imagepng($dest,'/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  10. Resize in GD
    // open original and memorize dimensions
    $src = imagecreatefrompng('/path/to/image.png');
    $srcWidth = imagesx($src);
    $srcHeight = imagesy($src);
    // desclare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // create target canvas
    $dest = imagecreatetruecolor($destWidth, $destHeight);
    // keep transparency
    imagealphablending($dest, false);
    imagesavealpha($dest, true);
    // stretch image to fit target size
    // and put it on target canvas
    imagecopyresampled(
    $dest, $src,
    0, 0, 0, 0,
    $width, $height, $srcWidth, $srcHeight
    );
    // save image on filesystem as png
    imagepng($dest,'/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  11. Resize in GD
    // open original and memorize dimensions
    $src = imagecreatefrompng('/path/to/image.png');
    $srcWidth = imagesx($src);
    $srcHeight = imagesy($src);
    // desclare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // create target canvas
    $dest = imagecreatetruecolor($destWidth, $destHeight);
    // keep transparency
    imagealphablending($dest, false);
    imagesavealpha($dest, true);
    // stretch image to fit target size
    // and put it on target canvas
    imagecopyresampled(
    $dest, $src,
    0, 0, 0, 0,
    $width, $height, $srcWidth, $srcHeight
    );
    // save image on filesystem as png
    imagepng($dest,'/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  12. Resize in Imagick
    // declare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // open image
    $image = new Imagick('/path/to/image.png');
    // resize, constraining proportions
    $image->adaptiveResizeImage($width, $height);
    // write to disk
    $image->writeImage('/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  13. Resize in Imagick
    // declare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // open image
    $image = new Imagick('/path/to/image.png');
    // resize, constraining proportions
    $image->adaptiveResizeImage($width, $height);
    // write to disk
    $image->writeImage('/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  14. Resize in Imagick
    // declare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // open image
    $image = new Imagick('/path/to/image.png');
    // resize, constraining proportions
    $image->adaptiveResizeImage($width, $height);
    // write to disk
    $image->writeImage('/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  15. Resize in Imagick
    // declare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // open image
    $image = new Imagick('/path/to/image.png');
    // resize, constraining proportions
    $image->adaptiveResizeImage($width, $height);
    // write to disk
    $image->writeImage('/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  16. Resize in Imagick
    // declare target dimensions
    $destWidth = //target width
    $destHeight = //target height
    // open image
    $image = new Imagick('/path/to/image.png');
    // resize, constraining proportions
    $image->adaptiveResizeImage($width, $height);
    // write to disk
    $image->writeImage('/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  17. Existing tools
    don’t cut it
    Sunday, October 16, 11

    View Slide

  18. Imagine...
    • all drivers implemented the same interfaces
    • code could be reused with any driver
    • there were interfaces for mocking in tests
    • API was simple and intuitive
    Sunday, October 16, 11

    View Slide

  19. STOP
    Sunday, October 16, 11

    View Slide

  20. Imagine for PHP 5.3+
    stop imagining, it is all there
    Sunday, October 16, 11

    View Slide

  21. Imagine for PHP 5.3+
    Inspired by Python’s PIL
    http://www.pythonware.com/products/pil/
    Sunday, October 16, 11

    View Slide

  22. Resize in Imagine (GD)
    // declare target dimensions
    $width = //target width
    $height = //target height
    // get Imagine instance for GD
    $imagine = new Imagine\Gd\Imagine();
    // resize and save (format is inferred from extension)
    $imagine->open('/path/to/image.png')
    ->resize(new Imagine\Image\Box($width, $height))
    ->save('/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  23. Resize in Imagine (Imagick)
    // declare target dimensions
    $width = //target width
    $height = //target height
    // get Imagine instance for Imagick
    $imagine = new Imagine\Imagick\Imagine();
    // resize and save (format is inferred from extension)
    $imagine->open('/path/to/image.png')
    ->resize(new Imagine\Image\Box($width, $height))
    ->save('/path/to/resized/image.png');
    Sunday, October 16, 11

    View Slide

  24. Consistency
    1. identify operations
    2. split into groups
    3. implement per driver
    Sunday, October 16, 11

    View Slide

  25. Operations
    • resize
    • rotate
    • crop
    • save
    • copy
    • paste
    • apply mask
    • ellipse
    • polygon
    • line
    • dot
    • arc
    • pie slice
    • text
    Sunday, October 16, 11

    View Slide

  26. manipulations
    Operations
    • resize
    • rotate
    • crop
    • save
    • copy
    • paste
    • apply mask
    • ellipse
    • polygon
    • line
    • dot
    • arc
    • pie slice
    • text
    Sunday, October 16, 11

    View Slide

  27. Operations
    • resize
    • rotate
    • crop
    • save
    • copy
    • paste
    • apply mask
    • ellipse
    • polygon
    • line
    • dot
    • arc
    • pie slice
    • text
    drawings
    Sunday, October 16, 11

    View Slide

  28. Example
    Sunday, October 16, 11

    View Slide

  29. Thumbnail
    Sunday, October 16, 11

    View Slide

  30. Thumbnail
    $imagine = new Imagine\Gd\Imagine();
    $mode = Imagine\Image\ImageInterface::THUMBNAIL_OUTBOUND;
    //or
    $mode = Imagine\Image\ImageInterface::THUMBNAIL_INSET;
    $imagine->open('/path/to/google/logo.png')
    ->thumbnail(new Imagine\Image\Box(100, 100), $mode)
    ->save('/path/to/google/logo/thumbnail.png');
    Sunday, October 16, 11

    View Slide

  31. Reflection
    Sunday, October 16, 11

    View Slide

  32. Reflection
    $imagine = new Imagine\Gd\Imagine();
    $logo = $imagine->open('/path/to/google/logo.png');
    $size = $logo->getSize();
    $canvas = $imagine->create(
    new Imagine\Image\Box($size->getWidth(), $size->getHeight() * 2),
    new Imagine\Image\Color('000', 100)
    );
    $reflection = $logo->copy()
    ->flipVertically()
    ->applyMask(
    $imagine->create($size)
    ->fill(
    new Imagine\Image\Fill\Gradient\Vertical(
    $size->getHeight(),
    new Imagine\Image\Color(array(127, 127, 127)),
    new Imagine\Image\Color('fff')
    )
    )
    );
    $canvas->paste($logo, new Imagine\Image\Point(0, 0))
    ->paste($reflection, new Imagine\Image\Point(0, $size->getHeight()))
    ->save('/path/to/google/logo/reflection.png');
    Sunday, October 16, 11

    View Slide

  33. Reflection
    $imagine = new Imagine\Gd\Imagine();
    $logo = $imagine->open('/path/to/google/logo.png');
    $size = $logo->getSize();
    $canvas = $imagine->create(
    new Imagine\Image\Box($size->getWidth(), $size->getHeight() * 2),
    new Imagine\Image\Color('000', 100)
    );
    $reflection = $logo->copy()
    ->flipVertically()
    ->applyMask(
    $imagine->create($size)
    ->fill(
    new Imagine\Image\Fill\Gradient\Vertical(
    $size->getHeight(),
    new Imagine\Image\Color(array(127, 127, 127)),
    new Imagine\Image\Color('fff')
    )
    )
    );
    $canvas->paste($logo, new Imagine\Image\Point(0, 0))
    ->paste($reflection, new Imagine\Image\Point(0, $size->getHeight()))
    ->save('/path/to/google/logo/reflection.png');
    open image to reflect and remember its size
    Sunday, October 16, 11

    View Slide

  34. Reflection
    $imagine = new Imagine\Gd\Imagine();
    $logo = $imagine->open('/path/to/google/logo.png');
    $size = $logo->getSize();
    $canvas = $imagine->create(
    new Imagine\Image\Box($size->getWidth(), $size->getHeight() * 2),
    new Imagine\Image\Color('000', 100)
    );
    $reflection = $logo->copy()
    ->flipVertically()
    ->applyMask(
    $imagine->create($size)
    ->fill(
    new Imagine\Image\Fill\Gradient\Vertical(
    $size->getHeight(),
    new Imagine\Image\Color(array(127, 127, 127)),
    new Imagine\Image\Color('fff')
    )
    )
    );
    $canvas->paste($logo, new Imagine\Image\Point(0, 0))
    ->paste($reflection, new Imagine\Image\Point(0, $size->getHeight()))
    ->save('/path/to/google/logo/reflection.png');
    create empty canvas to fit image and reflection
    Sunday, October 16, 11

    View Slide

  35. Reflection
    $imagine = new Imagine\Gd\Imagine();
    $logo = $imagine->open('/path/to/google/logo.png');
    $size = $logo->getSize();
    $canvas = $imagine->create(
    new Imagine\Image\Box($size->getWidth(), $size->getHeight() * 2),
    new Imagine\Image\Color('000', 100)
    );
    $reflection = $logo->copy()
    ->flipVertically()
    ->applyMask(
    $imagine->create($size)
    ->fill(
    new Imagine\Image\Fill\Gradient\Vertical(
    $size->getHeight(),
    new Imagine\Image\Color(array(127, 127, 127)),
    new Imagine\Image\Color('fff')
    )
    )
    );
    $canvas->paste($logo, new Imagine\Image\Point(0, 0))
    ->paste($reflection, new Imagine\Image\Point(0, $size->getHeight()))
    ->save('/path/to/google/logo/reflection.png');
    make a copy of source, flipped vertically
    Sunday, October 16, 11

    View Slide

  36. $imagine = new Imagine\Gd\Imagine();
    $logo = $imagine->open('/path/to/google/logo.png');
    $size = $logo->getSize();
    $canvas = $imagine->create(
    new Imagine\Image\Box($size->getWidth(), $size->getHeight() * 2),
    new Imagine\Image\Color('000', 100)
    );
    $reflection = $logo->copy()
    ->flipVertically()
    ->applyMask(
    $imagine->create($size)
    ->fill(
    new Imagine\Image\Fill\Gradient\Vertical(
    $size->getHeight(),
    new Imagine\Image\Color(array(127, 127, 127)),
    new Imagine\Image\Color('fff')
    )
    )
    );
    $canvas->paste($logo, new Imagine\Image\Point(0, 0))
    ->paste($reflection, new Imagine\Image\Point(0, $size->getHeight()))
    ->save('/path/to/google/logo/reflection.png');
    Reflection
    create image like the one above
    Sunday, October 16, 11

    View Slide

  37. $imagine = new Imagine\Gd\Imagine();
    $logo = $imagine->open('/path/to/google/logo.png');
    $size = $logo->getSize();
    $canvas = $imagine->create(
    new Imagine\Image\Box($size->getWidth(), $size->getHeight() * 2),
    new Imagine\Image\Color('000', 100)
    );
    $reflection = $logo->copy()
    ->flipVertically()
    ->applyMask(
    $imagine->create($size)
    ->fill(
    new Imagine\Image\Fill\Gradient\Vertical(
    $size->getHeight(),
    new Imagine\Image\Color(array(127, 127, 127)),
    new Imagine\Image\Color('fff')
    )
    )
    );
    $canvas->paste($logo, new Imagine\Image\Point(0, 0))
    ->paste($reflection, new Imagine\Image\Point(0, $size->getHeight()))
    ->save('/path/to/google/logo/reflection.png');
    Reflection
    replace white regions with transparency
    Sunday, October 16, 11

    View Slide

  38. $imagine = new Imagine\Gd\Imagine();
    $logo = $imagine->open('/path/to/google/logo.png');
    $size = $logo->getSize();
    $canvas = $imagine->create(
    new Imagine\Image\Box($size->getWidth(), $size->getHeight() * 2),
    new Imagine\Image\Color('000', 100)
    );
    $reflection = $logo->copy()
    ->flipVertically()
    ->applyMask(
    $imagine->create($size)
    ->fill(
    new Imagine\Image\Fill\Gradient\Vertical(
    $size->getHeight(),
    new Imagine\Image\Color(array(127, 127, 127)),
    new Imagine\Image\Color('fff')
    )
    )
    );
    $canvas->paste($logo, new Imagine\Image\Point(0, 0))
    ->paste($reflection, new Imagine\Image\Point(0, $size->getHeight()))
    ->save('/path/to/google/logo/reflection.png');
    Reflection
    place original logo on top of created canvas
    place reflection underneath it
    Sunday, October 16, 11

    View Slide

  39. Piechart
    Sunday, October 16, 11

    View Slide

  40. Piechart
    $imagine = new Imagine\Imagick\Imagine();
    $volume = 20;
    $size = new Imagine\Image\Box(300, 200);
    $center = new Imagine\Image\Point\Center($size);
    $canvas = $size->increase($volume);
    $bg = new Imagine\Image\Color('000000', 100);
    $color1 = new Imagine\Image\Color('FFEF78');
    $color2 = new Imagine\Image\Color('8A834B');
    $color3 = new Imagine\Image\Color('8A554B');
    $color4 = new Imagine\Image\Color('D94616');
    $color5 = new Imagine\Image\Color('FEB48D');
    $chart = $imagine->create($canvas, $bg);
    for ($i = $volume; $i > 0; $i--) {
    $shift = $center->move($i);
    $chart->draw()
    ->pieSlice($shift, $size, -10, 70, $color1->darken(68), true)
    ->pieSlice($shift, $size, 70, 160, $color2->darken(68), true)
    ->pieSlice($shift, $size, 160, 170, $color3->darken(68), true)
    ->pieSlice($shift, $size, 170, 210, $color4->darken(68), true)
    ->pieSlice($shift, $size, 210, 350, $color5->darken(68), true);
    }
    $chart->draw()
    ->pieSlice($center, $size, -10, 70, $color1, true)
    ->pieSlice($center, $size, 70, 160, $color2, true)
    ->pieSlice($center, $size, 160, 170, $color3, true)
    ->pieSlice($center, $size, 170, 210, $color4, true)
    ->pieSlice($center, $size, 210, 350, $color5, true);
    $chart->save('/path/to/chart.png');
    Sunday, October 16, 11

    View Slide

  41. Piechart
    $imagine = new Imagine\Imagick\Imagine();
    $volume = 20;
    $size = new Imagine\Image\Box(300, 200);
    $center = new Imagine\Image\Point\Center($size);
    $canvas = $size->increase($volume);
    $bg = new Imagine\Image\Color('000000', 100);
    $color1 = new Imagine\Image\Color('FFEF78');
    $color2 = new Imagine\Image\Color('8A834B');
    $color3 = new Imagine\Image\Color('8A554B');
    $color4 = new Imagine\Image\Color('D94616');
    $color5 = new Imagine\Image\Color('FEB48D');
    $chart = $imagine->create($canvas, $bg);
    for ($i = $volume; $i > 0; $i--) {
    $shift = $center->move($i);
    $chart->draw()
    ->pieSlice($shift, $size, -10, 70, $color1->darken(68), true)
    ->pieSlice($shift, $size, 70, 160, $color2->darken(68), true)
    ->pieSlice($shift, $size, 160, 170, $color3->darken(68), true)
    ->pieSlice($shift, $size, 170, 210, $color4->darken(68), true)
    ->pieSlice($shift, $size, 210, 350, $color5->darken(68), true);
    }
    $chart->draw()
    ->pieSlice($center, $size, -10, 70, $color1, true)
    ->pieSlice($center, $size, 70, 160, $color2, true)
    ->pieSlice($center, $size, 160, 170, $color3, true)
    ->pieSlice($center, $size, 170, 210, $color4, true)
    ->pieSlice($center, $size, 210, 350, $color5, true);
    $chart->save('/path/to/chart.png');
    get imagine, define chart 3d volume and size
    Sunday, October 16, 11

    View Slide

  42. Piechart
    $imagine = new Imagine\Imagick\Imagine();
    $volume = 20;
    $size = new Imagine\Image\Box(300, 200);
    $center = new Imagine\Image\Point\Center($size);
    $canvas = $size->increase($volume);
    $bg = new Imagine\Image\Color('000000', 100);
    $color1 = new Imagine\Image\Color('FFEF78');
    $color2 = new Imagine\Image\Color('8A834B');
    $color3 = new Imagine\Image\Color('8A554B');
    $color4 = new Imagine\Image\Color('D94616');
    $color5 = new Imagine\Image\Color('FEB48D');
    $chart = $imagine->create($canvas, $bg);
    for ($i = $volume; $i > 0; $i--) {
    $shift = $center->move($i);
    $chart->draw()
    ->pieSlice($shift, $size, -10, 70, $color1->darken(68), true)
    ->pieSlice($shift, $size, 70, 160, $color2->darken(68), true)
    ->pieSlice($shift, $size, 160, 170, $color3->darken(68), true)
    ->pieSlice($shift, $size, 170, 210, $color4->darken(68), true)
    ->pieSlice($shift, $size, 210, 350, $color5->darken(68), true);
    }
    $chart->draw()
    ->pieSlice($center, $size, -10, 70, $color1, true)
    ->pieSlice($center, $size, 70, 160, $color2, true)
    ->pieSlice($center, $size, 160, 170, $color3, true)
    ->pieSlice($center, $size, 170, 210, $color4, true)
    ->pieSlice($center, $size, 210, 350, $color5, true);
    $chart->save('/path/to/chart.png');
    get center of the chart
    account for size of 3d volume in canvas
    Sunday, October 16, 11

    View Slide

  43. Piechart
    $imagine = new Imagine\Imagick\Imagine();
    $volume = 20;
    $size = new Imagine\Image\Box(300, 200);
    $center = new Imagine\Image\Point\Center($size);
    $canvas = $size->increase($volume);
    $bg = new Imagine\Image\Color('000000', 100);
    $color1 = new Imagine\Image\Color('FFEF78');
    $color2 = new Imagine\Image\Color('8A834B');
    $color3 = new Imagine\Image\Color('8A554B');
    $color4 = new Imagine\Image\Color('D94616');
    $color5 = new Imagine\Image\Color('FEB48D');
    $chart = $imagine->create($canvas, $bg);
    for ($i = $volume; $i > 0; $i--) {
    $shift = $center->move($i);
    $chart->draw()
    ->pieSlice($shift, $size, -10, 70, $color1->darken(68), true)
    ->pieSlice($shift, $size, 70, 160, $color2->darken(68), true)
    ->pieSlice($shift, $size, 160, 170, $color3->darken(68), true)
    ->pieSlice($shift, $size, 170, 210, $color4->darken(68), true)
    ->pieSlice($shift, $size, 210, 350, $color5->darken(68), true);
    }
    $chart->draw()
    ->pieSlice($center, $size, -10, 70, $color1, true)
    ->pieSlice($center, $size, 70, 160, $color2, true)
    ->pieSlice($center, $size, 160, 170, $color3, true)
    ->pieSlice($center, $size, 170, 210, $color4, true)
    ->pieSlice($center, $size, 210, 350, $color5, true);
    $chart->save('/path/to/chart.png');
    colors of pie slices and background
    Sunday, October 16, 11

    View Slide

  44. Piechart
    $imagine = new Imagine\Imagick\Imagine();
    $volume = 20;
    $size = new Imagine\Image\Box(300, 200);
    $center = new Imagine\Image\Point\Center($size);
    $canvas = $size->increase($volume);
    $bg = new Imagine\Image\Color('000000', 100);
    $color1 = new Imagine\Image\Color('FFEF78');
    $color2 = new Imagine\Image\Color('8A834B');
    $color3 = new Imagine\Image\Color('8A554B');
    $color4 = new Imagine\Image\Color('D94616');
    $color5 = new Imagine\Image\Color('FEB48D');
    $chart = $imagine->create($canvas, $bg);
    for ($i = $volume; $i > 0; $i--) {
    $shift = $center->move($i);
    $chart->draw()
    ->pieSlice($shift, $size, -10, 70, $color1->darken(68), true)
    ->pieSlice($shift, $size, 70, 160, $color2->darken(68), true)
    ->pieSlice($shift, $size, 160, 170, $color3->darken(68), true)
    ->pieSlice($shift, $size, 170, 210, $color4->darken(68), true)
    ->pieSlice($shift, $size, 210, 350, $color5->darken(68), true);
    }
    $chart->draw()
    ->pieSlice($center, $size, -10, 70, $color1, true)
    ->pieSlice($center, $size, 70, 160, $color2, true)
    ->pieSlice($center, $size, 160, 170, $color3, true)
    ->pieSlice($center, $size, 170, 210, $color4, true)
    ->pieSlice($center, $size, 210, 350, $color5, true);
    $chart->save('/path/to/chart.png');
    create chart canvas with transparent background
    Sunday, October 16, 11

    View Slide

  45. Piechart
    $imagine = new Imagine\Imagick\Imagine();
    $volume = 20;
    $size = new Imagine\Image\Box(300, 200);
    $center = new Imagine\Image\Point\Center($size);
    $canvas = $size->increase($volume);
    $bg = new Imagine\Image\Color('000000', 100);
    $color1 = new Imagine\Image\Color('FFEF78');
    $color2 = new Imagine\Image\Color('8A834B');
    $color3 = new Imagine\Image\Color('8A554B');
    $color4 = new Imagine\Image\Color('D94616');
    $color5 = new Imagine\Image\Color('FEB48D');
    $chart = $imagine->create($canvas, $bg);
    for ($i = $volume; $i > 0; $i--) {
    $shift = $center->move($i);
    $chart->draw()
    ->pieSlice($shift, $size, -10, 70, $color1->darken(68), true)
    ->pieSlice($shift, $size, 70, 160, $color2->darken(68), true)
    ->pieSlice($shift, $size, 160, 170, $color3->darken(68), true)
    ->pieSlice($shift, $size, 170, 210, $color4->darken(68), true)
    ->pieSlice($shift, $size, 210, 350, $color5->darken(68), true);
    }
    $chart->draw()
    ->pieSlice($center, $size, -10, 70, $color1, true)
    ->pieSlice($center, $size, 70, 160, $color2, true)
    ->pieSlice($center, $size, 160, 170, $color3, true)
    ->pieSlice($center, $size, 170, 210, $color4, true)
    ->pieSlice($center, $size, 210, 350, $color5, true);
    $chart->save('/path/to/chart.png');
    build 3d shade of the chart in darker colors
    Sunday, October 16, 11

    View Slide

  46. Piechart
    $imagine = new Imagine\Imagick\Imagine();
    $volume = 20;
    $size = new Imagine\Image\Box(300, 200);
    $center = new Imagine\Image\Point\Center($size);
    $canvas = $size->increase($volume);
    $bg = new Imagine\Image\Color('000000', 100);
    $color1 = new Imagine\Image\Color('FFEF78');
    $color2 = new Imagine\Image\Color('8A834B');
    $color3 = new Imagine\Image\Color('8A554B');
    $color4 = new Imagine\Image\Color('D94616');
    $color5 = new Imagine\Image\Color('FEB48D');
    $chart = $imagine->create($canvas, $bg);
    for ($i = $volume; $i > 0; $i--) {
    $shift = $center->move($i);
    $chart->draw()
    ->pieSlice($shift, $size, -10, 70, $color1->darken(68), true)
    ->pieSlice($shift, $size, 70, 160, $color2->darken(68), true)
    ->pieSlice($shift, $size, 160, 170, $color3->darken(68), true)
    ->pieSlice($shift, $size, 170, 210, $color4->darken(68), true)
    ->pieSlice($shift, $size, 210, 350, $color5->darken(68), true);
    }
    $chart->draw()
    ->pieSlice($center, $size, -10, 70, $color1, true)
    ->pieSlice($center, $size, 70, 160, $color2, true)
    ->pieSlice($center, $size, 160, 170, $color3, true)
    ->pieSlice($center, $size, 170, 210, $color4, true)
    ->pieSlice($center, $size, 210, 350, $color5, true);
    $chart->save('/path/to/chart.png');
    draw and save the actual chart
    Sunday, October 16, 11

    View Slide

  47. Simplify
    1. use value objects
    2. make ‘em smart
    Sunday, October 16, 11

    View Slide

  48. Color
    $color = new Imagine\Image\Color('000');
    $color->lighten(127);
    $color->dissolve(50);
    $color->lighten(127)->dissolve(50);
    $color->getRed()
    $color->getGreen()
    $color->getBlue()
    $color->getAlpha()
    $color->isOpaque()
    0
    0
    0
    0
    true
    Sunday, October 16, 11

    View Slide

  49. Box
    $box = new Imagine\Image\Box(100, 100);
    $box->scale(2);
    $box->increase(25);
    100
    100
    200
    200
    125
    125
    Sunday, October 16, 11

    View Slide

  50. Point
    $point = new Imagine\Image\Point(50, 50);
    Sunday, October 16, 11

    View Slide

  51. Make it testable
    1. interface end user code interactions
    2. close unexpected inheritance
    Sunday, October 16, 11

    View Slide

  52. Filters
    Sunday, October 16, 11

    View Slide

  53. Filter
    namespace Imagine\Filter;
    use Imagine\Image\ImageInterface;
    interface FilterInterface
    {
    /**
    * Applies scheduled transformation to ImageInterface instance
    * Returns processed ImageInterface instance
    *
    * @param Imagine\Image\ImageInterface $image
    *
    * @return Imagine\Image\ImageInterface
    */
    function apply(ImageInterface $image);
    }
    Sunday, October 16, 11

    View Slide

  54. Filters
    Filter is a collection of manipulations, calculations and other
    operations, that can be applied to an image
    Sunday, October 16, 11

    View Slide

  55. Reflection filter
    class ReflectionFilter implements Imagine\Filter\FilterInterface
    {
    private $imagine;
    public function __construct(Imagine\Image\ImagineInterface $imagine)
    {
    $this->imagine = $imagine;
    }
    public function apply(Imagine\Image\ImageInterface $image)
    {
    $size = $image->getSize();
    $canvas = new Imagine\Image\Box($size->getWidth(), $size->getHeight() * 2);
    $reflection = $image->copy()
    ->flipVertically()
    ->applyMask($this->getTransparencyMask($size))
    ;
    return $this->imagine->create($canvas, new Imagine\Image\Color('fff', 100))
    ->paste($image, new Imagine\Image\Point(0, 0))
    ->paste($reflection, new Imagine\Image\Point(0, $size->getHeight()));
    }
    private function getTransparencyMask(Imagine\Image\BoxInterface $size)
    {
    $white = new Imagine\Image\Color('fff');
    $fill = new Imagine\Image\Fill\Gradient\Vertical(
    $size->getHeight(),
    $white->darken(127),
    $white
    );
    return $this->imagine->create($size)
    ->fill($fill)
    ;
    }
    }
    Sunday, October 16, 11

    View Slide

  56. Reflection filter
    $imagine = new Imagine\Gd\Imagine();
    $filter = new ReflectionFilter($imagine);
    $filter->apply($imagine->open('/path/to/google/logo.png'))
    ->save('/path/to/google/logo/reflection.png');
    Sunday, October 16, 11

    View Slide

  57. Transformation
    Delayed image processing using a filter
    Sunday, October 16, 11

    View Slide

  58. Transformation
    operate on a transformation as on a regular image, except
    nothing is being executed
    $path = '/path/to/processed/image.png';
    $size = new Imagine\Image\Box(50, 50);
    $resize = new Imagine\Image\Box(200, 200);
    $angle = 90;
    $background = new Imagine\Image\Color('fff');
    $transformation = new Imagine\Filter\Transformation();
    $transformation->resize($resize)
    ->copy()
    ->rotate($angle, $background)
    ->thumbnail($size, Imagine\Image\ImageInterface::THUMBNAIL_INSET)
    ->save($path);
    Sunday, October 16, 11

    View Slide

  59. Transformation
    Apply them when you’re ready
    $transformation->apply($imagine->open('/path/to/source/image.png'));
    Sunday, October 16, 11

    View Slide

  60. Transformation
    Or even batch process...
    foreach(glob('/path/to/many/images/*.png') as $path) {
    $transformation->apply($imagine->open($path))
    ->save('/path/to/processed/image/'.md5($path).'.png');
    }
    Sunday, October 16, 11

    View Slide

  61. Imagine and Symfony2
    Sunday, October 16, 11

    View Slide

  62. Integration
    1. configure
    2. use in templates
    3. profit
    Sunday, October 16, 11

    View Slide

  63. Configure
    avalanche_imagine:
    web_root: %kernel.root_dir%/../web
    driver: gd
    filters:
    preview:
    type: thumbnail
    options: { size: [100, 50], mode: outbound }
    Sunday, October 16, 11

    View Slide

  64. Templates
    Twig
    PHP


    Sunday, October 16, 11

    View Slide

  65. Process
    first request processes image and outputs response
    other controller requests result in a 301 redirect to file

    Sunday, October 16, 11

    View Slide

  66. Summary
    Sunday, October 16, 11

    View Slide

  67. To be improved
    • advanced operations are still not easy (look
    at the reflection example)
    • only these drivers are supported
    • Imagick
    • GD
    • Gmagick
    Sunday, October 16, 11

    View Slide

  68. Was improved
    • thumbnails are easy
    • code is readable
    • foundation is solid
    • its available today
    • its gonna be great
    Sunday, October 16, 11

    View Slide

  69. What’s next?
    • Documentation - imagine.readthedocs.org
    • Implement charting API (piecharts, bar-charts,
    linear graphs)
    • Add advanced filters (reflection, rounded
    corners, etc.)
    • Add effects (twirl, blur, sharpen, etc.)
    Sunday, October 16, 11

    View Slide

  70. Imagine
    image processing reloaded
    https://github.com/avalanche123/Imagine
    Sunday, October 16, 11

    View Slide