~ubuntu-branches/ubuntu/gutsy/pygame/gutsy

« back to all changes in this revision

Viewing changes to src/surfarray.c

  • Committer: Bazaar Package Importer
  • Author(s): Ed Boraas
  • Date: 2002-02-20 06:39:24 UTC
  • Revision ID: james.westby@ubuntu.com-20020220063924-amlzj7tqkeods4eq
Tags: upstream-1.4
ImportĀ upstreamĀ versionĀ 1.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    pygame - Python Game Library
 
3
    Copyright (C) 2000-2001  Pete Shinners
 
4
 
 
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.
 
9
 
 
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.
 
14
 
 
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
 
18
 
 
19
    Pete Shinners
 
20
    pete@shinners.org
 
21
*/
 
22
 
 
23
#include"pygame.h"
 
24
#include<Numeric/arrayobject.h>
 
25
#include<SDL_byteorder.h>
 
26
 
 
27
 
 
28
 
 
29
 
 
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"
 
33
    /*DOC*/    "\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"
 
38
    /*DOC*/    "\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"
 
42
    /*DOC*/    "\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"
 
45
    /*DOC*/    "exists\n"
 
46
    /*DOC*/ ;
 
47
 
 
48
static PyObject* pixels3d(PyObject* self, PyObject* arg)
 
49
{
 
50
        int dim[3];
 
51
        PyObject* array, *surfobj;
 
52
        SDL_Surface* surf;
 
53
        char* startpixel;
 
54
        int pixelstep;
 
55
        const int lilendian = (SDL_BYTEORDER == SDL_LIL_ENDIAN);
 
56
        PyObject* lifelock;
 
57
        
 
58
        if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
 
59
                return NULL;
 
60
        surf = PySurface_AsSurface(surfobj);
 
61
 
 
62
        if(surf->format->BytesPerPixel <= 2 || surf->format->BytesPerPixel > 4)
 
63
                return RAISE(PyExc_ValueError, "unsupport bit depth for 3D reference array");
 
64
 
 
65
        lifelock = PySurface_LockLifetime(surfobj);
 
66
        if(!lifelock) return NULL;
 
67
 
 
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)
 
72
        {
 
73
                pixelstep = (lilendian ? -1 : 1);
 
74
                startpixel = ((char*)surf->pixels) + (lilendian ? 2 : 0);
 
75
        }
 
76
        else if(surf->format->Bmask == 0xff<<16 && 
 
77
                                surf->format->Gmask == 0xff<<8 &&
 
78
                                surf->format->Rmask == 0xff)
 
79
        {
 
80
                pixelstep = (lilendian ? 1 : -1);
 
81
                startpixel = ((char*)surf->pixels) + (lilendian ? 0 : 2);
 
82
        }
 
83
        else
 
84
                return RAISE(PyExc_ValueError, "unsupport colormasks for 3D reference array");
 
85
        if(!lilendian && surf->format->BytesPerPixel == 4)
 
86
            ++startpixel;
 
87
    
 
88
        /*create the referenced array*/
 
89
        dim[0] = surf->w;
 
90
        dim[1] = surf->h;
 
91
        dim[2] = 3; /*could be 4 if alpha in the house*/
 
92
        array = PyArray_FromDimsAndData(3, dim, PyArray_UBYTE, startpixel);
 
93
        if(array)
 
94
        {
 
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;
 
100
        }
 
101
        return array;
 
102
}
 
103
 
 
104
 
 
105
 
 
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"
 
109
    /*DOC*/    "\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"
 
114
    /*DOC*/    "\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"
 
117
    /*DOC*/    "values.\n"
 
118
    /*DOC*/    "\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"
 
121
    /*DOC*/    "exists\n"
 
122
    /*DOC*/ ;
 
123
 
 
124
static PyObject* pixels2d(PyObject* self, PyObject* arg)
 
