Author Topic: It seems that transparent colors are badly written to memory (explained)  (Read 3916 times)

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Hi. Maybe that's just my fault, but this program returns faulty results for _RGBA32 colors. When writing _RGB32 colors, the values return correct. That's why I was sitting at the computer at 3:00 am yesterday and didn't understand what the hell was going on ...

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. test = _NEWIMAGE(1, 1, 32)
  3. _DEST test
  4. PSET (0, 0), _RGBA32(20, 40, 60, 80)
  5. m = _MEMIMAGE(test)
  6. _MEMGET m, m.OFFSET, value
  7. PRINT value
  8. _SOURCE test: PRINT POINT(0, 0)
  9. PRINT _RED32(value)
  10. PRINT _BLUE32(value)
  11.  
  12. 'the same results for _RGBA32 if reading 4 * _UNSIGNED _BYTE type...
  13.  
« Last Edit: May 01, 2019, 09:17:33 am by Petr »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: It seems that transparent colors are badly written to memory
« Reply #1 on: May 01, 2019, 07:56:20 am »
Confirm. 32 bit values are writed as _RGB and not as _RGB32.

Bug is between _RGB and RGBA: With _RGB and _RED, _GREEN, _BLUE return corect values, With RGBA it return bad values:

Edit: RGB return bad alpha. Return 255 and not 80. RGBA return bad colors and correct alpha.
Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. test = _NEWIMAGE(1, 1, 32)
  3. _DEST test
  4. PSET (0, 0), _RGB(20, 40, 60, 80) 'Rewrite to _RGBA for BUG show
  5. m = _MEMIMAGE(test)
  6. _MEMGET m, m.OFFSET, value
  7. _SOURCE test:
  8. PRINT POINT(0, 0)
  9. PRINT value
  10. PRINT _RED(value)
  11. PRINT _GREEN(value)
  12. PRINT _BLUE(value)
  13. PRINT _ALPHA(value)
  14.  
  15. 'the same results for _RGBA32 if reading 4 * _UNSIGNED _BYTE type...
  16.  
« Last Edit: May 01, 2019, 07:59:57 am by Petr »

FellippeHeitor

  • Guest
Re: It seems that transparent colors are badly written to memory
« Reply #2 on: May 01, 2019, 08:13:34 am »
Not to turn down your findings but the syntax for_RGB() doesn't take a fourth alpha parameter. Please check the wiki:

Code: QB64: [Select]

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: It seems that transparent colors are badly written to memory
« Reply #3 on: May 01, 2019, 08:41:09 am »
Yeah I know, in the heat of searching ...

Fellippe, if I write the color value using MEMPUT, it's fine.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. test = _NEWIMAGE(1, 1, 32)
  3. _DEST test
  4. 'PSET (0, 0), _RGBA32(20, 40, 60, 80) ' PSET write it bad
  5. clr~& = _RGBA32(20, 40, 60, 80)
  6. 'PSET (0, 0), clr~& 'also wrong
  7.  
  8. m = _MEMIMAGE(test)
  9. _MEMPUT m, m.OFFSET, clr~& 'MEMPUT write it good
  10. _MEMGET m, m.OFFSET, value
  11. PRINT value
  12. _SOURCE test: PRINT POINT(0, 0)
  13. PRINT _RED32(value)
  14. PRINT _BLUE32(value)
  15.  
  16. 'the same results for _RGBA32 if reading 4 * _UNSIGNED _BYTE type...
  17.  
  18.  
  19.  
  20.  

FellippeHeitor

  • Guest
Re: It seems that transparent colors are badly written to memory
« Reply #4 on: May 01, 2019, 08:45:56 am »
Maybe this will clear things:

Code: QB64: [Select]
  1. col~& = _RGBA32(20, 40, 60, 80)
  2.  
  3. test = _NEWIMAGE(1, 1, 32)
  4. _DEST test
  5. PSET (0, 0), col~&
  6. _SOURCE test
  7. col2~& = POINT(0, 0)
  8.  
  9. m = _MEMIMAGE(test)
  10. _MEMGET m, m.OFFSET, value
  11.  
  12. PRINT "Size of memory block:"; m.SIZE
  13. PRINT "This:"; col~&
  14. PRINT "Shouldn't be the same as this: "; col2~&
  15. PRINT "But this should be the same as above: "; value
  16.  
  17. PRINT "These are the original RGBA values:"
  18. PRINT _RED32(col~&), _GREEN32(col~&), _BLUE32(col~&), _ALPHA32(col~&)
  19. PRINT "These, though, are the result of the values above *after being PSET/BLENDed on top of black*:"
  20. PRINT _RED32(col2~&), _GREEN32(col2~&), _BLUE32(col2~&), _ALPHA32(col2~&)
  21. PRINT _RED32(value), _GREEN32(value), _BLUE32(value), _ALPHA32(value)
  22.  
