Slide 1

Slide 1 text

Pixel Punching with PHP GD and Imagick

Slide 2

Slide 2 text

Introduction  Working with pictures is a must anymore to complete the whole social experience of the internet.  You will not memorize the API’s today. There are too many and they are full of weird.  Hopefully you get a feeling of knowing what you can/cannot do easy and know where to look to implement further.

Slide 3

Slide 3 text

PHP Graphic Library Overview  GD  Imagick  GMagick  Ignored because it is [just] a fork of Imagick with the design principles of never advancing API’s for sake of backwards compat. A noble goal but...  Could not find a working Windows build anyway.  Cairo  Vector graphics, neato stuff, but...  Not enough actual filled out documentation, so I haven’t really used it and I'd sound like a retard talking about it.  Exif  Not actually an image library. A JPEG meta data reading library. It cannot even write.

Slide 4

Slide 4 text

GD Graphics Library  Graphics Draw Library  Originally GIF Draw.  Was unable to actually render GIF’s from 1999 to 2004 because the GIF license was revoked. In 2004 the GIF patent expired.  Has bindings for nearly every language [that matters] ever.  Not really worked on anymore. PHP maintains their copy that is how we get along with that.  Sort of a “Copy and Paste” based system.

Slide 5

Slide 5 text

PHP GD Pro/Con Pros  Comes bundled with PHP.  Compiles anywhere first time.  Lightweight for lightweight work.  Most web hosts will have it. Cons  Cumbersome to do advanced work with.  OLD style API (pre-OOP) – Procedural  Larger jobs consume LOTS of resources.  Terribad at Alpha Channel (opacity)

Slide 6

Slide 6 text

ImageMagick  ImageMagick is the utility. Imagick is the PHP binding.  Huge graphics library able to write support nearly any image format you could care to think of.  Basically, Photoshop for your CLI.  Layer based system.  Has support for OpenCL  Meaning, it can use your GPU to do stuff.

Slide 7

Slide 7 text

Imagick Pro/Con Pros  Lots of advanced features.  Decent OOP interface. *  Does heavy lifting with ease. Cons  Arse and a half to compile the dependencies.  Method names a bit goofy. *

Slide 8

Slide 8 text

Uploading Tangent: Getting images (or whatever) to the PHPs.

Slide 9

Slide 9 text

The Server Important configuration options for uploading  PHP.INI  file_uploads = On  Enables uploads  upload_max_filesize = 10M  How large each file can be.  post_max_size = 10M  Technically this would limit you to files slightly less than 10M as there is other post data involved in the request taking up space.  max_file_uploads = 10  How many files per form.  Large uploads take time.  May want to set_time_limit() a higher value in the upload script if you are expecting huge stuffs.

Slide 10

Slide 10 text

The Form  enctype is the only real key here.   Allows multiple files with ease.  $_FILES[‘something’][‘name’][\d+]

Slide 11

Slide 11 text

The Upload $_FILES[‘derp’] Array ( [name] => Array ( [0] => hail__king_arthas_menethil.jpg [1] => zInfg.jpg [2] => f6Kik.jpg ) [type] => Array ( [0] => image/jpeg [1] => image/jpeg [2] => image/jpeg ) [tmp_name] => Array ( [0] => C:\Users\bob\AppData\Local\Temp\phpA18.tmp [1] => C:\Users\bob\AppData\Local\Temp\phpA19.tmp [2] => C:\Users\bob\AppData\Local\Temp\phpA1A.tmp ) [error] => Array ( [0] => 0 [1] => 0 [2] => 0 ) [size] => Array ( [0] => 235038 [1] => 176960 [2] => 61551 ) )

Slide 12

Slide 12 text

Resources Open, Save, Release

Slide 13

Slide 13 text

Opening and Saving Files with GD  GD is resource based, so you open a resource pointer and pass it to image functions.  GD is also limited in types, and the opening functions you use depend on the type of file it is. That means you have to check for JPEG, PNG, etc.  $img = imagecreatefromjpeg($filename);  imagecreatefrompng();  imagecreatefromgif();  ...  Error? if(!$img) { ... }  Saving has all the same issues, you have to use a function named for the type of file you want to save.  imagejpeg($img,$filename,$quality);  imagepng();  imagegif();  ...

Slide 14

Slide 14 text