125
{
 
126
        int types[] = {PyArray_UBYTE, PyArray_SHORT, 0, PyArray_INT};
 
127
        int dim[3];
 
128
        int type;
 
129
        PyObject *array, *surfobj;
 
130
        SDL_Surface* surf;
 
131
        PyObject* lifelock;
 
132
 
 
133
        if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
 
134
                return NULL;
 
135
        surf = PySurface_AsSurface(surfobj);
 
136
 
 
137
 
 
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");
 
140
 
 
141
        lifelock = PySurface_LockLifetime(surfobj);
 
142
        if(!lifelock) return NULL;
 
143
 
 
144
        dim[0] = surf->w;
 
145
        dim[1] = surf->h;
 
146
        type = types[surf->format->BytesPerPixel-1];
 
147
        array = PyArray_FromDimsAndData(2, dim, type, (char*)surf->pixels);
 
148
        if(array)
 
149
        {
 
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;
 
154
        }
 
155
        return array;
 
156
}
 
157
 
 
158
 
 
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"
 
162
    /*DOC*/    "\n"
 
163
    /*DOC*/    "This returns a new noncontigous array that directly\n"
 
164
    /*DOC*/    "effects a Surface's alpha contents.\n"
 
165
    /*DOC*/    "\n"
 
166
    /*DOC*/    "This will only work for 32bit surfaces with a pixel\n"
 
167
    /*DOC*/    "alpha channel enabled.\n"
 
168
    /*DOC*/    "\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"
 
171
    /*DOC*/    "exists\n"
 
172
    /*DOC*/ ;
 
173
 
 
174
static PyObject* pixels_alpha(PyObject* self, PyObject* arg)
 
175
{
 
176
        int dim[3];
 
177
        PyObject *array, *surfobj;
 
178
        PyObject* lifelock;
 
179
        SDL_Surface* surf;
 
180
        char* startpixel;
 
181
        const int lilendian = (SDL_BYTEORDER == SDL_LIL_ENDIAN);
 
182
 
 
183
        if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
 
184
                return NULL;
 
185
        surf = PySurface_AsSurface(surfobj);
 
186
 
 
187
        if(surf->format->BytesPerPixel != 4)
 
188
                return RAISE(PyExc_ValueError, "unsupport bit depth for alpha array");
 
189
 
 
190
        lifelock = PySurface_LockLifetime(surfobj);
 
191
        if(!lifelock) return NULL;
 
192
 
 
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);
 
198
        else
 
199
                return RAISE(PyExc_ValueError, "unsupport colormasks for alpha reference array");
 
200
 
 
201
        dim[0] = surf->w;
 
202
        dim[1] = surf->h;
 
203
        array = PyArray_FromDimsAndData(2, dim, PyArray_UBYTE, startpixel);
 
204
        if(array)
 
205
        {
 
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;
 
210
        }
 
211
        return array;
 
212
}
 
213
 
 
214
 
 
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"
 
218
    /*DOC*/    "\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"
 
222
    /*DOC*/    "\n"
 
223
    /*DOC*/    "This function will temporarily lock the surface.\n"
 
224
    /*DOC*/ ;
 
225
 
 
226
PyObject* array2d(PyObject* self, PyObject* arg)
 
227
{
 
228
        int dim[2], loopy;
 
229
        Uint8* data;
 
230
        PyObject *surfobj, *array;
 
231
        SDL_Surface* surf;
 
232
        int stridex, stridey;
 
233
 
 
234
        if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
 
235
                return NULL;
 
236
        surf = PySurface_AsSurface(surfobj);
 
237
 
 
238
        dim[0] = surf->w;
 
239
        dim[1] = surf->h;
 
240
 
 
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;
 
245
 
 
246
        stridex = ((PyArrayObject*)array)->strides[0];
 
247
        stridey = ((PyArrayObject*)array)->strides[1];
 
248
 
 
249
        if(!PySurface_Lock(surfobj)) return NULL;
 
250
 
 
251
        switch(surf->format->BytesPerPixel)
 
252
        {
 
253
        case 1:
 
254
                for(loopy = 0; loopy < surf->h; ++loopy)
 
255
                {
 
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;
 
259
                        while(pix < end)
 
260
                        {
 
261
                                *(Uint32*)data = *pix++;
 
262
                                data += stridex;
 
263
                        }
 
264
                }break;
 
265
        case 2:
 
266
                for(loopy = 0; loopy < surf->h; ++loopy)
 
267
                {
 
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;
 
271
                        while(pix < end)
 
272
                        {
 
273
                                *(Uint32*)data = *pix++;
 
274
                                data += stridex;
 
275
                        }
 
276
                }break;
 
277
        case 3:
 
278
                for(loopy = 0; loopy < surf->h; ++loopy)
 
279
                {
 
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;
 
283
                        while(pix < end)
 
284
                        {
 
285
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
 
286
                                *(Uint32*)data = pix[0] + (pix[1]<<8) + (pix[2]<<16);
 
287
#else
 
288
                                *(Uint32*)data = pix[2] + (pix[1]<<8) + (pix[0]<<16);
 
289
#endif
 
290
                                pix += 3;
 
291
                                data += stridex;
 
292
                        }
 
293
                }break;
 
294
        default: /*case 4*/
 
295
                for(loopy = 0; loopy < surf->h; ++loopy)
 
296
                {
 
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;
 
300
                        while(pix < end)
 
301
                        {
 
302
                                *(Uint32*)data = *pix++;
 
303
                                data += stridex;
 
304
                        }
 
305
                }break;
 
306
        }
 
307
 
 
308
        if(!PySurface_Unlock(surfobj)) return NULL;
 
309
        return array;
 
310
}
 
