/* * call-seq: * get_at(pos) * get_at(x,y) * * Return the color [r,g,b,a] of the pixel at the given coordinate. * * This method takes these argument: * - pos:: the coordinate of the pixel to get the color of. * * The coordinate can also be given as two arguments, separate +x+ and +y+ * positions. */ VALUE rbgm_surface_getat( int argc, VALUE *argv, VALUE self ) { SDL_Surface *surf; int x,y; int locked=0; Uint32 color; Uint8 *pixels, *pix; Uint8 r,g,b,a; Data_Get_Struct(self, SDL_Surface, surf); if(argc>2) rb_raise(rb_eArgError,"wrong number of arguments (%d for 1)",argc); if(argc==1) { x = NUM2INT(rb_ary_entry(argv[0],0)); y = NUM2INT(rb_ary_entry(argv[0],1)); } else { x = NUM2INT(argv[0]); y = NUM2INT(argv[1]); } if(x<0 || x>surf->w) rb_raise(rb_eIndexError,"x index out of bounds (%d, min 0, max %d)",\ x,surf->w); if(y<0 || y>surf->h) rb_raise(rb_eIndexError,"y index out of bounds (%d, min 0, max %d)",\ y,surf->h); /* lock surface */ if(SDL_MUSTLOCK(surf)) { if(SDL_LockSurface(surf)==0) locked += 1; else rb_raise(eSDLError,"could not lock surface: %s",SDL_GetError()); } /* borrowed from pygame */ pixels = (Uint8 *) surf->pixels; switch(surf->format->BytesPerPixel) { case 1: color = (Uint32)*((Uint8 *)(pixels + y * surf->pitch) + x); break; case 2: color = (Uint32)*((Uint16 *)(pixels + y * surf->pitch) + x); break; case 3: pix = ((Uint8 *)(pixels + y * surf->pitch) + x * 3); #if SDL_BYTEORDER == SDL_LIL_ENDIAN color = (pix[0]) + (pix[1]<<8) + (pix[2]<<16); #else color = (pix[2]) + (pix[1]<<8) + (pix[0]<<16); #endif break; default: /*case 4:*/ color = *((Uint32*)(pixels + y * surf->pitch) + x); break; } /* end borrowed from pygame */ /* recursively unlock surface*/ while(locked>1) { SDL_UnlockSurface(surf); locked -= 1; } if((int *)color == NULL) { VALUE zero = INT2NUM(0); return rb_ary_new3(4,zero,zero,zero,zero); } SDL_GetRGBA(color, surf->format, &r, &g, &b, &a); return rb_ary_new3(4,UINT2NUM(r),UINT2NUM(g),UINT2NUM(b),UINT2NUM(a)); }