Swapping RGB channels

Discuss any general programming issues here
Post Reply
ilbarbax
Posts: 130
Joined: Thu Apr 01, 2010 6:41 pm

Swapping RGB channels

Post by ilbarbax »

How is it possible to swap the red channel with the green channel in a picture?
Should I use BrushToRGBArray and scan the whole array by swapping the R & G components values for each pixel? There is a faster way?
ReplaceColors does not seems to be suitable.

thanks
User avatar
Juan Carlos
Posts: 906
Joined: Mon Sep 06, 2010 1:02 pm

Re: Swapping RGB channels

Post by Juan Carlos »

I think that's impossible with the current Hollywood instruction sets. I tryed during several year make and easy 3D anaglyph program and game, and one option is to have one instruction to change between red and cyan, for example.
plouf
Posts: 496
Joined: Sun Feb 04, 2018 11:51 pm
Location: Athens,Greece

Re: Swapping RGB channels

Post by plouf »

A possible solution is to make image to brush
Then use BrushToRGBArray()
That makes a picture pixel from pixel into a argb array(data)

Swapp data in array and then write back pixel by pixel data

Slow ..but doable..
Christos
ilbarbax
Posts: 130
Joined: Thu Apr 01, 2010 6:41 pm

Re: Swapping RGB channels

Post by ilbarbax »

yes this was the solution I also saw, but I was hoping on some faster solution.
On a picture 2560x1920 it took 13.8 seconds to swap red with green
User avatar
Juan Carlos
Posts: 906
Joined: Mon Sep 06, 2010 1:02 pm

Re: Swapping RGB channels

Post by Juan Carlos »

plouf wrote: Thu Jun 27, 2024 5:38 pm A possible solution is to make image to brush
Then use BrushToRGBArray()
That makes a picture pixel from pixel into a argb array(data)

Swapp data in array and then write back pixel by pixel data

Slow ..but doable..
interesting starting point to make a graph with anaglyphic color.
User avatar
Juan Carlos
Posts: 906
Joined: Mon Sep 06, 2010 1:02 pm

Re: Swapping RGB channels

Post by Juan Carlos »

Well I tryed to easy way to do it with this code:

Code: Select all

  @BRUSH 1, "Photo.jpg", {Loader="inbuilt"}

  HEIGHT=GetAttribute(#BRUSH, 1, #ATTRHEIGHT)
  WIDTH=GetAttribute(#BRUSH, 1, #ATTRWIDTH)


  pixels=BrushToRGBArray(1)

  col = $66ffff
  For Local y = 0 To WIDTH
     For Local x = 0 To HEIGHT Do pixels[y * HEIGHT + x] = col
  Next

  RGBArrayToBrush(2, pixels, WIDTH, HEIGHT)
  pixels = Nil 

  DisplayBrush(2, #CENTER, #CENTER)
But only it shows a blue box, and with directly this:
pixels=BrushToRGBArray(1)
PenArrayToBrush(2, pixels, 640, 480, {Palette = #PALETTE_AGA})
Hollywood shows problem wit the Palette = #PALETTE_AGA
ilbarbax
Posts: 130
Joined: Thu Apr 01, 2010 6:41 pm

Re: Swapping RGB channels

Post by ilbarbax »

Thi is my code. Need to be polished by mi other stuffs related to my program however this is the basic function working

Code: Select all

Function p_pic_swapRGB(C1,C2)
;	StartTimer(10)
	picmodified=True
	p_font(36,#BLACK,#BOLD)
	TextOut(#CENTER,#CENTER,"[border=#yellow,2]Wait![/botder]",{AnchorX =.5, AnchorY = .5})		
	Local t=BrushToRGBArray(98)
	For k=0 To ListItems(t)-1 
		RR=Red(t[k])
		BB=Blue(t[k])
		GG=Green(t[k])
		If C1="R" And C2="B" Then t[k]=RGB(BB,GG,RR)
		If C1="R" And C2="G" Then t[k]=RGB(GG,RR,BB)
		If C1="B" And C2="G" Then t[k]=RGB(RR,BB,GG)	
	Next
	RGBArrayToBrush(98, t,GetAttribute(#BRUSH, 98, #ATTRWIDTH),GetAttribute(#BRUSH, 98, #ATTRHEIGHT))
	t=Nil
;	t = GetTimer(10)
;	DebugPrint(t)
	CopyBrush(98,99)
	p_pic_adaptBrush(99)
	p_refresh_pic()
EndFunction

				p_pic_swapRGB("B","G")

User avatar
jPV
Posts: 616
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: Swapping RGB channels

Post by jPV »

Here's what I tested about ilbarbax's situation:

Code: Select all

w, h = 2560, 1920
CreateBrush(1, w, h, $FF0000)

StartTimer(1)
DisableLineHook()
t = BrushToRGBArray(1)
For Local i = 0 To ListItems(t) - 1
    t[i] = RGB(Green(t[i]), Red(t[i]), Blue(t[i]))
Next
RGBArrayToBrush(1, t, w, h)
t = Nil
EnableLineHook()
DebugPrint(GetTimer(1)/1000) ; 16 secs on Mac mini G4

DisplayBrush(1, 0, 0)

StartTimer(1)
DisableLineHook()
For Local y = 0 To h - 1
    For Local x = 0 To w - 1
        Local c = ReadBrushPixel(1, x, y)
        WriteBrushPixel(1, x, y, RGB(Green(c), Red(c), Blue(c)))
    Next
Next
EnableLineHook()
DebugPrint(GetTimer(1)/1000)  ; 19 secs on Mac mini G4

DisplayBrush(1, 0, 0)
WaitLeftMouse()
So two different solutions, but the BrushToRGBArray seems to be faster.

In any case I would put the main For loop between DisableLineHook() and EnableLineHook(), they make a big difference in these kinds of situations.

I also noticed that using table values directly instead of placing them in variables is a bit faster solution.

Notes about ilbarbax's code:
1) Local variables are always faster, so do "For Local k=0 To ListItems(t)-1"
2) Again do "Local RR=Red(t[k])" rather than global variables inside a loop
3) Although according to my test it would better not use RR, BB, and GG as variables at all, but do "t[k]=RGB(Blue(t[k]), Green(t[k]), Red(t[k]))". Or "Local c=t[k]" and "t[k]=RGB(Blue(c), Green(c), Red(c))" could be theoreticaly faster.
4) Use ElseIf:s instead of calling If three times, because if the first If does it, it useless to check the rest.
5) Actually, don't check these C1 and C2 at all inside the very big loop, it's useless to waste time on them. So forget 4) and figure out some another solution. Even three separate loop code blocks would be better.
6) And remember to disable that line hook for heavy loops as told few lines ago

These might sound small things, but when looping millions of times, they do affect to the total time used. Although you never get this one that quick.. it's only "minimizing the damage".

Here's an untested suggestion for the looping part:

Code: Select all

	DisableLineHook()
	If C1="R" And C2="B"
		For Local k=0 To ListItems(t)-1 
			t[k]=RGB(Blue(t[k]),Green(t[k]),Red(t[k]))
		Next			
	ElseIf C1="R" And C2="G"
		For Local k=0 To ListItems(t)-1
			t[k]=RGB(Green(t[k]),Red(t[k]),Blue(t[k]))
		Next
	ElseIf C1="B" And C2="G"
		For Local k=0 To ListItems(t)-1
			t[k]=RGB(Red(t[k]),Blue(t[k]),Green(t[k]))
		Next
	EndIf
	EnableLineHook()
So, have as little code inside a long loop as possible to avoid unnecessary work for the machine.
User avatar
jPV
Posts: 616
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: Swapping RGB channels

Post by jPV »

A small speedup can be achieved by using bitwise operators instead of Hollywood functions, like this:

Code: Select all

For Local k = 0 To ListItems(t) - 1
    Local c = t[k]
    Local r = (c >> 16) & 0xFF
    Local g = (c >> 8) & 0xFF
    Local b = (c >> 0) & 0xFF   
    t[k] = (g << 16) | (r << 8) | (b << 0)
Next 
ilbarbax
Posts: 130
Joined: Thu Apr 01, 2010 6:41 pm

Re: Swapping RGB channels

Post by ilbarbax »

thanks JPV applying your suggests I got a sensible speed improvement on the same picture from 13 to 3 seconds approx. With bitwise option I earn a further second (something less)

thanks
Post Reply