311
 
 
312
 
 
313
 
 
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"
 
317
    /*DOC*/    "\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"
 
321
    /*DOC*/    "\n"
 
322
    /*DOC*/    "This function will temporarily lock the surface.\n"
 
323
    /*DOC*/ ;
 
324
 
 
325
PyObject* array3d(PyObject* self, PyObject* arg)
 
326
{
 
327
        int dim[3], loopy;
 
328
        Uint8* data;
 
329
        PyObject *array, *surfobj;
 
330
        SDL_Surface* surf;
 
331
        SDL_PixelFormat* format;
 
332
        int Rmask, Gmask, Bmask, Rshift, Gshift, Bshift, Rloss, Gloss, Bloss;
 
333
        int stridex, stridey;
 
334
        SDL_Color* palette;
 
335
 
 
336
        if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
 
337
                return NULL;
 
338
        surf = PySurface_AsSurface(surfobj);
 
339
 
 
340
        format = surf->format;
 
341
        dim[0] = surf->w;
 
342
        dim[1] = surf->h;
 
343
        dim[2] = 3;
 
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;
 
347
 
 
348
        if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
 
349
                return RAISE(PyExc_ValueError, "unsupport bit depth for surface array");
 
350
 
 
351
        array = PyArray_FromDims(3, dim, PyArray_UBYTE);
 
352
        if(!array) return NULL;
 
353
 
 
354
        stridex = ((PyArrayObject*)array)->strides[0];
 
355
        stridey = ((PyArrayObject*)array)->strides[1];
 
356
 
 
357
        if(!PySurface_Lock(surfobj)) return NULL;
 
358
        
 
359
        switch(surf->format->BytesPerPixel)
 
360
        {
 
361
        case 1:
 
362
                if(!format->palette)
 
363
                {
 
364
                        if(!PySurface_Unlock(surfobj)) return NULL;
 
365
                        return RAISE(PyExc_RuntimeError, "8bit surface has no palette");
 
366
                }
 
367
                palette = format->palette->colors;
 
368
                for(loopy = 0; loopy < surf->h; ++loopy)
 
369
                {
 
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;
 
373
                        while(pix < end)
 
374
                        {
 
375
                                SDL_Color* c = palette + (*pix++);
 
376
                                data[0] = c->r;
 
377
                                data[1] = c->g;
 
378
                                data[2] = c->b;
 
379
                                data += stridex;
 
380
                        }
 
381
                }break;
 
382
        case 2:
 
383
                for(loopy = 0; loopy < surf->h; ++loopy)
 
384
                {
 
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;
 
388
                        while(pix < end)
 
389
                        {
 
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;
 
394
                                data += stridex;
 
395
                        }
 
396
                }break;
 
397
        case 3:
 
398
                for(loopy = 0; loopy < surf->h; ++loopy)
 
399
                {
 
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;
 
403
                        while(pix < end)
 
404
                        {
 
405
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
 
406
                                Uint32 color = (pix[0]) + (pix[1]<<8) + (pix[2]<<16); pix += 3;
 
407
#else
 
408
                                Uint32 color = (pix[2]) + (pix[1]<<8) + (pix[0]<<16); pix += 3;
 
409
#endif
 
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*/;
 
413
                                data += stridex;
 
414
                        }
 
415
                }break;
 
416
        default: /*case 4*/
 
417
                for(loopy = 0; loopy < surf->h; ++loopy)
 
418
                {
 
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;
 
422
                        while(pix < end)
 
423
                        {
 
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*/;
 
428
                                data += stridex;
 
429
                        }
 
430
                }break;
 
431
        }
 
432
 
 
433
        if(!PySurface_Unlock(surfobj)) return NULL;
 
434
        return array;
 
435
}
 
