Additional Information |
1. Converting to Rounded
======================
function imageRoundedCopyResampled(&$dstimg, &$srcimg, $dstx, $dsty,
$srcx,
$srcy, $dstw, $dsth, $srcw, $srch,
$radius) {
# Resize the Source Image
$srcResized = imagecreatetruecolor($dstw, $dsth);
imagecopyresampled($srcResized, $srcimg, 0, 0, $srcx, $srcy,
$dstw, $dsth, $srcw, $srch);
# Copy the Body without corners
imagecopy($dstimg, $srcResized, $dstx+$radius, $dsty,
$radius, 0, $dstw-($radius*2), $dsth);
imagecopy($dstimg, $srcResized, $dstx, $dsty+$radius,
0, $radius, $dstw, $dsth-($radius*2));
# Create a list of iterations; array(array(X1, X2, CenterX,
CenterY), ...)
# Iterations in order are: Top-Left, Top-Right, Bottom-Left,
Bottom-Right
$iterations = array(
array(0, 0, $radius, $radius),
array($dstw-$radius, 0, $dstw-$radius, $radius),
array(0, $dsth-$radius, $radius, $dsth-$radius),
array($dstw-$radius, $dsth-$radius, $dstw-$radius, $dsth-
$radius)
);
# Loop through each corner 'iteration'
foreach($iterations as $iteration) {
list($x1,$y1,$cx,$cy) = $iteration;
for ($y=$y1; $y<=$y1+$radius; $y++) {
for ($x=$x1; $x<=$x1+$radius; $x++) {
# If length (X,Y)->(CX,CY) is less then radius draw
the point
$length = sqrt(pow(($cx - $x), 2) + pow(($cy - $y),
2));
if ($length < $radius) {
imagecopy($dstimg, $srcResized, $x+$dstx, $y+
$dsty,
$x, $y, 1, 1);
}
}
}
}
}
could be a better solution, which does this:
- draws white square based on source image dimensions
- cuts circle from the midle
- places original image under prepared image so only image part, that fits the hole is visible
This approach will use standard GD function, like "imagefilledellipse" and
so on.
2. Converting to Grayscale
======================
$source_file = "test_image.jpg";
$im = ImageCreateFromJpeg($source_file);
$imgw = imagesx($im);
$imgh = imagesy($im);
for ($i=0; $i<$imgw; $i++)
{
for ($j=0; $j<$imgh; $j++)
{
// get the rgb value for current pixel
$rgb = ImageColorAt($im, $i, $j);
// extract each value for r, g, b
$rr = ($rgb >> 16) & 0xFF;
$gg = ($rgb >> 8) & 0xFF;
$bb = $rgb & 0xFF;
// get the Value from the RGB value
$g = round(($rr + $gg + $bb) / 3);
// grayscale values have r=g=b=g
$val = imagecolorallocate($im, $g, $g, $g);
// set the gray value
imagesetpixel ($im, $i, $j, $val);
}
}
header('Content-type: image/jpeg');
imagejpeg($im); |
Attached Files |
rounded_grayscale_images.patch [^] (9,060 bytes) 2010-05-06 15:15
[Show Content]
Index: core/units/images/image_tag_processor.php
===================================================================
--- core/units/images/image_tag_processor.php (revision 13488)
+++ core/units/images/image_tag_processor.php (working copy)
@@ -306,7 +306,19 @@
$max_width = (is_null($max_height) ? $max_width : $resize_format) . ';wm:' . $watermark;
$max_height = null;
}
-
+
+ $grayscale = $this->SelectParam($params, 'Grayscale,grayscale');
+ if ($grayscale) {
+ $max_width = (is_null($max_height) ? $max_width : $resize_format) . ';grayscale';
+ $max_height = null;
+ }
+
+ $rounded = $this->SelectParam($params, 'Rounded,rounded');
+ if ($rounded) {
+ $max_width = (is_null($max_height) ? $max_width : $resize_format) . ';rounded:' . $rounded;
+ $max_height = null;
+ }
+
return Array ($max_width, $max_height);
}
@@ -389,7 +401,7 @@
* @return string
*/
function Image($params)
- {
+ {
$image_url = $this->ImageSrc($params);
if (!$image_url) {
return ;
Index: core/units/helpers/image_helper.php
===================================================================
--- core/units/helpers/image_helper.php (revision 13488)
+++ core/units/helpers/image_helper.php (working copy)
@@ -46,10 +46,20 @@
}
elseif (preg_match('/fill:(.*)/', $format_part, $regs)) {
$res['fill'] = $regs[1];
- } elseif (preg_match('/default:(.*)/', $format_part, $regs)) {
+ }
+ elseif ($format_part == 'grayscale') {
+ $res['grayscale'] = 'grayscale';
+ }
+ elseif (preg_match('/rounded:([^\|]*)\|([^\|]*)/', $format_part, $regs)) {
+ $res['rounded_radius'] = strtolower($regs[1]);
+ $res['rounded_color'] = strtolower($regs[2]);
+ }
+ elseif (preg_match('/default:(.*)/', $format_part, $regs)) {
$res['default'] = FULL_PATH.THEMES_PATH.'/'.$regs[1];
}
}
+
+
return $res;
}
@@ -65,21 +75,21 @@
function ResizeImage($src_image, $max_width, $max_height = null)
{
$image_size = false;
-
+
if(isset($max_height)) {
$params['max_height'] = $max_height;
- $params['max_width'] = $max_width;
+ $params['max_width'] = $max_width;
}
else {
$params = $this->parseFormat($max_width);
-
+
if (array_key_exists('image_size', $params)) {
// image_size param shouldn't affect resized file name (crc part)
$image_size = $params['image_size'];
unset($params['image_size']);
}
}
-
+
if ((!$src_image || !file_exists($src_image)) && array_key_exists('default', $params)) {
$src_image = $params['default'];
}
@@ -96,7 +106,7 @@
}
$src_path = dirname($src_image);
- $transform_keys = Array ('crop_x', 'crop_y', 'fill', 'wm_filename');
+ $transform_keys = Array ('crop_x', 'crop_y', 'fill', 'wm_filename', 'grayscale', 'rounded_radius');
if ($needs_resize || array_intersect(array_keys($params), $transform_keys)) {
// resize required OR watermarking required -> change resulting image name !
@@ -190,10 +200,20 @@
$dst_image_rs =& $this->_applyFill($dst_image_rs, $params);
$watermark_size = 'max';
}
+
+ // 3. make rounded corners or circled
+ if (array_key_exists('rounded_radius', $params)) {
+ $dst_image_rs =& $this->_makeRounded($dst_image_rs, $params['rounded_radius'], $params['rounded_color']);
+ }
+
+ // 4. apply grayscale
+ if (array_key_exists('grayscale', $params)) {
+ $dst_image_rs =& $this->_applyGrayscale($dst_image_rs);
+ }
- // 3. apply watermark
+ // 5. apply watermark
$dst_image_rs =& $this->_applyWatermark($dst_image_rs, $params[$watermark_size . '_width'], $params[$watermark_size . '_height'], $params);
-
+
return @$write_function($dst_image_rs, $params['dst_image'], 100);
}
}
@@ -206,6 +226,136 @@
return false;
}
+
+ /**
+ * Make image Rounded
+ *
+ * @param resource $src_image_rs resized image resource
+ * @param string $input_radius radius in 100x100 (for circled) or 100 (for rounded) format in percent or pixelsi
+ * @param string $input_color color in RGB format
+ * @return resource $src_image_rs
+ */
+ function &_makeRounded(&$src_image_rs, $input_radius, $input_color)
+ {
+ $source_width = imagesx($src_image_rs);
+ $source_height = imagesy($src_image_rs);
+
+ // determine type of effect (rounded or circled) and calculate radiuses
+ $input_radius = explode('x', $input_radius);
+
+ if ($input_radius[0] && isset($input_radius[1])) {
+ // doing circled image
+ $image_effect_type = 'circled';
+
+ if (substr($input_radius[0], -1) == '%') {
+ // radius defined in percentage prepare and calculate
+ $input_radius[0] = (int)str_replace('%', '', $input_radius[0]);
+ $input_radius[0] = ($input_radius[0] > 100) ? 100 : $input_radius[0];
+ $input_radius[1] = (int)str_replace('%', '', $input_radius[1]);
+ $input_radius[1] = ($input_radius[1] > 100) ? 100 : $input_radius[1];
+ $radius['x'] = floor($source_width * ($input_radius[0] / 100) -1); // -1 pixel for better circle results
+ $radius['y'] = floor($source_height * ($input_radius[1] / 100) -1);
+ }
+ else {
+ // radius defined in pixels
+ $radius['x'] = (int)$input_radius[0];
+ $radius['y'] = (int)$input_radius[1];
+ }
+ $mask_size['x'] = $source_width;
+ $mask_size['y'] = $source_height;
+ }
+ else {
+ // doing rounded corners image
+ $image_effect_type = 'rounded';
+ $radius = (int)$input_radius[0];
+ $mask_size['x'] = $mask_size['y'] = $radius;
+ }
+
+ // remove # from color
+ $input_color = substr($input_color, 1);
+
+ // convert input color to RGB
+ $color['r'] = hexdec( substr( $input_color, 0, 2 ) );
+ $color['g'] = hexdec( substr( $input_color, 2, 4 ) );
+ $color['b'] = hexdec( substr( $input_color, 4, 2 ) );
+
+ // create main mask image
+ $mask_image = imagecreatetruecolor( $mask_size['x'], $mask_size['y'] );
+ imageantialias( $mask_image, true );
+
+ // define solid and clear colors
+ $solid_color = imagecolorallocate( $mask_image, $color['r'], $color['g'], $color['b']);
+ $clear_color = imagecolorallocate( $mask_image, 255 - $color['r'], 255 - $color['g'], 255 - $color['b']);
+
+ // prepare mask image - define transperent color, fill with solid color, draw eclipse with transperent color
+ imagecolortransparent( $mask_image, $clear_color );
+ imagefill( $mask_image, 0, 0, $solid_color );
+
+ if ($image_effect_type == 'rounded') {
+ // create mask ellipse image for top-left corner in memory
+ imagefilledellipse( $mask_image, $radius, $radius, $radius * 2, $radius * 2, $clear_color );
+
+ // render top-left corner by copying the mask
+ imagecopymerge( $src_image_rs, $mask_image, 0, 0, 0, 0, $radius, $radius, 100 );
+
+ // render bottom-left corner by rotating and copying the mask
+ $mask_image = imagerotate( $mask_image, 90, 0 );
+ imagecopymerge( $source_image, $mask_image, 0, $source_height - $radius, 0, 0, $radius, $radius, 100 );
+
+ // render bottom-right corner by rotating and copying the mask
+ $mask_image = imagerotate( $mask_image, 90, 0 );
+ imagecopymerge( $src_image_rs, $mask_image, $source_width - $radius, $source_height - $radius, 0, 0, $radius, $radius, 100 );
+
+ // render btop-right corner by rotating and copying the mask
+ $mask_image = imagerotate( $mask_image, 90, 0 );
+ imagecopymerge( $src_image_rs, $mask_image, $source_width - $radius, 0, 0, 0, $radius, $radius, 100 );
+ }
+ else {
+ // create mask ellipse image
+ imagefilledellipse( $mask_image, floor($source_width / 2), floor($source_height / 2), $radius['x'], $radius['y'], $clear_color );
+
+ // copying the mask over the source image
+ imagecopymerge( $src_image_rs, $mask_image, 0, 0, 0, 0, $mask_size['x'], $mask_size['y'], 100 );
+ }
+
+ return $src_image_rs;
+ }
+
+ /**
+ * Converts image to Grayscale
+ *
+ * @param resource $src_image_rs resized image resource
+ * @return resource $src_image_rs
+ */
+ function &_applyGrayscale(&$src_image_rs)
+ {
+ $imgw = imagesx($src_image_rs);
+ $imgh = imagesy($src_image_rs);
+
+ for ($i = 0; $i < $imgw; $i++) {
+ for ($j = 0; $j < $imgh; $j++) {
+ // get the rgb value for current pixel
+ $rgb = ImageColorAt($src_image_rs, $i, $j);
+
+ // extract each value for r, g, b
+ $rr = ($rgb >> 16) & 0xFF;
+ $gg = ($rgb >> 8) & 0xFF;
+ $bb = $rgb & 0xFF;
+
+ // get the Value from the RGB value
+ $g = round(($rr + $gg + $bb) / 3);
+
+ // grayscale values have r=g=b=g
+ $val = imagecolorallocate($src_image_rs, $g, $g, $g);
+
+ // set the gray value
+ imagesetpixel($src_image_rs, $i, $j, $val);
+ }
+ }
+
+ return $src_image_rs;
+ }
+
/**
* Preserve transparency for GIF and PNG images
radius_grayscale_image.patch [^] (9,424 bytes) 2010-05-20 12:09
[Show Content]
Index: helpers/image_helper.php
===================================================================
--- helpers/image_helper.php (revision 13557)
+++ helpers/image_helper.php (working copy)
@@ -46,9 +46,22 @@
}
elseif (preg_match('/fill:(.*)/', $format_part, $regs)) {
$res['fill'] = $regs[1];
- } elseif (preg_match('/default:(.*)/', $format_part, $regs)) {
+ }
+ elseif ($format_part == 'grayscale') {
+ $res['grayscale'] = true;
+ }
+ elseif (preg_match('/corner_radius:(\d*)/', $format_part, $regs)) {
+ $res['corner_radius'] = strtolower($regs[1]);
+ }
+ elseif (preg_match('/ellipse_radius:(.*)/', $format_part, $regs)) {
+ $res['ellipse_radius'] = strtolower($regs[1]);
+ }
+ elseif (preg_match('/default:(.*)/', $format_part, $regs)) {
$res['default'] = FULL_PATH.THEMES_PATH.'/'.$regs[1];
}
+ else {
+ trigger_error('Unknown format part "<strong>' . $format_part . '</strong>".', E_USER_ERROR);
+ }
}
return $res;
@@ -96,7 +109,7 @@
}
$src_path = dirname($src_image);
- $transform_keys = Array ('crop_x', 'crop_y', 'fill', 'wm_filename');
+ $transform_keys = Array ('crop_x', 'crop_y', 'fill', 'wm_filename', 'grayscale', 'corner_radius', 'ellipse_radius');
if ($needs_resize || array_intersect(array_keys($params), $transform_keys)) {
// resize required OR watermarking required -> change resulting image name !
@@ -191,7 +204,24 @@
$watermark_size = 'max';
}
- // 3. apply watermark
+ // 3. make circled
+ if (array_key_exists('ellipse_radius', $params)) {
+ $fill_color = array_key_exists('fill', $params) ? $params['fill'] : '#FFFFFF';
+ $this->_makeEllipse($dst_image_rs, $params['ellipse_radius'], $fill_color);
+ }
+
+ // 4. make rounded corners
+ if (array_key_exists('corner_radius', $params)) {
+ $fill_color = array_key_exists('fill', $params) ? $params['fill'] : '#FFFFFF';
+ $this->_makeRoundedCorners($dst_image_rs, $params['corner_radius'], $fill_color);
+ }
+
+ // 5. apply grayscale
+ if (array_key_exists('grayscale', $params)) {
+ $this->_applyGrayscale($dst_image_rs);
+ }
+
+ // 6. apply watermark
$dst_image_rs =& $this->_applyWatermark($dst_image_rs, $params[$watermark_size . '_width'], $params[$watermark_size . '_height'], $params);
if ($write_function == 'imagegif') {
@@ -212,6 +242,163 @@
}
/**
+ * Makes rounded corners
+ *
+ * @param resource $src_image_rs
+ * @param int $radius
+ * @param string $fill_color
+ */
+ function _makeRoundedCorners(&$src_image_rs, $radius, $fill_color)
+ {
+ $fill_color = $this->_colorFromString($fill_color);
+
+ if ($fill_color === false) {
+ return false;
+ }
+
+ $source_width = imagesx($src_image_rs);
+ $source_height = imagesy($src_image_rs);
+ $mask_image_rs =& $this->getMaskImage($radius, $radius, $fill_color);
+ $transparent_color = imagecolorallocate($mask_image_rs, 255 - $fill_color[0], 255 - $fill_color[1], 255 - $fill_color[2]);
+
+ // create mask ellipse image for top-left corner in memory
+ imagefilledellipse($mask_image_rs, $radius, $radius, $radius * 2, $radius * 2, $transparent_color);
+
+ // render top-left corner by copying the mask
+ imagecopymerge($src_image_rs, $mask_image_rs, 0, 0, 0, 0, $radius, $radius, 100);
+
+ // render bottom-left corner by rotating and copying the mask
+ $mask_image = imagerotate($mask_image_rs, 90, 0);
+ imagecopymerge($src_image_rs, $mask_image_rs, 0, $source_height - $radius, 0, 0, $radius, $radius, 100);
+
+ // render bottom-right corner by rotating and copying the mask
+ $mask_image = imagerotate($mask_image_rs, 90, 0);
+ imagecopymerge($src_image_rs, $mask_image_rs, $source_width - $radius, $source_height - $radius, 0, 0, $radius, $radius, 100);
+
+ // render top-right corner by rotating and copying the mask
+ $mask_image = imagerotate($mask_image_rs, 90, 0);
+ imagecopymerge($src_image_rs, $mask_image_rs, $source_width - $radius, 0, 0, 0, $radius, $radius, 100);
+ }
+
+ /**
+ * Make circled or ellipsed image
+ *
+ * @param resource $src_image_rs
+ * @param string $radius
+ * @param string $fill_color
+ */
+ function _makeEllipse(&$src_image_rs, $radius, $fill_color)
+ {
+ $fill_color = $this->_colorFromString($fill_color);
+
+ if ($fill_color === false) {
+ return false;
+ }
+
+ $source_width = imagesx($src_image_rs);
+ $source_height = imagesy($src_image_rs);
+ $mask_image_rs =& $this->getMaskImage($source_width, $source_height, $fill_color);
+ $transparent_color = imagecolorallocate($mask_image_rs, 255 - $fill_color[0], 255 - $fill_color[1], 255 - $fill_color[2]);
+
+ // process case when different/same radius for X and Y axis used
+ if (strpos($radius, 'x') !== false) {
+ list ($x_radius, $y_radius) = explode('x', $radius, 2);
+ }
+ else {
+ $x_radius = $y_radius = $radius;
+ }
+
+ // -1 pixel for better circle results
+ if (substr($x_radius, -1) == '%') {
+ $x_radius = min( (int)substr($x_radius, 0, -1), 100 );
+ $x_radius = floor($source_width * ($x_radius / 100) - 1);
+ }
+
+ if (substr($y_radius, -1) == '%') {
+ $y_radius = min( (int)substr($y_radius, 0, -1), 100 );
+ $y_radius = floor($source_height * ($y_radius / 100) - 1);
+ }
+
+ // create mask ellipse image
+ imagefilledellipse($mask_image_rs, floor($source_width / 2), floor($source_height / 2), $x_radius, $y_radius, $transparent_color);
+
+ // copying the mask over the source image
+ imagecopymerge($src_image_rs, $mask_image_rs, 0, 0, 0, 0, $source_width, $source_height, 100);
+ }
+
+ /**
+ * Returns RGB component of given color string
+ *
+ * @param string $string
+ * @return Array
+ */
+ function _colorFromString($string)
+ {
+ if (preg_match('/^#(.*){2}(.*){2}(.*){2}$/', $string, $regs)) {
+ array_shift($regs);
+ return array_map('hexdec', $regs);
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns mask image if given size and color
+ *
+ * @param int $width
+ * @param int $height
+ * @param Array $color
+ * @return resource
+ */
+ function &getMaskImage($width, $height, $color)
+ {
+ // create mask image
+ $mask_image_rs = imagecreatetruecolor($width, $height);
+ imageantialias($mask_image_rs, true);
+
+ // define fill and transparent colors
+ $fill_color = imagecolorallocate($mask_image_rs, $color[0], $color[1], $color[2]);
+ $transparent_color = imagecolorallocate($mask_image_rs, 255 - $color[0], 255 - $color[1], 255 - $color[2]);
+
+ imagecolortransparent($mask_image_rs, $transparent_color);
+ imagefill($mask_image_rs, 0, 0, $fill_color);
+
+ return $mask_image_rs;
+ }
+
+ /**
+ * Converts image to grayscale
+ *
+ * @param resource $src_image_rs resized image resource
+ */
+ function _applyGrayscale(&$src_image_rs)
+ {
+ $width = imagesx($src_image_rs);
+ $height = imagesy($src_image_rs);
+
+ for ($i = 0; $i < $width; $i++) {
+ for ($j = 0; $j < $height; $j++) {
+ // get the rgb value for current pixel
+ $rgb = imagecolorat($src_image_rs, $i, $j);
+
+ // extract each value for r, g, b
+ $rr = ($rgb >> 16) & 0xFF;
+ $gg = ($rgb >> 8) & 0xFF;
+ $bb = $rgb & 0xFF;
+
+ // get the Value from the RGB value
+ $g = round(($rr + $gg + $bb) / 3);
+
+ // grayscale values have r=g=b=g
+ $val = imagecolorallocate($src_image_rs, $g, $g, $g);
+
+ // set the gray value
+ imagesetpixel($src_image_rs, $i, $j, $val);
+ }
+ }
+ }
+
+ /**
* Preserve transparency for GIF and PNG images
*
* @param resource $src_image_rs
@@ -275,15 +462,15 @@
$fill = $params['fill'];
- if (substr($fill, 0, 1) == '#') {
- // hexdecimal color
- $color = imagecolorallocate($fill_image_rs, hexdec( substr($fill, 1, 2) ), hexdec( substr($fill, 3, 2) ), hexdec( substr($fill, 5, 2) ));
- }
- else {
+ $color = $this->_colorFromString($fill);
+
+ if ($color === false) {
// for now we don't support color names, but we will in future
return $src_image_rs;
}
+ $color = imagecolorallocate($fill_image_rs, $color[0], $color[1], $color[2]);
+
imagefill($fill_image_rs, 0, 0, $color);
imagecopy($fill_image_rs, $src_image_rs, $x_position, $y_position, 0, 0, $params['target_width'], $params['target_height']);
Index: images/image_tag_processor.php
===================================================================
--- images/image_tag_processor.php (revision 13557)
+++ images/image_tag_processor.php (working copy)
@@ -339,6 +339,24 @@
$max_height = null;
}
+ $grayscale = $this->SelectParam($params, 'Grayscale,grayscale');
+ if ($grayscale) {
+ $max_width = (is_null($max_height) ? $max_width : $resize_format) . ';grayscale';
+ $max_height = null;
+ }
+
+ $corner_radius = $this->SelectParam($params, 'CornerRadius,corner_radius');
+ if ($corner_radius) {
+ $max_width = (is_null($max_height) ? $max_width : $resize_format) . ';corner_radius:' . $corner_radius;
+ $max_height = null;
+ }
+
+ $ellipse_radius = $this->SelectParam($params, 'EllipseRadius,ellipse_radius');
+ if ($ellipse_radius) {
+ $max_width = (is_null($max_height) ? $max_width : $resize_format) . ';ellipse_radius:' . $ellipse_radius;
+ $max_height = null;
+ }
+
return Array ($max_width, $max_height);
}
|