Author Topic: Xor Magic ^2  (Read 6798 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Xor Magic ^2
« on: April 09, 2021, 09:37:55 pm »
Code: QB64: [Select]
  1. _Title "XOR Magic ^2" ' b+ revisit 2021-04-09
  2. Screen _NewImage(768, 512, 32)
  3. _Delay .25
  4.  
  5. For y = 0 To _Height
  6.     For x = 0 To _Width
  7.         PSet (x, y), _RGB(x Mod 256, (x Mod 256 Xor y) Mod 256, y Mod 256)
  8.     Next
  9.     red = Rnd * 255 \ 1
  10.     green = Rnd * 255 \ 1
  11.     blue = Rnd * 255 \ 1
  12.     _Title "XOR Magic ^2 " + Str$(red) + Str$(green) + Str$(blue)
  13.     For y = 0 To _Height
  14.         For x = 0 To _Width
  15.             c~& = Point(x, y)
  16.             cAnalysis c~&, r, g, b, a
  17.             PSet (x, y), _RGB32(r Xor red, g Xor green, b Xor blue, a)
  18.         Next
  19.     Next
  20.     _Limit 3
  21.  
  22. Sub cAnalysis (c As _Unsigned Long, outRed, outGrn, outBlu, outAlp)
  23.     outRed = _Red32(c): outGrn = _Green32(c): outBlu = _Blue32(c): outAlp = _Alpha32(c)
  24.  
  25.  

Offline euklides

  • Forum Regular
  • Posts: 128
    • View Profile
Re: Xor Magic ^2
« Reply #1 on: April 10, 2021, 11:29:47 am »
Very useful for making Scottish kilts !!! :)
Why not yes ?

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: Xor Magic ^2
« Reply #2 on: April 10, 2021, 11:31:48 am »
Hi @bplus
Nice graphics! I like it! :)
I modified your a code a little and I have used _MEM instead of POINT for getting color (_MEM is faster than POINT )
Code: QB64: [Select]
  1. _Title "XOR Magic ^2" ' b+ revisit 2021-04-09
  2. 'MEM mod by Ashish
  3. Screen _NewImage(768, 512, 32)
  4. _Delay .25
  5.  
  6. For y = 0 To _Height
  7.     For x = 0 To _Width
  8.         PSet (x, y), _RGB(x Mod 256, (x Mod 256 Xor y) Mod 256, y Mod 256)
  9.     Next
  10. m = _MemImage(0)
  11.  
  12.     red = Rnd * 255 \ 1
  13.     green = Rnd * 255 \ 1
  14.     blue = Rnd * 255 \ 1
  15.     _Title "XOR Magic ^2 " + Str$(red) + Str$(green) + Str$(blue)
  16.     For y = 0 To _Height - 1
  17.         For x = 0 To _Width - 1
  18.             b = _MemGet(m, m.OFFSET + (y * _Width + x) * 4, _Unsigned _Byte)
  19.             g = _MemGet(m, m.OFFSET + (y * _Width + x) * 4 + 1, _Unsigned _Byte)
  20.             r = _MemGet(m, m.OFFSET + (y * _Width + x) * 4 + 2, _Unsigned _Byte)
  21.             a = _MemGet(m, m.OFFSET + (y * _Width + x) * 4 + 3, _Unsigned _Byte)
  22.             'c~& = Point(x, y)
  23.             'cAnalysis c~&, r, g, b, a
  24.             PSet (x, y), _RGB32(r Xor red, g Xor green, b Xor blue, a)
  25.         Next
  26.     Next
  27.     _Limit 10
  28.  
  29. Sub cAnalysis (c As _Unsigned Long, outRed, outGrn, outBlu, outAlp)
  30.     outRed = _Red32(c): outGrn = _Green32(c): outBlu = _Blue32(c): outAlp = _Alpha32(c)
  31.  
  32.  
  33.  
  34.  
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Xor Magic ^2
« Reply #3 on: April 10, 2021, 12:56:32 pm »
Thanks!

@Ashish that is very nice demo for getting colors and using mem techniques.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Xor Magic ^2
« Reply #4 on: April 10, 2021, 04:45:54 pm »
Hi @bplus
Nice graphics! I like it! :)
I modified your a code a little and I have used _MEM instead of POINT for getting color (_MEM is faster than POINT )
Code: QB64: [Select]
  1. _Title "XOR Magic ^2" ' b+ revisit 2021-04-09
  2. 'MEM mod by Ashish
  3. Screen _NewImage(768, 512, 32)
  4. _Delay .25
  5.  
  6. For y = 0 To _Height
  7.     For x = 0 To _Width
  8.         PSet (x, y), _RGB(x Mod 256, (x Mod 256 Xor y) Mod 256, y Mod 256)
  9.     Next
  10. m = _MemImage(0)
  11.  
  12.     red = Rnd * 255 \ 1
  13.     green = Rnd * 255 \ 1
  14.     blue = Rnd * 255 \ 1
  15.     _Title "XOR Magic ^2 " + Str$(red) + Str$(green) + Str$(blue)
  16.     For y = 0 To _Height - 1
  17.         For x = 0 To _Width - 1
  18.             b = _MemGet(m, m.OFFSET + (y * _Width + x) * 4, _Unsigned _Byte)
  19.             g = _MemGet(m, m.OFFSET + (y * _Width + x) * 4 + 1, _Unsigned _Byte)
  20.             r = _MemGet(m, m.OFFSET + (y * _Width + x) * 4 + 2, _Unsigned _Byte)
  21.             a = _MemGet(m, m.OFFSET + (y * _Width + x) * 4 + 3, _Unsigned _Byte)
  22.             'c~& = Point(x, y)
  23.             'cAnalysis c~&, r, g, b, a
  24.             PSet (x, y), _RGB32(r Xor red, g Xor green, b Xor blue, a)
  25.         Next
  26.     Next
  27.     _Limit 10
  28.  
  29. Sub cAnalysis (c As _Unsigned Long, outRed, outGrn, outBlu, outAlp)
  30.     outRed = _Red32(c): outGrn = _Green32(c): outBlu = _Blue32(c): outAlp = _Alpha32(c)
  31.  
  32.  
  33.  
  34.  

If you’re looking for speed, move as much math as possible outside your loop.

  For y = 0 To (_Height -1) * 4 * _WIDTH STEP 4 * _WIDTH
        For x = 0 To (_Width - 1) * 4 STEP 4
            t = y + x
            b = _MemGet(m, m.OFFSET + t, _Unsigned _Byte)
            g = _MemGet(m, m.OFFSET + t + 1, _Unsigned _Byte)
            r = _MemGet(m, m.OFFSET + t + 2, _Unsigned _Byte)
            a = _MemGet(m, m.OFFSET + t + 3, _Unsigned _Byte)
            'c~& = Point(x, y)
            'cAnalysis c~&, r, g, b, a
            PSet (x, y), _RGB32(r Xor red, g Xor green, b Xor blue, a)
        Next
    Next

The fewer math calculations you do inside your loop, the faster it can process — which can really affect performance with _MEM.

Personally, since this checks the whole screen, I’d just make it a simple DO...LOOP

t = 0
DO UNTIL t >= m.size
    b = _MemGet(m, m.OFFSET + t, _Unsigned _Byte)
    g = _MemGet(m, m.OFFSET + t + 1, _Unsigned _Byte)
    r = _MemGet(m, m.OFFSET + t + 2, _Unsigned _Byte)
    _MEMPUT m, m.OFFSET + t, _RGB32(r Xor red, g Xor green, b Xor blue) AS STRING * 3
    t = t + 4
LOOP

Once it’s right, $CHECKING:OFF before it and $CHECKING:ON after it, and you’re not going to get it any faster.  (And since you’re not changing alpha levels at all, I don’t think you’re going to need to read or write them either, unless I’m missing something.)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Xor Magic ^2
« Reply #5 on: April 10, 2021, 05:21:36 pm »
Code: QB64: [Select]
  1.   _Limit 10

Really don't need speed, the above is already too fast to appreciate the varieties of color combinations.

I am sure in a 3D Game it would be different story.


Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Xor Magic ^2
« Reply #6 on: April 10, 2021, 08:04:43 pm »
Code: QB64: [Select]
  1.   _Limit 10

Really don't need speed, the above is already too fast to appreciate the varieties of color combinations.

I am sure in a 3D Game it would be different story.

Aye.  With a limit 10, POINT would be sufficient enough.  I just mentioned the difference with _MEM for: “ that is very nice demo for getting colors and using mem techniques”. 

I figured an example of how to optimize those MEM techniques might be useful  as well. ;D
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: Xor Magic ^2
« Reply #7 on: April 11, 2021, 04:30:11 am »
With MEM, the for next loops are not needed because _MEMIMAGE does all the work.

Slight mod on Steve's code example

Ya I like to DIM everything.  If T is DIMed as an INTEGER the code crashes so that's why it is DIMed as a _UNSIGNED LONG

If T is DIMed as a SINGLE it works too, but I think the _UNSIGNED LONG is faster?

That is another reason why DEFINT A-Z   is bad practice.