436
 
 
437
 
 
438
 
 
439
 
 
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"
 
443
    /*DOC*/    "\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"
 
448
    /*DOC*/    "\n"
 
449
    /*DOC*/    "This function will temporarily lock the surface.\n"
 
450
    /*DOC*/ ;
 
451
 
 
452
PyObject* array_alpha(PyObject* self, PyObject* arg)
 
453
{
 
454
        int dim[2], loopy;
 
455
        Uint8* data;
 
456
        Uint32 color;
 
457
        PyObject *array, *surfobj;
 
458
        SDL_Surface* surf;
 
459
        int stridex, stridey;
 
460
        int Ashift, Amask, Aloss;
 
461
 
 
462
        if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
 
463
                return NULL;
 
464
        surf = PySurface_AsSurface(surfobj);
 
465
 
 
466
        dim[0] = surf->w;
 
467
        dim[1] = surf->h;
 
468
 
 
469
        if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
 
470
                return RAISE(PyExc_ValueError, "unsupport bit depth for alpha array");
 
471
 
 
472
        array = PyArray_FromDims(2, dim, PyArray_UBYTE);
 
473
        if(!array) return NULL;
 
474
 
 
475
        Amask = surf->format->Amask;
 
476
        Ashift = surf->format->Ashift;
 
477
        Aloss = surf->format->Aloss;
 
478
 
 
479
        if(!Amask || surf->format->BytesPerPixel==1) /*no pixel alpha*/
 
480
        {
 
481
                memset(((PyArrayObject*)array)->data, 255, surf->w * surf->h);
 
482
                return array;
 
483
        }
 
484
 
 
485
        stridex = ((PyArrayObject*)array)->strides[0];
 
486
        stridey = ((PyArrayObject*)array)->strides[1];
 
487
 
 
488
        if(!PySurface_Lock(surfobj)) return NULL;
 
489
 
 
490
        switch(surf->format->BytesPerPixel)
 
491
        {
 
492
        case 2:
 
493
                for(loopy = 0; loopy < surf->h; ++loopy)
 
494
                {
 
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;
 
498
                        while(pix < end)
 
499
                        {
 
500
                                color = *pix++;
 
501
                                *data = (color & Amask) >> Ashift << Aloss;
 
502
                                data += stridex;
 
503
                        }
 
504
                }break;
 
505
        case 3:
 
506
                for(loopy = 0; loopy < surf->h; ++loopy)
 
507
                {
 
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;
 
511
                        while(pix < end)
 
512
                        {
 
513
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
 
514
                                color = pix[0] + (pix[1]<<8) + (pix[2]<<16);
 
515
#else
 
516
                                color = pix[2] + (pix[1]<<8) + (pix[0]<<16);
 
517
#endif
 
518
                                *data = (color & Amask) >> Ashift << Aloss;
 
519
                                pix += 3;
 
520
                                data += stridex;
 
521
                        }
 
522
                }break;
 
523
        default: /*case 4*/
 
524
                for(loopy = 0; loopy < surf->h; ++loopy)
 
525
                {
 
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;
 
529
                        while(pix < end)
 
530
                        {
 
531
                                color = *pix++;
 
532
                                *data = (color & Amask) >> Ashift /*<< Aloss*/; /*assume no loss in 32bit*/
 
533
                                data += stridex;
 
534
                        }
 
535
                }break;
 
536
        }
 
537
 
 
538
        if(!PySurface_Unlock(surfobj)) return NULL;
 
539
        return array;
 
540
}
 