« Last Edit: May 01, 2019, 08:47:14 am by FellippeHeitor »

FellippeHeitor

  • Guest
Re: It seems that transparent colors are badly written to memory
« Reply #5 on: May 01, 2019, 08:49:42 am »
The thing is: You place a transparent color onto a black image. Pixels will blend with black. Read those back: they are not the same values anymore - because they blended. That's the purpose of transparency and alpha blending: having colors transform upon being applied.

Marked as best answer by Petr on May 01, 2019, 05:15:49 am

FellippeHeitor

  • Guest
Re: It seems that transparent colors are badly written to memory
« Reply #6 on: May 01, 2019, 08:55:01 am »
To make it even clearer (I hope):

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 400, 32)
  2.  
  3. color1~& = _RGBA32(255, 0, 0, 127)
  4. color2~& = _RGBA32(0, 0, 255, 127)
  5.  
  6. LINE (0, 0)-(300, 300), color1~&, BF
  7. LINE (100, 100)-(399, 399), color2~&, BF
  8.  
  9. PRINT "Color 1 = "; color1~&, _RED32(color1~&), _GREEN32(color1~&), _BLUE32(color1~&), _ALPHA32(color1~&)
  10. PRINT "Color 2 = "; color2~&, _RED32(color2~&), _GREEN32(color2~&), _BLUE32(color2~&), _ALPHA32(color2~&)
  11.  
  12. mix~& = POINT(200, 200)
  13.  
  14. PRINT "Mix     = "; mix~&, _RED32(mix~&), _GREEN32(mix~&), _BLUE32(mix~&), _ALPHA32(mix~&)
  15.  

Just as red and blue merge in the example above to form a new color, your transparent colors will merge with black to form a new color after they are put to the image. That's why you don't get the same values of the original color, because it's not the same color anymore after blending.
« Last Edit: May 01, 2019, 08:56:29 am by FellippeHeitor »

FellippeHeitor

  • Guest
Re: It seems that transparent colors are badly written to memory
« Reply #7 on: May 01, 2019, 08:57:35 am »
Also:
Quote
PSET write it bad

PSET write is good because it *does* blend. Memory write doesn't blend because it's raw manipulation.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: It seems that transparent colors are badly written to memory
« Reply #8 on: May 01, 2019, 09:14:14 am »
Oh, my God... Now it's clear to me. Thank you. Knowledge + :-D I assumed the background was 0,0,0,0, so it doesn't affect. Basically, a new screen without CLS is transparent. Alpha mixes everything together to create a new color. When I add the mutual transparency between the _SOFTWARE and _HARDWARE layers, that's the power to put this together. I go into the corner and I'll silent sit. :-D



Thank you, Fellippe.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: It seems that transparent colors are badly written to memory
« Reply #9 on: May 01, 2019, 09:19:03 am »
Alpha images blend with the background, by default.  If you have a red background, put a 50% transparent green background onto it, you end up with a faded yellow background.

If you want to maintain that 50% transparent green, and completely overwrite the red with it, use _DONTBLEND.  (Much like you’re doing with the MEM commands.)

************

Personally, since _DONTBLEND runs much faster than when blending is turned on by default, and since a lot of folks never use alpha images, I’ve always felt that it should be our default setting — but it’s not.  QB64 automatically tries to blend all images onto the original canvas, unless _DONTBLEND is invoked manually.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Thank you Steve. I didn't know that. I'll  try it.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
If someone was wondering how is the alpha channel calculated, when using MEM, it's easy. See this example.

Code: QB64: [Select]
  1.  
  2. img = _NEWIMAGE(1, 1, 32)
  3. _DEST img
  4. CLS 'alpha = 255
  5. PSET (0, 0), _RGB32(10, 20, 30, 204) '204 is 80 percent (base 100 percent is 255), 2.55(1 percent) * 80 (80 percent for alpha channel transparency) = 204.
  6. '                                     so output RED GREEN BLUE values are: 80 percent from 10 for RED: 0.1 * 80 = 8,
  7. '                                                                          80 percent from 20 for GREEN: 0.2 * 80 = 16
  8. '                                                                          80 percent from 30 for BLUE: 0.3 * 80 = 24
  9. '                                                                          ALPHA is allways 255, because RGB colors already reflect background
  10.  
  11. m = _MEMIMAGE(img)
  12. _MEMGET m, m.OFFSET, k~&
  13.  
  14.  
  15.  

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Here is sample application with an alpha channel with MEM for a PNG image that has an alpha channel. The purpose of this feature is to rotate the image 90 degrees, no more. It's one of the many subroutines I develop.

