You do not have to have Mac machine and you do not have to join the Apple developer center, yet you can still develop apps for Apple’s i-devices. The following resources are great for beginners. The list will getting longer… …

HOWTO: Create native-looking iPhone/iPad applications from HTML, CSS and JavaScript
Written by Matthew Might
 
How to Make an HTML5 iPhone App
Written by Alex Kessinger
 
iPhone events
 
Detecting iPhone’s App Mode (Full Screen Mode) For Web Applications
Quick Note:  Since iPhone/iPod touch gave different window size  when running in app mode and web mode, detecting the running mode of your site is necessary to help you layout your application correctly. When you are in app mode, you have a screen size of 320×460. When you are in web mode, it has a screen size of 320×356.
 
Web Development for the iPhone
Creating native looking iPhone web apps with CSS3 (no images)
Implementing doubletap on iPhones and iPads
Simple drag n drop Javascript for iPhone and iPad
Using CSS3 Transitions, Transforms and Animation
TouchScroll, a scrolling layer for WebKit mobile

jQuery Mobile, a touch-optimized web framework for smartphones & tablets were released Alpha 3 version. If you want your site looks and feels just like an touch-based app when accessed through mobile device, this framework will ease a lot of your pain.  The framework “increased our A-Grade browser support to include Firefox Mobile (Fennec), Opera Mobile / Mini, and refined our support for iOS, Android, BlackBerry 6, Palm WebOS, and most modern desktop browser”.

image

With the help of this framework, you can now start developing native-look-like app for iPad/iPhone/iPod Touch without using Objective C++. Read this article on HOWTO: Create native-looking iPhone/iPad applications from HTML, CSS and JavaScript.

If you do not have iPhone/iPad to test your apps, you can configure Safari browser installed on your computer to act just like an mobile browser, here is how:  Using Safari for iPhone, iPad and iPod Touch Website Testing.

This is the continuation of my series regarding digital image blending algorithms. If you want to read other posts in this series, here is the list:

  1. Image Blending Algorithm–Part I
  2. Image Blending Algorithm–Part II

This post will bring in five more image blending algorithms: Darken, Lighten, Difference, Exclusion and Reflex.

Blending Mode: Darken

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    //
    // previous introduced blending modes will be skipped to save page space.
    // ....
    //
    //
    darken:  function(v1,v2){return Math.min(v1,v2);}
};

Now to apply the Darken blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"darken");

Blending Effect Screenshot taken from iPaintPro:

blending_darken
iPaintPro Image Blending: Darken
 
Blending Mode: Lighten

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    //
    // previous introduced blending modes will be skipped to save page space.
    // ....
    //
    //
    darken:  function(v1,v2){return Math.min(v1,v2);},
    lighten: function(v1,v2){return Math.max(v1,v2);}
};

Now to apply the Lighten blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"lighten");

Blending Effect Screenshot taken from iPaintPro:

blending_lighten
iPaintPro Image Blending: Lighten
Blending Mode: Difference

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    //
    // previous introduced blending modes will be skipped to save page space.
    // ....
    //
    //
    darken:     function(v1,v2){return Math.min(v1,v2);},
    lighten:    function(v1,v2){return Math.max(v1,v2);},
    difference: function(v1,v2){return Math.abs(v1-v2);}
};

Now to apply the Difference blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"difference");

Blending Effect Screenshot taken from iPaintPro:

blending_difference
iPaintPro Image Blending: Difference
 
Blending Mode: Exclusion

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    //
    // previous introduced blending modes will be skipped to save page space.
    // ....
    //
    //
    darken:     function(v1,v2){return Math.min(v1,v2);},
    lighten:    function(v1,v2){return Math.max(v1,v2);},
    difference: function(v1,v2){return Math.abs(v1-v2);},
    exclusion:  function(v1,v2){return v1 + v2 - v1 * v2 / 127.5;}
};

Now to apply the Exclusion blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"exclusion");

Blending Effect Screenshot taken from iPaintPro:

blending_exclusion
iPaintPro Image Blending: Exclusion
 