541
 
 
542
 
 
543
 
 
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"
 
547
    /*DOC*/    "\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"
 
552
    /*DOC*/    "\n"
 
553
    /*DOC*/    "This function will temporarily lock the surface.\n"
 
554
    /*DOC*/ ;
 
555
 
 
556
PyObject* array_colorkey(PyObject* self, PyObject* arg)
 
557
{
 
558
        int dim[2], loopy;
 
559
        Uint8* data;
 
560
        Uint32 color, colorkey;
 
561
        PyObject *array, *surfobj;
 
562
        SDL_Surface* surf;
 
563
        int stridex, stridey;
 
564
 
 
565
        if(!PyArg_ParseTuple(arg, "O!", &PySurface_Type, &surfobj))
 
566
                return NULL;
 
567
        surf = PySurface_AsSurface(surfobj);
 
568
 
 
569
        dim[0] = surf->w;
 
570
        dim[1] = surf->h;
 
571
 
 
572
        if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
 
573
                return RAISE(PyExc_ValueError, "unsupport bit depth for colorkey array");
 
574
 
 
575
        array = PyArray_FromDims(2, dim, PyArray_UBYTE);
 
576
        if(!array) return NULL;
 
577
 
 
578
        colorkey = surf->format->colorkey;
 
579
        if(!(surf->flags & SDL_SRCCOLORKEY)) /*no pixel alpha*/
 
580
        {
 
581
                memset(((PyArrayObject*)array)->data, 255, surf->w * surf->h);
 
582
                return array;
 
583
        }
 
584
 
 
585
        stridex = ((PyArrayObject*)array)->strides[0];
 
586
        stridey = ((PyArrayObject*)array)->strides[1];
 
587
 
 
588
        if(!PySurface_Lock(surfobj)) return NULL;
 
589
 
 
590
        switch(surf->format->BytesPerPixel)
 
591
        {
 
592
        case 1:
 
593
                for(loopy = 0; loopy < surf->h; ++loopy)
 
594
                {
 
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;
 
598
                        while(pix < end)
 
599
                        {
 
600
                                color = *pix++;
 
601
                                *data = (color != colorkey) * 255;
 
602
                                data += stridex;
 
603
                        }
 
604
                }break;
 
605
        case 2:
 
606
                for(loopy = 0; loopy < surf->h; ++loopy)
 
607
                {
 
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;
 
611
                        while(pix < end)
 
612
                        {
 
613
                                color = *pix++;
 
614
                                *data = (color != colorkey) * 255;
 
615
                                data += stridex;
 
616
                        }
 
617
                }break;
 
618
        case 3:
 
619
                for(loopy = 0; loopy < surf->h; ++loopy)
 
620
                {
 
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;
 
624
                        while(pix < end)
 
625
                        {
 
626
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
 
627
                                color = pix[0] + (pix[1]<<8) + (pix[2]<<16);
 
628
#else
 
629
                                color = pix[2] + (pix[1]<<8) + (pix[0]<<16);
 
630
#endif
 
631
                                *data = (color != colorkey) * 255;
 
632
                                pix += 3;
 
633
                                data += stridex;
 
634
                        }
 
635
                }break;
 
636
        default: /*case 4*/
 
637
                for(loopy = 0; loopy < surf->h; ++loopy)
 
638
                {
 
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;
 
642
                        while(pix < end)
 
643
                        {
 
644
                                color = *pix++;
 
645
                                *data = (color != colorkey) * 255;
 
646
                                data += stridex;
 
647
                        }
 
648
                }break;
 
649
        }
 
650
 
 
651
        if(!PySurface_Lock(surfobj)) return NULL;
 
652
        return array;
 
653
}
 
654
 
 
655
 
 
656
 
 
657
 
 
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"
 
661
    /*DOC*/    "\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"
 
664
    /*DOC*/    "\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"
 
667
    /*DOC*/    "values\n"
 
668
    /*DOC*/ ;
 
669
 
 
670
PyObject* map_array(PyObject* self, PyObject* arg)
 
671
{
 
672
        int* data;
 
673
        PyObject *surfobj, *arrayobj, *newarray;
 
674
        SDL_Surface* surf;
 
675
        SDL_PixelFormat* format;
 
676
        PyArrayObject* array;
 
677
        int loopx, loopy;
 
678
        int stridex, stridey, stridez, stridez2, sizex, sizey;
 
679
        int dims[2];
 
680
 
 
681
        if(!PyArg_ParseTuple(arg, "O!O!", &PySurface_Type, &surfobj, &PyArray_Type, &arrayobj))
 
682
                return NULL;
 
683
        surf = PySurface_AsSurface(surfobj);
 
684
        format = surf->format;
 
685
        array = (PyArrayObject*)arrayobj;
 
686
 
 
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");
 
689
 
 
690
        if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
 
691
                return RAISE(PyExc_ValueError, "unsupport bit depth for surface array");
 
692
 
 
693
        switch(array->nd)
 
694
        {
 
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];
 
706
                break;
 
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;
 
712
                stridex = 0;
 
713
                stridey = array->strides[0];
 
714
                stridez = array->strides[1];
 
715
                sizex = 1;
 
716
                sizey = array->dimensions[0];
 
717
                break;
 
718
#if 1 /*kinda like a scalar here, use normal map_rgb*/
 
719
        case 1: /*single color*/
 
720
                dims[0] = 1;
 
721
                newarray = PyArray_FromDims(1, dims, PyArray_INT);
 
722
                if(!newarray) return NULL;
 
723
                data = (int*)((PyArrayObject*)newarray)->data;
 
724
                stridex = 0;
 
725
                stridey = 0;
 
726
                stridez = array->strides[0];
 
727
                sizex = 1;
 
728
                sizey = 1;
 
729
                break;
 
730
#endif
 
731
        default:
 
732
                return RAISE(PyExc_ValueError, "unsupported array shape");
 
733
        }
 
734
        stridez2 = stridez*2;
 
735
 
 
736
 
 
737
        switch(array->descr->elsize)
 
738
        {
 
739
        case sizeof(char):
 
740
                for(loopx = 0; loopx < sizex; ++loopx)
 
741
                {
 
742
                        char* col = array->data + stridex * loopx;
 
743
                        for(loopy = 0; loopy < sizey; ++loopy)
 
744
                        {
 
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);
 
752
                        }
 
753
                }break;
 
754
        case sizeof(short):
 
755
                for(loopx = 0; loopx < sizex; ++loopx)
 
756
                {
 
757
                        char* col = array->data + stridex * loopx;
 
758
                        for(loopy = 0; loopy < sizey; ++loopy)
 
759
                        {
 
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);
 
767
                        }
 
768
                }break;
 
769
        case sizeof(int):
 
770
                for(loopx = 0; loopx < sizex; ++loopx)
 
771
                {
 
772
                        char* col = array->data + stridex * loopx;
 
773
                        for(loopy = 0; loopy < sizey; ++loopy)
 
774
                        {
 
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);
 
782
                        }
 
783
                }break;
 
784
        default: 
 
785
                Py_DECREF(newarray);
 
786
                return RAISE(PyExc_ValueError, "unsupported bytesperpixel for array\n");
 
787
        }
 
788
 
 
789
        return newarray;
 
790
}
 
791
 
 
792
 
 
793
#if 0
 
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"
 
798
    /*DOC*/    "\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"
 
802
    /*DOC*/    "\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"
 
805
    /*DOC*/ ;
 
806
 
 
807
PyObject* clamp_array(PyObject* self, PyObject* arg)
 
808
{
 
809
        PyObject *arrayobj;
 
810
        PyArrayObject* array;
 
811
        int loopx, loopy, loopz;
 
812
        int stridex, stridey, stridez, sizex, sizey, sizez;
 
813
        int minval = 0, maxval = 255;
 
814
 
 
815
        if(!PyArg_ParseTuple(arg, "O!|ii", &PyArray_Type, &arrayobj, &minval, &maxval))
 
816
                return NULL;
 
817
        array = (PyArrayObject*)arrayobj;
 
818
 
 
819
        switch(array->nd)
 
820
        {
 
821
        case 3:
 
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];
 
828
                break;
 
829
        case 2:
 
830
                stridex = 0;
 
831
                stridey = array->strides[0];
 
832
                stridez = array->strides[1];
 
833
                sizex = 1;
 
834
                sizey = array->dimensions[0];
 
835
                sizez = array->dimensions[1];
 
836
                break;
 
837
        case 1:
 
838
                stridex = 0;
 
839
                stridey = 0;
 
840
                stridez = array->strides[0];
 
841
                sizex = 1;
 
842
                sizey = 1;
 
843
                sizez = array->dimensions[0];
 
844
                break;
 
845
        default:
 
846
                return RAISE(PyExc_ValueError, "unsupported dimensions for array");
 
847
        }
 