Code: QB64: [Select]
  1.  
  2. img = _LOADIMAGE("cat.png", 32)
  3. SCREEN MEM_ROTO_90(img)
  4.  
  5. FUNCTION MEM_ROTO_90 (img AS LONG)
  6.     DIM W AS LONG, H AS LONG
  7.     W = _WIDTH(img)
  8.     H = _HEIGHT(img)
  9.     MEM_ROTO_90 = _NEWIMAGE(H, W, 32)
  10.     m = _MEMIMAGE(img)
  11.     m2 = _MEMIMAGE(MEM_ROTO_90)
  12.     FOR Y = 0 TO H - 1
  13.         FOR X = W - 1 TO 1 STEP -1
  14.             _MEMGET m, m.OFFSET + (4 * (W - X + _WIDTH(img) * Y)), k
  15.             R = _RED32(k)
  16.             G = _GREEN32(k)
  17.             B = _BLUE32(k)
  18.             A = _ALPHA32(k)
  19.             nA = A / 2.55
  20.  
  21.             nR = R / 100 * nA
  22.             nG = G / 100 * nA
  23.             nB = B / 100 * nA
  24.  
  25.             k = _RGBA32(nR, nG, nB, 255)
  26.  
  27.             _MEMPUT m2, m2.OFFSET + (4 * (Y + _WIDTH(MEM_ROTO_90) * X)), k
  28.     NEXT X, Y
  29.     _MEMFREE m
  30.     _MEMFREE m2
  31.  


Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Previous source is just for black background. This one is for all background colors:

Code: QB64: [Select]
  1.  
  2. img = _LOADIMAGE("cat.png", 32)
  3. SCREEN _NEWIMAGE(800, 600, 32)
  4. CLS , _RGB32(255, 25, 125)
  5. a = MEM_ROTO_90(img)
  6. _PUTIMAGE (10, 10), a
  7.  
  8.  
  9.  
  10. FUNCTION MEM_ROTO_90 (img AS LONG)
  11.     DIM W AS LONG, H AS LONG
  12.     W = _WIDTH(img)
  13.     H = _HEIGHT(img)
  14.     MEM_ROTO_90 = _NEWIMAGE(H, W, 32)
  15.     m = _MEMIMAGE(img)
  16.     m2 = _MEMIMAGE(MEM_ROTO_90)
  17.     m3 = _MEMIMAGE(0)
  18.     FOR Y = 0 TO H - 1
  19.         FOR X = W - 1 TO 1 STEP -1
  20.             _MEMGET m, m.OFFSET + (4 * (W - X + _WIDTH(img) * Y)), k
  21.             _MEMGET m3, m3.OFFSET + (4 * (W - X + _WIDTH(img) * Y)), k3
  22.  
  23.             R = _RED32(k)
  24.             G = _GREEN32(k)
  25.             B = _BLUE32(k)
  26.             A = _ALPHA32(k)
  27.             nA = A / 2.55
  28.  
  29.             R3 = _RED32(k3)
  30.             G3 = _GREEN32(k3)
  31.             B3 = _BLUE32(k3)
  32.  
  33.             '            nR = R / 100 * nA
  34.             '            nG = G / 100 * nA
  35.             '            nB = B / 100 * nA
  36.  
  37.  
  38.             nR = NColor(R3, R, nA)
  39.             nG = NColor(G3, G, nA)
  40.             nB = NColor(B3, B, nA)
  41.             k = _RGBA32(nR, nG, nB, 255)
  42.             _MEMPUT m2, m2.OFFSET + (4 * (Y + _WIDTH(MEM_ROTO_90) * X)), k
  43.     NEXT X, Y
  44.     _MEMFREE m
  45.     _MEMFREE m2
  46.     _MEMFREE m3
  47.  
  48. FUNCTION NColor~& (Background AS _UNSIGNED _BYTE, Foreground AS _UNSIGNED _BYTE, Alpha AS SINGLE)
  49.     NColor = Background - ((Background - Foreground) / 100) * Alpha
  50.