Blending Mode: Reflex

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    //
    // previous introduced blending modes will be skipped to save page space.
    // ....
    //
    //
    darken:     function(v1,v2){return Math.min(v1,v2);},
    lighten:    function(v1,v2){return Math.max(v1,v2);},
    difference: function(v1,v2){return Math.abs(v1-v2);},
    exclusion:  function(v1,v2){return v1 + v2 - v1 * v2 / 127.5;},
    reflex:     function(v1,v2){return ((v1 === 255) ? v1:Math.min(255, (v2 * v2 / (255 - v1))));}
};

Now to apply the Reflex blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"reflex");

Blending Effect Screenshot taken from iPaintPro:

blending_reflex
iPaintPro Image Blending: Reflex
 
 
 
To be continued…
global-composite-operation_thumb.png

Since Microsoft released the beta version of IE 9 last September, I started waiting for the implementation of the globalCompositeOperation of the <canvas> element in the hope that it’s going to make my image process program more easier in some aspects. Since then rumors came out that Microsoft has no plan to support that but I do see this property listed in MSDN (http://msdn.microsoft.com/en-us/library/ff974909(v=vs.85).aspx) for a long time even the Beta and the RC1 do not support it.  On Monday evening at the hip SXSW festival, Microsoft announced the availability of its new Web browser, Internet Explorer 9. Now let’s do a test.

The following is the source code I used to do the test. You can copy&paste the source code to any text editor and save it as a html file to do the test on your own. Or you can click here to run the test (open the following code in a new window/tab)

<!DOCTYPE html>
<html>
   <head>
      <meta http-equiv="X-UA-Compatible" content="IE=9" />
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <title>Test globalCompositeOperation Support</title>
      <style type="text/css">
      .container{float:left;position:relative;background:#cccccc;margin:1px;}
      .container canvas{position:absolute;left:0px;top:0px;}
      .container .name{position:absolute;left:0px;bottom:0px;right:0px;
                       height:20px;font:11px arial;line-height:20px;
                       text-align:center;background:#eeeeee;}
      </style>
   </head>

   <body>
      <script type="text/javascript">
      var operation = [
         "source-over",
         "source-in",
         "source-out",
         "source-atop",
         "destination-over",
         "destination-in",
         "destination-out",
         "destination-atop",
         "lighter",
         "xor",
         "copy"
      ];

      setupLayout(80);

      for ( var i = 0; i < operation.length; i ++ ){
         var canvas = document.getElementById(operation[i]);
         testGlobalCompositeOperation(canvas,operation[i]);
      }

      function setupLayout(size){
         var divTmpl = document.createElement("div");
         divTmpl.className = "container";
         divTmpl.style.width  = size + "px";
         //leave 20 pixel height for the operation name
         divTmpl.style.height = size + 20 + "px"; 

         var canvas = document.createElement("canvas");
         canvas.width = size; canvas.height = size;

         var div2 = document.createElement("div"); div2.className = "name";

         divTmpl.appendChild(canvas);
         divTmpl.appendChild(div2);
         for ( var i = 0; i < operation.length; i ++ ){
            var div = divTmpl.cloneNode(true);
            div.firstChild.id = operation[i];
            div.lastChild.innerHTML = operation[i];
            document.body.appendChild(div);
         }
      }
      function testGlobalCompositeOperation(canvas,op){
         var w = canvas.width/3 * 2, h = canvas.height/3 * 2;
         var ctx = canvas.getContext("2d");
         ctx.beginPath();
         ctx.fillStyle = "rgba(0,152,255,1)";
         ctx.fillRect(0,0,w,h);

         ctx.save();
         ctx.beginPath();

         ctx.globalCompositeOperation = op;

         ctx.fillStyle = "rgba(255,0,0,1)";
         ctx.arc(w,h,w/2,0,Math.PI * 2,false);
         ctx.fill();
         ctx.restore();
      }

      </script>
   </body>
</html>   

The following image is the test result combined from different browsers so that you can see the effects side-by-side after the globalCompositeOperation being applied. Basically, only source-over,  source-atop,  destination-over, destination-out, lighter and xor are cross-browser the same.

As a web developer, I really hates this. The behavior differences can not be programmatically tested at all because they all claim that they support this feature. To me, all I can do is to avoid using those non-consistent features at first place. Then the point goes:  why the  heck browser even supports them? And another funny thing is that for all the variances with other browsers, Microsoft simply claims that IE9 passed and other browsers failed. See here for more detail information.

Hey, people do not follow the standard except me”, the browser said.

global-composite-operation

Hey, people do not follow the standard except me

This is the continuation of my previous post Image Blending Algorithm–Part I regarding digital image blending algorithms. I will continue to reveal more blending mode algorithms used in Adobe Photoshop and iPaintPro.  In part I, five image blending algorithms have been revealed: Multiply, Screen, Overlay, Hard Light and Soft Light.  This post will introduce another 4 image blending algorithms: Color Dodge, Color Burn, Linear Color Dodge and Linear Color Burn.

Blending Mode: Color Dodge

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    multiply: function(v1,v2){return v1 * v2 / 255;},
    screen  : function(v1,v2){return v1 + v2 – v1 * v2 / 255;},
    overlay : function(v1,v2){
       return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
    },
    softlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }else{
         return v2 - v2 * ((127.5 -  v1) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }
    },
    hardlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5);
      }else{
         return v2 * v1 / 127.5;
      }
    },
    colordodge: function (v1,v2){
      return (v1 === 255) ? v1:Math.min(255, ((v2 << 8 ) / (255 - v1)));
    }
};

Now to apply the Color Dodge blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"colordodge");

Blending Effect Screenshot taken from iPaintPro:

blending_colordodge
iPaintPro Image Blending: Color Dodge
 
Blending Mode: Color Burn

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    multiply: function(v1,v2){return v1 * v2 / 255;},
    screen  : function(v1,v2){return v1 + v2 – v1 * v2 / 255;},
    overlay : function(v1,v2){
       return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
    },
    softlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }else{
         return v2 - v2 * ((127.5 -  v1) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }
    },
    hardlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5);
      }else{
         return v2 * v1 / 127.5;
      }
    },
    colordodge: function (v1,v2){
      return (v1 === 255) ? v1:Math.min(255, ((v2 << 8 ) / (255 - v1)));
    },
    colorburn:function(v1,v2){
      return (v1 === 0) ? v1:Math.max(0, (255 - ((255 - v2) << 8 ) / v1));
    }
};

Now to apply the Color Burn blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"colorburn");

Blending Effect Screenshot taken from iPaintPro:

blending_colorburn
iPaintPro Image Blending: Color Burn
 
Blending Mode: Linear Color Dodge

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    multiply: function(v1,v2){return v1 * v2 / 255;},
    screen  : function(v1,v2){return v1 + v2 – v1 * v2 / 255;},
    overlay : function(v1,v2){
       return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
    },
    softlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }else{
         return v2 - v2 * ((127.5 -  v1) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }
    },
    hardlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5);
      }else{
         return v2 * v1 / 127.5;
      }
    },
    colordodge: function (v1,v2){
      return (v1 === 255) ? v1:Math.min(255, ((v2 << 8 ) / (255 - v1)));
    },
    colorburn:function(v1,v2){
      return (v1 === 0) ? v1:Math.max(0, (255 - ((255 - v2) << 8 ) / v1));
    },
    linearcolordodge:function(v1,v2){
      return Math.min(v1 + v2, 255);
    }
};

Now to apply the Linear Color Dodge blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"linearcolordodge");

Blending Effect Screenshot taken from iPaintPro:

blending_linearcolordodge
iPaintPro Image Blending: Linear Color Dodge
Blending Mode: Linear Color Burn

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    multiply: function(v1,v2){return v1 * v2 / 255;},
    screen  : function(v1,v2){return v1 + v2 – v1 * v2 / 255;},
    overlay : function(v1,v2){
       return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
    },
    softlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }else{
         return v2 - v2 * ((127.5 -  v1) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }
    },
    hardlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5);
      }else{
         return v2 * v1 / 127.5;
      }
    },
    colordodge: function (v1,v2){
      return (v1 === 255) ? v1:Math.min(255, ((v2 << 8 ) / (255 - v1)));
    },
    colorburn:function(v1,v2){
      return (v1 === 0) ? v1:Math.max(0, (255 - ((255 - v2) << 8 ) / v1));
    },
    linearcolordodge:function(v1,v2){
      return Math.min(v1 + v2, 255);
    },
    linearcolorburn:function(v1,v2){
      return ((v1 + v2) < 255) ? 0 : (v1 + v2 - 255);
    },
};

Now to apply the Linear Color Burn blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"linearcolorburn");