848
 
 
849
 
 
850
        switch(array->descr->elsize)
 
851
        {
 
852
        case sizeof(char):
 
853
                for(loopx = 0; loopx < sizex; ++loopx)
 
854
                {
 
855
                        char* col = array->data + stridex * loopx;
 
856
                        for(loopy = 0; loopy < sizey; ++loopy)
 
857
                        {
 
858
                                char* row = col + stridey * loopy;
 
859
                                for(loopz = 0; loopz < sizez; ++loopz)
 
860
                                {
 
861
                                        char* data = (char*)row;
 
862
                                        if(*data < minval) *data = minval;
 
863
                                        else if(*data > maxval) *data = maxval;
 
864
                                        row += sizez;
 
865
                                }
 
866
                        }
 
867
                }break;
 
868
        case sizeof(short):
 
869
                for(loopx = 0; loopx < sizex; ++loopx)
 
870
                {
 
871
                        char* col = array->data + stridex * loopx;
 
872
                        for(loopy = 0; loopy < sizey; ++loopy)
 
873
                        {
 
874
                                char* row = col + stridey * loopy;
 
875
                                for(loopz = 0; loopz < sizez; ++loopz)
 
876
                                {
 
877
                                        short* data = (short*)row;
 
878
                                        if(*data < minval) *data = minval;
 
879
                                        else if(*data > maxval) *data = maxval;
 
880
                                        row += sizez;
 
881
                                }
 
882
                        }
 
883
                }break;
 
884
        case sizeof(int):
 
885
                for(loopx = 0; loopx < sizex; ++loopx)
 
886
                {
 
887
                        char* col = array->data + stridex * loopx;
 
888
                        for(loopy = 0; loopy < sizey; ++loopy)
 
889
                        {
 
890
                                char* row = col + stridey * loopy;
 
891
                                for(loopz = 0; loopz < sizez; ++loopz)
 
892
                                {
 
893
                                        int* data = (int*)row;
 
894
                                        if(*data < minval) *data = minval;
 
895
                                        else if(*data > maxval) *data = maxval;
 
896
                                        row += sizez;
 
897
                                }
 
898
                        }
 
899
                }break;
 
900
        }
 
901
 
 
902
        RETURN_NONE
 
903
}
 
904
#endif
 
905
 
 
906
 
 
907
 
 
908
 
 
909
/*macros used to blit arrays*/
 
910
 
 
911
 
 
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); \
 
918
     }
 
919
 
 
920
 
 
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; \
 
927
     }{ \
 
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; \
 
932
     }
 
933
 
 
934
 
 
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); \
 
943
             pix += stridex; \
 
944
     }    }
 
945
 
 
946
 
 
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); \
 
955
             pix += stridex; \
 
956
     }    }
 
957
 
 
958
 
 
959
 
 
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"
 
963
    /*DOC*/    "\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"
 
973
    /*DOC*/    "\n"
 
974
    /*DOC*/    "This function will temporarily lock the surface.\n"
 
975
    /*DOC*/ ;
 
976
 
 
977
PyObject* blit_array(PyObject* self, PyObject* arg)
 
