Swapping RGB channels
Swapping RGB channels
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
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
- Juan Carlos
- Posts: 932
- Joined: Mon Sep 06, 2010 1:02 pm
Re: Swapping RGB channels
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.
Re: Swapping RGB channels
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..
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
Re: Swapping RGB channels
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
On a picture 2560x1920 it took 13.8 seconds to swap red with green
- Juan Carlos
- Posts: 932
- Joined: Mon Sep 06, 2010 1:02 pm
Re: Swapping RGB channels
interesting starting point to make a graph with anaglyphic color.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..
- Juan Carlos
- Posts: 932
- Joined: Mon Sep 06, 2010 1:02 pm
Re: Swapping RGB channels
Well I tryed to easy way to do it with this code:
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
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)
pixels=BrushToRGBArray(1)
PenArrayToBrush(2, pixels, 640, 480, {Palette = #PALETTE_AGA})
Hollywood shows problem wit the Palette = #PALETTE_AGA
Re: Swapping RGB channels
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")
Re: Swapping RGB channels
Here's what I tested about ilbarbax's situation:
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:
So, have as little code inside a long loop as possible to avoid unnecessary work for the machine.
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()
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()
Re: Swapping RGB channels
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
Re: Swapping RGB channels
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
thanks