[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] blit anomalies in pygame 1.8.1release (2)



Hi Nicholas,

Nicholas Dudfield wrote:
Lenard, Rene and co,

>> There is no unit test for blitting a SRCALPHA source with non-zero alpha to a SRCALPHA destination with non-zero alpha

I'm writing some tests for surface.blit atm. What is the expected behaviour of such an operation?

    def test_blit__SRCALPHA_to_SRCALPHA_non_zero(self):
# " There is no unit test for blitting a SRCALPHA source with non-zero
        #   alpha to a SRCALPHA destination with non-zero alpha " LL

        w,h = size = 32,32

        s = pygame.Surface(size, pygame.SRCALPHA, 32)
        s2 = s.copy()

        s.fill((32,32,32,111))
        s2.fill((32,32,32,31))

        s.blit(s2, (0,0))

        # TODO:
# what is the correct behaviour ?? should it blend? what algorithm?

        self.assertEquals(s.get_at((0,0)), (32,32,32,31))

Cheers. I'm not sure here.

I get (32, 32, 32, 129).

Here is a floating point equation for alpha blend of an rgb color element in a pixel. It is adapted from the one in the Python Image Library (PIL):

(dst * (255.0 - alpha) + src * alpha) / 255.0

So when src = dst = c:

(c * (255.0 - alpha) + c * alpha) / 255.0 =
(c * 255.0 - c * alpha + c * alpha) =
c

If source and destination colors are the same the resulting color is also the same, irregardless of alpha. Pygame calculates the new alpha value with some averaging formula I don't recognize:

dA = sA + dA - ((sA * dA) / 255)

So sA = 31 and dA = 111 gives 129.

Also, wrt to the blitting opaque source behaviour, are we considering this a bug? A failed test? I'm that way inclined and have written a test for that, will wait for approval before committing.

    def test_blit__SRCALPHA_opaque_source(self):
        src = pygame.Surface( (256,256), SRCALPHA ,32)
        dst = src.copy()

        for i, j in test_utils.rect_area_pts(src.get_rect()):
            dst.set_at( (i,j), (i,0,0,j) )
            src.set_at( (i,j), (0,i,0,255) )
dst.blit(src, (0,0))

        for pt in test_utils.rect_area_pts(src.get_rect()):
            self.assertEquals ( dst.get_at(pt)[1], src.get_at(pt)[1] )

According to the above floating point blend equation and Pygame's alpha equation this unit test should hold true. I have made it so in SVN. But will the change stick this time? Maybe there are some other instances where the new blend equation gives a slightly different value to the replaced equation. But will this truly cause breakage?

--
Lenard Lindstrom
<len-l@xxxxxxxxx>