Attached is a patch for image.fromstring with ARGB. Also attached is a script (not a unit test) to demonstrate the error on the trunk and confirm the fix (all 4 columns should be identical, and it shouldn't print "ERROR")
... I should say even though I am confident the fix should work well on both endian architectures, I've only tested it myself on an intel machine... so somebody ought to test it on Mac too...
Attachment:
CorrectFromStringARGB.patch
Description: Binary data
import pygame import array #################################################################### def AreSurfacesIdentical(surf_a, surf_b): if surf_a.get_width() != surf_b.get_width() or surf_a.get_height() != surf_b.get_height(): return False for y in xrange(surf_a.get_height()): for x in xrange(surf_b.get_width()): if surf_a.get_at((x,y)) != surf_b.get_at((x,y)): return False return True #################################################################### def RotateRGBAtoARGB(str_buf): byte_buf = array.array("B", str_buf) num_quads = len(byte_buf)/4 for i in xrange(num_quads): alpha = byte_buf[i*4 + 3] byte_buf[i*4 + 3] = byte_buf[i*4 + 2] byte_buf[i*4 + 2] = byte_buf[i*4 + 1] byte_buf[i*4 + 1] = byte_buf[i*4 + 0] byte_buf[i*4 + 0] = alpha return byte_buf.tostring() #################################################################### def RotateARGBtoRGBA(str_buf): byte_buf = array.array("B", str_buf) num_quads = len(byte_buf)/4 for i in xrange(num_quads): alpha = byte_buf[i*4 + 0] byte_buf[i*4 + 0] = byte_buf[i*4 + 1] byte_buf[i*4 + 1] = byte_buf[i*4 + 2] byte_buf[i*4 + 2] = byte_buf[i*4 + 3] byte_buf[i*4 + 3] = alpha return byte_buf.tostring() #################################################################### test_surface = pygame.Surface((48, 256), flags=pygame.SRCALPHA, depth=32) for i in xrange(256): for j in xrange(16): intensity = j*16 + 15 test_surface.set_at((j + 0, i), (intensity, i, i, 255)) test_surface.set_at((j + 16, i), (i, intensity, i, 255)) test_surface.set_at((j + 32, i), (i, i, intensity, 255)) assert(AreSurfacesIdentical(test_surface, test_surface)) rgba_buf = pygame.image.tostring(test_surface, "RGBA") rgba_buf = RotateARGBtoRGBA(RotateRGBAtoARGB(rgba_buf)) test_rotate_functions = pygame.image.fromstring(rgba_buf, test_surface.get_size(), "RGBA") assert(AreSurfacesIdentical(test_surface, test_rotate_functions)) rgba_buf = pygame.image.tostring(test_surface, "RGBA") argb_buf = RotateRGBAtoARGB(rgba_buf) test_from_argb_string = pygame.image.fromstring(argb_buf, test_surface.get_size(), "ARGB") if not AreSurfacesIdentical(test_surface, test_from_argb_string): print "ERROR: image.fromstring with ARGB failed" argb_buf = pygame.image.tostring(test_surface, "ARGB") rgba_buf = RotateARGBtoRGBA(argb_buf) test_to_argb_string = pygame.image.fromstring(rgba_buf, test_surface.get_size(), "RGBA") if not AreSurfacesIdentical(test_surface, test_to_argb_string): print "ERROR: image.tostring with ARGB failed" argb_buf = pygame.image.tostring(test_surface, "ARGB") test_to_from_argb_string = pygame.image.fromstring(argb_buf, test_surface.get_size(), "ARGB") if not AreSurfacesIdentical(test_surface, test_to_from_argb_string): print "ERROR: image.fromstring and image.tostring with ARGB are not symmetric" pygame.display.init() screen = pygame.display.set_mode((320,256)) screen.fill((0,0,0)) screen.blit(test_surface,(0,0)) screen.blit(test_from_argb_string,(80,0)) screen.blit(test_to_argb_string,(160,0)) screen.blit(test_to_from_argb_string,(240,0)) pygame.display.update() while 1: for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == 27: raise SystemExit pygame.display.update()