Image creation with PHP

First published at Tuesday 11 December 2007

Warning: This blog post is more then 17 years old – read and use with care.

Image creation with PHP

There are several ways to create images or graphics with PHP. First there are some well known extensions, like ext/GD, or perhaps ext/ming everybody immediately remembers, when it comes to graphics generation. But there are several structural differences not in between the avaliable libraries, but also between the image formats you can create. This article series will give you some insight on the formats and libraries, and then shows how an abstraction layer could be build.

Introduction

General notes, relevant for this article.

Terms

Some terms I use in a special way.

Image
I use it as a generalization of pictures and graphics.
Picture
Images with natural contents, like photos or drawings. Usually there are no or only few clear borders in those images.
Graphic
Computer generated graphics with technical illustrations or charts. They often contain clear borders.

Agenda

The first part of this article describes the various image formats and backends.

  • Formats

    Describes the advantages and drawbacks of the different extensions and the formats they can generate.

  • Simple shapes

    Describes the basic required data structure and the generation of a first simple shape.

  • Gradients

    Describes how you can add radial and linear gradients to your generated graphics with each of the backends.

  • Integrated bitmaps

    Integrating bitmaps with the backends.

  • Text rendering

    The basics of text rendering with all extensions.

  • Additional image tools

    With a small set of tools the automatic generation of images gets a lot simpler and allows you the construction of nice images using the existing APIs.

The code

I provide completely working code within this article, which will not be developed any further, because there are already existing packages, which try to provide such an abstraction layer, like Image_Canvas in PEAR. In the graph component from the eZ Components I personally develop very similar backends under the New BSD license, which will stay limited to the drawing methods we need for the graph component for now.

The complete source code can be downloaded here, or partially copied from the code examples. The source code is not provided under some OpenSource license, but stays under my personal copyright, like the article does. If you want to take the code and continue developing it, please send me a mail and we can discuss this.

The code is written for PHP 5.3, which can currently be compiled from the CVS and makes use of the namespaces features in 5.3.

To run the provided code, you need at least the following extensions installed:

  • GD (with PNG and FreeType 2 support)

  • cairo_wrapper 0.2.3-beta

  • Ming 0.3.0

  • The default extensions: DOM, SPL

The formats

First there are two classes of graphics you generate, and each of those classes again has several different formats. I will classify them by the pros and cons and give a common use case for each of them. This will give you a general overview - the technical details for the relevant formats will be part of a later section.

Vector formats

On the one hand we have vector based graphics formats, which means, that the format describes shapes, their fills, line styles etc. With those formats it is up to some client (image viewer) to actually render the graphics, as the current normal display expects pixels, the clients needs to transform the shapes into pixels. This may result in differently rendered results, or quality differences of the output depending on the renderer.

SVG

SVG is a W3C standard for XML based "Scalable Vector Graphics". It is a open standard, and due its nature being XML, easy to generate and sometimes even user readable. XML always has the drawback of quite large files, compared with the contained information. But, as vector graphics formats don't need to describe each pixel, but shapes which may be far bigger, and you may compress XML using gzip, which nearly each client may read, this is negotiable. Common SVG graphics are mostly smaller then similar images which use a bitmap format.

As SVG is XML you may include stuff from other namespaces directly in your SVG document, or even define your own extensions. You may, for example, use data URLs to directly include other documents, like bitmap images. When displayed in browser you may also include ECMAScript to interactively modify the DOM tree, creating animations or user interfaces. Some other displaying clients may also be capable of interpreting ECMAScript, but you shouldn't expect that from the average image viewer.

There are two real drawbacks when it comes to SVG rendering in image viewers. The subset of supported SVG elements may differ. The W3C defines a standard called SVG Tiny which contains a small subset which is common to nearly all clients, and will be a good base for estimations, what some client may support, and which may even be displayed on mobile clients.

The largest issue with those different clients is the rendering of text. You just can't know which fonts may be available on the client, and because of this you can't know how much space some text will consume, or how it will look like. To bypass this issue you may convert text to paths, which is supported by some editors, but this increases the complexity of rendering for the client and the size of your SVG document.

