QB64 Phoenix Edition
_CLEARCOLOR evety color EXCEPT ...? - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: Chatting and Socializing (https://qb64phoenix.com/forum/forumdisplay.php?fid=11)
+--- Forum: General Discussion (https://qb64phoenix.com/forum/forumdisplay.php?fid=2)
+--- Thread: _CLEARCOLOR evety color EXCEPT ...? (/showthread.php?tid=3643)



_CLEARCOLOR evety color EXCEPT ...? - madscijr - 04-27-2025

Hey all. I know _CLEARCOLOR can be used multiple times if you want more than one color transparent, but is there a way to -quickly- copy only pixels of a given color to another image? This would need to be fast, like for animation. I think a command like "_CLEARCOLOR ExceptColor~&" would be useful for this. Or do we just have to compare POINT for every pixel?


RE: _CLEARCOLOR evety color EXCEPT ...? - hsiangch_ong - 04-27-2025

(04-27-2025, 03:21 PM)madscijr Wrote: Or do we just have to compare POINT for every pixel?
what i would do is use _red, _green and _blue as well as point.  sometimes _alpha in addition.  because point is unreliable.  have one "target" color to compare each of the color registers.  then use abs with a threshold.  could use one threshold for all registers, or a separate threshold for each register for finer control.

sadly for typical 32-bit images it could be a bit sloppy.  it could produce dots spread out in far portions of the image.  which could look ugly for an user.

Code: (Select All)
dim as long targetcolor, readcolor
dim as integer rr, gg, bb, r1, g1, b1, x, y, threshcolor
targetcolor = _rgba(128, 0, 0, 255)
r1 = _red(targetcolor)
g1 = _green(targetcolor)
b1 = _blue(targetcolor)
threshcolor = 8
':
readcolor = point(x, y)
rr = _red(readcolor)
gg = _green(readcolor)
bb = _blue(readcolor)
if abs(rr - r1) <= threshcolor and abs(gg - g1) <= threshcolor and abs(bb - b1) <= threshcolor then
'do something
end if



RE: _CLEARCOLOR evety color EXCEPT ...? - Petr - 04-27-2025

(04-27-2025, 03:21 PM)madscijr Wrote: Hey all. I know _CLEARCOLOR can be used multiple times if you want more than one color transparent, but is there a way to -quickly- copy only pixels of a given color to another image? This would need to be fast, like for animation. I think a command like "_CLEARCOLOR ExceptColor~&" would be useful for this. Or do we just have to compare POINT for every pixel?

That is why it is recommended to use the _Mem commands. It is much faster than Point and PSet. However, you must watch the area that is read/written and take into account the type of image. An 8bit image uses the palette index number in the range 0 to 255 as information about the pixel color, so the size of one pixel of an 8bit image is equal to 1byte. (_Unsigned _Byte specifically).

While a 32bit image uses 4bytes in memory: (RGBA)

The following is an example - how to copy one color from one image to another FAST. I wrote a classic solution and then the same with _Mem.

Code: (Select All)

image1 = _NewImage(800, 600, 32)
image2 = _NewImage(800, 600, 32)

Repeat = 10

_Dest image1
Cls , _RGB32(255, 27, 0)
Line (100, 100)-(300, 300), _RGB32(250, 120, 100), BF

_Dest image2
Cls , _RGB32(100, 127, 169)
Line (600, 400)-(700, 550), _RGB32(255, 0, 100), BF
_Dest 0
Print "Two images created. Press any key for view first image..."
Sleep
Screen image1
Print "Press any key for view second image..."
Sleep
Screen image2
Print "Press any key for copying image 1 to image 2 using POINT..."
Sleep

'copy image1 to newhandle my
my = _CopyImage(image1, 32)

T = Timer

For r = 1 To Repeat
    For x = 0 To 799
        For y = 0 To 599
            _Source image2 'read pixels from image2
            _Dest my 'write pixels to my
            If Point(x, y) = _RGB32(255, 0, 100) Then PSet (x, y), _RGB32(255, 0, 100)
    Next y, x
Next

Screen my
Print "Done using POINT in"; Timer - T; "Press any key for the same operation using _MEM"
Sleep
Screen 0
_FreeImage my
my = _CopyImage(image1, 32)
T = Timer
Dim As _MEM m, n
Dim c As Long
Dim Search As _Unsigned Long
Search = _RGB32(255, 0, 100)

m = _MemImage(image2)
n = _MemImage(my)

For r = 1 To Repeat
    c = 0
    Do Until c = m.SIZE
        If _MemGet(m, m.OFFSET + c, _Unsigned Long) = Search Then
            _MemPut n, n.OFFSET + c, Search
        End If
        c = c + 4 'step is 4 byte in memory for 32 bit image
    Loop
Next r

Screen my
Print "Done using MEM in: "; Timer - T


Note that I intentionally set the program to execute the action 10 times in a row to highlight the difference in speed between PSET/POINT vs _MemGet and _MemPut. In my case, the speed difference is 100x.

Furthermore, when processing graphics (and other data), if you want it really fast, use loops DO... LOOP, While...Wend - they are faster than For...Next. When it comes to copying a square memory area, there are even faster _MEM methods than writing 4 bytes at 1 step per loop.


RE: _CLEARCOLOR evety color EXCEPT ...? - madscijr - 04-27-2025

Thanks for your replies - I'll look at these in more detail when at the PC as this seems to be more to consider than I expected, but I think this will work for me. Thanks again!


RE: _CLEARCOLOR evety color EXCEPT ...? - TempodiBasic - 04-27-2025

Hi
Quote:This would need to be fast, like for animation.
can you be more specific with an example?
Maybe the path is NOT _clearcolor

in the meanwhile I had 2 study with _Clearcolor and _SetAlpha

I took the third example from the wiki and going on I develop this first snippet...
BUT I brought with me a conceptual error that is in that example....
as result of running the code we must get that the foreground parts of the image copied over the screen always overwrite the background image of the screen, while increasing the alpha channel from 0 to 255, we must see the presence of the background of the image copied over the screen covering the background image of the screen. This doesn't happen because in the code it has been used _Setalpha  without a specific color OR range of colors so all the colors of the image copied over the screen (including its background color that before by _Clearcolor made transparent) change their degree of transparency. So all the image changes from transparent to opaque with no blending between image of the screen and the background of image pasted over it.
I must say that wiki says clearly that _Setalpha changes the alpha channel of all the colors of the image, also those that have been treated with _clearcolor before .

here the code
Code: (Select All)

Dim Shared As Long mainScreen, Image1, NewImage1, a
mainScreen = _NewImage(1200, 800, 32) ' Main Screen (viewable)
Screen mainScreen
_Title "Clearcolor study 1"
_ScreenMove 1, 1
Image1 = _NewImage(1200, 800, 32)

init


a = 0
d = 5
Do
    _Limit 10 'regulate speed of fades

    _PutImage , Image1
    a = a + d
    If a >= 255 Or a <= 0 Then d = -d: a = a + d: Sleep 2 'reverse fade
    _SetAlpha a, , NewImage1 'sets alpha level of all colors to fade image page in/out
    _PutImage (0, 342), NewImage1
    Locate 1, 1: Print "Alpha: "; a: Locate 1, 12: Print " Press a key to pause, r to restart, a to change alpha step, spacebar to quit    "
    _Display
    Kp$ = InKey$
    Select Case Kp$
        Case " ":
            System
        Case "r", "R":
            init
            a = 0
        Case "a", "A":
            Select Case d
                Case 1
                    d = 5
                Case 5
                    d = 10
                Case 10
                    d = 15
                Case 15
                    d = 1
            End Select
        Case Else
            If Kp$ <> "" Then Sleep
    End Select
Loop
End

Sub init
    If Image1& < -1 Then 'check loaded image handle value before using!
        _Dest Image1&
        Cls , _RGB32(Rnd * 255, Rnd * 255, Rnd * 255)
        For I = 1 To 10
            x = Rnd * 800
            y = Rnd * 400
            k = _RGB32(Rnd * 255, Rnd * 255, Rnd * 255)
            Circle (x, y), Rnd * 100, k
            Paint Step(0, 0), _RGB32(Rnd * 255, Rnd * 255, Rnd * 255), k
        Next I
        _Source Image1
        clr~& = Point(0, 0) 'get background color from image source
        _ClearColor clr~&, Image1 'clear background color of image
        NewImage1 = _NewImage(_Width(Image1), _Height(Image1), 32) 'new image page
        _PutImage , Image1, NewImage1 'put image without background color on new page
        _FreeImage Image1 'free loaded image from memory
    End If
    _Dest mainScreen:
    Cls , _RGB32(0, 0, 0, 255) 'the background of mainscreen is opaque black
    For I = 1 To 10
        Line (Rnd * 1200, Rnd * 800)-(Rnd * 1200, Rnd * 800), _RGB32(Rnd * 255, Rnd * 255, Rnd * 255), BF
    Next I
    Image1 = _CopyImage(mainScreen)

End Sub
it remains a good example of how to exclude a color of an image to avoid to be copied to another one.

So going on in the wiki I found the right information in page _SetAlpha and I keep informations from the example about the specific :
how to give the range of colors to treat with _setalpha without affecting all the colors of the image

here the code in which finally the background of the image copied on the screen goes ranging from transparent to opaque
Code: (Select All)

Dim Shared As Long mainScreen, Image1, NewImage1, a, topcolor
mainScreen = _NewImage(1200, 800, 32) ' Main Screen (viewable)
Screen mainScreen
_Title "Clearcolor study 2"
_ScreenMove 1, 1
Image1 = _NewImage(1200, 800, 32)

init


a = 0
d = 5
Do
    _Limit 10 'regulate speed of fades

    _PutImage , Image1
    a = a + d
    If a >= 255 Or a <= 0 Then d = -d: a = a + d: Sleep 2 'reverse fade
    _SetAlpha a, 0 To topcolor, NewImage1 'sets alpha level of all colors to fade image page in/out
    _PutImage (0, 342), NewImage1
    Locate 1, 1: Print "Alpha: "; a: Locate 1, 12: Print " Press a key to pause, r to restart, a to change alpha step, spacebar to quit    "
    _Display
    Kp$ = InKey$
    Select Case Kp$
        Case " ":
            System
        Case "r", "R":
            init
            a = 0
        Case "a", "A":
            Select Case d
                Case 1
                    d = 5
                Case 5
                    d = 10
                Case 10
                    d = 15
                Case 15
                    d = 1
            End Select
        Case Else
            If Kp$ <> "" Then Sleep
    End Select
Loop
End

Sub init
    If Image1 < -1 Then 'check loaded image handle value before using!
        _Dest Image1
        Cls , _RGB32(Rnd * 255, Rnd * 255, Rnd * 255)
        For I = 1 To 10
            x = Rnd * 800
            y = Rnd * 400
            k = _RGB32(Rnd * 255, Rnd * 255, Rnd * 255)
            Circle (x, y), Rnd * 100, k
            Paint Step(0, 0), _RGB32(Rnd * 255, Rnd * 255, Rnd * 255), k
        Next I
        _Source Image1
        clr~& = Point(0, 0) 'get background color from image source
        _ClearColor clr~&, Image1 'clear background color of image
        topcolor = clr~& - _RGBA(1, 1, 1, 0)
        NewImage1 = _NewImage(_Width(Image1), _Height(Image1), 32) 'new image page
        _PutImage , Image1, NewImage1 'put image without background color on new page
        _FreeImage Image1 'free loaded image from memory
    End If
    _Dest mainScreen:
    Cls , _RGB32(0, 0, 0, 255) 'the background of mainscreen is opaque black
    For I = 1 To 10
        Line (Rnd * 1200, Rnd * 800)-(Rnd * 1200, Rnd * 800), _RGB32(Rnd * 255, Rnd * 255, Rnd * 255), BF
    Next I
    Image1 = _CopyImage(mainScreen)

End Sub

I have found no day for _Clearcolor and _Setalpha keywords also if it seems a recurrent issue dealing with them

making mask or use _clearcolor
setting _cleacolor
printing to image handle
[/url][url=https://qb64phoenix.com/forum/showthread.php?tid=3606&highlight=_clearcolor]setalpha and clearcolor

I think that it is useful to have more example about how to specify the range of colors to treat with _Setalpha.
the range from Color1& TO Color2& must be continue? 
(i.e. from _RGB32(255,0,0) TO _RGB32(0,255,0) means that all colors with values between full Red and full Green are treated by _Setalpha?)
for different colors must I  use an array with handles of colors and apply _setalpha on each one at a time? (i.e. simulating the action of Palette Using and _SetPalette of legacy graphic screens?)
in the example taken from the wiki why topcolor = _RGBA(0,0,0,0)- _RGBA(1,1,1,0) and not only _RGBA(1,1,1,0) that is the next one after black transparent? 
Is it possible to claim a day for _Clearcolor and _Setalpha in the keyword of day?
a good day like this _Putimage day