Blending Effect Screenshot taken from iPaintPro:

blending_linearcolorburn
iPaintPro Image Blending: Linear Color Burn

 

 

 

To be continued…

Image blending can easily help you seamlessly blend two images together to create another different special effect.  Image blending has been seen in almost all of the image processing program.  iPaintPro implements most of the often seen image blending mode in Adobe Photoshop. In this post I will reveal the algorithms I used for each of the blending method with a screenshot to show you the effect.  However, I am not guarantee that will be truly the algorithms used in Adobe Photoshop.

Since there are so many different blending methods, I will split this topic in a series of post.

Before we start,  let’s create  a generic function blending_canvas(canvas1,cavas2,blending_mode). This function will blend canvas1 into canvas2 using specified blending_mode.  We will implement each blending_mode into a global object BLENDING_MACRO that is called within this function.


// blend canvas1 to canvas2 using given blending_mode

function blending_canvas(canvas1, canvas2, blending_mode){
   // Although it doesn't have to be, but for the sake of simplicity, let's assume
   // the two canvas must have same size;
   if ( canvas1.width != canvas2.width || canvas1.height != canvas2.height ){
      return canvas2;
   }
   var ctx1 = canvas1.getContext("2d"),
       ctx2 = canvas2.getContext("2d");
   var data1 = ctx1.getImageData(0,0,canvas1.width,canvas2.height).data;
   var imgData = ctx2.getImageData(0,0,canvas1.width,canvas2.height);
   var data2 = imgData.data;

   for ( var i = 0; i < data1.length; i += 4 ){
      //blending red channel
      data2[i]   = BLENDING_MACRO[blending_mode](data1[i],data2[i]);

      //blending green channel
      data2[i+1] = BLENDING_MACRO[blending_mode](data1[i],data2[i+1]);

      //blending blue channel
      data2[i+2] = BLENDING_MACRO[blending_mode](data1[i],data2[i+2]);
   }

   ctx2.putImageData(imgData,0,0);

   return canvas2;
}

Ok, with this powerful function ready in hand, let’s buckle up and start our journey…

Blending Mode: Multiply

Code Fragment:


//v1: channel value taken from source image

//v2: channel value taken from destination image

var BLENDING_MACRO = {
       multiply: function(v1,v2){
          return v1* v2 / 255;
       }
    };
}

Now to multiply two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"multiply");	 

Blending Effect Screenshot taken from iPaintPro:

 blending_multiply
iPaintPro Image Blending: Multiply
 
Blending Mode: Screen

Code Fragment:


//v1: channel value taken from source image

//v2: channel value taken from destination image

var BLENDING_MACRO = {
       multiply: function(v1,v2){return v1 * v2 / 255;},

       screen:function(v1,v2){

          // some web page present the formula as:

          // 255 – ( 255 – v1 ) * ( 255 – v2 ) / 255

          // With a little mathematic reasoning, you will found that they are equivalent

          // but with less burden to the cpu.

          return v1 + v2 – v1 * v2/ 255;

       }
    };
}

Now to apply the Screen blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"screen");	 

Blending Effect Screenshot taken from iPaintPro:

blending_screen
iPaintPro Image Blending: Screen
Blending Mode: Overlay

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    multiply: function(v1,v2){return v1 * v2 / 255;},
    screen  : function(v1,v2){return v1 + v2 – v1 * v2 / 255;},
    overlay : function(v1,v2){
       return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
    }
};

Now to apply the Overlay blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"overlay");

Blending Effect Screenshot taken from iPaintPro:

blending_overlay
iPaintPro Image Blending: Overlay
 
Blending Mode: Soft Light

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    multiply: function(v1,v2){return v1 * v2 / 255;},
    screen  : function(v1,v2){return v1 + v2 – v1 * v2 / 255;},
    overlay : function(v1,v2){
       return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
    },
    softlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }else{
         return v2 - v2 * ((127.5 -  v1) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }
    }
};

Now to apply the Soft Light blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"softlight");

Blending Effect Screenshot taken from iPaintPro:

blending_softlight
iPaintPro Image Blending: Soft Light
 
Blending Mode: Hard Light

Code Fragment:

