SwapImageColor(Image, OldColor, NewColor)
Posted: Thu Apr 23, 2009 12:49 pm
i needed a function, to swap a color of a loaded image. the usual Point() + Plot() method was very slow, so i searched for an alternative and came across this -> thread. unfortunately the snippet provided by JLC, didnt work on 24bit images. after a short consultation with him and some thought, here is the result.
note that this function doesnt work on images with less than 24bit or greater than 32bit!
i compared the speed against Point() + Plot() on a random 1920x1280 image:
not bad eh?
edit1: RGB Macros added.
edit2: only one For : Next loop is used now. hope it works the way it should. feel free to report otherwise.
edit3: macros updated and removed unused variables.
c ya,
nco2k
note that this function doesnt work on images with less than 24bit or greater than 32bit!
Code: Select all
EnableExplicit
Macro RGB(Red, Green, Blue)
(((Blue << 8 + Green) << 8 ) + Red)
EndMacro
Macro Red(Color)
(Color & $FF)
EndMacro
Macro Green(Color)
((Color & $FFFF) >> 8)
EndMacro
Macro Blue(Color)
(Color >> 16)
EndMacro
Procedure SwapImageColor(Image, OldColor, NewColor)
Protected NewBlue, NewGreen, NewRed, CurrentBlue, CurrentGreen, CurrentRed
Protected bmp.BITMAP, Size, Bits, *Memory, Offset, i
If GetObject_(Image, SizeOf(BITMAP), @bmp)
Size = (bmp\bmWidth * bmp\bmHeight) - 1
Bits = Int(bmp\bmBitsPixel / 8)
*Memory = bmp\bmBits
If Bits > 2 And Bits < 5
NewBlue = Blue(NewColor)
NewGreen = Green(NewColor)
NewRed = Red(NewColor)
For i=0 To Size
CurrentBlue = PeekB(*Memory + Offset) & $FF
CurrentGreen = PeekB(*Memory + Offset + 1) & $FF
CurrentRed = PeekB(*Memory + Offset + 2) & $FF
If RGB(CurrentRed, CurrentGreen, CurrentBlue) = OldColor
PokeB(*Memory + Offset, NewBlue)
PokeB(*Memory + Offset + 1, NewGreen)
PokeB(*Memory + Offset + 2, NewRed)
EndIf
Offset + Bits
Next
EndIf
EndIf
EndProcedure
Define SwapColor
If CreateImage(0, 128, 128, 24) And StartDrawing(ImageOutput(0))
Box(16, 0, 16, 128, RGB(255, 255, 255))
Box(32, 0, 16, 128, RGB(255, 0, 0))
Box(48, 0, 16, 128, RGB(0, 255, 0))
Box(64, 0, 16, 128, RGB(0, 0, 255))
Box(80, 0, 16, 128, RGB(0, 255, 255))
Box(96, 0, 16, 128, RGB(255, 0, 255))
Box(112, 0, 16, 128, RGB(255, 255, 0))
StopDrawing()
If OpenWindow(0, 0, 0, 138, 168, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ImageGadget(0, 5, 5, 128, 128, ImageID(0))
ButtonGadget(1, 5, 138, 128, 25, "Swap")
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
If EventGadget() = 1
If SwapColor
SwapImageColor(ImageID(0), RGB(128, 0, 128), RGB(255, 0, 255))
Else
SwapImageColor(ImageID(0), RGB(255, 0, 255), RGB(128, 0, 128))
EndIf
SwapColor ! 1
InvalidateRect_(GadgetID(0), 0, #True)
UpdateWindow_(GadgetID(0))
EndIf
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
EndIf
EndIf : End
Code: Select all
Point() + Plot() took 2882ms
SwapImageColor() took 27ms

edit1: RGB Macros added.
edit2: only one For : Next loop is used now. hope it works the way it should. feel free to report otherwise.
edit3: macros updated and removed unused variables.
c ya,
nco2k