Ah, PixelArray. Of course! I'm actually using a PixelArray elsewhere in my
code to extract the integer values of the surface which is fed to a dot
matrix display. (My project is for a pinball machine.) My surface blits are
used to create an on screen representation in a display window of the
physical dot matrix display which is where I use the palette to set the
colors. (The actual physical dot matrix display only has 16 shades of pixel
brightness which is why I'm using an 8-bit surface.)

Anyway I don't know why I didn't think of using a PixelArray here, but
yeah, that makes total sense. Awesome.

Thanks so much for the feedback and ideas!
Brian

On Wed, Dec 3, 2014 at 4:25 PM, Lenard Lindstrom <le...@telus.net> wrote:

> Hi Brian,
>
> On 14-12-02 09:56 AM, Brian Madden wrote:
>
>> Hi. I'm working with 8-bit surfaces in Python 2.7 with Pygame 1.9.2pre.
>> Everything I've read says that if I blit an 8-bit surface to another 8-bit
>> surface, Pygame will ignore both palettes and only copy each pixel's 8-bit
>> integer value from the source surface to the destination surface.
>>
>>  A Pygame Surface lets the programmer work with SDL surfaces without the
> concern of how the pixel data is actually represented in memory. A Pygame
> Surface pixel is the decoded--unmapped--(R, G, B, A) representation of the
> color encoded--mapped--into the pixel's actual integer value. Since a
> Pygame Surface is a color representation its pixel data, it is natural that
> Surface methods do high level color transformations rather than direct
> integer value manipulation. So, Surface.blit() actually blits unmapped
> pixel colors, with the result mapped back into the destination surface
> binary format (Of course, shortcuts are taken when possible.)
>
>  My experience so far is that this is *not* what happens. Rather, I'm
>> seeing that that when blitting, Pygame will use the source surface's
>> palette to get the 24-bit entry for each pixel, then look for that 24-bit
>> value in the destination surface's palette, and then write the 8-bit
>> integer value from the destination surface's palette as the pixel value in
>> the destination surface. If there are no matching 24-bit palette entries
>> for the palettes for both surfaces, then the resulting pixel's integer
>> value in the destination surface is 0.
>>
> For two 8-bit surfaces without surface alpha or a color key the
> Surface.blit() method has SDL do the blit.
>
>
>> I'm just curious as to whether this is this a bug, or is my understanding
>> of how Pygame works with 8-bit surfaces not correct? (In my case I have
>> multiple surfaces each with their own palettes, and if I blit a pixel value
>> of "1" then I want it to be "1" on my destination surface regardless of
>> what any of the palettes are! :)
>>
>>  Yes, the Pygame.blit() method description lacks detail. It assumes the
> reader has some understanding of the SDL library. But this is no longer a
> reasonable expectation. The pygame.Surface documentation needs updating.
>
>
> It is possible to do a direct integer copy with pygame.PixelArray. Here is
> a basic example:
>
> def pxcopy(source, target, dest=None):
>     """Copy raw surface pixels from source to target
>
>        Argument dest is the (x, y) coordinates within the target surface
>        where the source surface will be copied. The default is (0, 0).
>        This simple example fails if the source rect does not fit entirely
>        within the target boundary."""
>
>     if dest is None:
>         dest = (0, 0)
>     x, y = dest
>     s = PixelArray(source)
>     w, h = s.shape
>     t = PixelArray(target)
>     t[x:x+w, y:y+h] = s
>
> >>> import pygame
> >>> pygame.display.init()  # Need this to enable Surface.set_palette()
> >>> from pygame import Surface, PixelArray
> >>> palette = [(i, i, i) for i in range(256)]
> >>> target = Surface((100, 100), 0, 8)
> >>> target.set_palette(palette)
> >>> target.set_palette(palette)
> >>> target.fill((30, 30, 30))
>  <rect(0, 0, 100, 100)>
> >>> target.get_at((10, 15))
> (30, 30, 30, 255)
> >>> target.get_at_mapped((10, 15))
> 30
> >>> source = Surface((20, 30), 0, 8)
> >>> source.fill((255, 0, 0))
> <rect(0, 0, 20, 30)>
> >>> source.get_at((0, 0))
> (255, 0, 0, 255)
> >>> source.get_at_mapped((0, 0))
> 96
> >>> pxcopy(source, target, (10, 15))
> >>> target.get_at_mapped((10, 15))
> 96
> >>> target.get_at((10, 15))
> (96, 96, 96, 255)
> >>> target.get_at((0, 0))
> (30, 30, 30, 255)
> >>>
>
>
> Lenard Lindstrom
>
>


-- 
*Brian Madden*
Mission Pinball (blog <http://missionpinball.com> | twitter
<https://twitter.com/missionpinball> | MPF software framework
<http://missionpinball.com/framework> | sample games
<https://missionpinball.com/blog/category/big-shot-em-conversion/>)

Reply via email to