Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitee4785a

Browse files
authored
Merge pull request#3717 from pygame/greyscale
Add grayscale for surfaces and colors by@ScriptLineStudios
2 parentsbdd364b +af31079 commitee4785a

File tree

10 files changed

+206
-0
lines changed

10 files changed

+206
-0
lines changed

‎buildconfig/stubs/pygame/color.pyi‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@ class Color(Collection[int]):
5353
defupdate(self,r:int,g:int,b:int,a:int=255)->None: ...
5454
@overload
5555
defupdate(self,rgbvalue:ColorValue)->None: ...
56+
defgrayscale(self)->Color: ...

‎buildconfig/stubs/pygame/transform.pyi‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def scale_by(
1919
defrotate(surface:Surface,angle:float)->Surface: ...
2020
defrotozoom(surface:Surface,angle:float,scale:float)->Surface: ...
2121
defscale2x(surface:Surface,dest_surface:Optional[Surface]=None)->Surface: ...
22+
defgrayscale(surface:Surface,dest_surface:Optional[Surface]=None)->Surface: ...
2223
defsmoothscale(
2324
surface:Surface,
2425
size:Coordinate,

‎docs/reST/ref/color.rst‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,15 @@
226226

227227
.. ## Color.set_length ##
228228
229+
..method::grayscale
230+
231+
|:sl:`returns the grayscale of a Color`
232+
|:sg:`grayscale() -> Color`
233+
234+
Returns a Color which represents the grayscaled version of self using the luminosity formula which weights red, green and blue according to their wavelengths..
235+
236+
.. ## Color.grayscale ##
237+
229238
..method::lerp
230239

231240
|:sl:`returns a linear interpolation to the given Color.`

‎docs/reST/ref/transform.rst‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,18 @@ Instead, always begin with the original image and scale to the desired size.)
243243

244244
.. ## pygame.transform.average_color ##
245245
246+
..function::grayscale
247+
248+
|:sl:`grayscale a surface`
249+
|:sg:`grayscale(surface, dest_surface=None) -> Surface`
250+
251+
Returns a grayscaled version of the original surface using the luminosity formula which weights red, green and blue according to their wavelengths.
252+
253+
An optional destination surface can be passed which is faster than creating a new Surface.
254+
This destination surface must have the same dimensions (width, height) and depth as the source Surface.
255+
256+
.. ## pygame.transform.grayscale ##
257+
246258
..function::threshold
247259

248260
|:sl:`finds which, and how many pixels in a surface are within a threshold of a 'search_color' or a 'search_surf'.`

‎src_c/color.c‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ _color_set_length(pgColorObject *, PyObject *);
9393
staticPyObject*
9494
_color_lerp(pgColorObject*,PyObject*,PyObject*);
9595
staticPyObject*
96+
_color_grayscale(pgColorObject*);
97+
staticPyObject*
9698
_premul_alpha(pgColorObject*,PyObject*);
9799
staticPyObject*
98100
_color_update(pgColorObject*self,PyObject*const*args,Py_ssize_tnargs);
@@ -201,6 +203,8 @@ static PyMethodDef _color_methods[] = {
201203
DOC_COLORSETLENGTH},
202204
{"lerp", (PyCFunction)_color_lerp,METH_VARARGS |METH_KEYWORDS,
203205
DOC_COLORLERP},
206+
{"grayscale", (PyCFunction)_color_grayscale,METH_VARARGS |METH_KEYWORDS,
207+
DOC_COLORGRAYSCALE},
204208
{"premul_alpha", (PyCFunction)_premul_alpha,METH_NOARGS,
205209
DOC_COLORPREMULALPHA},
206210
{"update", (PyCFunction)PG_FASTCALL_NAME(_color_update),PG_FASTCALL,
@@ -784,6 +788,24 @@ _color_correct_gamma(pgColorObject *color, PyObject *args)
784788
return (PyObject*)_color_new_internal(Py_TYPE(color),rgba);
785789
}
786790

791+
/**
792+
* color.grayscale()
793+
*/
794+
staticPyObject*
795+
_color_grayscale(pgColorObject*self)
796+
{
797+
Uint8grayscale_pixel=
798+
(Uint8)(0.299*self->data[0]+0.587*self->data[1]+
799+
0.114*self->data[2]);
800+
801+
Uint8new_rgba[4];
802+
new_rgba[0]=grayscale_pixel;
803+
new_rgba[1]=grayscale_pixel;
804+
new_rgba[2]=grayscale_pixel;
805+
new_rgba[3]=self->data[3];
806+
return (PyObject*)_color_new_internal(Py_TYPE(self),new_rgba);
807+
}
808+
787809
/**
788810
* color.lerp(other, x)
789811
*/

‎src_c/doc/color_doc.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#defineDOC_COLORNORMALIZE "normalize() -> tuple\nReturns the normalized RGBA values of the Color."
1212
#defineDOC_COLORCORRECTGAMMA "correct_gamma (gamma) -> Color\nApplies a certain gamma value to the Color."
1313
#defineDOC_COLORSETLENGTH "set_length(len) -> None\nSet the number of elements in the Color to 1,2,3, or 4."
14+
#defineDOC_COLORGRAYSCALE "grayscale() -> Color\nreturns the grayscale of a Color"
1415
#defineDOC_COLORLERP "lerp(Color, float) -> Color\nreturns a linear interpolation to the given Color."
1516
#defineDOC_COLORPREMULALPHA "premul_alpha() -> Color\nreturns a Color where the r,g,b components have been multiplied by the alpha."
1617
#defineDOC_COLORUPDATE "update(r, g, b) -> None\nupdate(r, g, b, a=255) -> None\nupdate(color_value) -> None\nSets the elements of the color"
@@ -70,6 +71,10 @@ pygame.Color.set_length
7071
set_length(len) -> None
7172
Set the number of elements in the Color to 1,2,3, or 4.
7273
74+
pygame.Color.grayscale
75+
grayscale() -> Color
76+
returns the grayscale of a Color
77+
7378
pygame.Color.lerp
7479
lerp(Color, float) -> Color
7580
returns a linear interpolation to the given Color.

‎src_c/doc/transform_doc.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#defineDOC_PYGAMETRANSFORMLAPLACIAN "laplacian(surface, dest_surface=None) -> Surface\nfind edges in a surface"
1515
#defineDOC_PYGAMETRANSFORMAVERAGESURFACES "average_surfaces(surfaces, dest_surface=None, palette_colors=1) -> Surface\nfind the average surface from many surfaces."
1616
#defineDOC_PYGAMETRANSFORMAVERAGECOLOR "average_color(surface, rect=None, consider_alpha=False) -> Color\nfinds the average color of a surface"
17+
#defineDOC_PYGAMETRANSFORMGRAYSCALE "grayscale(surface, dest_surface=None) -> Surface\ngrayscale a surface"
1718
#defineDOC_PYGAMETRANSFORMTHRESHOLD "threshold(dest_surface, surface, search_color, threshold=(0,0,0,0), set_color=(0,0,0,0), set_behavior=1, search_surf=None, inverse_set=False) -> num_threshold_pixels\nfinds which, and how many pixels in a surface are within a threshold of a 'search_color' or a 'search_surf'."
1819

1920

@@ -80,6 +81,10 @@ pygame.transform.average_color
8081
average_color(surface, rect=None, consider_alpha=False) -> Color
8182
finds the average color of a surface
8283
84+
pygame.transform.grayscale
85+
grayscale(surface, dest_surface=None) -> Surface
86+
grayscale a surface
87+
8388
pygame.transform.threshold
8489
threshold(dest_surface, surface, search_color, threshold=(0,0,0,0), set_color=(0,0,0,0), set_behavior=1, search_surf=None, inverse_set=False) -> num_threshold_pixels
8590
finds which, and how many pixels in a surface are within a threshold of a 'search_color' or a 'search_surf'.

‎src_c/transform.c‎

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,6 +2110,85 @@ clamp_4
21102110

21112111
#endif
21122112

2113+
SDL_Surface*
2114+
grayscale(pgSurfaceObject*srcobj,pgSurfaceObject*dstobj)
2115+
{
2116+
SDL_Surface*src=pgSurface_AsSurface(srcobj);
2117+
SDL_Surface*newsurf;
2118+
2119+
if (!dstobj) {
2120+
newsurf=newsurf_fromsurf(src,srcobj->surf->w,srcobj->surf->h);
2121+
if (!newsurf)
2122+
returnNULL;
2123+
}
2124+
else {
2125+
newsurf=pgSurface_AsSurface(dstobj);
2126+
}
2127+
2128+
if (newsurf->w!=src->w||newsurf->h!=src->h) {
2129+
return (SDL_Surface*)(RAISE(
2130+
PyExc_ValueError,
2131+
"Destination surface must be the same size as source surface."));
2132+
}
2133+
2134+
if (src->format->BytesPerPixel!=newsurf->format->BytesPerPixel) {
2135+
return (SDL_Surface*)(RAISE(
2136+
PyExc_ValueError,
2137+
"Source and destination surfaces need the same format."));
2138+
}
2139+
2140+
intx,y;
2141+
for (y=0;y<src->h;y++) {
2142+
for (x=0;x<src->w;x++) {
2143+
Uint32pixel;
2144+
Uint8*pix;
2145+
SURF_GET_AT(pixel,src,x,y, (Uint8*)src->pixels,src->format,
2146+
pix);
2147+
Uint8r,g,b,a;
2148+
SDL_GetRGBA(pixel,src->format,&r,&g,&b,&a);
2149+
Uint8grayscale_pixel= (Uint8)(0.299*r+0.587*g+0.114*b);
2150+
Uint32new_pixel=
2151+
SDL_MapRGBA(newsurf->format,grayscale_pixel,grayscale_pixel,
2152+
grayscale_pixel,a);
2153+
SURF_SET_AT(new_pixel,newsurf,x,y, (Uint8*)newsurf->pixels,
2154+
newsurf->format,pix);
2155+
}
2156+
}
2157+
2158+
SDL_UnlockSurface(newsurf);
2159+
2160+
returnnewsurf;
2161+
}
2162+
2163+
staticPyObject*
2164+
surf_grayscale(PyObject*self,PyObject*args,PyObject*kwargs)
2165+
{
2166+
pgSurfaceObject*surfobj;
2167+
pgSurfaceObject*surfobj2=NULL;
2168+
SDL_Surface*newsurf;
2169+
2170+
staticchar*keywords[]= {"surface","dest_surface",NULL};
2171+
2172+
if (!PyArg_ParseTupleAndKeywords(args,kwargs,"O!|O!",keywords,
2173+
&pgSurface_Type,&surfobj,
2174+
&pgSurface_Type,&surfobj2))
2175+
returnNULL;
2176+
2177+
newsurf=grayscale(surfobj,surfobj2);
2178+
2179+
if (!newsurf) {
2180+
returnNULL;
2181+
}
2182+
2183+
if (surfobj2) {
2184+
Py_INCREF(surfobj2);
2185+
return (PyObject*)surfobj2;
2186+
}
2187+
else {
2188+
return (PyObject*)pgSurface_New(newsurf);
2189+
}
2190+
}
2191+
21132192
/*
21142193
number to use for missing samples
21152194
*/
@@ -2997,6 +3076,8 @@ static PyMethodDef _transform_methods[] = {
29973076
METH_VARARGS |METH_KEYWORDS,DOC_PYGAMETRANSFORMAVERAGESURFACES},
29983077
{"average_color", (PyCFunction)surf_average_color,
29993078
METH_VARARGS |METH_KEYWORDS,DOC_PYGAMETRANSFORMAVERAGECOLOR},
3079+
{"grayscale", (PyCFunction)surf_grayscale,METH_VARARGS |METH_KEYWORDS,
3080+
DOC_PYGAMETRANSFORMGRAYSCALE},
30003081
{NULL,NULL,0,NULL}};
30013082

