8 differnt ways to select and replace a colour.
There are many plugins allowing selection and replacement of colours and
there are the built in tools, magic wand and recolor. These are all good and useful
in different situations. However, I was working on a picture and found I couldn't select the region I wanted,
so I decided to experiment with different algorithms.
I have also included a 'blend' slider to soften the replaced colour.
If you duplicate the layer first and select the 'keep unaltered selected' checkbox,
you will be left with the selected region as an object on its own layer for further
processing.
Tip: It's easiest to use the ink dropper tool to select the desired detection colour before running the plugin.
It is in my plugin pack here:
Red ochre plugin pack

Here's the codelab code if you want to play with the algorithms!
This thread is relevant too http://forums.getpai...or-bucket-tool/
Hidden Content:
/* =================================================== */
/* */
/* recolour choice */
/* © 2012 Red Ochre */
/* */
/* Description: colour replacement with more options */
/* */
/* ========================================== ======== */
// Name: recolour choice
// Author: Red ochre (John Robbins)
// Submenu: Color
// URL: http://www.getpaint.net/redirect/plugins.html
// Title: recolour choice April 2012 Red Ochre
#region UICode
byte Amount1 = 0; // colour detection method by:|H,S & V|B,G & R|Euclidean distance|tone (B + G + R) only|tone (HSV Value)only|Saturation only|Hue only|transparency value only (over-rides checkbox)
ColorBgra Amount2 = ColorBgra.FromBgr(120,124,172); // colour to detect
bool Amount3 = true; // [0,1] include transparency (alpha) in detection
int Amount4 = 255; // [0,255] detection transparency
double Amount5 = 10; // [0,100] detection tolerance %
ColorBgra Amount6 = ColorBgra.FromBgr(255,0,0); // replacement colour
int Amount7 = 255; // [0,255] replacement transparency
double Amount8 = 0; // [0,100] blend edges
bool Amount9 = false; // [0,1] keep unaltered detected only
#endregion
void Render(Surface dst, Surface src, Rectangle rect)
{
ColorBgra cp;
int B, G, R,A,lum, B1,G1,R1,A1,lum1, B2,G2,R2,A2;
double t1,t1b,t1p,t1d,t1e,t1l, t2, euc,euc1;
for(int y = rect.Top; y < rect.Bottom; y++)
{ for (int x = rect.Left; x < rect.Right; x++)
{cp = src[x,y];// cp = current pixel = set to source pixel
B = cp.B;G = cp.G;R = cp.R;A = cp.A;// source pixel
B1 = (int)Amount2.B;G1 = (int)Amount2.G;R1 = (int)Amount2.R;// colour to detect
A1 = Amount4; // detection transparency from slider - not from primary
t1 = Amount5/100; //detection tolerance
t1b = t1 * 255;// t1 byte, from 0 to 255 but a double for easier maths!
t1p = t1 * 100;// t1 percent, from 0 to 100
t1d = t1 * 360;// t1 degrees, from 0 to 360
t1e = t1 * 441.67;// Euclidean range
t1l = t1 * 765;// tone/ lum range (255 * 3)
t2 = Amount8/100; //blend tolerance
B2 = (int)Amount6.B;G2 = (int)Amount6.G;R2 = (int)Amount6.R;// replacement colour from color wheel
A2 = (int)Amount7;// replacement transparency from slider
Color col = cp.ToColor();// from Boltbait's tutorial part4 - thanks BB!
HsvColor hsv = HsvColor.FromColor(col);// source HSV color
int H = hsv.Hue;// from 0 to 360 (Red,Orange,Yellow,Green,Turquoise,Blue,Magenta,Carmine)
int S = hsv.Saturation;// from 0(grey) to 100 (full colour)
int V = hsv.Value;// from 0 (black) to 100 (white)
Color col1 = Amount2.ToColor();
HsvColor hsv1 = HsvColor.FromColor(col1);// detection HSV color
int H1 = hsv1.Hue;
int S1 = hsv1.Saturation;
int V1 = hsv1.Value;
double blend1 = 1;// have to assign a value
double blend;
double iblend;
int Adiff = Math.Abs(A - A1);// declare here as used in many cases
double Hdiff = Math.Abs(H - H1);
double Sdiff = Math.Abs(S - S1);
double Vdiff = Math.Abs(V - V1);
switch (Amount1)
{
case 0:// by H,S & V
if((Hdiff < t1d)
&&(Sdiff < t1p)
&&(Vdiff < t1p))
{if(!Amount3 ||(Amount3 && Adiff < t1b))
{
blend1 = t2 * ((Hdiff / t1d)
+ (Sdiff / t1p)
+ (Vdiff / t1p));
}
}
break;
case 1:// % change per colour
int Bdiff = Math.Abs(B - B1);// declare here
int Gdiff = Math.Abs(G - G1);// as only case
int Rdiff = Math.Abs(R - R1);// to use them
if(Bdiff < t1b && Gdiff < t1b && Rdiff < t1b)
{
if((Amount3 && Adiff < t1b)||!Amount3)
{
blend1 = t2 * (Bdiff + Gdiff + Rdiff) / t1b;
}
}
break;
case 2:// Euclidean
// sqrt of (255 * 255 * 3 ) = 441.67
// 255 * 255 = 65025
euc = Math.Sqrt((B * <img src='http://forums.getpaint.net/public/style_emoticons/<#EMO_DIR#>/boltbait.cool.png' class='bbc_emoticon' alt='B)' /> + (G * G) + (R * R)) ;
euc1 = Math.Sqrt((B1 * B1) + (G1 * G1) + (R1 * R1));
double eucdiff = Math.Abs(euc - euc1);
if(eucdiff < t1e)
{ if((Amount3 && Adiff < t1b)||!Amount3)
{blend1 = t2 * eucdiff / t1e;}
}
break;
case 3:// B,G,R tone only (lum = approx luminance)
lum = B + G + R;// source
lum1 = B1 + G1 + R1;// primary color
double lumdiff = Math.Abs(lum - lum1);
if(lumdiff < t1l)
{if((Amount3 && Adiff < t1b)||!Amount3)
{blend1 = t2 * lumdiff / t1l;}
}
break;
case 4:// (H,S,V tone)Value only
if(Vdiff < t1p)
{
if(!Amount3 ||(Amount3 && Adiff < t1b))
{
blend1 = t2 * Vdiff / t1p;
}
}
break;
case 5:// Saturation value only
if(Sdiff < t1p)
{
if(!Amount3 ||(Amount3 && Adiff < t1b))
{
blend1 = t2 * Sdiff / t1p;
}
}
break;
case 6:// Hue value only
if(Hdiff < t1d)
{
if(!Amount3 ||(Amount3 && Adiff < t1b))
{
blend1 = t2 * Hdiff/ t1d;
}
}
break;
case 7:// transparency only
if(Adiff < t1b)
{
blend1 = t2 * Adiff/ t1b;
}
break;
}// end of switch block
if(blend1 > 1){blend1 = 1;}// to prevent colour reversal if more than 1
blend = 1 - blend1; // as in cases 1 & 7
iblend = 1 - blend;
B = (int)((B2 * blend) + (B * iblend));
G = (int)((G2 * blend) + (G * iblend));
R = (int)((R2 * blend) + (R * iblend));
A = (int)((A2 * blend) + (A * iblend));
// keep unaltered detected - transparency srcA * blend
if(Amount9){if(blend > 0){ B = src[x,y].B;G = src[x,y].G;R = src[x,y].R;A = (int)(src[x,y].A * blend);}
if(blend == 0){A = 0;}}
// Reassemble the color from B, G, and R
cp = ColorBgra.FromBgra( Int32Util.ClampToByte(<img src='http://forums.getpaint.net/public/style_emoticons/<#EMO_DIR#>/boltbait.cool.png' class='bbc_emoticon' alt='B)' />, Int32Util.ClampToByte(G), Int32Util.ClampToByte®, Int32Util.ClampToByte(A));
dst[x,y] = cp;
}
}
}