Pros:

  • Open standard

  • Common syntax (XML)

  • Easy to debug, because it is user readable

  • A lot of clients, which may display SVG (Gecko engine, Opera, webkit (khtml), Adobe SVG Viewer (IE plugin), a LOT of image creation tools.

Cons:

  • Different client side rendering

  • Font issues

Common usecases:

  • Graphics in web

  • Scalable graphics

  • Vector graphics which should still be usable in several years...

Flash

Flash is a closed standard defined by Adobe for animated and interactive web graphics. When it comes to image generation you can consider this as vector graphics format, by omitting all possibility to add frames, or user interaction.

There is only one real client so that you can be pretty sure how some stuff will be rendered, until you use some of evolving open source clients, which grew because the official client does not run on several platforms, can not be compiled and the chance for violating your privacy by security issues or other unknown code is quite high...

Pros:

  • Rich vector graphics format with installed clients on nearly all systems (~98%)

Cons:

  • Closed proprietary format.

  • Clients are not available or easy to develop for all platforms.

  • Not accessible to users with limited access

Common usecase:

  • Online marketing presentations with mainstream centric target group.

PDF / PS

PDF and PS also have support for basic vector graphics, which may be generated by one of the extensions, I will mention later. Due to their limited support of graphics features and completely different common usecase I won't go into detail here.

Bitmaps

On the other hand there are bitmap formats, like the well known PNG, GIF, JPEG or BMP. Those formats already describe the pixels, so that there is no more required transformation by the client, it just needs to output the stuff. With these formats the quality and overall result complete depends on the image generation tool.

GIF

THE GIF format had patent issues for some time, which made it unavailable on some platforms or some tools. Even the format is now available everywhere it has some severe limitations, like a limited colorspace - maximum are 256 colors - and bad support for transparency - you may define only one color as fully transparent, which makes alpha blending impossible.

The size of GIF files mainly depends on the count of used colors which results in quite big files for complex images.

Pros:

  • Well known established image format

Cons:

  • Bad transparency support

  • Limited colorspace

Common usecase:

  • Web applications, where the author did not know about PNG.

  • Animated images

JPEG

Also affected by several patent issues, it is also a very widely supported format, but the compression algorithm makes it useless for graphics, but more appropriate for common pictures. The algorithm performs a fourier transformation, so that you will have a three dimensional cosine function for parts of the images, which are not able to describe sharp edges. With a lower quality factor for JPEG images, the amount of cosine terms in the resulting function will be reduced, which makes it harder and harder to describe sharp edges. The resulting artifacts are commonly known and shown on the image below, in which I saved a 10 * 10 pixel image with sharp edges with as a JPEG image with a quality of 95.

JPEG compression (Quality: 95)JPEG compression (Quality: 95)

Another drawback of the JPEG format is, that it does not have any support for transparency - which is OK for its normal usecase, pictures, but makes it very useless for common generated graphics.

Pros:

  • Well known and established image format

  • Good compression of pictures

Cons:

  • Bad compression and artifacts for graphics.

  • No transparency

Common usecase:

  • Pictures

PNG

PNG has been developed and standardized by the W3C because of the GIF patent issues and is the ultimate format for graphics, especially on the web. It has a lossless compression, supports the full RGB colorspace, 128 alpha channels for each color and results in quite small files, especially, when the quality is compared with GIF or JPEG graphics of the same size. Currently the only drawback is, that the outdated browser Internet Explorer 6 still does not support the alpha channels in PNG, which can be fixed using a hack in most cases, though...

Pros:

  • Well known and established image format

  • Good compression of graphics

  • Full RGB with 128 alpha channels

Cons:

  • Limited support in one browser

Common usecase:

  • Graphics in the web.

BMP, TIF, ...

There are far more (generic) bitmap formats, which do no compression or support other colorspaces like CMYK or HSL. They do not matter for web related images, because they normally result in far too big files, to use them in the web.

Conclusion

If you may want to use a vector graphic format you should use SVG, even some windows people may need to download a plugin to display those graphics. This is the right choice for a future proof format, with an independent consortium behind it.

On the other hand you might want to use a bitmap format which will make it much harder to integrate user interaction or animations. In this case you should use PNG for graphics and JPEG for pictures, because they offer the best compression for their designated use case and both have very wide support in all kinds of possible image viewers.

The libraries

Talking about several formats, there is a list of specialized libraries to generate each of them. Let's start with the bitmap libraries.

ext/GD

The GD extension is the best known PHP library for image generation, and in use for years now. It is very well documented, and you can find examples for nearly everything on the web, you may want to do using the GD library - but there are several major drawbacks. As said, when it comes to bitmaps, the generating library has to take care of the rendering, so that the decision about the used library will have a major effect on the quality of the resulting image.

ext/GD does not support anti aliasing in most of the cases - each line you draw has bad aliasing steps, each circle and each polygon. The aliasing of fonts depends on the backend library you use, for PS type 1 fonts you get no anti aliasing, while TTF fonts, rendered with FreeType 2, have. There is no native support for gradients, and some shapes, like circle sectors may look very bad when used with transparency. Trying to emulate gradients will fail, because setting lots of single pixels in a image is just far to slow.

The only real benefit from using GD is, that it is available nearly everywhere.

ext/cairo_wrapper

Cairo is a fantastic 2D graphic library, for example used by Gnome since 2.8 to draw the GUI, or by Firefox 2 to render SVGs and Firefox 3 to render the complete documents. It has native support for paths, gradients, anti aliasing and nearly everything you could demand from a 2D graphics library. Besides this, it is really fast and uses established libraries like Pango for text rendering.

The original Cairo library may not only output bitmap formats, but also SVG, PDF or PS. Additionally it may also render directly to X windows, or use OpenGL through Glitz for hardware acceleration.

Hartmut Holzgraefe wrote a wrapper for the cairo library using his pear/CodeGen_PECL package for extension generation. The package is available from cvs or from the pear channel, both documented on the packages homepage. To install the package just type:

# pear channel-discover pear.php-baustelle.de # pear install php-baustelle/cairo_wrapper-beta

If you are looking for documentation of the cairo API the best source currently is the C API documentation and the samples at cairo-graphics.org. As Hartmut really implemented a pure API wrapper for PHP you can use nearly all methods equivalently to their C examples.

ext/ming

The extension is still in an alpha state, but it is designed to create flash's SWF files. It currently supports a subset of functions, which does not match any defined flash version, but you can expect support for texts, gradients, basic shapes a very limited set of bitmaps and action script - even the documentation is often missing or may contain broken examples. Some of the documented functions and methods do not work as expected, or do not work at all - but that is something you have to live with, when using an alpha extension.

The only reason to use this extension is, that it is the only free possibility to create flash graphics or animations.

ext/DOM

For SVG generation we will use ext/DOM and I think every user of PHP 5 knows about it, as it is THE way to work with XML, like it is in several other languages, like ECMAScript and many others. Even XMLWriter is faster for document generation, we will have to insert nodes without the knowledge about the complete document prior to the final generation, so that we need something which holds the complete structure of the XML document. DOM perfectly solves this with a known and handy API.

Conclusion

I will introduce a wrapper which wraps all the mentioned libraries to make the differences transparent to the user - with some limitation in one or another wrapper, which will be mentioned in the implementation description.

Subscribe to updates

There are multiple ways to stay updated with new posts on my blog: