Notifications
Clear all

[Closed] Swap green for blue wisely

			for j = 1 to 255 while not done do
			(
				c2.v = j
				done = (GetLuminance c2) > l1
			)
			
			for j = c2.g to 255 while not done do
			(
				c2.g += 1
				done = (GetLuminance c2) > l1
			)

the method is slow now. but as I see it can simply be changed to use the bisection method instead of the linear algorithm.

If you need to perform many operations, then this iterative approach isn’t any good.

As usual, the first step was to get the algorithm working, so now that we have 50% of the task solved, we can try to improve it.

My first attempt was to solve this in a direct way, but since I failed to solve one exponential equation, I decided to go with an iterative solver.

Here is a starting idea for a “direct algorithm”. This new functions is around 65 times faster than the iterative approach, but when values of blue goes over 255 it uses a LUT to solve the GREEN curve.

It would be good to get it solved in an equation. However, I don’t know how much faster it would perform.

(	
	try destroydialog ::RO_SWAP_CHANNELS catch()

	rollout RO_SWAP_CHANNELS "" width:348 height:258
	(
		group "Master Color: "
		(
			colorPicker cp1 fieldwidth:315 height:76 color:gray align:#left
			
			label lb0 offset:[0,-14]
		)
		group "Swapped Channels: "
		(
			colorPicker cp2 fieldwidth:100 height:76 color:gray align:#left enabled:off across:3
			colorPicker cp3 fieldwidth:100 height:76 color:gray align:#left enabled:off
			colorPicker cp4 fieldwidth:100 height:76 color:gray align:#left enabled:off

			label lb2 "Direct Swap" align:#center across:3
			label lb3 "Brightness [Iterative]"
			label lb4 "Brightness [Direct]"
			
			label lb2c "[0,0]" align:#center across:3
			label lb3c "[0,0]"
			label lb4c "[0,0]"
		)
		
		local LUTGreen = #()
		
		fn GetLuminance1 colour =
		(
			return (colour.r^2 * 0.299 + colour.g^2 * 0.587 + colour.b^2 * 0.114)
		)
		
		fn GetLuminance2 colour =
		(
			-- Removed RED component
			return (colour.g^2 * 0.587 + colour.b^2 * 0.114)^0.5
		)
		
		fn SwapBlueGreenChannels1 colour =
		(
			if colour.g == colour.b do return colour
			
			c1 = color 0 colour.g colour.b
			c2 = color 0 colour.b colour.g
			
			l1 = GetLuminance1 c1
			
			done = false
			
			for j = 1 to 255 while not done do
			(
				c2.v = j
				done = (GetLuminance1 c2) > l1
			)
			
			for j = c2.g to 255 while not done do
			(
				c2.g += 1
				done = (GetLuminance1 c2) > l1
			)
			
			c2.r = colour.r
			c2.g = int (c2.g + 0.5)
			c2.b = int (c2.b + 0.5)
			
			return c2
		)
		
		-- This function is around 65 times faster than SwapBlueGreenChannels1()
		fn SwapBlueGreenChannels2 colour =
		(
			if colour.g != colour.b then
			(
				c1 = color 0 colour.g colour.b
				c2 = color 0 colour.b colour.g
				
				l1 = GetLuminance2 c1
				l2 = GetLuminance2 c2
				
				delta = l1 / l2
				
				c2.r = int colour.r
				c2.g = int ((c2.g * delta)+0.5)
				c2.b = int ((c2.b * delta)+0.5)
				
				-- We need to solve the equation for the green
				-- component when the blue value goes over 255
				if c2.b > 255 do
				(
					c2.g = LUTGreen[c1.g]
					c2.b = 255
				)
				-----------------------------------------------
				
			)else(
				c2 = colour
			)
			
			return c2
		)
		
		fn BuildLUTGreen =
		(
			for j = 100 to 255 do
			(
				LUTGreen[j] = (SwapBlueGreenChannels1 (color 0 j 0)).g
			)
		)
		
		fn UpdateControls =
		(
			c = cp1.color
			
			cp2.color = color c.r c.b c.g
			cp3.color = SwapBlueGreenChannels1 c
			cp4.color = SwapBlueGreenChannels2 c
			
			lb2c.text = [cp2.color.g, cp2.color.b] as string
			lb3c.text = [cp3.color.g, cp3.color.b] as string
			lb4c.text = [cp4.color.g, cp4.color.b] as string
		)
		
		on RO_SWAP_CHANNELS open do
		(
			BuildLUTGreen()
			
			c = random black white
			cp1.color = [int c.r, int c.g, int c.b]
			
			UpdateControls()
		)
		
		on cp1 changed arg do UpdateControls()
		
	)

	createdialog RO_SWAP_CHANNELS style:#(#style_titlebar, #style_toolwindow, #style_sysmenu)
)

PD: haven’t tried bisecting the previous algorithm, but it may be also good, since we would reduce the iterations from a maximum of 512 to 16 in worst case. Yet 16 looks like a big number for intensive use.

How about solvig all the variants with a LUT? That should be a lot faster than any other approach.

EDIT: Confirmed, a LUT version is around 200 times faster than the iterative version for a 128×128 image.

I have played with my math skills too…

here is my ‘direct algorithm’ version:

(	
	try destroydialog ::SWAP_GB_Rollout catch()

	rollout SWAP_GB_Rollout "" width:840 --height:244
	(
		local sw = 280
		local sw2 = sw+sw
		
		groupbox org_gr "Origin Color: " width:270 height:410 pos:[6,4]
		colorPicker org_cp color:black fieldwidth:256 height:40 pos:[9,24] modal:off
		label org_rgb_lb "RGB:" align:#left pos:[20, 70]
		label org_rgb_vb "0" align:#left pos:[50, 70]
		label org_lum_lb "Lume:" align:#left pos:[210, 70]
		label org_lum_vb "0" align:#left pos:[245, 70]
		imgtag org_bm bitmap:(bitmap 256 256) transparent:(color -1 -1 -1) width:256 height:256 pos:[13,90] 
	
		groupbox dir_gr "Direct Swap: " width:270 height:410 pos:[6+sw,4]
		colorPicker dir_cp color:black fieldwidth:256 height:40 pos:[9+sw,24] modal:off
		label dir_rgb_lb "RGB:" align:#left pos:[20+sw, 70]
		label dir_rgb_vb "0" align:#left pos:[50+sw, 70]
		label dir_lum_lb "Lume:" align:#left pos:[210+sw, 70]
		label dir_lum_vb "0" align:#left pos:[245+sw, 70]
		imgtag dir_bm bitmap:(bitmap 256 256) transparent:(color -1 -1 -1) width:256 height:256 pos:[13+sw,90] 
	
		groupbox scr_gr "Correct Swap: " width:270 height:410 pos:[6+sw2,4]
		colorPicker scr_cp color:black fieldwidth:256 height:40 pos:[9+sw2,24] modal:off
		label scr_rgb_lb "RGB:" align:#left pos:[20+sw2, 70]
		label scr_rgb_vb "0" align:#left pos:[50+sw2, 70]
		label scr_lum_lb "Lume:" align:#left pos:[210+sw2, 70]
		label scr_lum_vb "0" align:#left pos:[245+sw2, 70]
		imgtag scr_bm bitmap:(bitmap 256 256) transparent:(color -1 -1 -1) width:256 height:256 pos:[13+sw2,90] 	
		
		checkbox squared_cb "Squared" checked:on pos:[580, 354] enabled:off
		radiobuttons factor_type_rb labels:#("Luminance: (0.213, 0.715, 0.072)", "Brightness: (0.299, 0.587, 0.114)") default:2 columns:1 pos:[620, 354+22]
		
		local luminance_factor = [0.213, 0.715, 0.072]
		local brightness_factor = [0.299, 0.587, 0.114]
		
		fn luminance v factor:brightness_factor =
		(
			R = factor.x
			G = factor.y
			B = factor.z

			if not ispoint3 v do v = [v.r, v.g, v.b]  
			sqrt(v.x^2 * R + v.y^2 * G + v.z^2 * B)
		)
		fn quadEquation a b c = 
		(
			d = b*b - 4*a*c
			if (d >= 0) do
			(
				[(-b + sqrt(d))/(2*a), (-b - sqrt(d))/(2*a)]
			)
		)		
		--fn colorClamp v = clamppoint v max:255
		
		fn swapGreenBlue cp factor:brightness_factor =
		(
			R = factor.x
			G = factor.y
			B = factor.z

			local org = copy [cp.r, cp.g, cp.b]
			local scr = [org.x, org.z, org.y]
			
			lume = luminance org factor:factor
			lumc = luminance scr factor:factor
			
			dx = 0
			dy = 0
			dz = 0

			if (lumc > lume) then 
			(
				y = sqrt((scr.z^2 * (G - B) + scr.y^2 * B)/ G)
				scr = [scr.x, y, scr.z]
			)
			else
			(
				if (lumc < lume) then 
				(
					z = sqrt((scr.y^2 * (B - G) + scr.z^2 * G) / B)
					if z >= 255.0 then
					(
						y = sqrt(scr.z^2 + scr.y^2*B/G - 255^2*B/G)
						scr = [scr.x, y, 255]
					)
					else scr = [scr.x, scr.y, z]
				)
			)

			--scr = clamppoint scr max:255
			scr = color scr.x scr.y scr.z 
		)

		fn stringColor col = 
		(
			ss = stringstream ""
			format "%  %  %" (int col.r) (int col.g) (int col.b) to:ss
			ss as string
		)
		fn stringValue val = 
		(
			ss = stringstream ""
			format "%" (int val) to:ss
			ss as string
		)
		
		fn updateColors col factor: squared: = 
		(
			factor = if factor_type_rb.state == 1 then luminance_factor else brightness_factor

			col0 = col
			dir_cp.color = col1 = color col.r col.b col.g
			d = color col.r col.b col.g
			s = swapGreenBlue col factor:factor
			scr_cp.color = col2 = s --vlerp s d 
			
			org_rgb_vb.text = stringColor col0
			dir_rgb_vb.text = stringColor col1
			scr_rgb_vb.text = stringColor col2

			org_lum_vb.text = stringValue (luminance col0 factor:factor)
			dir_lum_vb.text = stringValue (luminance col1 factor:factor)
			scr_lum_vb.text = stringValue (luminance col2 factor:factor)
		)

		fn hsv_to_rgb hsv = 
		(
			col = black -- it might be any color
			col.v = hsv.b
			col.s = hsv.g
			col.h = hsv.r
			col
		)
		
		fn updateUI col: complete:on = 
		(
			setwaitcursor()
			factor = if factor_type_rb.state == 1 then luminance_factor else brightness_factor
			
			if col != unsupplied then org_cp.color = col else col = org_cp.color 
			updateColors col factor:factor
						
			local bmc = org_bm.bitmap
			local bmd = dir_bm.bitmap
			local bms = scr_bm.bitmap
			
			for y=0 to 255 do
			(
				cc = #()
				cd = #()
				cs = #()
				
				for x=0 to 255 collect 
				(
					c = hsv_to_rgb (color x 255.0 (255.0-y))
					d = color c.r c.b c.g
					if complete do
					(
						append cc c 
						append cd d
					)
					s = swapGreenBlue c factor:factor
					append cs s --(vlerp s d)
				)
				if complete do
				(
					setPixels bmc [0,y] cc  
					setPixels bmd [0,y] cd 
				)
				setPixels bms [0,y] cs  
			)
			if complete do
			(
				org_bm.bitmap = bmc
				dir_bm.bitmap = bmd
			)
			
			scr_bm.bitmap = bms
			
			setarrowcursor()
		)
		
	
		on org_cp changed col do updateColors col
		on factor_type_rb changed state do updateUI complete:off
			
		on SWAP_GB_Rollout open do
		(
			org_cp.color = col = green
			updateUI()
		)
	)

	createdialog SWAP_GB_Rollout style:#(#style_titlebar, #style_toolwindow, #style_sysmenu)
)

what do you think?

hmm … no. I’m still wrong

fixed

now it seems correct:

(	
	try destroydialog ::SWAP_GB_Rollout catch()

	rollout SWAP_GB_Rollout "" width:840 --height:244
	(
		local sw = 280
		local sw2 = sw+sw
		
		groupbox org_gr "Origin Color: " width:270 height:410 pos:[6,4]
		colorPicker org_cp color:black fieldwidth:256 height:40 pos:[9,24] modal:off
		label org_rgb_lb "RGB:" align:#left pos:[20, 70]
		label org_rgb_vb "0" align:#left pos:[50, 70]
		label org_lum_lb "Lume:" align:#left pos:[210, 70]
		label org_lum_vb "0" align:#left pos:[245, 70]
		imgtag org_bm bitmap:(bitmap 256 256) transparent:(color -1 -1 -1) width:256 height:256 pos:[13,90] 
	
		groupbox dir_gr "Direct Swap: " width:270 height:410 pos:[6+sw,4]
		colorPicker dir_cp color:black fieldwidth:256 height:40 pos:[9+sw,24] modal:off
		label dir_rgb_lb "RGB:" align:#left pos:[20+sw, 70]
		label dir_rgb_vb "0" align:#left pos:[50+sw, 70]
		label dir_lum_lb "Lume:" align:#left pos:[210+sw, 70]
		label dir_lum_vb "0" align:#left pos:[245+sw, 70]
		imgtag dir_bm bitmap:(bitmap 256 256) transparent:(color -1 -1 -1) width:256 height:256 pos:[13+sw,90] 
	
		groupbox scr_gr "Correct Swap: " width:270 height:410 pos:[6+sw2,4]
		colorPicker scr_cp color:black fieldwidth:256 height:40 pos:[9+sw2,24] modal:off
		label scr_rgb_lb "RGB:" align:#left pos:[20+sw2, 70]
		label scr_rgb_vb "0" align:#left pos:[50+sw2, 70]
		label scr_lum_lb "Lume:" align:#left pos:[210+sw2, 70]
		label scr_lum_vb "0" align:#left pos:[245+sw2, 70]
		imgtag scr_bm bitmap:(bitmap 256 256) transparent:(color -1 -1 -1) width:256 height:256 pos:[13+sw2,90] 	
		
		checkbox squared_cb "Squared" checked:on pos:[580, 354] enabled:off across:2
		spinner blend_direct_sp "Blend Direct: " type:#float range:[0,1,0] scale:0.01 fieldwidth:46 pos:[702, 355]
		radiobuttons factor_type_rb labels:#("Luminance: (0.213, 0.715, 0.072)", "Brightness: (0.299, 0.587, 0.114)") default:2 columns:1 pos:[600, 354+22]
		
		local luminance_factor = [0.213, 0.715, 0.072]
		local brightness_factor = [0.299, 0.587, 0.114]
		
		fn luminance v factor:brightness_factor =
		(
			R = factor.x
			G = factor.y
			B = factor.z

			(v.x^2*R + v.y^2*G + v.z^2*B)
		)
		fn luminanceSquared col factor: = 
		(
			v = [col.r, col.g, col.b]  
			sqrt(luminance v factor:factor)
		)
		
		fn swapGreenBlue cp factor:brightness_factor =
		(
			R = factor.x
			G = factor.y
			B = factor.z

			local org = copy [cp.r, cp.g, cp.b]
			local scr = [org.x, org.z, org.y]
			
			lume = luminance org factor:factor
			lumc = luminance scr factor:factor
			
			v = org.y^2*G + org.z^2*B 
			
			if (lumc > lume) then 
			(
				scr.y = sqrt((v - org.y^2*B)/G)
			)
			else
			(
				if (lumc < lume) then 
				(
					z = sqrt((v - org.z^2*G)/B)
					if z > 255.0 then
					(
						y = sqrt((v - 255^2 * B)/G)
						scr.y = y
						scr.z = 255
					)
					else scr.z = z
				)
			)
			scr = color scr.x scr.y scr.z 
		)

		fn stringColor col = 
		(
			ss = stringstream ""
			format "%  %  %" (int col.r) (int col.g) (int col.b) to:ss
			ss as string
		)
		fn stringValue val = 
		(
			ss = stringstream ""
			format "%" (int val) to:ss
			ss as string
		)
		
		fn updateColors col factor: squared: = 
		(
			factor = if factor_type_rb.state == 1 then luminance_factor else brightness_factor
			t = blend_direct_sp.value
			
			col0 = col
			dir_cp.color = col1 = color col.r col.b col.g
			s = swapGreenBlue col factor:factor
			scr_cp.color = col2 = s*(1 - t) + col1*t
			
			org_rgb_vb.text = stringColor col0
			dir_rgb_vb.text = stringColor col1
			scr_rgb_vb.text = stringColor col2

			org_lum_vb.text = stringValue (luminanceSquared col0 factor:factor)
			dir_lum_vb.text = stringValue (luminanceSquared col1 factor:factor)
			scr_lum_vb.text = stringValue (luminanceSquared col2 factor:factor)
		)

		fn hsv_to_rgb hsv = 
		(
			col = black -- it might be any color
			col.v = hsv.b
			col.s = hsv.g
			col.h = hsv.r
			col
		)
		
		fn updateUI col: complete:on = 
		(
			setwaitcursor()
			factor = if factor_type_rb.state == 1 then luminance_factor else brightness_factor
			t = blend_direct_sp.value
			
			if col != unsupplied then org_cp.color = col else col = org_cp.color 
			updateColors col factor:factor
						
			local bmc = org_bm.bitmap
			local bmd = dir_bm.bitmap
			local bms = scr_bm.bitmap
			
			for y=0 to 255 do
			(
				cc = #()
				cd = #()
				cs = #()
				
				for x=0 to 255 collect 
				(
					c = hsv_to_rgb (color x 255.0 (255.0-y))
					d = color c.r c.b c.g
					if complete do
					(
						append cc c 
						append cd d
					)
					s = swapGreenBlue c factor:factor
					v = s*(1 - t) + d*t
					append cs v
				)
				if complete do
				(
					setPixels bmc [0,y] cc  
					setPixels bmd [0,y] cd 
				)
				setPixels bms [0,y] cs  
			)
			if complete do
			(
				org_bm.bitmap = bmc
				dir_bm.bitmap = bmd
			)
			
			scr_bm.bitmap = bms
			
			setarrowcursor()
		)
		
	
		on org_cp changed col do updateColors col
		on factor_type_rb changed state do updateUI complete:off
		on blend_direct_sp entered do updateUI complete:off
			
		on SWAP_GB_Rollout open do
		(
			org_cp.color = col = green
			updateUI()
		)
	)

	createdialog SWAP_GB_Rollout style:#(#style_titlebar, #style_toolwindow, #style_sysmenu)
)

this is optimized … and ‘blend with direct’ feature added.

Nice

Although it produces different results than the iterative version. Not sure which one is better, but you have some options to choose from now.

This was the remaining piece I needed to complete my code:

y = sqrt((v - 255^2 * B)/G)

Here is the updated version:

(	
	try destroydialog ::RO_SWAP_CHANNELS catch()

	rollout RO_SWAP_CHANNELS "" width:348 height:258
	(
		group "Master Color: "
		(
			colorPicker cp1 fieldwidth:315 height:76 color:gray align:#left
			
			label lb0 offset:[0,-14]
		)
		group "Swapped Channels: "
		(
			colorPicker cp2 fieldwidth:100 height:76 color:gray align:#left enabled:off across:3
			colorPicker cp3 fieldwidth:100 height:76 color:gray align:#left --enabled:off
			colorPicker cp4 fieldwidth:100 height:76 color:gray align:#left --enabled:off
			
			label lb2 "Direct Swap" align:#center across:3
			label lb3 "Brightness [Iterative]"
			label lb4 "Brightness [Direct]"
			
			label lb2c "[0,0]" align:#center across:3
			label lb3c "[0,0]"
			label lb4c "[0,0]"
		)
		
		fn GetLuminance colour =
		(
			return (colour.g^2 * 0.587 + colour.b^2 * 0.114)
		)
		
		fn SwapBlueGreenChannels1 colour =
		(
			if colour.g == colour.b do return colour
			
			c1 = color 0 colour.g colour.b
			c2 = color 0 colour.b colour.g
			
			l1 = GetLuminance c1
			
			done = false
			
			for j = 1 to 255 while not done do
			(
				c2.v = j
				done = (GetLuminance c2) > l1
			)
			
			for j = c2.g to 255 while not done do
			(
				c2.g += 1
				done = (GetLuminance c2) > l1
			)
			
			c2.r = colour.r
			c2.g = int (c2.g + 0.5)
			c2.b = int (c2.b + 0.5)
			
			return c2
		)
		
		-- Can be optimized -----------------------------------------------
		fn SwapBlueGreenChannels2 colour =
		(
			if colour.g != colour.b then
			(
				c1 = color 0 colour.g colour.b
				c2 = color 0 colour.b colour.g
				
				l1 = GetLuminance c1
				l2 = GetLuminance c2
				
				delta = l1^0.5 / l2^0.5
				
				c2.r = int colour.r
				c2.g = int ((c2.g * delta)+0.5)
				c2.b = int ((c2.b * delta)+0.5)
				
				if c2.b > 255 do
				(
					c2.g = int (sqrt ((l1 - (255^2 * 0.114))/0.587)+0.5) -- DenisT ;)
					c2.b = 255
				)
			)else(
				c2 = colour
			)
			
			return c2
		)
		
		fn UpdateControls =
		(
			c = cp1.color
			
			cp2.color = color c.r c.b c.g
			cp3.color = SwapBlueGreenChannels1 c
			cp4.color = SwapBlueGreenChannels2 c
			
			lb2c.text = [cp2.color.g, cp2.color.b] as string
			lb3c.text = [cp3.color.g, cp3.color.b] as string
			lb4c.text = [cp4.color.g, cp4.color.b] as string
		)
		
		on RO_SWAP_CHANNELS open do
		(
			c = random black white
			cp1.color = [int c.r, int c.g, int c.b]
			
			UpdateControls()
		)
		
		on cp1 changed arg do UpdateControls()
		
	)

	createdialog RO_SWAP_CHANNELS style:#(#style_titlebar, #style_toolwindow, #style_sysmenu)
)

I added ‘color-box gradient’… now it looks almost identical:

(	
	try destroydialog ::RO_SWAP_CHANNELS catch()

	rollout RO_SWAP_CHANNELS "" width:348
	(
		group "Master Color: "
		(
			colorPicker cp1 fieldwidth:315 height:76 color:gray align:#left
			
			label lb0 offset:[0,-14]
		)
		group "Swapped Channels: "
		(
			colorPicker cp2 fieldwidth:100 height:76 color:gray align:#left enabled:off across:3
			colorPicker cp3 fieldwidth:100 height:76 color:gray align:#left enabled:off
			colorPicker cp4 fieldwidth:100 height:76 color:gray align:#left enabled:off

			label lb2 "Direct Swap" align:#center across:3
			label lb3 "Brightness [Iterative]"
			label lb4 "Brightness [Direct]"
			
			label lb2c "[0,0]" align:#center across:3
			label lb3c "[0,0]"
			label lb4c "[0,0]"
		)

		imgtag scr_bm bitmap:(bitmap 256 256) transparent:(color -1 -1 -1) width:256 height:256 align:#center	
		
		fn GetLuminance colour =
		(
			return (colour.g^2 * 0.587 + colour.b^2 * 0.114)
		)
		fn GetLuminance1 colour =
		(
			return (colour.r^2 * 0.299 + colour.g^2 * 0.587 + colour.b^2 * 0.114)
		)

		fn SwapBlueGreenChannels1 colour =
		(
			if colour.g == colour.b do return colour
			
			c1 = color 0 colour.g colour.b
			c2 = color 0 colour.b colour.g
			
			l1 = GetLuminance c1
			
			done = false
			
			for j = 1 to 255 while not done do
			(
				c2.v = j
				done = (GetLuminance c2) > l1
			)
			
			for j = c2.g to 255 while not done do
			(
				c2.g += 1
				done = (GetLuminance c2) > l1
			)
			
			c2.r = colour.r
			c2.g = int (c2.g + 0.5)
			c2.b = int (c2.b + 0.5)
			
			return c2
		)
		
		-- Can be optimized -----------------------------------------------
		fn SwapBlueGreenChannels2 colour =
		(
			if colour.g != colour.b then
			(
				c1 = color 0 colour.g colour.b
				c2 = color 0 colour.b colour.g
				
				l1 = GetLuminance c1
				l2 = GetLuminance c2
				
				delta = l1^0.5 / l2^0.5
				
				c2.r = int colour.r
				c2.g = int ((c2.g * delta)+0.5)
				c2.b = int ((c2.b * delta)+0.5)
				
				if c2.b > 255 do
				(
					c2.g = int (sqrt ((l1 - (255^2 * 0.114))/0.587)+0.5) -- DenisT ;)
					c2.b = 255
				)
			)else(
				c2 = colour
			)
			
			return c2
		)
		
		fn UpdateControls =
		(
			c = cp1.color
			
			cp2.color = color c.r c.b c.g
			cp3.color = c3 = SwapBlueGreenChannels1 c
			cp4.color = c4 = SwapBlueGreenChannels2 c
			
			lb2c.text = [cp2.color.g, cp2.color.b, round(sqrt(GetLuminance1 c))] as string
			lb3c.text = [cp3.color.g, cp3.color.b, round(sqrt(GetLuminance1 c3))] as string
			lb4c.text = [cp4.color.g, cp4.color.b, round(sqrt(GetLuminance1 c4))] as string
		)
		
		fn HSV_to_RGB hsv = 
		(
			rgb = black -- it might be any color
			rgb.v = hsv.b
			rgb.s = hsv.g
			rgb.h = hsv.r
			rgb
		)
		on RO_SWAP_CHANNELS open do
		(
			c = random black white
			cp1.color = [int c.r, int c.g, int c.b]
			
			UpdateControls()
			
			local bms = scr_bm.bitmap
			
			for y=0 to 255 do
			(
				cs = #()
				
				for x=0 to 255 collect 
				(
					c = HSV_to_RGB (color x 255.0 (255.0-y))
					d = color c.r c.b c.g
					s = SwapBlueGreenChannels2 c 
					append cs s --(vlerp s d)
				)
				setPixels bms [0,y] cs  
			)

			scr_bm.bitmap = bms
			
		)
		
		on cp1 changed arg do UpdateControls()
		
	)

	createdialog RO_SWAP_CHANNELS style:#(#style_titlebar, #style_toolwindow, #style_sysmenu)
)

this is the difference I see

but I’m happy enough. It was a fun to play with a new toy. Thank you guys.

I just want you to know why I went for this “research”…

In my real-time shader I found that an image desaturation is going with different visual ‘speed’ for greenish and blueish images… that’s was the reason to search for solution.

Page 3 / 4