imageapi_gd.module in ImageAPI 5
Same filename and directory in other branches
GD2 toolkit functions
File
imageapi_gd.moduleView source
<?php
// $Id$
/**
* @file
* GD2 toolkit functions
*/
/**
* Implementation of hook_imageapi_toolkit().
*
* this hook only gets called to see is a module implements the imageapi hooks...
*/
function imageapi_gd_imageapi_toolkit() {
}
/**
* Settings form for the toolkit.
*/
function imageapi_gd_settings_form() {
$form['imageapi_jpeg_quality'] = array(
'#type' => 'textfield',
'#title' => t('JPEG quality'),
'#description' => t('Define the image quality for JPEG manipulations. Ranges from 0 to 100. Higher values mean better image quality, but bigger files.'),
'#size' => 10,
'#maxlength' => 3,
'#default_value' => variable_get('imageapi_jpeg_quality', 75),
'#field_suffix' => '%',
);
return system_settings_form($form);
}
/**
* Open an image file.
*
* @param $image
* An image object. The $image->resource value will populated by this call.
* @return
* TRUE or FALSE, based on success.
*/
function imageapi_gd_image_open($image) {
$extension = str_replace('jpg', 'jpeg', $image->info['extension']);
$function = 'imagecreatefrom' . $extension;
return function_exists($function) && ($image->resource = $function($image->source));
}
/**
* Save an image file to a destination.
*
* @param $image
* An image object.
* @param $destination
* A string file path where the image should be saved.
* @param $extension
* A string containing one of the following extensions: gif, jpg, jpeg, png.
* @return
* TRUE or FALSE, based on success.
*/
function imageapi_gd_image_close($image, $destination) {
$extension = str_replace('jpg', 'jpeg', $image->info['extension']);
$function = 'image' . $extension;
if (!function_exists($function)) {
return FALSE;
}
if ($extension == 'jpeg') {
return $function($image->resource, $destination, variable_get('imageapi_jpeg_quality', 75));
}
else {
// Always save PNG images with full transparency.
if ($extension == 'png') {
imagealphablending($image->resource, FALSE);
imagesavealpha($image->resource, TRUE);
}
return $function($image->resource, $destination);
}
}
/**
* Crop an image using the GD toolkit.
*
* @param $image
* An image object. The $image->resource, $image->info['width'], and
* $image->info['height'] values will be modified by this call.
* @param $x
* The starting x offset at which to start the crop, in pixels.
* @param $y
* The starting y offset at which to start the crop, in pixels.
* @param $width
* The width of the cropped area, in pixels.
* @param $height
* The height of the cropped area, in pixels.
* @return
* TRUE or FALSE, based on success.
*/
function imageapi_gd_image_crop(&$image, $x, $y, $width, $height) {
$res = imageapi_gd_create_tmp($image, $width, $height);
if (!imagecopyresampled($res, $image->resource, 0, 0, $x, $y, $width, $height, $width, $height)) {
return FALSE;
}
// Destroy the original image and return the modified image.
imagedestroy($image->resource);
$image->resource = $res;
$image->info['width'] = $width;
$image->info['height'] = $height;
return TRUE;
}
/**
* Scale an image to the specified size using GD.
*
* @param $image
* An image object. The $image->resource, $image->info['width'], and
* $image->info['height'] values will be modified by this call.
* @param $width
* The new width of the resized image, in pixels.
* @param $height
* The new height of the resized image, in pixels.
* @return
* TRUE or FALSE, based on success.
*/
function imageapi_gd_image_resize(&$image, $width, $height) {
$res = imageapi_gd_create_tmp($image, $width, $height);
if (!imagecopyresampled($res, $image->resource, 0, 0, 0, 0, $width, $height, $image->info['width'], $image->info['height'])) {
return FALSE;
}
imagedestroy($image->resource);
// Update image object.
$image->resource = $res;
$image->info['width'] = $width;
$image->info['height'] = $height;
return TRUE;
}
/**
* Rotate an image the given number of degrees.
*
* @param $image
* An image object. The $image->resource, $image->info['width'], and
* $image->info['height'] values will be modified by this call.
* @param $degrees
* The number of (clockwise) degrees to rotate the image.
* @param $background
* An hexadecimal integer specifying the background color to use for the
* uncovered area of the image after the rotation. E.g. 0x000000 for black,
* 0xff00ff for magenta, and 0xffffff for white. For images that support
* transparency, this will default to transparent. Otherwise it will
* be white.
* @return
* TRUE or FALSE, based on success.
*/
function imageapi_gd_image_rotate(&$image, $degrees, $background) {
// PHP installations using non-bundled GD do not have imagerotate.
if (!function_exists('imagerotate')) {
require_once drupal_get_path('module', 'imageapi_gd') . '/imagerotate.inc';
}
$width = $image->info['width'];
$height = $image->info['height'];
// Convert the hexadecimal background value to a color index value.
if (isset($background)) {
$rgb = array();
for ($i = 16; $i >= 0; $i -= 8) {
$rgb[] = $background >> $i & 0xff;
}
$background = imagecolorallocatealpha($image->resource, $rgb[0], $rgb[1], $rgb[2], 0);
}
else {
// Get the current transparent color.
$background = imagecolortransparent($image->resource);
// If no transparent colors, use white.
if ($background == 0) {
$background = imagecolorallocatealpha($image->resource, 255, 255, 255, 0);
}
}
// Images are assigned a new color pallete when rotating, removing any
// transparency flags. For GIF images, keep a record of the transparent color.
if ($image->info['extension'] == 'gif') {
$transparent_index = imagecolortransparent($image->resource);
if ($transparent_index != 0) {
$transparent_gif_color = imagecolorsforindex($image->resource, $transparent_index);
}
}
$image->resource = imagerotate($image->resource, 360 - $degrees, $background);
// GIFs need to reassign the transparent color after performing the rotate.
if (isset($transparent_gif_color)) {
$background = imagecolorexactalpha($image->resource, $transparent_gif_color['red'], $transparent_gif_color['green'], $transparent_gif_color['blue'], $transparent_gif_color['alpha']);
imagecolortransparent($image->resource, $background);
}
$image->info['width'] = imagesx($image->resource);
$image->info['height'] = imagesy($image->resource);
return TRUE;
}
function imageapi_gd_image_sharpen(&$image, $radius, $sigma, $amount, $threshold) {
$threshold = round($threshold * 255);
$image->resource = imageapi_gd_unsharp_mask($image->resource, $radius, $sigma, $amount, $threshold);
return TRUE;
}
/**
* Convert an image resource to grayscale.
*
* Note that transparent GIFs loose transparency when desaturated.
*
* @param $image
* An image object. The $image->resource value will be modified by this call.
* @return
* TRUE or FALSE, based on success.
*/
function imageapi_gd_image_desaturate(&$image) {
// PHP installations using non-bundled GD do not have imagefilter.
if (!function_exists('imagefilter')) {
require_once drupal_get_path('module', 'imageapi_gd') . '/imagefilter.inc';
}
return imagefilter($image->resource, IMG_FILTER_GRAYSCALE);
}
/**
* Create a truecolor image preserving transparency from a provided image.
*
* @param $image
* An image object.
* @param $width
* The new width of the new image, in pixels.
* @param $height
* The new height of the new image, in pixels.
* @return
* A GD image handle.
*/
function imageapi_gd_create_tmp($image, $width, $height) {
$res = imagecreatetruecolor($width, $height);
if ($image->info['extension'] == 'gif') {
// Grab transparent color index from image resource.
$transparent = imagecolortransparent($image->resource);
if ($transparent >= 0) {
// The original must have a transparent color, allocate to the new image.
$transparent_color = imagecolorsforindex($image->resource, $transparent);
$transparent = imagecolorallocate($res, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
// Flood with our new transparent color.
imagefill($res, 0, 0, $transparent);
imagecolortransparent($res, $transparent);
}
}
elseif ($image->info['extension'] == 'png') {
imagealphablending($res, FALSE);
$transparency = imagecolorallocatealpha($res, 0, 0, 0, 127);
imagefill($res, 0, 0, $transparency);
imagealphablending($res, TRUE);
imagesavealpha($res, TRUE);
}
else {
imagefill($res, 0, 0, imagecolorallocate($res, 255, 255, 255));
}
return $res;
}
/**
* $sigma is currently unused for _gd_sharp_mask due to 3x3 convolution matrix limit.
* we should explore properly implementing sigma.
*/
function imageapi_gd_unsharp_mask($img, $radius, $sigma, $amount, $threshold) {
//////////////////////////////////////////////////////////////
////
//// Unsharp Mask for PHP - version 2.1.1
////
//// Unsharp mask algorithm by Torstein H�nsi 2003-07.
//// thoensi_at_netcom_dot_no.
//// Please leave this notice.
////
//////////////////////////////////////////////////////////////
// http://vikjavev.no/computing/ump.php
// $img is an image that is already created within php using
// imgcreatetruecolor. No url! $img must be a truecolor image.
// Attempt to calibrate the parameters to Photoshop:
if ($amount > 500) {
$amount = 500;
}
$amount = $amount * 0.016;
if ($radius > 50) {
$radius = 50;
}
$radius = $radius * 2;
if ($threshold > 255) {
$threshold = 255;
}
$radius = abs(round($radius));
// Only integers make sense.
if ($radius == 0) {
return $img;
imagedestroy($img);
break;
}
$w = imagesx($img);
$h = imagesy($img);
$img_canvas = imagecreatetruecolor($w, $h);
$img_blur = imagecreatetruecolor($w, $h);
// Gaussian blur matrix:
//
// 1 2 1
// 2 4 2
// 1 2 1
//
//////////////////////////////////////////////////
$matrix = array(
array(
1,
2,
1,
),
array(
2,
4,
2,
),
array(
1,
2,
1,
),
);
imagecopy($img_blur, $img, 0, 0, 0, 0, $w, $h);
imageconvolution($img_blur, $matrix, 16, 0);
if ($threshold > 0) {
// Calculate the difference between the blurred pixels and the original
// and set the pixels
for ($x = 0; $x < $w - 1; $x++) {
// each row
for ($y = 0; $y < $h; $y++) {
// each pixel
$rgb_orig = imagecolorat($img, $x, $y);
$r_orig = $rgb_orig >> 16 & 0xff;
$g_orig = $rgb_orig >> 8 & 0xff;
$b_orig = $rgb_orig & 0xff;
$rgb_blur = imagecolorat($img_blur, $x, $y);
$r_blur = $rgb_blur >> 16 & 0xff;
$g_blur = $rgb_blur >> 8 & 0xff;
$b_blur = $rgb_blur & 0xff;
// When the masked pixels differ less from the original
// than the threshold specifies, they are set to their original value.
$r_new = abs($r_orig - $r_blur) >= $threshold ? max(0, min(255, $amount * ($r_orig - $r_blur) + $r_orig)) : $r_orig;
$g_new = abs($g_orig - $g_blur) >= $threshold ? max(0, min(255, $amount * ($g_orig - $g_blur) + $g_orig)) : $g_orig;
$b_new = abs($b_orig - $b_blur) >= $threshold ? max(0, min(255, $amount * ($b_orig - $b_blur) + $b_orig)) : $b_orig;
if ($r_orig != $r_new || $g_orig != $g_new || $b_orig != $b_new) {
$pix_col = imagecolorallocate($img, $r_new, $g_new, $b_new);
imagesetpixel($img, $x, $y, $pix_col);
}
}
}
}
else {
for ($x = 0; $x < $w; $x++) {
// each row
for ($y = 0; $y < $h; $y++) {
// each pixel
$rgb_orig = imagecolorat($img, $x, $y);
$r_orig = $rgb_orig >> 16 & 0xff;
$g_orig = $rgb_orig >> 8 & 0xff;
$b_orig = $rgb_orig & 0xff;
$rgb_blur = imagecolorat($img_blur, $x, $y);
$r_blur = $rgb_blur >> 16 & 0xff;
$g_blur = $rgb_blur >> 8 & 0xff;
$b_blur = $rgb_blur & 0xff;
$r_new = $amount * ($r_orig - $r_blur) + $r_orig;
if ($r_new > 255) {
$r_new = 255;
}
elseif ($r_new < 0) {
$r_new = 0;
}
$g_new = $amount * ($g_orig - $g_blur) + $g_orig;
if ($g_new > 255) {
$g_new = 255;
}
elseif ($g_new < 0) {
$g_new = 0;
}
$b_new = $amount * ($b_orig - $b_blur) + $b_orig;
if ($b_new > 255) {
$b_new = 255;
}
elseif ($b_new < 0) {
$b_new = 0;
}
$rgb_new = ($r_new << 16) + ($g_new << 8) + $b_new;
imagesetpixel($img, $x, $y, $rgb_new);
}
}
}
imagedestroy($img_canvas);
imagedestroy($img_blur);
return $img;
}
Functions
Name | Description |
---|---|
imageapi_gd_create_tmp | Create a truecolor image preserving transparency from a provided image. |
imageapi_gd_imageapi_toolkit | Implementation of hook_imageapi_toolkit(). |
imageapi_gd_image_close | Save an image file to a destination. |
imageapi_gd_image_crop | Crop an image using the GD toolkit. |
imageapi_gd_image_desaturate | Convert an image resource to grayscale. |
imageapi_gd_image_open | Open an image file. |
imageapi_gd_image_resize | Scale an image to the specified size using GD. |
imageapi_gd_image_rotate | Rotate an image the given number of degrees. |
imageapi_gd_image_sharpen | |
imageapi_gd_settings_form | Settings form for the toolkit. |
imageapi_gd_unsharp_mask | $sigma is currently unused for _gd_sharp_mask due to 3x3 convolution matrix limit. we should explore properly implementing sigma. |