QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: Petr on May 01, 2019, 07:39:12 am

Title: It seems that transparent colors are badly written to memory (explained)
Post by: Petr on May 01, 2019, 07:39:12 am
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.  
Title: Re: It seems that transparent colors are badly written to memory
Post by: Petr 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.  
Title: Re: It seems that transparent colors are badly written to memory
Post by: FellippeHeitor 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]
Title: Re: It seems that transparent colors are badly written to memory
Post by: Petr 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.  
Title: Re: It seems that transparent colors are badly written to memory
Post by: FellippeHeitor 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.  
Title: Re: It seems that transparent colors are badly written to memory
Post by: FellippeHeitor 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.
Title: Re: It seems that transparent colors are badly written to memory
Post by: FellippeHeitor 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.
Title: Re: It seems that transparent colors are badly written to memory
Post by: FellippeHeitor 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.
Title: Re: It seems that transparent colors are badly written to memory
Post by: Petr 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.
Title: Re: It seems that transparent colors are badly written to memory
Post by: SMcNeill 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.
Title: Re: It seems that transparent colors are badly written to memory (explained)
Post by: Petr on May 01, 2019, 09:23:23 am
Thank you Steve. I didn't know that. I'll  try it.
Title: Re: It seems that transparent colors are badly written to memory (explained)
Post by: Petr on May 10, 2019, 12:48:17 pm
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.  
Title: Re: It seems that transparent colors are badly written to memory (explained)
Post by: Petr on May 10, 2019, 01:23:48 pm
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.  

Title: Re: It seems that transparent colors are badly written to memory (explained)
Post by: Petr on May 10, 2019, 02:35:48 pm
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.