Sign in to follow this  
Red ochre

Recolour choice

Recommended Posts

Recolour choice

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

recolourchoiceUI.png

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	*/
/* (c) 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 *  + (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(, Int32Util.ClampToByte(G), Int32Util.ClampToByte(R), Int32Util.ClampToByte(A));
		dst[x,y] = cp;


	}
}
}


Share this post


Link to post
Share on other sites

Thank you Red ochre. Being able to play with different algorithms in addition to colour tolerance will certainly make life easier for a lot of users.

The "keep unaltered" selection option is brilliant too.

Share this post


Link to post
Share on other sites

Well, this is just cool! Recolor doesn't always work the way I want but this does. And I can get neat effects when I play with the tolerance and transparency.

Thank you!

Share this post


Link to post
Share on other sites

Hello Djisves, Blackpenny and Nitenurse. Many thanks for replying - it's very appreciated :smile:

I'm glad you're finding it useful. Writing plugins is addictive you know!

Share this post


Link to post
Share on other sites

Hi Red ochre,

Thanks for this neat plugin. I know Christmas is still a long time from now, but if I may write my wish list for this plugin, it would be :

- On the top of the window, next to the RGB values, put the HSV values. (like in the Paint.NET color picker windows) so that the user can see both values (RGB and HSV).

- Instead of having a Tolerance slider which applies to the 3 values, leave the possibility to have a tolerance for each value (RGB or HSV). And the Tolerance, instead of being in %, should be a threshold. For example you could say : I want to replace the colors with Hue = 130 (with a Threshold of 10, meaning that I can go from 120 to 140), and Saturation = 50 (with a threshold of 30 : I take all the values from 20 to 80) and Value = 10 (with a threshold of 40 : I take all the values from 0 to 50)

I hope my description is clear.

Thanks again for your great plugin.

Share this post


Link to post
Share on other sites

Hello Origami, welcome to the forum.

Thanks for the positive feedback.

Re: the Christmas wish list (I can think of few things myself!),

The color picker is generated by 'codelab' and is standard. It would be great if it offered the less/more option (showing HSV and alpha) like the main color window, but sadly it does'nt. A similar window could be created using Visual studio, but unfortunately that's too hard to use (for a simpleton like myself anyway).

The other suggestion for seperate sliders for Hue, Saturation and Value, with corresponding integer tolerance sliders would be possible but would ideally be 'linked' to the BGR values (again something that can only be done in Visual studio). Also adding 6 more sliders would make the interface massive. So I won't be changing this plugin.

It would however be relatively easy to create a simpler plugin that only does the specific task you described (using codelab). Probably easiest to have one plugin just for HSV and another just for BGR.

eg/ 3 HSV sliders, 3 tolerance sliders, a BGR color picker for the replacement colour? - or use the secondary color as replacement (easiest)? - or 3 HSV sliders and a transparency slider for the replacement?

(It would be tricky to show the detection colour range from the HSV values on the interface, but a checkbox could be used to show this on an area of the image [uncheck before rendering].)

I have included the codelab code above and I'd like to encourage you to download codelab and have a go at altering my code to suit your needs. Read BoltBait's tutorials first and see how you get on.

If you really need this, and I get the time, I'll see what Santa can do.

All the best

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this