DEFINT A-Z is just like buying a set of tools with one missing.



Code: QB64: [Select]
  1. DIM Handle AS LONG
  2.  
  3. Handle = _NEWIMAGE(500, 500, 32)
  4.  
  5. SCREEN Handle
  6.  
  7. M = _MEMIMAGE(Handle)
  8.  
  9.  
  10.  
  11. LOCATE 10, 20: PRINT "SIZE OF IMAGE IS "; M.SIZE; "BYTES"
  12.  
  13.  
  14. LL1:
  15. T = 0
  16. DO UNTIL T >= M.SIZE
  17.     b = _MEMGET(M, M.OFFSET + T, _UNSIGNED _BYTE)
  18.     b = b XOR 255
  19.     _MEMPUT M, M.OFFSET + T, b
  20.  
  21.     g = _MEMGET(M, M.OFFSET + T + 1, _UNSIGNED _BYTE)
  22.     g = g XOR 255
  23.     _MEMPUT M, M.OFFSET + T + 1, g
  24.  
  25.     r = _MEMGET(M, M.OFFSET + T + 2, _UNSIGNED _BYTE)
  26.     r = r XOR 0
  27.     _MEMPUT M, M.OFFSET + T + 2, r
  28.  
  29.     T = T + 4
  30.  
  31.     i$ = INKEY$
  32.     IF i$ = CHR$(27) THEN EXIT DO
  33.     _DELAY 1: GOTO LL1
  34.  
  35.  
« Last Edit: April 11, 2021, 04:46:30 am by NOVARSEG »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Xor Magic ^2
« Reply #8 on: April 11, 2021, 06:05:08 am »
@bplus
your squared pattern of colors have ipnotized me!

Cool!
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Xor Magic ^2
« Reply #9 on: April 11, 2021, 12:33:58 pm »
With MEM, the for next loops are not needed because _MEMIMAGE does all the work.

Slight mod on Steve's code example

Ya I like to DIM everything.  If T is DIMed as an INTEGER the code crashes so that's why it is DIMed as a _UNSIGNED LONG

If T is DIMed as a SINGLE it works too, but I think the _UNSIGNED LONG is faster?

That is another reason why DEFINT A-Z   is bad practice.

DEFINT A-Z is just like buying a set of tools with one missing.



Code: QB64: [Select]
  1. DIM Handle AS LONG
  2.  
  3. Handle = _NEWIMAGE(500, 500, 32)
  4.  
  5. SCREEN Handle
  6.  
  7. M = _MEMIMAGE(Handle)
  8.  
  9.  
  10.  
  11. LOCATE 10, 20: PRINT "SIZE OF IMAGE IS "; M.SIZE; "BYTES"
  12.  
  13.  
  14. LL1:
  15. T = 0
  16. DO UNTIL T >= M.SIZE
  17.     b = _MEMGET(M, M.OFFSET + T, _UNSIGNED _BYTE)
  18.     b = b XOR 255
  19.     _MEMPUT M, M.OFFSET + T, b
  20.  
  21.     g = _MEMGET(M, M.OFFSET + T + 1, _UNSIGNED _BYTE)
  22.     g = g XOR 255
  23.     _MEMPUT M, M.OFFSET + T + 1, g
  24.  
  25.     r = _MEMGET(M, M.OFFSET + T + 2, _UNSIGNED _BYTE)
  26.     r = r XOR 0
  27.     _MEMPUT M, M.OFFSET + T + 2, r
  28.  
  29.     T = T + 4
  30.  
  31.     i$ = INKEY$
  32.     IF i$ = CHR$(27) THEN EXIT DO
  33.     _DELAY 1: GOTO LL1
  34.  
  35.  


Yes, good practice to Dim or ReDIM everything.

@NOVARSEG  can you see why T as INTEGER is bad idea?

Quote
DEFINT A-Z is just like buying a set of tools with one missing.

These days we should use DefLng A-Z where we used DEFINT in old days, because Longs may actually be faster certainly wont be significantly slower and gives you much more range.

Missing a tool? Only if you expect that to cover everything. On the other hand, it could serve as a crack filler, automatically dimensioning variables you haven't formally dimensioned.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Xor Magic ^2
« Reply #10 on: April 11, 2021, 05:45:07 pm »
T as an integer works fine, as long as your image is less than 32767 bytes.  As a long, it works for images less than 2,147,483,647 bytes.

I’d suggest  making T an OFFSET, since you’re working with _MEM.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: Xor Magic ^2
« Reply #11 on: April 11, 2021, 10:09:41 pm »
A possible bug in QB64??

So I'm running this code