978
{
 
979
        PyObject *surfobj, *arrayobj;
 
980
        SDL_Surface* surf;
 
981
        SDL_PixelFormat* format;
 
982
        PyArrayObject* array;
 
983
        int loopx, loopy;
 
984
        int stridex, stridey, stridez=0, stridez2=0, sizex, sizey;
 
985
        int Rloss, Gloss, Bloss, Rshift, Gshift, Bshift;
 
986
 
 
987
        if(!PyArg_ParseTuple(arg, "O!O!", &PySurface_Type, &surfobj, &PyArray_Type, &arrayobj))
 
988
                return NULL;
 
989
        surf = PySurface_AsSurface(surfobj);
 
990
        format = surf->format;
 
991
        array = (PyArrayObject*)arrayobj;
 
992
 
 
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");
 
995
 
 
996
        if(surf->format->BytesPerPixel <= 0 || surf->format->BytesPerPixel > 4)
 
997
                return RAISE(PyExc_ValueError, "unsupport bit depth for surface");
 
998
 
 
999
        stridex = array->strides[0];
 
1000
        stridey = array->strides[1];
 
1001
        if(array->nd == 3)
 
1002
        {
 
1003
                stridez = array->strides[2];
 
1004
                stridez2 = stridez*2;
 
1005
        }
 
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;
 
1010
 
 
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;
 
1014
 
 
1015
        switch(surf->format->BytesPerPixel)
 
1016
        {
 
1017
        case 1:
 
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;
 
1023
                                default: 
 
1024
                                        if(!PySurface_Unlock(surfobj)) return NULL;
 
1025
                                        return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 
1026
                        }
 
1027
                }
 
1028
                break;
 
1029
        case 2:
 
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;
 
1035
                                default: 
 
1036
                                        if(!PySurface_Unlock(surfobj)) return NULL;
 
1037
                                        return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 
1038
                        }
 
1039
                } else {
 
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;
 
1044
                                default: 
 
1045
                                        if(!PySurface_Unlock(surfobj)) return NULL;
 
1046
                                        return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 
1047
                        }
 
1048
                }
 
1049
                break;
 
1050
        case 3:
 
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;
 
1056
                                default: 
 
1057
                                        if(!PySurface_Unlock(surfobj)) return NULL;
 
1058
                                        return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 
1059
                        }
 
1060
                } else {
 
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;
 
1065
                                default: 
 
1066
                                        if(!PySurface_Unlock(surfobj)) return NULL;
 
1067
                                        return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 
1068
                        }
 
1069
                }
 
1070
                break;
 
1071
        case 4:
 
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;
 
1077
                        default: 
 
1078
                                        if(!PySurface_Unlock(surfobj)) return NULL;
 
1079
                                        return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 
1080
                        }
 
1081
                } else {
 
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;
 
1086
                                default: 
 
1087
                                        if(!PySurface_Unlock(surfobj)) return NULL;
 
1088
                                        return RAISE(PyExc_ValueError, "unsupported datatype for array\n");
 
1089
                        }
 
1090
                }
 
1091
                break;
 
1092
        default:
 
1093
                if(!PySurface_Unlock(surfobj)) return NULL;
 
1094
                return RAISE(PyExc_RuntimeError, "unsupported bit depth for image");
 
1095
        }
 
1096
 
 
1097
        if(!PySurface_Unlock(surfobj)) return NULL;
 
1098
        RETURN_NONE
 
1099
}
 
1100
 
 
1101
 
 
1102
static PyMethodDef surfarray_builtins[] =
 
1103
{
 
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 :[ */
 
1115
 
 
1116
        { NULL, NULL }
 
1117
};
 
1118
 
 
1119
 
 
1120
 
 
1121
 
 
1122
 
 
1123
    /*DOC*/ static char doc_pygame_surfarray_MODULE[] =
 
1124
    /*DOC*/    "Contains routines for mixing numeric arrays with\n"
 
1125
    /*DOC*/    "surfaces\n"
 
1126
    /*DOC*/ ;
 
1127
 
 
1128
PYGAME_EXPORT
 
1129
void initsurfarray(void)
 
1130
{
 
1131
        PyObject *module, *dict;
 
1132
 
 
1133
    /* create the module */
 
1134
        module = Py_InitModule3("surfarray", surfarray_builtins, doc_pygame_surfarray_MODULE);
 
1135
        dict = PyModule_GetDict(module);
 
1136
 
 
1137
        /*imported needed apis*/
 
1138
        import_pygame_base();
 
1139
        import_pygame_surface();
 
1140
        import_array();
 
1141
}
 
1142
 
 
1143
 
 
1144