|
|
 |
LIII. Image Functions
PHP is not limited to creating just HTML output. It can also be
used to create and manipulate image files in a variety of different
image formats, including gif, png, jpg, wbmp, and xpm. Even more
convenient, PHP can output image streams directly to a browser. You
will need to compile PHP with the GD library of image functions for
this to work. GD and PHP may also require other libraries, depending
on which image formats you want to work with.
You can use the image functions in PHP to get the size of
JPEG, GIF,
PNG, SWF,
TIFF and JPEG2000 images.
Note:
Read requirements section about how to expand image capabilities
to read, write and modify images and to read meta data of pictures
taken by digital cameras.
If you have the GD library (available at http://www.boutell.com/gd/) you will also be able to create
and manipulate images.
The format of images you are able to manipulate depend on the
version of GD you install, and any other libraries
GD might need to access those image formats.
Versions of GD older than gd-1.6
support GIF format images, and do not support PNG, where versions
greater than gd-1.6 and less than gd-2.0.28 support PNG, not GIF. GIF
support was re-enabled in gd-2.0.28.
Note:
Since PHP 4.3 there is a bundled version of the GD lib. This bundled
version has some additional features like alpha blending, and should
be used in preference to the external library
since its codebase is better maintained and more stable.
You may wish to enhance GD to handle more image formats.
Table 1. Supported image formats
You may wish to enhance GD to deal with different fonts. The following
font libraries are supported:
Table 2. Supported font libraries
If you have PHP compiled with --enable-exif
you are able to work with information stored in headers of
JPEG and TIFF images. This way you can
read meta data generated by digital cameras as mentioned above. These
functions do not require the GD library.
To enable GD-support configure PHP
--with-gd[=DIR], where DIR is the GD base
install directory. To use the recommended bundled version of the GD library
(which was first bundled in PHP 4.3.0), use the configure option
--with-gd.
GD library requires libpng and
libjpeg to compile.
In Windows, you'll include the GD2 DLL php_gd2.dll as
an extension in php.ini. The GD1 DLL php_gd.dll was
removed in PHP 4.3.2. Also note that the preferred truecolor image
functions, such as imagecreatetruecolor(), require GD2.
Note:
To enable exif support in Windows, php_mbstring.dll must be loaded prior
to php_exif.dll in php.ini.
To disable GD support in PHP 3 add
--without-gd to your configure line.
Enhance the capabilities of GD to handle more image formats by specifying
the --with-XXXX configure switch to your PHP configure
line.
Table 3. Supported image formats | Image Format | Configure Switch |
|---|
| jpeg-6b |
To enable support for jpeg-6b add
--with-jpeg-dir=DIR.
| | png |
To enable support for png add
--with-png-dir=DIR. Note, libpng
requires the zlib library,
therefore add --with-zlib-dir[=DIR]
to your configure line.
| | xpm |
To enable support for xpm add
--with-xpm-dir=DIR. If configure
is not able to find the required libraries, you may add the path to
your X11 libraries.
|
Note:
When compiling PHP with libpng, you must use the same version that was
linked with the GD library.
Enhance the capabilities of GD to deal with different fonts by specifying
the --with-XXXX configure switch to your PHP configure
line.
Table 4. Supported font libraries | Font library | Configure Switch |
|---|
| FreeType 1.x |
To enable support for FreeType 1.x add
--with-ttf[=DIR].
| | FreeType 2 |
To enable support for FreeType 2 add
--with-freetype-dir=DIR.
| | T1lib |
To enable support for T1lib (Type 1 fonts) add
--with-t1lib[=DIR].
| | Native TrueType string function |
To enable support for native TrueType string function add
--enable-gd-native-ttf.
|
There are no image specific configurations but you may be interested in the
exif extension directives.
This extension has no resource types defined.
The constants below are defined by this extension, and
will only be available when the extension has either
been compiled into PHP or dynamically loaded at runtime.
Example 1. PNG creation with PHP |
<?php
header("Content-type: image/png");
$string = $_GET['text'];
$im = imagecreatefrompng("images/button1.png");
$orange = imagecolorallocate($im, 220, 210, 60);
$px = (imagesx($im) - 7.5 * strlen($string)) / 2;
imagestring($im, 3, $px, 9, $string, $orange);
imagepng($im);
imagedestroy($im);
?>
|
|
This example would be called from a page with a tag like: <img
src="button.php?text=text">. The above button.php script
then takes this "text" string and overlays it on top of a
base image which in this case is "images/button1.png"
and outputs the resulting image. This is a very convenient way to
avoid having to draw new button images every time you want to
change the text of a button. With this method they are
dynamically generated.
User Contributed Notes
Image Functions
Michiel van de Vis
12-May-2005 02:08
After testing this more carefully, i noticed a bug.
This can be resolved by replacing the getDeltaArray function by this one:
<?php
function getDeltaArray($col1, $col2, $size)
{
$r_range = $col1[0] - $col2[0];
$g_range = $col1[1] - $col2[1];
$b_range = $col1[2] - $col2[2];
$delta_r = $r_range/$size;
$delta_g = $g_range/$size;
$delta_b = $b_range/$size;
return array($delta_r, $delta_g, $delta_b);
}
?>
Hope this can be of help for anyone.
Michiel van de Vis
11-May-2005 12:48
Inspirated by several functions below, i wrote a function to create a gradient like in a color picker.
----------------------------------
| COL 1 COL2|
| |
| |
| |
| |
| COL 3 COL4|
----------------------------------
That is, 4 color which "gradient" to the center of the image.
Not 100% tested, but i believe most errors are gone.
<?php
function imagegradient($x_size,
$y_size,
$left_upper="FFFFFF", $right_upper="FF0000",
$left_lower="000000", $right_lower="000000")
{
$image = imagecreatetruecolor($x_size,$y_size);
$right_upper = getColorArray($right_upper);
$left_upper = getColorArray($left_upper);
$left_lower = getColorArray($left_lower);
$right_lower = getColorArray($right_lower);
if(($x_size*$y_size)<=10000)
$size = 1;
else
$size = 5;
$left = $left_upper;
$right = $left_lower;
list($r, $g, $b) = $left;
$delta_x1 = getDeltaArray($left, $right_upper, $x_size);
$delta_x2 = getDeltaArray($right, $right_lower, $x_size);
for($i=0;$i<$x_size;$i+=$size)
{
list($r, $g, $b) = $left;
for($j=0;$j<$y_size;$j+=$size)
{
$delta_y = getDeltaArray($left, $right, $y_size);
$r = $r - ($delta_y[0]*$size);
$g = $g - ($delta_y[1]*$size);
$b = $b - ($delta_y[2]*$size);
$col = imagecolorallocate($image, round($r), round($g), round($b));
imagefilledrectangle($image, $i, $j, $i+$size, $j+$size, $col);
}
$left[0] = $left[0] - ($delta_x1[0]*$size);
$left[1] = $left[1] - ($delta_x1[1]*$size);
$left[2] = $left[2] - ($delta_x1[2]*$size);
$right[0] = $right[0] - ($delta_x2[0]*$size);
$right[1] = $right[1] - ($delta_x2[1]*$size);
$right[2] = $right[2] - ($delta_x2[2]*$size);
}
return $image;
}
function getDeltaArray($col1, $col2, $size)
{
$r_range = $col1[0] - $col2[0];
$g_range = $col1[1] - $col2[1];
$b_range = $col1[2] - $col2[2];
if($r_range<0) $r_range*=-1;
if($g_range<0) $g_range*=-1;
if($b_range<0) $b_range*=-1;
$delta_r = $r_range/$size;
$delta_g = $g_range/$size;
$delta_b = $b_range/$size;
return array($delta_r, $delta_g, $delta_b);
}
function getColorArray($col)
{
list($r, $g, $b) = sscanf($col, "%2x%2x%2x");
return array($r, $g, $b);
}
?>
j at jgdataworks dot com
05-May-2005 10:33
Here is a class that I wrote, it supports scaling images on the fly:
scale to desired dimensions
scale to maximum
scale to ratio (relative to 1.0)
it could be easily modified for other features as well.
It can be included in your scripts, or called directly like this: <img src="image.php?img=/imgs/logo.png;sm,200">
Check it out:
http://jgdataworks.com/OSS/Image.class.phps
If you like it, drop me a note. Thanks.
info at b1g dot de
24-Apr-2005 12:35
Sorry, my function had got a little bug. Here is the corrected one.
<?php
function Graph($data, $w, $h, $titel, $y_titel, $x_titel, $y_start_with_null=true, $x_start_with_null=true)
{
$typ_farben = array('0000FF', 'FF0000', '006600', 'FF9900', '663300');
$min_x = 0xFFFFFFFF;
$max_x = 0x00000000;
$min_y = 0xFFFFFFFF;
$max_y = 0x00000000;
foreach($data as $typ)
{
foreach($typ['data'] as $x => $y)
{
$min_x = min($min_x, $x);
$max_x = max($max_x, $x);
$min_y = min($min_y, $y);
$max_y = max($max_y, $y);
}
}
reset($data);
if($y_start_with_null)
$min_y = 0;
if($x_start_with_null)
$min_x = 0;
$im = imagecreate($w, $h);
$grey = imagecolorallocate($im, 240, 240, 240);
$black = imagecolorallocate($im, 0, 0, 0);
$i = 0;
foreach($data as $key=>$typ)
{
if($i > (count($typ_farben)-1))
$i = 0;
$data[$key]['color'] = imagecolorallocate($im, hexdec(substr($typ_farben[$i], 0, 2)), hexdec(substr($typ_farben[$i], 2, 2)), hexdec(substr($typ_farben[$i], 4, 2)));
$i++;
}
reset($data);
imagestring($im, 2, (($w/2) - ((strlen($titel)*6)/2)), 8, $titel, $black);
imagestring($im, 2, 60, 28, $y_titel, $black);
imagestring($im, 2, $w-30-(strlen($x_titel)*6), $h-28, $x_titel, $black);
imageline($im, 40, 30, 40, $h-60, $black);
imageline($im, 40, $h-60, $w-30, $h-60, $black);
$graph_width = $w-30-40;
$graph_height = $h-40-60;
$x_segment = @($graph_width / ($max_x - $min_x));
$y_segment = @($graph_height / ($max_y - $min_y));
$raster_y = ($max_y > (floor($graph_height/22)) ? floor($graph_height/22) : $max_y);
for($i=$min_y; $i<=$raster_y; $i++)
{
$y = ($h-60) - (($i-$min_y)*@($graph_height/($raster_y-$min_y)));
$zahl = round(($i-$min_y)*@($max_y/($raster_y-$min_y)), 0)+$min_y;
imageline($im, 36, $y, 40, $y, $black);
imagestring($im, 2, $max_y < 10 ? 15 : 10, $y-6, $zahl, $black);
}
$raster_x = ($max_x > floor($graph_width/32)) ? floor($graph_width/32) : $max_x;
for($i=$min_x; $i<=$raster_x; $i++)
{
$x = 40 + (($i-$min_x)*($graph_width/($raster_x-$min_x)));
$zahl = round(($i-$min_x)*($max_x/($raster_x-$min_x)), 0)+$min_x;
imageline($im, $x, $h-60, $x, $h-54, $black);
imagestring($im, 2, $max_x < 10 ? $x-3 : $x-5, $h-45, $zahl, $black);
}
$last_legend_x = 10;
foreach($data as $typ)
{
imagefilledrectangle($im, $last_legend_x, $h-25, $last_legend_x+6, $h-18, $typ['color']);
imagerectangle($im, $last_legend_x, $h-25, $last_legend_x+6, $h-18, $black);
$last_legend_x += 10;
imagestring($im, 2, $last_legend_x, $h-28, $typ['titel'], $typ['color']);
$last_legend_x += (strlen($typ['titel']) * 6) + 10;
$last_x = 0;
$last_y = 0;
foreach($typ['data'] as $x=>$y)
{
$new_x = 40+(($x-$min_x)*$x_segment);
$new_y = ($h-60)-(($y-$min_y)*$y_segment);
imageline($im, $last_x==0 ? $new_x : $last_x, $last_y==0 ? $new_y : $last_y, $new_x, $new_y, $typ['color']);
imagefilledrectangle($im, $new_x-1, $new_y-1, $new_x+1, $new_y+1, $typ['color']);
$last_x = $new_x;
$last_y = $new_y;
}
}
header('Content-Type: image/png');
imagepng($im);
}
?>
the_slim_jim at hotmail dot com
21-Apr-2005 04:43
if using gd under a windows environment, remember to load ansi.sys in the config.sys file, or there are no ansi C color drivers.
-Jimmy
snagnever at gmail dot com
03-Apr-2005 12:27
Here i'm again... i have made little improvements on the last post, so i'll post the new one here. The same that the old one image to "asci"
<?php
$name = basename($_GET['name']);
$file = "/path/to/images/" . $name;
if( file_exists($file) ) {
$what = getimagesize($file);
switch( $what['mime'] ){
case 'image/png' : $src_id = imagecreatefrompng($file); break;
case 'image/jpeg': $src_id = imagecreatefromjpeg($file); break;
case 'image/gif' : $old_id = imagecreatefromgif($file); $src_id = imagecreatetruecolor($what[0],$what[1]); imagecopy($src_id,$old_id,0,0,0,0,$what[0],$what[1]); break;
default: break;
}
}
else die("No such file");
if( $src_id ){
$x_size = imagesx($src_id);
$y_size = imagesy($src_id);
$x_jump = 2;
$y_jump = 3;
$pixel_char = array(0);
echo "The image is $x_size x $y_size\n";
echo "<span style='font-size:8px; font-weight:bold;'>";
echo "<pre>";
for( $y = 0; $y < $y_size; $y+=$y_jump ){
for( $x = 0; $x < $x_size; $x+=$x_jump ){
if( $x >= $x_size || $y >= $y_size ) break;
$rgb = @imagecolorat($src_id, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
if( $x >= $x_size ) break;
if( $y >= $y_size ) break;
$pc = rand(0,count($pixel_char)-1);
$pc = $pixel_char[$pc];
echo "<font style='color:rgb($r,$g,$b)'>$pc</font>";
} echo "\r\n"; } }
?>
jasperbg at gmail dot com
27-Mar-2005 12:14
To those writing a new function to create a generic imagecreatefromfile() function: You are making it needlessly complex. Why not just:
<?php
$image = imagecreatefromstring(file_get_contents("/path/to/image.ext"));
?>
2064*nojunk* at earthlink dot net
17-Mar-2005 10:15
.::SHARPEN YOUR IMAGES::.
---by Alex R. Austin
I became aware that there is just NO image sharpening in PHP4. Thus, writing code for my photo album I found that using resize function "imagecopyresampled" would blur my thumbnails. After not finding any way to sharpen my thumbs I wrote this code. Please keep in mind that PHP is not C++ and speed is somewhat slow. I have optimised my code as far as I could. If you can make it faster be my guest. The 800x600 image gets sharpened on my machine in 9 seconds. A 200x150 thumbnail takes only half a second. Thus, it is not that bad.
<?
$filename='test.jpg';
list($width, $height) = getimagesize($filename);
$img = imagecreatefromjpeg($filename);
$pix=array();
for($hc=0; $hc<$height; ++$hc){
for($wc=0; $wc<$width; ++$wc){
$rgb = ImageColorAt($img, $wc, $hc);
$pix[$hc][$wc][0]= $rgb >> 16;
$pix[$hc][$wc][1]= $rgb >> 8 & 255;
$pix[$hc][$wc][2]= $rgb & 255;
}
}
$height--; $width--;
for($hc=1; $hc<$height; ++$hc){
$r5=$pix[$hc][0][0];
$g5=$pix[$hc][0][1];
$b5=$pix[$hc][0][2];
$hcc=$hc-1;
for($wc=1; $wc<$width; ++$wc){
$r=-($pix[$hcc][$wc][0]);
$g=-($pix[$hcc][$wc][1]);
$b=-($pix[$hcc][$wc][2]);
$r-=$r5+$r5; $g-=$g5+$g5; $b-=$b5+$b5;
$r5=$pix[$hc][$wc][0];
$g5=$pix[$hc][$wc][1];
$b5=$pix[$hc][$wc][2];
$r+=$r5*5; $g+=$g5*5; $b+=$b5*5;
$r*=.5; $g*=.5; $b*=.5;
$r=(($r-$r5)*.75)+$r5;
$g=(($g-$g5)*.75)+$g5;
$b=(($b-$b5)*.75)+$b5;
if ($r<0) $r=0; elseif ($r>255) $r=255;
if ($g<0) $g=0; elseif ($g>255) $g=255;
if ($b<0) $b=0; elseif ($b>255) $b=255;
imagesetpixel($img,$wc,$hc,($r << 16)|($g << 8)|$b);
}
}
imageinterlace($img,1);
imagejpeg($img,'test_save.jpg',99);
imagedestroy($img);
?>
ozeryumsek
14-Mar-2005 04:33
3 level questionary image:
It shows each 3 level graph
<?php
function drawRating($rating1,$rating2,$rating3) {
$image = imagecreate(550,100);
$back = ImageColorAllocate($image,255,255,255);
$border = ImageColorAllocate($image,0,0,0);
$fill = ImageColorAllocate($image,44,81,150);
ImageFilledRectangle($image,0,0,302,20,$back);
ImageFilledRectangle($image,0,30,302,50,$back);
ImageFilledRectangle($image,0,60,302,80,$back);
ImageFilledRectangle($image,1,1,$rating1,19,$fill);
ImageFilledRectangle($image,1,31,$rating2,49,$fill);
ImageFilledRectangle($image,1,61,$rating3,79,$fill);
ImageRectangle($image,0,0,300,20,$border);
ImageRectangle($image,0,30,300,50,$border);
ImageRectangle($image,0,60,300,80,$border);
ImageString($image,5 , 310, 0 ,"Yetersiz Buldum - %$rateyuz1",$border);
ImageString($image,5 , 310, 30,"Daha Iyi Olabilir - %$rateyuz2", $border);
ImageString($image,5 , 310, 60,"Begendim - %$rateyuz3", $border);
imagePNG($image);
imagedestroy($image);
}
drawRating (48,26,34);?>
KaHa6uc at abv dot bg
14-Mar-2005 12:53
When generating an image (my case was a counter, and I needed to load it every time), some browsers, Opera was this particular case, received the "HTTP/1.1 301 Not Modified" header, so it skipped loading it and took it from the cache. The best workaround for this was to use
header("HTTP/1.1 202 Accepted");
before sending the image as a direct output:
header("HTTP/1.1 202 Accepted");
header("Content-type: image/gif");
Thus the image is now loaded every time ;)
---------------------------------------------------
Division from within invalidates suffering
andreaskalsch at gmx dot de
09-Mar-2005 01:24
You get some trouble if you create an image by using the function imagettfbbox(). The x value is correct but the y value doesn't consider that a text can have more than one line.
The second problem is to find the start position when you want to use imagettftext(), especially by using an angle > 90°.
My solution uses some params to generate an image with any text. The image size is as small as possible, but you can add a margin without problems:
params:
$text > the string you want to write
$format > output format "jpeg" or "png"
$quality > jpeg quality, from 1 to 100
$font > font path and file
$size > font size (px)
$angle > angle of text in degrees
$r > font color: red part
$g > font color: green part
$b > font color: blue part
$bgr > background color: red part
$bgg > bg color: green part
$bgb > bg color: blue part
$margin > a margin between text and border of pic
code:
<?
if ($text != '')
{
list(,,$w) = imagettfbbox($size, 0, $font, $text);
$lines = count(explode("\n", $text));
$angle_rad = $angle / 180 * pi();
$h = 2 * $size * $lines;
$x = round($h * abs(sin($angle_rad)) + $w * abs(cos($angle_rad))) + $size;
$y = round($h * abs(cos($angle_rad)) + $w * abs(sin($angle_rad))) + $size;
$run_y = - $lines * $size + 1.5 * $size;
$s_x = round($x / 2 - ($w / 2) * cos($angle_rad) + $run_y *
| |