Code: QB64: [Select]
  1. DIM Handle AS LONG
  2.  
  3. Handle = _NEWIMAGE(500, 50, 32)
  4.  
  5. SCREEN Handle
  6.  
  7. M = _MEMIMAGE(Handle)
  8.  
  9.  
  10.  
  11. 'LOCATE 10, 20: PRINT "SIZE OF IMAGE IS "; M.SIZE; "BYTES"
  12. PRINT "SIZE OF IMAGE IS "; M.SIZE; "BYTES"
  13.  
  14. LL1:
  15. T = 0
  16. DO UNTIL T >= M.SIZE
  17.     b = _MEMGET(M, M.OFFSET + T, _UNSIGNED _BYTE)
  18.     b = b XOR 255
  19.     _MEMPUT M, M.OFFSET + T, b
  20.  
  21.     g = _MEMGET(M, M.OFFSET + T + 1, _UNSIGNED _BYTE)
  22.     g = g XOR 255
  23.     _MEMPUT M, M.OFFSET + T + 1, g
  24.  
  25.     r = _MEMGET(M, M.OFFSET + T + 2, _UNSIGNED _BYTE)
  26.     r = r XOR 0
  27.     _MEMPUT M, M.OFFSET + T + 2, r
  28.  
  29.     T = T + 4
  30.  
  31.     i$ = INKEY$
  32.     IF i$ = CHR$(27) THEN EXIT DO
  33.     _DELAY 1: GOTO LL1
  34.  

and can see the text display on screen

when I change
Handle = _NEWIMAGE(500, 50, 32)

to

Handle = _NEWIMAGE(500, 40, 32)

The text no longer displays, why?

more tests
Handle = _NEWIMAGE(500, 48, 32) displays text

Handle = _NEWIMAGE(500, 47, 32)  does not display text


« Last Edit: April 11, 2021, 10:49:28 pm by NOVARSEG »

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: Xor Magic ^2
« Reply #12 on: April 11, 2021, 11:23:54 pm »
more tests

changing line

PRINT "SIZE OF IMAGE IS "; M.SIZE; "BYTES"
to
PRINT "SIZE OF IMAGE IS "; M.SIZE; "BYTES";

works. 

Handle = _NEWIMAGE(500, 16, 32) displays text

Handle = _NEWIMAGE(500, 15, 32)  does not display text

It looks like text is 16 pixels high.  Without the semi colon there is an additional 2 lines of  what looks to be line feeds

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: Xor Magic ^2
« Reply #13 on: April 12, 2021, 03:31:26 am »
Blinking cursor with MEM

The lines with MEMGET can be commented out and it still works.

Code: QB64: [Select]
  1. DIM Handle AS LONG
  2. DIM curWidth AS INTEGER
  3. DIM curPosX AS INTEGER
  4. DIM curOffset AS _UNSIGNED LONG
  5.  
  6. Text = "Blinking cursor with MEM"
  7.  
  8. Handle = _NEWIMAGE(500, 300, 32)
  9.  
  10. SCREEN Handle
  11.  
  12. M = _MEMIMAGE(Handle)
  13.  
  14.  
  15. 'DIM a AS _UNSIGNED _BYTE
  16. curWidth = (_PRINTWIDTH(CHR$(a)) - 2) * 4
  17.  
  18. curPosX = _PRINTWIDTH(Text) * 4
  19.  
  20. PRINT Text
  21.  
  22. curOffset = 4 * _WIDTH * (14 + 16) + curPosX
  23. LL1:
  24.  
  25. FOR T = curOffset TO curOffset + curWidth STEP 4
  26.  
  27.     b = _MEMGET(M, M.OFFSET + T, _UNSIGNED _BYTE)
  28.     b = 255
  29.     _MEMPUT M, M.OFFSET + T, b
  30.  
  31.     g = _MEMGET(M, M.OFFSET + T + 1, _UNSIGNED _BYTE)
  32.     g = 255
  33.     _MEMPUT M, M.OFFSET + T + 1, g
  34.  
  35.     r = _MEMGET(M, M.OFFSET + T + 2, _UNSIGNED _BYTE)
  36.     r = 0
  37.     _MEMPUT M, M.OFFSET + T + 2, r
  38.  
  39.  
  40. FOR T = curOffset TO curOffset + curWidth STEP 4
  41.  
  42.     b = _MEMGET(M, M.OFFSET + T, _UNSIGNED _BYTE)
  43.     b = 0
  44.     _MEMPUT M, M.OFFSET + T, b
  45.  
  46.     g = _MEMGET(M, M.OFFSET + T + 1, _UNSIGNED _BYTE)
  47.     g = 0
  48.     _MEMPUT M, M.OFFSET + T + 1, g
  49.  
  50.     r = _MEMGET(M, M.OFFSET + T + 2, _UNSIGNED _BYTE)
  51.     r = 0
  52.     _MEMPUT M, M.OFFSET + T + 2, r
  53.  
  54. i$ = INKEY$
  55. IF i$ = CHR$(27) THEN END
  56. GOTO LL1
  57.  

« Last Edit: April 12, 2021, 03:44:29 am by NOVARSEG »

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: Xor Magic ^2
« Reply #14 on: April 12, 2021, 04:30:25 am »
Moving cursor with MEM

Code: QB64: [Select]
  1. DIM Handle AS LONG
  2. DIM curWidth AS INTEGER
  3. DIM curPosX AS INTEGER
  4. DIM curOffset AS _UNSIGNED LONG
  5.  
  6. Text = "Moving cursor with MEM"
  7.  
  8. Handle = _NEWIMAGE(400, 400, 32)
  9.  
  10. SCREEN Handle
  11.  
  12. M = _MEMIMAGE(Handle)
  13.  
  14. 'DIM a AS _UNSIGNED _BYTE
  15. curWidth = (_PRINTWIDTH(CHR$(a)) - 2) * 4
  16.  
  17. curPosX = _PRINTWIDTH(Text) * 4
  18.  
  19. PRINT "  l to move left, r to move right"
  20. PRINT Text
  21.  
  22. curOffset = 4 * _WIDTH * (15 + 32) + curPosX
  23. FOR T = curOffset TO curOffset + curWidth STEP 4
  24.  
  25.     'b = _MEMGET(M, M.OFFSET + T, _UNSIGNED _BYTE)
  26.     b = 255
  27.     _MEMPUT M, M.OFFSET + T, b
  28.  
  29.     'g = _MEMGET(M, M.OFFSET + T + 1, _UNSIGNED _BYTE)
  30.     g = 255
  31.     _MEMPUT M, M.OFFSET + T + 1, g
  32.  
  33.     ' r = _MEMGET(M, M.OFFSET + T + 2, _UNSIGNED _BYTE)
  34.     r = 0
  35.     _MEMPUT M, M.OFFSET + T + 2, r
  36.  
  37.     i$ = INKEY$
  38.     IF i$ = CHR$(27) THEN END
  39.  
  40.     IF i$ = "l" AND curPosX > 0 THEN
  41.         GOSUB curoff
  42.         curPosX = curPosX - _PRINTWIDTH(CHR$(a)) * 4
  43.         curOffset = 4 * _WIDTH * (15 + 32) + curPosX
  44.         GOSUB curon
  45.     END IF
  46.  
  47.     IF i$ = "r" AND curPosX + _PRINTWIDTH(CHR$(a)) * 4 < _WIDTH * 4 THEN
  48.         GOSUB curoff
  49.         curPosX = curPosX + _PRINTWIDTH(CHR$(a)) * 4
  50.         curOffset = 4 * _WIDTH * (15 + 32) + curPosX
  51.         GOSUB curon
  52.     END IF
  53.  
  54. curon:
  55. FOR T = curOffset TO curOffset + curWidth STEP 4
  56.  
  57.     'b = _MEMGET(M, M.OFFSET + T, _UNSIGNED _BYTE)
  58.     b = 255
  59.     _MEMPUT M, M.OFFSET + T, b
  60.  
  61.     'g = _MEMGET(M, M.OFFSET + T + 1, _UNSIGNED _BYTE)
  62.     g = 255
  63.     _MEMPUT M, M.OFFSET + T + 1, g
  64.  
  65.     ' r = _MEMGET(M, M.OFFSET + T + 2, _UNSIGNED _BYTE)
  66.     r = 0
  67.     _MEMPUT M, M.OFFSET + T + 2, r
  68.  
  69.  
  70.  
  71. curoff:
  72.  
  73. FOR T = curOffset TO curOffset + curWidth STEP 4
  74.  
  75.     'b = _MEMGET(M, M.OFFSET + T, _UNSIGNED _BYTE)
  76.     b = 0
  77.     _MEMPUT M, M.OFFSET + T, b
  78.  
  79.     ' g = _MEMGET(M, M.OFFSET + T + 1, _UNSIGNED _BYTE)
  80.     g = 0
  81.     _MEMPUT M, M.OFFSET + T + 1, g
  82.  
  83.     'r = _MEMGET(M, M.OFFSET + T + 2, _UNSIGNED _BYTE)
  84.     r = 0
  85.     _MEMPUT M, M.OFFSET + T + 2, r
  86.