Opening and Saving Files with Imagick  Imagick is object oriented. You create one and you use its own methods to against it.  Imagick is smart about filetypes. One call to rule them all...  $img = new Imagick($filename);  Error? An exception is thrown so you you can tryblock it.  Saving is just as smart. If the filename ends in .jpg, you get a JPEG file.  $img->writeImage($filename);

Slide 15

Slide 15 text

Getting Image Size Handy to have laying around for the maths later  There is getimagesize() which is said to work without GD. Returns an array of various graphic data.  Also returns mime type as part of the array so you could use it for “is this an image” checking. Here I only care about the size as we already opened images on the last two slides.  list($imgw,$imgh) = getimagesize($filename);  GD  $imgw = imagesx($img);  $imgh = imagesy($img);  Imagick  $imgw = $img->getImageWidth();  $imgh = $img->getImageHeight();

Slide 16

Slide 16 text

Closing Files / Freeing Resources  In both cases, we need to free system resources when we are done with an image.  You will quickly run into memory limit issues if you fail to free your resources when you are done using them.  GD  imagedestroy($img);  unset($img);  Imagick  $img->destroy();  unset($img);

Slide 17

Slide 17 text

Pseudocode [startup] for later examples. Assuming an always valid JPEG file for the examples - Open and Size Up. GD $img = imagecreatefromjpeg($filename); $imgw = imagesx($img); $imgh = imagesy($img); Imagick $img = new Imagick($filename); $imgw = $img->getImageWidth(); $imgh = $img->getImageHeight(); Pseudocode [shutdown] for later examples. Assuming an always valid image resource - Save and Free. imagejpeg($img,$filename,100); imagedestroy($img); unset($img); $img->writeImage($filename); $img->destroy(); unset($img);

Slide 18

Slide 18 text

Manipulation Simple Image Tasks

Slide 19

Slide 19 text

Basic Geometric Tasks  Cropping  Resizing  Scaling  Thumbnailing  GD  imagecopyresampled  We use this with different maths to do it all.  Imagick  cropImage  resizeImage  thumbnailImage

Slide 20

Slide 20 text

Cropping  Cutting an image smaller than it already is, much like cutting a picture out of the newspaper or magazine.  Need to know:  X and Y of top corner.  W and H of desired cut.

Slide 21

Slide 21 text

Cropping Images – GD Crop a 200px square, 100px from the top corner. [startup] // a new blank image buffer to copy to. $new = imagecreatetruecolor(200,200); imagecopyresampled( $new, // destination buffer $img, // source buffer 0, 0, // destination x,y 100, 100, // source region top left x,y 200, 200, // destination w,h 200, 200 // source region w,h ); imagedestroy($img); $img = $new; unset($new); [shutdown]

Slide 22

Slide 22 text

