2
pygame - Python Game Library
3
Copyright (C) 2000-2001 Pete Shinners
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License as published by the Free Software Foundation; either
8
version 2 of the License, or (at your option) any later version.
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public
16
License along with this library; if not, write to the Free
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
#include<Numeric/arrayobject.h>
25
#include<SDL_byteorder.h>
30
/*DOC*/ static char doc_pixels3d[] =
31
/*DOC*/ "pygame.surfarray.pixels3d(Surface) -> Array\n"
32
/*DOC*/ "get a 3d reference array to a surface\n"
34
/*DOC*/ "This returns a new noncontigous 3d array that\n"
35
/*DOC*/ "directly effects a Surface's contents. Think of it\n"
36
/*DOC*/ "as a 2d image array with an RGB array for each\n"
37
/*DOC*/ "pixel value.\n"
39
/*DOC*/ "This will only work for 24 and 32 bit surfaces,\n"
40
/*DOC*/ "where the RGB components can be accessed as 8-bit\n"
41
/*DOC*/ "components.\n"
43
/*DOC*/ "This function will lock the given surface, and it\n"
44
/*DOC*/ "will remained locked for as long as the pixel array\n"
48
static PyObject* pixels3d(PyObject* self, PyObject* arg)
51
PyObject* array, *surfobj;
55
const int lilendian = (SDL_BYTEORDER == SDL_LIL_ENDIAN);
58
if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
60
surf = PySurface_AsSurface(surfobj);
62
if(surf->format->BytesPerPixel <= 2 || surf->format->BytesPerPixel > 4)
63
return RAISE(PyExc_ValueError, "unsupport bit depth for 3D reference array");
65
lifelock = PySurface_LockLifetime(surfobj);
66
if(!lifelock) return NULL;
68
/*must discover information about how data is packed*/
69
if(surf->format->Rmask == 0xff<<16 &&
70
surf->format->Gmask == 0xff<<8 &&
71
surf->format->Bmask == 0xff)
73
pixelstep = (lilendian ? -1 : 1);
74
startpixel = ((char*)surf->pixels) + (lilendian ? 2 : 0);
76
else if(surf->format->Bmask == 0xff<<16 &&
77
surf->format->Gmask == 0xff<<8 &&
78
surf->format->Rmask == 0xff)
80
pixelstep = (lilendian ? 1 : -1);
81
startpixel = ((char*)surf->pixels) + (lilendian ? 0 : 2);
84
return RAISE(PyExc_ValueError, "unsupport colormasks for 3D reference array");
85
if(!lilendian && surf->format->BytesPerPixel == 4)
88
/*create the referenced array*/
91
dim[2] = 3; /*could be 4 if alpha in the house*/
92
array = PyArray_FromDimsAndData(3, dim, PyArray_UBYTE, startpixel);
95
((PyArrayObject*)array)->flags = OWN_DIMENSIONS|OWN_STRIDES|SAVESPACE;
96
((PyArrayObject*)array)->strides[2] = pixelstep;
97
((PyArrayObject*)array)->strides[1] = surf->pitch;
98
((PyArrayObject*)array)->strides[0] = surf->format->BytesPerPixel;
99
((PyArrayObject*)array)->base = lifelock;
106
/*DOC*/ static char doc_pixels2d[] =
107
/*DOC*/ "pygame.surfarray.pixels2d(Surface) -> Array\n"
108
/*DOC*/ "get a 2d reference array to a surface\n"
110
/*DOC*/ "This returns a new noncontigous 2d array that\n"
111
/*DOC*/ "directly effects a Surface's contents. Think of it\n"
112
/*DOC*/ "as a 2d image array with a mapped pixel value at\n"
113
/*DOC*/ "each index.\n"
115
/*DOC*/ "This will not work on 24bit surfaces, since there\n"
116
/*DOC*/ "is no native 24bit data type to access the pixel\n"
119
/*DOC*/ "This function will lock the given surface, and it\n"
120
/*DOC*/ "will remained locked for as long as the pixel array\n"
124
static PyObject* pixels2d(PyObject* self, PyObject* arg)
126
int types[] = {PyArray_UBYTE, PyArray_SHORT, 0, PyArray_INT};
129
PyObject *array, *surfobj;
133
if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
135
surf = PySurface_AsSurface(surfobj);
138
if(surf->format->BytesPerPixel == 3 || surf->format->BytesPerPixel < 1 || surf->format->BytesPerPixel > 4)
139
return RAISE(PyExc_ValueError, "unsupport bit depth for 2D reference array");
141
lifelock = PySurface_LockLifetime(surfobj);
142
if(!lifelock) return NULL;
146
type = types[surf->format->BytesPerPixel-1];
147
array = PyArray_FromDimsAndData(2, dim, type, (char*)surf->pixels);
150
((PyArrayObject*)array)->strides[1] = surf->pitch;
151
((PyArrayObject*)array)->strides[0] = surf->format->BytesPerPixel;
152
((PyArrayObject*)array)->flags = OWN_DIMENSIONS|OWN_STRIDES;
153
((PyArrayObject*)array)->base = lifelock;
159
/*DOC*/ static char doc_pixels_alpha[] =
160
/*DOC*/ "pygame.surfarray.pixels_alpha(Surface) -> Array\n"
161
/*DOC*/ "get a reference array to a surface alpha data\n"
163
/*DOC*/ "This returns a new noncontigous array that directly\n"
164
/*DOC*/ "effects a Surface's alpha contents.\n"
166
/*DOC*/ "This will only work for 32bit surfaces with a pixel\n"
167
/*DOC*/ "alpha channel enabled.\n"
169
/*DOC*/ "This function will lock the given surface, and it\n"
170
/*DOC*/ "will remained locked for as long as the pixel array\n"
174
static PyObject* pixels_alpha(PyObject* self, PyObject* arg)
177
PyObject *array, *surfobj;
181
const int lilendian = (SDL_BYTEORDER == SDL_LIL_ENDIAN);
183
if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
185
surf = PySurface_AsSurface(surfobj);
187
if(surf->format->BytesPerPixel != 4)
188
return RAISE(PyExc_ValueError, "unsupport bit depth for alpha array");
190
lifelock = PySurface_LockLifetime(surfobj);
191
if(!lifelock) return NULL;
193
/*must discover information about how data is packed*/
194
if(surf->format->Amask == 0xff<<24)
195
startpixel = ((char*)surf->pixels) + (lilendian ? 3 : 0);
196
else if(surf->format->Amask == 0xff)
197
startpixel = ((char*)surf->pixels) + (lilendian ? 0 : 3);
199
return RAISE(PyExc_ValueError, "unsupport colormasks for alpha reference array");
203
array = PyArray_FromDimsAndData(2, dim, PyArray_UBYTE, startpixel);
206
((PyArrayObject*)array)->strides[1] = surf->pitch;
207
((PyArrayObject*)array)->strides[0] = surf->format->BytesPerPixel;
208
((PyArrayObject*)array)->flags = OWN_DIMENSIONS|OWN_STRIDES;
209
((PyArrayObject*)array)->base = lifelock;
215
/*DOC*/ static char doc_array2d[] =
216
/*DOC*/ "pygame.surfarray.array2d(Surface) -> Array\n"
217
/*DOC*/ "get a 2d array copied from a surface\n"
219
/*DOC*/ "This returns a new contigous 2d array. Think of it\n"
220
/*DOC*/ "as a 2d image array with a mapped pixel value at\n"
221
/*DOC*/ "each index.\n"
223
/*DOC*/ "This function will temporarily lock the surface.\n"
226
PyObject* array2d(PyObject* self, PyObject* arg)
230
PyObject *surfobj, *array;
232
int stridex, stridey;
234
if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
236
surf = PySurface_AsSurface(surfobj);
241
if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
242
return RAISE(PyExc_ValueError, "unsupport bit depth for surface array");
243
array = PyArray_FromDims(2, dim, PyArray_INT);
244
if(!array) return NULL;
246
stridex = ((PyArrayObject*)array)->strides[0];
247
stridey = ((PyArrayObject*)array)->strides[1];
249
if(!PySurface_Lock(surfobj)) return NULL;
251
switch(surf->format->BytesPerPixel)
254
for(loopy = 0; loopy < surf->h; ++loopy)
256
Uint8* pix = (Uint8*)(((char*)surf->pixels)+loopy*surf->pitch);
257
Uint8* end = (Uint8*)(((char*)pix)+surf->w);
258
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
261
*(Uint32*)data = *pix++;
266
for(loopy = 0; loopy < surf->h; ++loopy)
268
Uint16* pix = (Uint16*)(((char*)surf->pixels)+loopy*surf->pitch);
269
Uint16* end = (Uint16*)(((char*)pix)+surf->w*2);
270
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
273
*(Uint32*)data = *pix++;
278
for(loopy = 0; loopy < surf->h; ++loopy)
280
Uint8* pix = (Uint8*)(((char*)surf->pixels)+loopy*surf->pitch);
281
Uint8* end = pix+surf->w*3;
282
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
285
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
286
*(Uint32*)data = pix[0] + (pix[1]<<8) + (pix[2]<<16);
288
*(Uint32*)data = pix[2] + (pix[1]<<8) + (pix[0]<<16);
295
for(loopy = 0; loopy < surf->h; ++loopy)
297
Uint32* pix = (Uint32*)(((char*)surf->pixels)+loopy*surf->pitch);
298
Uint32* end = (Uint32*)(((char*)pix)+surf->w*4);
299
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
302
*(Uint32*)data = *pix++;
308
if(!PySurface_Unlock(surfobj)) return NULL;
314
/*DOC*/ static char doc_array3d[] =
315
/*DOC*/ "pygame.surfarray.array3d(Surface) -> Array\n"
316
/*DOC*/ "get a 3d array copied from a surface\n"
318
/*DOC*/ "This returns a new contigous 3d array. Think of it\n"
319
/*DOC*/ "as a 2d image array with an RGB array for each\n"
320
/*DOC*/ "pixel value.\n"
322
/*DOC*/ "This function will temporarily lock the surface.\n"
325
PyObject* array3d(PyObject* self, PyObject* arg)
329
PyObject *array, *surfobj;
331
SDL_PixelFormat* format;
332
int Rmask, Gmask, Bmask, Rshift, Gshift, Bshift, Rloss, Gloss, Bloss;
333
int stridex, stridey;
336
if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
338
surf = PySurface_AsSurface(surfobj);
340
format = surf->format;
344
Rmask = format->Rmask; Gmask = format->Gmask; Bmask = format->Bmask;
345
Rshift = format->Rshift; Gshift = format->Gshift; Bshift = format->Bshift;
346
Rloss = format->Rloss; Gloss = format->Gloss; Bloss = format->Bloss;
348
if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
349
return RAISE(PyExc_ValueError, "unsupport bit depth for surface array");
351
array = PyArray_FromDims(3, dim, PyArray_UBYTE);
352
if(!array) return NULL;
354
stridex = ((PyArrayObject*)array)->strides[0];
355
stridey = ((PyArrayObject*)array)->strides[1];
357
if(!PySurface_Lock(surfobj)) return NULL;
359
switch(surf->format->BytesPerPixel)
364
if(!PySurface_Unlock(surfobj)) return NULL;
365
return RAISE(PyExc_RuntimeError, "8bit surface has no palette");
367
palette = format->palette->colors;
368
for(loopy = 0; loopy < surf->h; ++loopy)
370
Uint8* pix = (Uint8*)(((char*)surf->pixels)+loopy*surf->pitch);
371
Uint8* end = (Uint8*)(((char*)pix)+surf->w*surf->format->BytesPerPixel);
372
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
375
SDL_Color* c = palette + (*pix++);
383
for(loopy = 0; loopy < surf->h; ++loopy)
385
Uint16* pix = (Uint16*)(((char*)surf->pixels)+loopy*surf->pitch);
386
Uint16* end = (Uint16*)(((char*)pix)+surf->w*surf->format->BytesPerPixel);
387
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
390
Uint32 color = *pix++;
391
data[0] = ((color&Rmask)>>Rshift)<<Rloss;
392
data[1] = ((color&Gmask)>>Gshift)<<Gloss;
393
data[2] = ((color&Bmask)>>Bshift)<<Bloss;
398
for(loopy = 0; loopy < surf->h; ++loopy)
400
Uint8* pix = (Uint8*)(((char*)surf->pixels)+loopy*surf->pitch);
401
Uint8* end = (Uint8*)(((char*)pix)+surf->w*surf->format->BytesPerPixel);
402
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
405
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
406
Uint32 color = (pix[0]) + (pix[1]<<8) + (pix[2]<<16); pix += 3;
408
Uint32 color = (pix[2]) + (pix[1]<<8) + (pix[0]<<16); pix += 3;
410
data[0] = ((color&Rmask)>>Rshift)/*<<Rloss*/; /*assume no loss on 24bit*/
411
data[1] = ((color&Gmask)>>Gshift)/*<<Gloss*/;
412
data[2] = ((color&Bmask)>>Bshift)/*<<Bloss*/;
417
for(loopy = 0; loopy < surf->h; ++loopy)
419
Uint32* pix = (Uint32*)(((char*)surf->pixels)+loopy*surf->pitch);
420
Uint32* end = (Uint32*)(((char*)pix)+surf->w*surf->format->BytesPerPixel);
421
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
424
Uint32 color = *pix++;
425
data[0] = ((color&Rmask)>>Rshift)/*<<Rloss*/; /*assume no loss on 32bit*/
426
data[1] = ((color&Gmask)>>Gshift)/*<<Gloss*/;
427
data[2] = ((color&Bmask)>>Bshift)/*<<Bloss*/;
433
if(!PySurface_Unlock(surfobj)) return NULL;
440
/*DOC*/ static char doc_array_alpha[] =
441
/*DOC*/ "pygame.surfarray.array_alpha(Surface) -> Array\n"
442
/*DOC*/ "get an array with a surface pixel alpha values\n"
444
/*DOC*/ "This returns a new contigous 2d array with the\n"
445
/*DOC*/ "alpha values of an image as unsigned bytes. If the\n"
446
/*DOC*/ "surface has no alpha, an array of all opaque values\n"
447
/*DOC*/ "is returned.\n"
449
/*DOC*/ "This function will temporarily lock the surface.\n"
452
PyObject* array_alpha(PyObject* self, PyObject* arg)
457
PyObject *array, *surfobj;
459
int stridex, stridey;
460
int Ashift, Amask, Aloss;
462
if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
464
surf = PySurface_AsSurface(surfobj);
469
if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
470
return RAISE(PyExc_ValueError, "unsupport bit depth for alpha array");
472
array = PyArray_FromDims(2, dim, PyArray_UBYTE);
473
if(!array) return NULL;
475
Amask = surf->format->Amask;
476
Ashift = surf->format->Ashift;
477
Aloss = surf->format->Aloss;
479
if(!Amask || surf->format->BytesPerPixel==1) /*no pixel alpha*/
481
memset(((PyArrayObject*)array)->data, 255, surf->w * surf->h);
485
stridex = ((PyArrayObject*)array)->strides[0];
486
stridey = ((PyArrayObject*)array)->strides[1];
488
if(!PySurface_Lock(surfobj)) return NULL;
490
switch(surf->format->BytesPerPixel)
493
for(loopy = 0; loopy < surf->h; ++loopy)
495
Uint16* pix = (Uint16*)(((char*)surf->pixels)+loopy*surf->pitch);
496
Uint16* end = (Uint16*)(((char*)pix)+surf->w*2);
497
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
501
*data = (color & Amask) >> Ashift << Aloss;
506
for(loopy = 0; loopy < surf->h; ++loopy)
508
Uint8* pix = (Uint8*)(((char*)surf->pixels)+loopy*surf->pitch);
509
Uint8* end = pix+surf->w*3;
510
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
513
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
514
color = pix[0] + (pix[1]<<8) + (pix[2]<<16);
516
color = pix[2] + (pix[1]<<8) + (pix[0]<<16);
518
*data = (color & Amask) >> Ashift << Aloss;
524
for(loopy = 0; loopy < surf->h; ++loopy)
526
Uint32* pix = (Uint32*)(((char*)surf->pixels)+loopy*surf->pitch);
527
Uint32* end = (Uint32*)(((char*)pix)+surf->w*4);
528
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
532
*data = (color & Amask) >> Ashift /*<< Aloss*/; /*assume no loss in 32bit*/
538
if(!PySurface_Unlock(surfobj)) return NULL;
544
/*DOC*/ static char doc_array_colorkey[] =
545
/*DOC*/ "pygame.surfarray.array_colorkey(Surface) -> Array\n"
546
/*DOC*/ "get an array with a surface colorkey values\n"
548
/*DOC*/ "This returns a new contigous 2d array with the\n"
549
/*DOC*/ "colorkey values of an image as unsigned bytes. If the\n"
550
/*DOC*/ "surface has no colorkey, an array of all opaque values\n"
551
/*DOC*/ "is returned. Otherwise the array is either 0's or 255's.\n"
553
/*DOC*/ "This function will temporarily lock the surface.\n"
556
PyObject* array_colorkey(PyObject* self, PyObject* arg)
560
Uint32 color, colorkey;
561
PyObject *array, *surfobj;
563
int stridex, stridey;
565
if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
567
surf = PySurface_AsSurface(surfobj);
572
if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
573
return RAISE(PyExc_ValueError, "unsupport bit depth for colorkey array");
575
array = PyArray_FromDims(2, dim, PyArray_UBYTE);
576
if(!array) return NULL;
578
colorkey = surf->format->colorkey;
579
if(!(surf->flags & SDL_SRCCOLORKEY)) /*no pixel alpha*/
581
memset(((PyArrayObject*)array)->data, 255, surf->w * surf->h);
585
stridex = ((PyArrayObject*)array)->strides[0];
586
stridey = ((PyArrayObject*)array)->strides[1];
588
if(!PySurface_Lock(surfobj)) return NULL;
590
switch(surf->format->BytesPerPixel)
593
for(loopy = 0; loopy < surf->h; ++loopy)
595
Uint8* pix = (Uint8*)(((char*)surf->pixels)+loopy*surf->pitch);
596
Uint8* end = (Uint8*)(((char*)pix)+surf->w);
597
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
601
*data = (color != colorkey) * 255;
606
for(loopy = 0; loopy < surf->h; ++loopy)
608
Uint16* pix = (Uint16*)(((char*)surf->pixels)+loopy*surf->pitch);
609
Uint16* end = (Uint16*)(((char*)pix)+surf->w*2);
610
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
614
*data = (color != colorkey) * 255;
619
for(loopy = 0; loopy < surf->h; ++loopy)
621
Uint8* pix = (Uint8*)(((char*)surf->pixels)+loopy*surf->pitch);
622
Uint8* end = pix+surf->w*3;
623
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
626
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
627
color = pix[0] + (pix[1]<<8) + (pix[2]<<16);
629
color = pix[2] + (pix[1]<<8) + (pix[0]<<16);
631
*data = (color != colorkey) * 255;
637
for(loopy = 0; loopy < surf->h; ++loopy)
639
Uint32* pix = (Uint32*)(((char*)surf->pixels)+loopy*surf->pitch);
640
Uint32* end = (Uint32*)(((char*)pix)+surf->w*4);
641
data = ((Uint8*)((PyArrayObject*)array)->data) + stridey*loopy;
645
*data = (color != colorkey) * 255;
651
if(!PySurface_Lock(surfobj)) return NULL;
658
/*DOC*/ static char doc_map_array[] =
659
/*DOC*/ "pygame.surfarray.map_array(surf, array3d) -> array2d\n"
660
/*DOC*/ "map an array with RGB values into mapped colors\n"
662
/*DOC*/ "Create a new array with the RGB pixel values of a\n"
663
/*DOC*/ "3d array into mapped color values in a 2D array.\n"
665
/*DOC*/ "Just so you know, this can also map a 2D array\n"
666
/*DOC*/ "with RGB values into a 1D array of mapped color\n"
670
PyObject* map_array(PyObject* self, PyObject* arg)
673
PyObject *surfobj, *arrayobj, *newarray;
675
SDL_PixelFormat* format;
676
PyArrayObject* array;
678
int stridex, stridey, stridez, stridez2, sizex, sizey;
681
if(!PyArg_ParseTuple(arg, "O!O!", &PySurface_Type, &surfobj, &PyArray_Type, &arrayobj))
683
surf = PySurface_AsSurface(surfobj);
684
format = surf->format;
685
array = (PyArrayObject*)arrayobj;
687
if(!array->nd || array->dimensions[array->nd-1] != 3)
688
return RAISE(PyExc_ValueError, "array must be a 3d array of 3-value color data\n");
690
if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
691
return RAISE(PyExc_ValueError, "unsupport bit depth for surface array");
695
case 3: /*image of colors*/
696
dims[0] = array->dimensions[0];
697
dims[1] = array->dimensions[1];
698
newarray = PyArray_FromDims(2, dims, PyArray_INT);
699
if(!newarray) return NULL;
700
data = (int*)((PyArrayObject*)newarray)->data;
701
stridex = array->strides[0];
702
stridey = array->strides[1];
703
stridez = array->strides[2];
704
sizex = array->dimensions[0];
705
sizey = array->dimensions[1];
707
case 2: /*list of colors*/
708
dims[0] = array->dimensions[0];
709
newarray = PyArray_FromDims(1, dims, PyArray_INT);
710
if(!newarray) return NULL;
711
data = (int*)((PyArrayObject*)newarray)->data;
713
stridey = array->strides[0];
714
stridez = array->strides[1];
716
sizey = array->dimensions[0];
718
#if 1 /*kinda like a scalar here, use normal map_rgb*/
719
case 1: /*single color*/
721
newarray = PyArray_FromDims(1, dims, PyArray_INT);
722
if(!newarray) return NULL;
723
data = (int*)((PyArrayObject*)newarray)->data;
726
stridez = array->strides[0];
732
return RAISE(PyExc_ValueError, "unsupported array shape");
734
stridez2 = stridez*2;
737
switch(array->descr->elsize)
740
for(loopx = 0; loopx < sizex; ++loopx)
742
char* col = array->data + stridex * loopx;
743
for(loopy = 0; loopy < sizey; ++loopy)
745
char* pix = col + stridey * loopy;
746
*data++ = (*((unsigned char*)(pix)) >>
747
format->Rloss << format->Rshift) |
748
(*((unsigned char*)(pix+stridez)) >>
749
format->Gloss << format->Gshift) |
750
(*((unsigned char*)(pix+stridez2)) >>
751
format->Bloss << format->Bshift);
755
for(loopx = 0; loopx < sizex; ++loopx)
757
char* col = array->data + stridex * loopx;
758
for(loopy = 0; loopy < sizey; ++loopy)
760
char* pix = col + stridey * loopy;
761
*data++ = (*((unsigned short*)(pix)) >>
762
format->Rloss << format->Rshift) |
763
(*((unsigned short*)(pix+stridez)) >>
764
format->Gloss << format->Gshift) |
765
(*((unsigned short*)(pix+stridez2)) >>
766
format->Bloss << format->Bshift);
770
for(loopx = 0; loopx < sizex; ++loopx)
772
char* col = array->data + stridex * loopx;
773
for(loopy = 0; loopy < sizey; ++loopy)
775
char* pix = col + stridey * loopy;
776
*data++ = (*((int*)(pix)) >>
777
format->Rloss << format->Rshift) |
778
(*((int*)(pix+stridez)) >>
779
format->Gloss << format->Gshift) |
780
(*((int*)(pix+stridez2)) >>
781
format->Bloss << format->Bshift);
786
return RAISE(PyExc_ValueError, "unsupported bytesperpixel for array\n");
794
/* not really fast enough to warrant this, using minimum(maximum()) is same */
795
/*DOC*/ static char XXX_clamp_array[] =
796
/*DOC*/ "pygame.surfarray.clamp_array(array3d, min=0, max=255) -> None\n"
797
/*DOC*/ "will clamp all integer values in an array between 0 and 255\n"
799
/*DOC*/ "Given an array of integer values, this will make sure\n"
800
/*DOC*/ "no values are outside the range between 0 and 255.\n"
801
/*DOC*/ "This will modify the array in-place.\n"
803
/*DOC*/ "You can specify the minimum and maximum values for clamping,\n"
804
/*DOC*/ "but they default to 0 and 255, which is most useful.\n"
807
PyObject* clamp_array(PyObject* self, PyObject* arg)
810
PyArrayObject* array;
811
int loopx, loopy, loopz;
812
int stridex, stridey, stridez, sizex, sizey, sizez;
813
int minval = 0, maxval = 255;
815
if(!PyArg_ParseTuple(arg, "O!|ii", &PyArray_Type, &arrayobj, &minval, &maxval))
817
array = (PyArrayObject*)arrayobj;
822
stridex = array->strides[0];
823
stridey = array->strides[1];
824
stridez = array->strides[2];
825
sizex = array->dimensions[0];
826
sizey = array->dimensions[1];
827
sizez = array->dimensions[2];
831
stridey = array->strides[0];
832
stridez = array->strides[1];
834
sizey = array->dimensions[0];
835
sizez = array->dimensions[1];
840
stridez = array->strides[0];
843
sizez = array->dimensions[0];
846
return RAISE(PyExc_ValueError, "unsupported dimensions for array");
850
switch(array->descr->elsize)
853
for(loopx = 0; loopx < sizex; ++loopx)
855
char* col = array->data + stridex * loopx;
856
for(loopy = 0; loopy < sizey; ++loopy)
858
char* row = col + stridey * loopy;
859
for(loopz = 0; loopz < sizez; ++loopz)
861
char* data = (char*)row;
862
if(*data < minval) *data = minval;
863
else if(*data > maxval) *data = maxval;
869
for(loopx = 0; loopx < sizex; ++loopx)
871
char* col = array->data + stridex * loopx;
872
for(loopy = 0; loopy < sizey; ++loopy)
874
char* row = col + stridey * loopy;
875
for(loopz = 0; loopz < sizez; ++loopz)
877
short* data = (short*)row;
878
if(*data < minval) *data = minval;
879
else if(*data > maxval) *data = maxval;
885
for(loopx = 0; loopx < sizex; ++loopx)
887
char* col = array->data + stridex * loopx;
888
for(loopy = 0; loopy < sizey; ++loopy)
890
char* row = col + stridey * loopy;
891
for(loopz = 0; loopz < sizez; ++loopz)
893
int* data = (int*)row;
894
if(*data < minval) *data = minval;
895
else if(*data > maxval) *data = maxval;
909
/*macros used to blit arrays*/
912
#define COPYMACRO_2D(DST, SRC) \
913
for(loopy = 0; loopy < sizey; ++loopy) { \
914
DST* imgrow = (DST*)(((char*)surf->pixels)+loopy*surf->pitch); \
915
Uint8* datarow = (Uint8*)array->data + stridey * loopy; \
916
for(loopx = 0; loopx < sizex; ++loopx) \
917
*(imgrow + loopx) = (DST)*(SRC*)(datarow + stridex * loopx); \
921
#define COPYMACRO_2D_24(SRC) \
922
for(loopy = 0; loopy < sizey-1; ++loopy) { \
923
Uint8* imgrow = ((Uint8*)surf->pixels)+loopy*surf->pitch; \
924
Uint8* datarow = (Uint8*)array->data + stridey * loopy; \
925
for(loopx = 0; loopx < sizex; ++loopx) \
926
*(int*)(imgrow + loopx*3) = (int)*(SRC*)(datarow + stridex * loopx)<<8; \
928
char* imgrow = ((char*)surf->pixels)+loopy*surf->pitch; \
929
char* datarow = array->data + stridey * loopy; \
930
for(loopx = 0; loopx < sizex-1; ++loopx) \
931
*(int*)(imgrow + loopx*3) = ((int)*(SRC*)(datarow + stridex * loopx))<<8; \
935
#define COPYMACRO_3D(DST, SRC) \
936
for(loopy = 0; loopy < sizey; ++loopy) { \
937
DST* data = (DST*)(((char*)surf->pixels) + surf->pitch * loopy); \
938
char* pix = array->data + stridey * loopy; \
939
for(loopx = 0; loopx < sizex; ++loopx) { \
940
*data++ = (DST)(*(SRC*)(pix) >> Rloss << Rshift) | \
941
(*(SRC*)(pix+stridez) >> Gloss << Gshift) | \
942
(*(SRC*)(pix+stridez2) >> Bloss << Bshift); \
947
#define COPYMACRO_3D_24(SRC) \
948
for(loopy = 0; loopy < sizey; ++loopy) { \
949
Uint8* data = ((Uint8*)surf->pixels) + surf->pitch * loopy; \
950
Uint8* pix = (Uint8*)array->data + stridey * loopy; \
951
for(loopx = 0; loopx < sizex; ++loopx) { \
952
*data++ = (Uint8)*(SRC*)(pix+stridez2); \
953
*data++ = (Uint8)*(SRC*)(pix+stridez); \
954
*data++ = (Uint8)*(SRC*)(pix); \
960
/*DOC*/ static char doc_blit_array[] =
961
/*DOC*/ "pygame.surfarray.blit_array(surf, array) -> None\n"
962
/*DOC*/ "quickly transfer an array to a Surface\n"
964
/*DOC*/ "Transfer an array of any type (3d or 2d) onto a\n"
965
/*DOC*/ "Surface. The array must be the same dimensions as\n"
966
/*DOC*/ "the destination Surface. While you can assign the\n"
967
/*DOC*/ "values of an array to the pixel referenced arrays,\n"
968
/*DOC*/ "using this blit method will usually be quicker\n"
969
/*DOC*/ "because of it's smarter handling of noncontiguous\n"
970
/*DOC*/ "arrays. Plus it allows you to blit from any image\n"
971
/*DOC*/ "array type to any surface format in one step, no\n"
972
/*DOC*/ "internal conversions.\n"
974
/*DOC*/ "This function will temporarily lock the surface.\n"
977
PyObject* blit_array(PyObject* self, PyObject* arg)
979
PyObject *surfobj, *arrayobj;
981
SDL_PixelFormat* format;
982
PyArrayObject* array;
984
int stridex, stridey, stridez=0, stridez2=0, sizex, sizey;
985
int Rloss, Gloss, Bloss, Rshift, Gshift, Bshift;
987
if(!PyArg_ParseTuple(arg, "O!O!", &PySurface_Type, &surfobj, &PyArray_Type, &arrayobj))
989
surf = PySurface_AsSurface(surfobj);
990
format = surf->format;
991
array = (PyArrayObject*)arrayobj;
993
if(!(array->nd == 2 || (array->nd == 3 && array->dimensions[2] == 3)))
994
return RAISE(PyExc_ValueError, "must be a valid 2d or 3d array\n");
996
if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
997
return RAISE(PyExc_ValueError, "unsupport bit depth for surface");
999
stridex = array->strides[0];
1000
stridey = array->strides[1];
1003
stridez = array->strides[2];
1004
stridez2 = stridez*2;
1006
sizex = array->dimensions[0];
1007
sizey = array->dimensions[1];
1008
Rloss = format->Rloss; Gloss = format->Gloss; Bloss = format->Bloss;
1009
Rshift = format->Rshift; Gshift = format->Gshift; Bshift = format->Bshift;
1011
if(sizex != surf->w || sizey != surf->h)
1012
return RAISE(PyExc_ValueError, "array must match surface dimensions");
1013
if(!PySurface_Lock(surfobj)) return NULL;
1015
switch(surf->format->BytesPerPixel)
1018
if(array->nd == 2) {
1019
switch(array->descr->elsize) {
1020
case sizeof(Uint8): COPYMACRO_2D(Uint8, Uint8) break;
1021
case sizeof(Uint16): COPYMACRO_2D(Uint8, Uint16) break;
1022
case sizeof(Uint32): COPYMACRO_2D(Uint8, Uint32) break;
1024
if(!PySurface_Unlock(surfobj)) return NULL;
1025
return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
1030
if(array->nd == 2) {
1031
switch(array->descr->elsize) {
1032
case sizeof(Uint8): COPYMACRO_2D(Uint16, Uint8) break;
1033
case sizeof(Uint16): COPYMACRO_2D(Uint16, Uint16) break;
1034
case sizeof(Uint32): COPYMACRO_2D(Uint16, Uint32) break;
1036
if(!PySurface_Unlock(surfobj)) return NULL;
1037
return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
1040
switch(array->descr->elsize) {
1041
case sizeof(Uint8): COPYMACRO_3D(Uint16, Uint8) break;
1042
case sizeof(Uint16):COPYMACRO_3D(Uint16, Uint16) break;
1043
case sizeof(Uint32):COPYMACRO_3D(Uint16, Uint32) break;
1045
if(!PySurface_Unlock(surfobj)) return NULL;
1046
return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
1051
if(array->nd == 2) {
1052
switch(array->descr->elsize) {
1053
case sizeof(Uint8): COPYMACRO_2D_24(Uint8) break;
1054
case sizeof(Uint16): COPYMACRO_2D_24(Uint16) break;
1055
case sizeof(Uint32): COPYMACRO_2D_24(Uint32) break;
1057
if(!PySurface_Unlock(surfobj)) return NULL;
1058
return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
1061
switch(array->descr->elsize) {
1062
case sizeof(Uint8): COPYMACRO_3D_24(Uint8) break;
1063
case sizeof(Uint16):COPYMACRO_3D_24(Uint16) break;
1064
case sizeof(Uint32):COPYMACRO_3D_24(Uint32) break;
1066
if(!PySurface_Unlock(surfobj)) return NULL;
1067
return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
1072
if(array->nd == 2) {
1073
switch(array->descr->elsize) {
1074
case sizeof(Uint8): COPYMACRO_2D(Uint32, Uint8) break;
1075
case sizeof(Uint16): COPYMACRO_2D(Uint32, Uint16) break;
1076
case sizeof(Uint32): COPYMACRO_2D(Uint32, Uint32) break;
1078
if(!PySurface_Unlock(surfobj)) return NULL;
1079
return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
1082
switch(array->descr->elsize) {
1083
case sizeof(Uint8): COPYMACRO_3D(Uint32, Uint8) break;
1084
case sizeof(Uint16):COPYMACRO_3D(Uint32, Uint16) break;
1085
case sizeof(Uint32):COPYMACRO_3D(Uint32, Uint32) break;
1087
if(!PySurface_Unlock(surfobj)) return NULL;
1088
return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
1093
if(!PySurface_Unlock(surfobj)) return NULL;
1094
return RAISE(PyExc_RuntimeError, "unsupported bit depth for image");
1097
if(!PySurface_Unlock(surfobj)) return NULL;
1102
static PyMethodDef surfarray_builtins[] =
1104
{ "pixels2d", pixels2d, 1, doc_pixels2d },
1105
{ "pixels3d", pixels3d, 1, doc_pixels3d },
1106
{ "pixels_alpha", pixels_alpha, 1, doc_pixels_alpha },
1107
{ "array2d", array2d, 1, doc_array2d },
1108
{ "array3d", array3d, 1, doc_array3d },
1109
{ "array_alpha", array_alpha, 1, doc_array_alpha },
1110
{ "array_colorkey", array_colorkey, 1, doc_array_colorkey },
1111
{ "map_array", map_array, 1, doc_map_array },
1112
/* { "unmap_array", unmap_array, 1, doc_unmap_array },*/
1113
{ "blit_array", blit_array, 1, doc_blit_array },
1114
/* { "clamp_array", clamp_array, 1, doc_clamp_array }, not quick enough to be worthwhile :[ */
1123
/*DOC*/ static char doc_pygame_surfarray_MODULE[] =
1124
/*DOC*/ "Contains routines for mixing numeric arrays with\n"
1125
/*DOC*/ "surfaces\n"
1129
void initsurfarray(void)
1131
PyObject *module, *dict;
1133
/* create the module */
1134
module = Py_InitModule3("surfarray", surfarray_builtins, doc_pygame_surfarray_MODULE);
1135
dict = PyModule_GetDict(module);
1137
/*imported needed apis*/
1138
import_pygame_base();
1139
import_pygame_surface();