Image_Tools
[ class tree: Image_Tools ] [ index: Image_Tools ] [ all elements ]

Source for file Blend.php

Documentation is available at Blend.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker */
  3.  
  4. /**
  5.  * Image_Tools_Blend
  6.  *
  7.  * PHP version 4 and 5
  8.  *
  9.  * LICENSE:
  10.  * Copyright (c) 2008 Firman Wandayandi <firman@php.net>
  11.  *
  12.  * This source file is subject to the BSD License license that is bundled
  13.  * with this package in the file LICENSE.txt.
  14.  * It is also available through the world-wide-web at this URL:
  15.  * http://www.opensource.org/licenses/bsd-license.php
  16.  * If you did not receive a copy of the license and are unable to
  17.  * obtain it through the world-wide-web, please send an email
  18.  * to pear-dev@list.php.net so we can send you a copy immediately.
  19.  *
  20.  * @category    Images
  21.  * @package     Image_Tools
  22.  * @author      Firman Wandayandi <firman@php.net>
  23.  * @copyright   Copyright (c) 2008 Firman Wandayandi <firman@php.net>
  24.  * @license     http://www.opensource.org/licenses/bsd-license.php
  25.  *               BSD License
  26.  * @version     $Id: Blend.php,v 1.3 2008/05/26 09:31:23 firman Exp $
  27.  * @since       File available since Release 1.0.0RC1
  28.  */
  29.  
  30. /**
  31.  * Image_Tools
  32.  */
  33. require_once 'Image/Tools.php';
  34.  
  35. /**
  36.  * Image_Tools_Utils
  37.  */
  38. require_once 'Image/Tools/Utils.php';
  39.  
  40. /**
  41.  * Class provide image blending functions.
  42.  *
  43.  * Algorithms base on article http://www.pegtop.net/delphi/articles/blendmodes
  44.  * written by Jens Gruschel.
  45.  *
  46.  * @category    Images
  47.  * @package     Image_Tools
  48.  * @author      Firman Wandayandi <firman@php.net>
  49.  * @copyright   Copyright (c) 2008 Firman Wandayandi <firman@php.net>
  50.  * @license     http://www.opensource.org/licenses/bsd-license.php
  51.  *               BSD License
  52.  * @version     Release: 1.0.0RC1
  53.  * @since       Class available since Release 1.0.0RC1
  54.  */
  55. {
  56.     /**
  57.      * Image_Tools_Thumbnail API version.
  58.      *
  59.      * @var     string 
  60.      * @access  protected
  61.      */
  62.     var $version = '0.1';
  63.  
  64.     /**
  65.      * Blend options:
  66.      * <pre>
  67.      * image1   mixed   First image or destination or background
  68.      * image2   mixed   Second image or sample or foreground
  69.      * mode     string  Blend mode, may one of normal, multiply,
  70.      *                  screen, darken, lighten, difference, exclusion,
  71.      *                  negation, interpolation, stamp, softlight, hardlight,
  72.      *                  overlay, colordodge, colorburn, softdodge, softburn,
  73.      *                  additive, subtractive, reflect, glow, freeze, heat,
  74.      *                  logicXOR, logicAND or logicOR
  75.      * x        int     X position of the second image on the first image
  76.      * y        int     Y position of the second image on the first image
  77.      * </pre>
  78.      *
  79.      * @var array 
  80.      * @access protected
  81.      */
  82.     var $options = array(
  83.         'image1' => null,
  84.         'image2' => null,
  85.         'mode'   => 'normal',
  86.         'x'      => 0,
  87.         'y'      => 0,
  88.         'params' => array()
  89.     );
  90.  
  91.     /**
  92.      * Available options.
  93.      *
  94.      * @var array 
  95.      * @access protected
  96.      * @see Image_Tools_Utils::$options
  97.      */
  98.     var $availableOptions = array(
  99.         'image1'    => 'mixed',
  100.         'image2'    => 'mixed',
  101.         'mode'      => 'string',
  102.         'x'         => 'integer',
  103.         'y'         => 'integer',
  104.         'params'    => 'array'
  105.     );
  106.  
  107.     /**
  108.      * First image resource.
  109.      *
  110.      * @var resource 
  111.      * @access private
  112.      */
  113.     var $_image1;
  114.  
  115.     /**
  116.      * Second image resource.
  117.      *
  118.      * @var resource 
  119.      * @access private
  120.      */
  121.     var $_image2;
  122.  
  123.     /**
  124.      * Cosine table for interpolation mode.
  125.      *
  126.      * @var array 
  127.      * @access private
  128.      * @see Image_Tools_Utils::interpolation()
  129.      */
  130.     var $_cosineTab = array();
  131.  
  132.     /**
  133.      * Function which called before render.
  134.      *
  135.      * @return  bool|PEAR_ErrorTRUE on success or PEAR_Error on failure.
  136.      * @access  protected
  137.      * @see     Image_Tools::createImage()
  138.      */
  139.     function preRender()
  140.     {
  141.         $res Image_Tools::createImage($this->options['image1']);
  142.         if (PEAR::isError($res)) {
  143.             return $res;
  144.         }
  145.         $this->_image1 $res;
  146.  
  147.         $res Image_Tools::createImage($this->options['image2']);
  148.         if (PEAR::isError($res)) {
  149.             return $res;
  150.         }
  151.         $this->_image2 $res;
  152.  
  153.         // initialize an array if only its interpolation mode
  154.         if ($this->options['mode'== 'interpolation'{
  155.             for ($i = 0; $i < 256; $i++{
  156.                 $this->cosineTab[= (int) (round(64 - cos($i * M_PI / 255* 64));
  157.             }
  158.         }
  159.  
  160.         return true;
  161.     }
  162.  
  163.     /**
  164.      * Apply the blend mode.
  165.      *
  166.      * @return true|PEAR_Error
  167.      * @access protected
  168.      */
  169.     function render()
  170.     {
  171.         $method = array($this"_{$this->options['mode']}");
  172.         if (!is_callable($method)) {
  173.             return PEAR::raiseError('Invalid mode or not supported');
  174.         }
  175.  
  176.         $width1 imagesx($this->_image1);
  177.         $height1 imagesy($this->_image1);
  178.         $width imagesx($this->_image2);
  179.         $height imagesy($this->_image2);
  180.  
  181.         // sets out of bound flags
  182.         $x_outbound $y_outbound = false;
  183.  
  184.         // walking through pixels
  185.         for ($x2 = 0$x1 $this->options['x']$x2 $width$x2++$x1++{
  186.             // x and y already out of bound, nothing to process
  187.             if ($x_outbound && $y_outbound{
  188.                 break;
  189.             }
  190.  
  191.             $x_outbound $y_outbound = false;
  192.  
  193.             // x is out bound
  194.             if ($x1 >= $width1{
  195.                 $x_outbound = true;
  196.                 continue;
  197.             }
  198.  
  199.             for ($y2 = 0$y1 $this->options['y']$y2 $height$y2++$y1++{
  200.                 // y is out bound
  201.                 if ($y1 >= $height1{
  202.                     $y_outbound = true;
  203.                     continue;
  204.                 }
  205.  
  206.                 $color1 Image_Tools_Utils::colorToRGBA(imagecolorat($this->_image1$x1$y1));
  207.                 $color2 Image_Tools_Utils::colorToRGBA(imagecolorat($this->_image2$x2$y2));
  208.  
  209.                 // ignore transparencies
  210.                 if ($color2['a'== 127{
  211.                     continue;
  212.                 }
  213.  
  214.                 $params array_merge(array($color1['r']$color2['r'])$this->options['params']);
  215.                 $red call_user_func_array($method$params);
  216.  
  217.                 $params array_merge(array($color1['g']$color2['g'])$this->options['params']);
  218.                 $green call_user_func_array($method$params);
  219.  
  220.                 $params array_merge(array($color1['b']$color2['b'])$this->options['params']);
  221.                 $blue call_user_func_array($method$params);
  222.  
  223.                 $color imagecolorallocatealpha($this->_image1$red$green$blue$color2['a']);
  224.                 imagesetpixel($this->_image1$x1$y1$color);
  225.             }
  226.         }
  227.  
  228.         $this->resultImage = $this->_image1;
  229.  
  230.         // frees up memory
  231.         imagedestroy($this->_image2);
  232.  
  233.         return true;
  234.     }
  235.  
  236.     /**
  237.      * Normal blend mode.
  238.      *
  239.      * @param integer $a Background color (0 to 255)
  240.      * @param integer $b Foreground color (0 to 255)
  241.      * @return integer 
  242.      * @access private
  243.      */
  244.     function _normal($a$b)
  245.     {
  246.         return $b;
  247.     }
  248.  
  249.     /**
  250.      * Multiply blend mode.
  251.      *
  252.      * @param integer $a Background color (0 to 255)
  253.      * @param integer $b Foreground color (0 to 255)
  254.      * @return integer 
  255.      * @access private
  256.      */
  257.     function _multiply($a$b)
  258.     {
  259.         return (int)($a $b / 255);
  260.     }
  261.  
  262.     /**
  263.      * Screen blend mode.
  264.      *
  265.      * @param integer $a Background color (0 to 255)
  266.      * @param integer $b Foreground color (0 to 255)
  267.      * @return integer 
  268.      * @access private
  269.      */
  270.     function _screen($a$b)
  271.     {
  272.         return (int)(255 - ((255 - $a(255 - $b/ 255));
  273.     }
  274.  
  275.     /**
  276.      * Darken blend mode.
  277.      *
  278.      * @param integer $a Background color (0 to 255)
  279.      * @param integer $b Foreground color (0 to 255)
  280.      * @return integer 
  281.      * @access private
  282.      */
  283.     function _darken($a$b)
  284.     {
  285.         if ($a $b{
  286.             return $a;
  287.         }
  288.         return $b;
  289.     }
  290.  
  291.     /**
  292.      * Lighten blend mode.
  293.      *
  294.      * @param integer $a Background color (0 to 255)
  295.      * @param integer $b Foreground color (0 to 255)
  296.      * @return integer 
  297.      * @access private
  298.      */
  299.     function _lighten($a$b)
  300.     {
  301.         if ($a $b{
  302.             return $a;
  303.         }
  304.         return $b;
  305.     }
  306.  
  307.     /**
  308.      * Difference blend mode.
  309.      *
  310.      * @param integer $a Background color (0 to 255)
  311.      * @param integer $b Foreground color (0 to 255)
  312.      * @return integer 
  313.      * @access private
  314.      */
  315.     function _difference($a$b)
  316.     {
  317.         return abs($a $b);
  318.     }
  319.  
  320.     /**
  321.      * Exclusion blend mode.
  322.      *
  323.      * @param integer $a Background color (0 to 255)
  324.      * @param integer $b Foreground color (0 to 255)
  325.      * @return integer 
  326.      * @access private
  327.      */
  328.     function _exclusion($a$b)
  329.     {
  330.         return (int)($a $b ($a $b / 127));
  331.     }
  332.  
  333.     /**
  334.      * Negation blend mode.
  335.      *
  336.      * @param integer $a Background color (0 to 255)
  337.      * @param integer $b Foreground color (0 to 255)
  338.      * @return integer 
  339.      * @access private
  340.      */
  341.     function _negation($a$b)
  342.     {
  343.         return 255 - abs(255 - $a $b);
  344.     }
  345.  
  346.     /**
  347.      * Interpolation blend mode.
  348.      *
  349.      * @param integer $a Background color (0 to 255)
  350.      * @param integer $b Foreground color (0 to 255)
  351.      * @return integer 
  352.      * @access private
  353.      */
  354.     function _interpolation($a$b)
  355.     {
  356.         $c $this->cosineTab[$b$this->cosineTab[$a];
  357.         if ($c > 255{
  358.             return 255;
  359.         else {
  360.             return $c;
  361.         }
  362.     }
  363.  
  364.     /**
  365.      * Stamp blend mode.
  366.      *
  367.      * @param integer $a Background color (0 to 255)
  368.      * @param integer $b Foreground color (0 to 255)
  369.      * @return integer 
  370.      * @access private
  371.      */
  372.     function _stamp($a$b)
  373.     {
  374.         $c $a + 2*$b - 256;
  375.         if ($c < 0{
  376.             return 0;
  377.         else if ($c > 255{
  378.             return 255;
  379.         else {
  380.             return $c;
  381.         }
  382.     }
  383.  
  384.     /**
  385.      * Soft Light blend mode.
  386.      *
  387.      * @param integer $a Background color (0 to 255)
  388.      * @param integer $b Foreground color (0 to 255)
  389.      * @return integer 
  390.      * @access private
  391.      */
  392.     function _softlight($a$b)
  393.     {
  394.         $c = (int)($a $b / 255);
  395.         return (int)($c $a (255 - ((255-$a(255-$b/ 255$c/ 255);
  396.     }
  397.  
  398.     /**
  399.      * Hard Light blend mode.
  400.      *
  401.      * @param integer $a Background color (0 to 255)
  402.      * @param integer $b Foreground color (0 to 255)
  403.      * @return integer 
  404.      * @access private
  405.      */
  406.     function _hardlight($a$b)
  407.     {
  408.         if ($b < 127{
  409.             $result ($a*$b/ 127;
  410.         else {
  411.             $result = 255 - ((255-$b(255-$a/ 127);
  412.         }
  413.         return (int) $result;
  414.     }
  415.  
  416.     /**
  417.      * Overlay blend mode.
  418.      *
  419.      * @param integer $a Background color (0 to 255)
  420.      * @param integer $b Foreground color (0 to 255)
  421.      * @return integer 
  422.      * @access private
  423.      */
  424.     function _overlay($a$b)
  425.     {
  426.         if ($a < 128{
  427.         $result $a $b / 127;
  428.         else {
  429.         $result = 255 - ((255 - $a(255 - $b/ 127);
  430.         }
  431.         return (int) $result;
  432.     }
  433.  
  434.     /**
  435.      * Color Dodge blend mode.
  436.      *
  437.      * @param integer $a Background color (0 to 255)
  438.      * @param integer $b Foreground color (0 to 255)
  439.      * @return integer 
  440.      * @access private
  441.      */
  442.     function _colordodge($a$b)
  443.     {
  444.         if ($b == 255{
  445.             return 255;
  446.         else {
  447.             $c = (int)(($a << 8(255-$b));
  448.             if ($c > 255{
  449.                 return 255;
  450.             else {
  451.                 return $c;
  452.             }
  453.         }
  454.     }
  455.  
  456.     /**
  457.      * Color Burn blend mode.
  458.      *
  459.      * @param integer $a Background color (0 to 255)
  460.      * @param integer $b Foreground color (0 to 255)
  461.      * @return integer 
  462.      * @access private
  463.      */
  464.     function _colorburn($a$b)
  465.     {
  466.         if ($b == 0{
  467.             return 0;
  468.         else {
  469.             $c = (int)(255 - (((255-$a<< 8$b));
  470.             if ($c < 0{
  471.                 return 0;
  472.             else {
  473.                 return $c;
  474.             }
  475.         }
  476.     }
  477.  
  478.     /**
  479.      * Soft Dodge blend mode.
  480.      *
  481.      * @param integer $a Background color (0 to 255)
  482.      * @param integer $b Foreground color (0 to 255)
  483.      * @return integer 
  484.      * @access private
  485.      */
  486.     function _softdodge($a$b)
  487.     {
  488.         if ($a $b < 256{
  489.             if ($b == 255{
  490.                 return 255;
  491.             else {
  492.                 $c = (int)(($a << 7(255-$b));
  493.                 if ($c > 255{
  494.                     return 255;
  495.                 else {
  496.                     return $c;
  497.                 }
  498.             }
  499.         else {
  500.             $c = (int)(255 - (((255-$b<< 7$a));
  501.             if ($c < 0{
  502.                 return 0;
  503.             else {
  504.                 return $c;
  505.             }
  506.         }
  507.     }
  508.  
  509.     /**
  510.      * Soft Burn blend mode.
  511.      *
  512.      * @param integer $a Background color (0 to 255)
  513.      * @param integer $b Foreground color (0 to 255)
  514.      * @return integer 
  515.      * @access private
  516.      */
  517.     function _softburn($a$b)
  518.     {
  519.         if ($a+$b < 256{
  520.             if ($a = 255{
  521.                 return 255;
  522.             else {
  523.                 $c = (int)(($b << 7(255-$a));
  524.                 if ($c > 255{
  525.                     return 255;
  526.                 else {
  527.                     return $c;
  528.                 }
  529.             }
  530.         else {
  531.             $c = (int)(255 - (((255-$a<< 7$b));
  532.             if ($c < 0{
  533.                 return 0;
  534.             else {
  535.                 return $c;
  536.             }
  537.         }
  538.     }
  539.  
  540.     /**
  541.      * Additive blend mode.
  542.      *
  543.      * @param integer $a Background color (0 to 255)
  544.      * @param integer $b Foreground color (0 to 255)
  545.      * @return integer 
  546.      * @access private
  547.      */
  548.     function _additive($a$b)
  549.     {
  550.         $c $a $b;
  551.         if ($c > 255{
  552.             return 255;
  553.         else {
  554.             return $c;
  555.         }
  556.     }
  557.  
  558.     /**
  559.      * Subtractive blend mode.
  560.      *
  561.      * @param integer $a Background color (0 to 255)
  562.      * @param integer $b Foreground color (0 to 255)
  563.      * @return integer 
  564.      * @access private
  565.      */
  566.     function _subtractive($a$b)
  567.     {
  568.         $c $a $b - 255;
  569.         if ($c < 0{
  570.             return 0;
  571.         else {
  572.             return $c;
  573.         }
  574.     }
  575.  
  576.     /**
  577.      * Reflect blend mode.
  578.      *
  579.      * @param integer $a Background color (0 to 255)
  580.      * @param integer $b Foreground color (0 to 255)
  581.      * @return integer 
  582.      * @access private
  583.      */
  584.     function _reflect($a$b)
  585.     {
  586.         if ($b == 255{
  587.             return 255;
  588.         else {
  589.             $c = (int)($a $a (255-$b));
  590.             if ($c > 255{
  591.                 return 255;
  592.             else {
  593.                 return $c;
  594.             }
  595.         }
  596.     }
  597.  
  598.     /**
  599.      * Glow blend mode.
  600.      *
  601.      * @param integer $a Background color (0 to 255)
  602.      * @param integer $b Foreground color (0 to 255)
  603.      * @return integer 
  604.      * @access private
  605.      */
  606.     function _glow($a$b)
  607.     {
  608.         if ($a == 255{
  609.             return 255;
  610.         else {
  611.             $c = (int)($b*$b (255-$a));
  612.             if ($c > 255{
  613.                 return 255;
  614.             else {
  615.                 return $c;
  616.             }
  617.         }
  618.     }
  619.  
  620.     /**
  621.      * Freeze blend mode.
  622.      *
  623.      * @param integer $a Background color (0 to 255)
  624.      * @param integer $b Foreground color (0 to 255)
  625.      * @return integer 
  626.      * @access private
  627.      */
  628.     function _freeze($a$b)
  629.     {
  630.         if ($b == 0{
  631.             return 0;
  632.         else {
  633.             $c = (int)(255 - sqrt(255-$a$b);
  634.             if ($c < 0{
  635.                 return 0;
  636.             else {
  637.                 return $c;
  638.             }
  639.         }
  640.     }
  641.  
  642.     /**
  643.      * Heat blend mode.
  644.      *
  645.      * @param integer $a Background color (0 to 255)
  646.      * @param integer $b Foreground color (0 to 255)
  647.      * @return integer 
  648.      * @access private
  649.      */
  650.     function _heat($a$b)
  651.     {
  652.         if ($a == 0{
  653.             return 0;
  654.         else {
  655.             $c = (int)(255 - sqrt(255-$b$a);
  656.             if ($c < 0{
  657.                 return 0;
  658.             else {
  659.                 return $c;
  660.             }
  661.         }
  662.     }
  663.  
  664.     /**
  665.      * Logic XOR blend mode.
  666.      *
  667.      * @param integer $a Background color (0 to 255)
  668.      * @param integer $b Foreground color (0 to 255)
  669.      * @return integer 
  670.      * @access private
  671.      */
  672.     function _logicXOR($a$b)
  673.     {
  674.         return $a $b;
  675.     }
  676.  
  677.     /**
  678.      * Logic AND blend mode.
  679.      *
  680.      * @param integer $a Background color (0 to 255)
  681.      * @param integer $b Foreground color (0 to 255)
  682.      * @return integer 
  683.      * @access private
  684.      */
  685.     function _logicAND($a$b)
  686.     {
  687.         return $a $b;
  688.     }
  689.  
  690.     /**
  691.      * Logic OR blend mode.
  692.      *
  693.      * @param integer $a Background color (0 to 255)
  694.      * @param integer $b Foreground color (0 to 255)
  695.      * @return integer 
  696.      * @access private
  697.      */
  698.     function _logicOR($a$b)
  699.     {
  700.         return $a $b;
  701.     }
  702. }

Documentation generated on Mon, 26 May 2008 06:30:06 -0400 by phpDocumentor 1.4.0. PEAR Logo Copyright © PHP Group 2004.