Cropping Images – Imagick Crop a 200px square, 100px from the top corner. [startup] $img->cropImage( 200, 200, // region w,h 100, 100 // region top left corner x,y ); [shutdown]

Slide 23

Slide 23 text

Resizing  Changing the Width and Height of an image to be a new Width and Height.  Aspect ratio? Honey badger don’t care.  Need to know:  Desired W and H

Slide 24

Slide 24 text

Resizing Images – GD Force image into a 200x100 pixel shape [startup] $new = imagecreatetruecolor(200,100); imagecopyresampled( $new, // destination buffer $img, // source buffer 0, 0, // destination x,y 0, 0, // source region x,y 200, 100, // destination w,h $imgw, $imgh // source region w, h ); imagedestroy($img); $img = $new; unset($new); [shutdown]

Slide 25

Slide 25 text

Resizing Images – Imagick Force image into a 200x100 pixel shape [startup] $img->resizeImage( 200, 200, Imagick::FILTER_LANCZOS, 1 ); [shutdown]

Slide 26

Slide 26 text

Scaling  Fit an image inside of a size but keep the aspect ratio intact.  One dimension will be smaller than the requested size, unless it was a perfect square and you asked for a perfect square.  Same as resize code but with an added magical function for maths. This function would check if the image is tall or wide, and then do the proportion math to give the final size.  Need to know:  W and H of image  W and H you want to fit it in

Slide 27

Slide 27 text

Scaling Images – GD Fit the image to be less than or equal to 200x200 [startup] list($nw,$nh) = bob_magic_proportion_func( $imgw, $imgh, // source size 200, 200 // desired max size ); $new = imagecreatetruecolor($nw,$nh); imagecopyresampled( $new, // destination buffer $img, // source buffer 0, 0, // destination x,y 0, 0, // source region x,y $nw, $nh, // destination w,h $imgw, $imgh // source region w, h ); imagedestroy($img); $img = $new; unset($new); [shutdown]

Slide 28

Slide 28 text

Scaling Images – Imagick Fit the image to be less than or equal to 200x200 [startup] $img->resizeImage( 200, 200, Imagick::FILTER_LANCZOS, 1, true ); [shutdown]

Slide 29

Slide 29 text

Thumbnailing  Creating a useful representation that is fill fit to a size, then with the excess cropped off.  Fill fit to the smallest dimension.  Crop excess in longest dimension.  For demo simplicity, our resulting image is a perfect square.  Need to know:  W and H of image  W and H of desired thumbnail

Slide 30

Slide 30 text

Thumbnailing Images – GD Create a scaled, centered, cropped, 200x200 thumbnail [startup] if($imgw > $imgh) list($nw,$nh) = bob_magic_proportion_func($imgw,$imgh,-1,200); else list($nw,$nh) = bob_magic_proportion_func($imgw,$imgh,200,-1); // scale it down to the calculated size. $new = imagecreatetruecolor($nw,$nh); imagecopyresampled($new,$img,0,0,0,0,$nw,$nh,$imgw,$imgh); imagedestroy($img); unset($img); // crop off the excess from either end to center it and fit it $last = imagecreatetruecolor(200,200); imagecopyresampled( $last, $new, 0, 0, ($nw / 2) – (200 / 2), ($nh / 2) – (200 / 2), 200, 200, 200, 200 ); imagedestroy($new); unset($new); $img = $last; unset($last); [shutdown]

Slide 31

Slide 31 text

Thumbnailing Images – Imagick Create a scaled, centered, cropped, 200x200 thumbnail [startup] $img->thumbnailImage(200,200); [shutdown]

Slide 32

Slide 32 text

Basic ‘Shoopin Shoop da woop  Desaturation  Sepia  Lots of other filters, but they are all more or less repetitive.  Watermarking  GD  imagefilter  imagecopyresampled  Imagick  modulateImage  sepiaToneImage  compositeImage

Slide 33

Slide 33 text

Filters Almost over 9,000 GD  Negative  Greyscale  Brightness  Contrast  Colorize  Edge  Emboss  Blur  Sketch  Pixelate Imagick  Blur  3 Different Kinds  Brightness  Charcoal  Combine  Colorize  Color Replace  Distort  Enhance  Equalize  Flop  Frame  Gamma  Hue Shift  Level  Magnify  Median Filter  Modulate  Normalize  Oil Paint  Posturize  Rolling  Round corners  Sepia  Shade  Sharpen  Solarize  Stegano  Swirl  Texturize  Vignette

Slide 34

Slide 34 text

Desaturate Images Black and white photographs GD [startup] imagefilter( $img, IMG_FILTER_GRAYSCALE ); [shutdown] Imagick [startup] $img->modulateImage( 100, // brightness 0, // saturation 100 // hue shift ); [shutdown]

Slide 35

Slide 35 text

Greyscale Results Not exactly the same if you look close. GD Imagick

Slide 36

Slide 36 text

Sepia Tone Images Old photo aged photograph GD [startup] imagefilter( $img, IMG_FILTER_GRAYSCALE ); imagefilter( $img, IMG_FILTER_COLORIZE, 90, // red 40, // green 3 // blue ); [shutdown] Imagick [startup] $img->sepiaToneImage(80); [shutdown]

Slide 37

Slide 37 text

Sepia Results GD Imagick

Slide 38

Slide 38 text

Watermarking Overlaying a ghost image on an image. GD [startup] $mark = imagefrompng($markfile); $markw = imagesx($mark); $markh = imagesy($mark); imagefilter( $mark, IMG_FILTER_GRAYSCALE ); imagecopyresampled( $img, $mark, ($imgw - $markw), ($imgh - $markh), 0, 0, $markw, $markh, $markw, $markh ); imagedestroy($mark); [shutdown] Imagick [startup] $mark = new Imagick($markfile); $x = $img->getImageWidth()-$mark->getImageWidth(); $y = $img->getImageHeight()-$mark->getImageHeight(); $mark->modulateImage(100,0,100); $img->compositeImage( $mark, Imagick::COMPOSITE_DEFAULT, $x, $y ); $mark->destroy(); [shutdown]

Slide 39

Slide 39 text

Watermarking Result GD Imagick

Slide 40

Slide 40 text

Drawing Shapes and Text

Slide 41

Slide 41 text

How they handle drawing. GD  Draw directly on to the image resource you want to draw on.  Fast.  Super easy if you do not need anything too involved. Imagick  Draw on a special “draw layer” and then lay it on top of the image.  Great for advanced drawing. Not as easy.

Slide 42

Slide 42 text

Drawing Shapes Drawing an ellipse over the entire image. GD [startup] $red = imagecolorallocate($img,255,0,0); imagefilledellipse( $img, floor($imgw/2), floor($imgh/2), $imgw, $imgh, $red ); [shutdown] Imagick [startup] $draw = new ImagickDraw; $draw->setFillColor( new ImagickPixel(‘red’) ); $draw->ellipse( floor($imgw/2), floor($imgh/2), floor($imgw/2), floor($imgh/2), 0, 360 ); $img->drawImage($draw); $draw->destroy(); [shutdown]

Slide 43

Slide 43 text

Writing Text on an Image Fonts are tricksy  Both Imagick and GD are suppose to have the ability to use the fonts installed on the system.  Except that works 0 times out of 10.  What does work? Absolute path to a font (TTF) file. That always works, in both libraries.  Font sizes: GD Points, Imagick Pixels. Derp.  PHP manual says Imagick is points too, but my own observations + other people say it is wrong.

Slide 44

Slide 44 text

Writing Text on an Image – GD Apply directly to the forehead. GD [startup] $color = imagecolorallocate($img,255,0,0); imagettftext( $img, $size, $angle, $x, $y, $color, $fontfile, $text ); [shutdown]

Slide 45

Slide 45 text

Writing Text on an Image – Imagick Sort of works like an old typewriter. Really. Imagick [startup] $color = new ImagickPixel(‘red’); $draw = new ImagickDraw; $draw->setFont($fontfile); $draw->setFontSize($size); $draw->setFillColor($color); $img->annotateImage( $draw, $x, $y, $angle, $text ); $draw->destroy(); [shutdown]

Slide 46

Slide 46 text

Text Rendering GD Imagick

Slide 47

Slide 47 text

Performance Speed and RAM use

Slide 48

Slide 48 text

So, You’re punching pixels in the face? Image processing is slow (relative to, say, a PING).  Try to avoid doing large image processing during a request, if possible.  Something goofy like cropping a user avatar? That’s something that is OK to do live.  Leaving the webserver and request hanging to render a 8 megapixel subway map is not.  How and when you process is something you have to think about how your app works.

Slide 49

Slide 49 text

Still pixel punching? I know, those little guys never give up. Punch harder.  The larger your images are, the more RAM you will need to allow PHP to use.  memory_limit=300M  You are probably looking at a value around this if your users are uploading photos off their new smarty telephones for you to scale down to web size.  memory_limit=2G  And this is what you are looking at if you are going to try stuff like this...

Slide 50

Slide 50 text

Doing something HUGE because I can Daniel said I was crazy. Daniel doesn’t even know. I can see you Daniel. 15306x7653 pixel map of the earth. 3650 long/lat points to plot. GD  3.5sec to open  3.3sec to desaturate  0.05sec to plot  6sec to write JPEG to disk. 11.1MB  74sec to write PNG to disk. 46.1MB.  Peak RAM use: 1,043 MB Imagick  3sec  1.5sec to desaturate  1sec to plot  0.4sec plot “done right”  4.5sec to write JPEG to disk. 9.4MB  30sec to write PNG to disk. 46.3MB  Peak RAM use: 450 MB

Slide 51

Slide 51 text

Performance Summary  Small images, lots of drawing? GD.  Small images, lots of filtering? Imagick.  Large images, doing anything? Ehh eh. Well. Imagick would probably be your best bet to try first.  Imagick if you value your alpha channel.

Slide 52

Slide 52 text

The End Twitter: @bobmajdakjr Email: [email protected] Blog: http://catch404.net This entire codebase (demo site, apps, libraries) on Github. https://joind.in/6339 https://github.com/bobmajdakjr/dall asphp-image-tools-code