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

[pygame] [PATCH] Surface.set_at() on BIG ENDIAN machines



Hi,

there seems to be bug in function Surface.set_at(). This bug appears
with 24-bit color depth Surface on BIG ENDIAN machines. 

I've attached patch for CVS version of pygame. The nicer solution would
be also to remove the code duplicities between src/draw.c:set_at() and
src/sruface.c:surf_set_at().

The other attached file "testSetAt.py" is simple script that should show
the bug. Please, try it on PowerPC machines. 
Its correct output should be:
==========
bytes per pixel: 3
old color expected: (100, 200, 255, 255)
old color: (100, 200, 255, 255)
new color expected: (10, 20, 30, 255)
new color: (10, 20, 30, 255)
==========

Note that function Surface.get_at() is correct, and you can use
Surface.fill(color, (position, (1,1))) instead of
Surface.set_at(position, color).

-- 
Ivo Danihelka
Index: src/draw.c
===================================================================
RCS file: /home/cvspsrv/cvsroot/games/pygame/src/draw.c,v
retrieving revision 1.39
diff -u -r1.39 draw.c
--- src/draw.c	3 Oct 2005 06:52:07 -0000	1.39
+++ src/draw.c	7 Jan 2006 11:41:48 -0000
@@ -910,9 +910,18 @@
 		default:/*case 3:*/
 			SDL_GetRGB(color, format, rgb, rgb+1, rgb+2);
 			byte_buf = (Uint8*)(pixels + y * surf->pitch) + x * 3;
-			*(byte_buf + (format->Rshift >> 3)) = rgb[0];
-			*(byte_buf + (format->Gshift >> 3)) = rgb[1];
-			*(byte_buf + (format->Bshift >> 3)) = rgb[2];
+			if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
+			{
+				*(byte_buf + (format->Rshift >> 3)) = rgb[0];
+				*(byte_buf + (format->Gshift >> 3)) = rgb[1];
+				*(byte_buf + (format->Bshift >> 3)) = rgb[2];
+			}
+			else
+			{
+				*(byte_buf + 2 - (format->Rshift >> 3)) = rgb[0];
+				*(byte_buf + 2 - (format->Gshift >> 3)) = rgb[1];
+				*(byte_buf + 2 - (format->Bshift >> 3)) = rgb[2];
+			}
 			break;
 	}
 	return 1;
Index: src/surface.c
===================================================================
RCS file: /home/cvspsrv/cvsroot/games/pygame/src/surface.c,v
retrieving revision 1.92
diff -u -r1.92 surface.c
--- src/surface.c	3 Oct 2005 06:52:07 -0000	1.92
+++ src/surface.c	7 Jan 2006 11:41:49 -0000
@@ -143,9 +143,18 @@
 			break;
 		case 3:
 			byte_buf = (Uint8*)(pixels + y * surf->pitch) + x * 3;
-			*(byte_buf + (format->Rshift >> 3)) = rgba[0];
-			*(byte_buf + (format->Gshift >> 3)) = rgba[1];
-			*(byte_buf + (format->Bshift >> 3)) = rgba[2];
+			if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
+			{
+				*(byte_buf + (format->Rshift >> 3)) = rgba[0];
+				*(byte_buf + (format->Gshift >> 3)) = rgba[1];
+				*(byte_buf + (format->Bshift >> 3)) = rgba[2];
+			}
+			else
+			{
+				*(byte_buf + 2 - (format->Rshift >> 3)) = rgba[0];
+				*(byte_buf + 2 - (format->Gshift >> 3)) = rgba[1];
+				*(byte_buf + 2 - (format->Bshift >> 3)) = rgba[2];
+			}
 			break;
 		default: /*case 4:*/
 			*((Uint32*)(pixels + y * surf->pitch) + x) = color;
#!/usr/bin/env python

import pygame

oldColor = (100, 200, 255, 255)
newColor = (10, 20, 30, 255)

def main():
    pygame.init()
    surface = pygame.Surface((1,1), 0, 24)
    print "bytes per pixel:", surface.get_bytesize()
    surface.fill(oldColor)
    surface.lock()
    print "old color expected:", oldColor
    print "old color:", surface.get_at((0,0))
    surface.set_at((0,0), newColor)
    print "new color expected:", newColor
    print "new color:", surface.get_at((0,0))
    surface.unlock()

#-----------------------------------------------------------------
main()