//v1: channel value taken from source image
//v2: channel value taken from destination image
var BLENDING_MACRO = {
    multiply: function(v1,v2){return v1 * v2 / 255;},
    screen  : function(v1,v2){return v1 + v2 – v1 * v2 / 255;},
    overlay : function(v1,v2){
       return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
    },
    softlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }else{
         return v2 - v2 * ((127.5 -  v1) / 127.5) * (0.5 - Math.abs(v2-127.5)/255);
      }
    },
    hardlight: function (v1,v2){
      if ( v1 > 127.5 ){
         return v2 + (255 - v2) * ((v1 - 127.5) / 127.5);
      }else{
         return v2 * v1 / 127.5;
      }
    }
};

Now to apply the Hard Light blending mode to two canvas, we can simply call our generic method using this macro.

blending_canvas(canvas1,canvas2,"hardlight");

Blending Effect Screenshot taken from iPaintPro:

blending_hardlight
iPaintPro Image Blending: Hard Light

 

 

 

To be continued…

The following code fragment provides a method to draw a heart shape within given rectangle region.

//
//        (x,y) - the top left corner of the surrounding rectangle
// width,height - the size of the surrounding rectangle
function drawHeart(canvas,x,y,width,height){
   var x0 = x + 0.5 * width, y0 = y + 0.3 * height;
   var x1 = x + 0.1 * width, y1 = y + 0.0 * height;
   var x2 = x + 0.0 * width, y2 = y + 0.6 * height;
   var x3 = x + 0.5 * width, y3 = y + 0.9 * height;
   var x4 = x + 1.0 * width, y4 = y + 0.6 * height;
   var x5 = x + 0.9 * width, y5 = y + 0.0 * height;

   var ctx = canvas.getContext("2d");
   ctx.save();

   ctx.beginPath();

   ctx.moveTo(x0,y0);
   ctx.bezierCurveTo(x1,y1,x2,y2,x3,y3);
   ctx.bezierCurveTo(x4,y4,x5,y5,x0,y0);

   ctx.stroke();

   ctx.restore();
}

To see this code in action, you can check out http://www.jswidget.com/ipaint.html

Image thresholding is the easiest method of image segmentation. It simply divides the image pixels into two categories. One contains the pixels with value less than the threshold and the other contains the pixels with value greater than the threshold. Though pick the right threshold value is difficult, there are many proposed methods on how to pick the right threshold value, such as using mean or median value, automatic thresholding algorithm, histogram valley point etc. In Adode Photoshop, it displays the luminosity histogram to help a user to pick the desired value. iPaintPro does the same as Adobe Photoshop.

The algorithm is very simple:

Lnew     = 0 if Lcur < threshold value

            = 255 if Lcur >= threshold value

Lcur is the calculated luminosity value of given (r, g, b) pixel using ITU-R BT.601 image grayscale method. (See my other post: http://jswidget.com/blog/2011/02/20/image-grayscale-itu-recommend-standards/).

Below is the screenshot taken from iPaintPro when doing image thresholding:

threshold


invert_complement

Invert and complement are two operations in digital image processing to get negative film effect. They are all to get the complement color from one color with a little different algorithm.

Invert operation is simple. We simply use 255 minus value in each channel. The result will be the negative film: COLORinvert = 255 – COLOR. From the formular, we can see that the invert operation actually make:

Inverted Color Table
Color     Inverted Color
Black
White
Red
Cyan
Green
Magenta
Blue
Yellow

In Color Theroy, this is actually also refered as complement color for RGB color model. Red, green, blue are primary colors. Cyan, magenta and yellow are secondary colors.

Complement is actually using this formular:

COLORcomplement = MAX(ColorR,ColorG,ColorB) + MIN(ColorR,ColorG,ColorB) – COLOR

This different between invert and complement is that invert not only change the hue value, the saturation and lightness are also changed. But the complement operation does not change the lightness.

For example,

Complement(Color(0,0,0)) = MAX(0,0,0) + MIN(0,0,0) – Color(0,0,0) = Color(0,0,0).
This means complement of black is still black

Complement(Color(255,255,255)) = MAX(255,255,255) + MIN(255,255,255) – Color(255,255,255) = Color(255,255,255)
This means complement of white is still white.

You can see the two different effects performed within iPainPro 1.0:


© 2011 iPaintPro Suffusion theme by Sayontan Sinha