30023083
MODINIT_DEFINE(transform)

‎test/color_test.py‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,31 @@ def test_color_contains(self):
11101110
self.assertRaises(TypeError,lambda:"string"inc)
11111111
self.assertRaises(TypeError,lambda:3.14159inc)
11121112

1113+
deftest_grayscale(self):
1114+
Color=pygame.color.Color
1115+
1116+
color=Color(255,0,0,255)
1117+
self.assertEqual(color.grayscale(),Color(76,76,76,255))
1118+
color=Color(3,5,7,255)
1119+
self.assertEqual(color.grayscale(),Color(4,4,4,255))
1120+
color=Color(3,5,70,255)
1121+
self.assertEqual(color.grayscale(),Color(11,11,11,255))
1122+
color=Color(3,50,70,255)
1123+
self.assertEqual(color.grayscale(),Color(38,38,38,255))
1124+
color=Color(30,50,70,255)
1125+
self.assertEqual(color.grayscale(),Color(46,46,46,255))
1126+
1127+
color=Color(255,0,0,144)
1128+
self.assertEqual(color.grayscale(),Color(76,76,76,144))
1129+
color=Color(3,5,7,144)
1130+
self.assertEqual(color.grayscale(),Color(4,4,4,144))
1131+
color=Color(3,5,70,144)
1132+
self.assertEqual(color.grayscale(),Color(11,11,11,144))
1133+
color=Color(3,50,70,144)
1134+
self.assertEqual(color.grayscale(),Color(38,38,38,144))
1135+
color=Color(30,50,70,144)
1136+
self.assertEqual(color.grayscale(),Color(46,46,46,144))
1137+
11131138
deftest_lerp(self):
11141139
# setup
11151140
Color=pygame.color.Color

‎test/transform_test.py‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,51 @@ def test_smoothscale_by(self):
158158
dest=pygame.Surface((64,48))
159159
pygame.transform.smoothscale_by(s, (2.0,1.5),dest_surface=dest)
160160

161+
deftest_grayscale(self):
162+
s=pygame.Surface((32,32))
163+
s.fill((255,0,0))
164+
165+
s2=pygame.transform.grayscale(s)
166+
self.assertEqual(pygame.transform.average_color(s2)[0],76)
167+
self.assertEqual(pygame.transform.average_color(s2)[1],76)
168+
self.assertEqual(pygame.transform.average_color(s2)[2],76)
169+
170+
dest=pygame.Surface((32,32),depth=32)
171+
pygame.transform.grayscale(s,dest)
172+
self.assertEqual(pygame.transform.average_color(dest)[0],76)
173+
self.assertEqual(pygame.transform.average_color(dest)[1],76)
174+
self.assertEqual(pygame.transform.average_color(dest)[2],76)
175+
176+
dest=pygame.Surface((32,32),depth=32)
177+
s.fill((34,12,65))
178+
pygame.transform.grayscale(s,dest)
179+
self.assertEqual(pygame.transform.average_color(dest)[0],24)
180+
self.assertEqual(pygame.transform.average_color(dest)[1],24)
181+
self.assertEqual(pygame.transform.average_color(dest)[2],24)
182+
183+
dest=pygame.Surface((32,32),depth=32)
184+
s.fill((123,123,123))
185+
pygame.transform.grayscale(s,dest)
186+
self.assertIn(pygame.transform.average_color(dest)[0], [123,122])
187+
self.assertIn(pygame.transform.average_color(dest)[1], [123,122])
188+
self.assertIn(pygame.transform.average_color(dest)[2], [123,122])
189+
190+
s=pygame.Surface((32,32),depth=24)
191+
s.fill((255,0,0))
192+
dest=pygame.Surface((32,32),depth=24)
193+
pygame.transform.grayscale(s,dest)
194+
self.assertEqual(pygame.transform.average_color(dest)[0],76)
195+
self.assertEqual(pygame.transform.average_color(dest)[1],76)
196+
self.assertEqual(pygame.transform.average_color(dest)[2],76)
197+
198+
s=pygame.Surface((32,32),depth=16)
199+
s.fill((255,0,0))
200+
dest=pygame.Surface((32,32),depth=16)
201+
pygame.transform.grayscale(s,dest)
202+
self.assertEqual(pygame.transform.average_color(dest)[0],72)
203+
self.assertEqual(pygame.transform.average_color(dest)[1],76)
204+
self.assertEqual(pygame.transform.average_color(dest)[2],72)
205+
161206
deftest_threshold__honors_third_surface(self):
162207
# __doc__ for threshold as of Tue 07/15/2008
163208

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp