Commits

illume committed 57ac2ed

Mask can now get bounding rects of set bits.

pygame.transform can find edges in an image, get the average surface of many
surfaces and also threshold an image by color.

  • Participants
  • Parent commits fbc077d

Comments (0)

Files changed (33)

 #
 #
 
+Dec 15, 2007
+    Mask can now get bounding rects of set bits.
+    pygame.transform can find edges in an image, get the average surface of many
+      surfaces and also threshold an image by color.
+
 Sep 1, 2007
     Added get_buffer() methods to Surface, and Sound - which return a new
      BufferProxy - which is a buffer interface only class.  Thanks Marcus!

File docs/ref/cdrom.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/cursors.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/display.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/draw.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/event.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/font.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/image.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;
  <li> RGBX, 32bit image with unused space </li>
  <li> RGBA, 32bit image with an alpha channel </li>
  <li> ARGB, 32bit image with alpha channel first </li>
+ <li> RGBA_PREMULT, 32bit image with colors scaled by alpha channel </li>
+ <li> ARGB_PREMULT, 32bit image with colors scaled by alpha channel, alpha channel first </li>
 </ul>
 <!--COMMENTS:pygame.image.tostring--> &nbsp;<br> 
 <br></ul>

File docs/ref/index.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;
 <ul>
 <li></li>
 <li><a href="mask.html#pygame.mask.get_at">pygame.mask.get_at</a> - <font size=-1>Returns nonzero if the bit at (x,y) is set.</font></li>
+<li><a href="mask.html#pygame.mask.get_bounding_rects">pygame.mask.get_bounding_rects</a> - <font size=-1>Returns a list of bounding rects of regions of set pixels.</font></li>
 <li><a href="mask.html#pygame.mask.get_size">pygame.mask.get_size</a> - <font size=-1>Returns the size of the mask.</font></li>
 <li><a href="mask.html#pygame.mask.overlap">pygame.mask.overlap</a> - <font size=-1>Returns nonzero if the masks overlap with the given offset.</font></li>
 <li><a href="mask.html#pygame.mask.overlap_area">pygame.mask.overlap_area</a> - <font size=-1>Returns the number of overlapping 'pixels'.</font></li>
 <li><a href="mixer.html#pygame.mixer.Sound">pygame.mixer.Sound</a> - <font size=-1>Create a new Sound object from a file</font></li>
 <ul>
 <li><a href="mixer.html#Sound.fadeout">Sound.fadeout</a> - <font size=-1>stop sound playback after fading out</font></li>
+<li><a href="mixer.html#Sound.get_buffer">Sound.get_buffer</a> - <font size=-1>acquires a buffer object for the sameples of the Sound.</font></li>
 <li><a href="mixer.html#Sound.get_length">Sound.get_length</a> - <font size=-1>get the length of the Sound</font></li>
 <li><a href="mixer.html#Sound.get_num_channels">Sound.get_num_channels</a> - <font size=-1>count how many times this Sound is playing</font></li>
 <li><a href="mixer.html#Sound.get_volume">Sound.get_volume</a> - <font size=-1>get the playback volume</font></li>
 <li><a href="overlay.html#Overlay.get_hardware">Overlay.get_hardware</a> - <font size=-1>test if the Overlay is hardware accelerated</font></li>
 <li><a href="overlay.html#Overlay.set_location">Overlay.set_location</a> - <font size=-1>control where the overlay is displayed</font></li>
 </ul>
+<li><a href="pixelarray.html#pygame.PixelArray">pygame.PixelArray</a> - <font size=-1>pygame Object for direct pixel access of surfaces</font></li>
+<ul>
+<li><a href="pixelarray.html#PixelArray.surface">PixelArray.surface</a> - <font size=-1>Gets the Surface, the PixelArray uses</font></li>
+</ul>
 <li><a href="rect.html#pygame.Rect">pygame.Rect</a> - <font size=-1>pygame object for storing rectangular coordinates</font></li>
 <ul>
 <li><a href="rect.html#Rect.clamp">Rect.clamp</a> - <font size=-1>moves the rectangle inside another</font></li>
 <li><a href="surface.html#Surface.get_alpha">Surface.get_alpha</a> - <font size=-1>get the current Surface transparency value</font></li>
 <li><a href="surface.html#Surface.get_at">Surface.get_at</a> - <font size=-1>get the color value at a single pixel</font></li>
 <li><a href="surface.html#Surface.get_bitsize">Surface.get_bitsize</a> - <font size=-1>get the bit depth of the Surface pixel format</font></li>
+<li><a href="surface.html#Surface.get_buffer">Surface.get_buffer</a> - <font size=-1>acquires a buffer object for the pixels of the Surface.</font></li>
 <li><a href="surface.html#Surface.get_bytesize">Surface.get_bytesize</a> - <font size=-1>get the bytes used per Surface pixel</font></li>
 <li><a href="surface.html#Surface.get_clip">Surface.get_clip</a> - <font size=-1>get the current clipping are of the Surface</font></li>
 <li><a href="surface.html#Surface.get_colorkey">Surface.get_colorkey</a> - <font size=-1>Get the current transparent colorkey</font></li>
 </ul>
 <li><a href="transform.html#pygame.transform">pygame.transform</a> - <font size=-1>pygame module to transform surfaces</font></li>
 <ul>
+<li></li>
+<li><a href="transform.html#pygame.transform.average_surfaces">pygame.transform.average_surfaces</a> - <font size=-1>find the average surface from many surfaces.</font></li>
 <li><a href="transform.html#pygame.transform.chop">pygame.transform.chop</a> - <font size=-1>remove interior area of an image</font></li>
 <li><a href="transform.html#pygame.transform.flip">pygame.transform.flip</a> - <font size=-1>flip vertically and horizontally</font></li>
+<li><a href="transform.html#pygame.transform.laplacian">pygame.transform.laplacian</a> - <font size=-1>find edges in a surface</font></li>
 <li><a href="transform.html#pygame.transform.rotate">pygame.transform.rotate</a> - <font size=-1>rotate an image</font></li>
 <li><a href="transform.html#pygame.transform.rotozoom">pygame.transform.rotozoom</a> - <font size=-1>filtered scale and rotation</font></li>
 <li><a href="transform.html#pygame.transform.scale">pygame.transform.scale</a> - <font size=-1>resize to new resolution</font></li>
 <li><a href="transform.html#pygame.transform.scale2x">pygame.transform.scale2x</a> - <font size=-1>specialized image doubler</font></li>
 <li><a href="transform.html#pygame.transform.smoothscale">pygame.transform.smoothscale</a> - <font size=-1>scale a surface to an arbitrary size smoothly</font></li>
+<li><a href="transform.html#pygame.transform.threshold">pygame.transform.threshold</a> - <font size=-1>finds which, and how many pixels in a surface are within a threshold of a color.</font></li>
 </ul>
 <li><a href="pygame.html#pygame.quit">pygame.quit</a> - <font size=-1>uninitialize all pygame modules</font></li>
 <li><a href="pygame.html#pygame.register_quit">pygame.register_quit</a> - <font size=-1>register a function to be called when pygame quits</font></li>

File docs/ref/joystick.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/key.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/mixer.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;
   <tr><td><a href="mixer.html#Sound.get_volume">Sound.get_volume</a> - <font size=-1>get the playback volume</font></td><td>get the playback volume</td></tr>
   <tr><td><a href="mixer.html#Sound.get_num_channels">Sound.get_num_channels</a> - <font size=-1>count how many times this Sound is playing</font></td><td>count how many times this Sound is playing</td></tr>
   <tr><td><a href="mixer.html#Sound.get_length">Sound.get_length</a> - <font size=-1>get the length of the Sound</font></td><td>get the length of the Sound</td></tr>
+  <tr><td><a href="mixer.html#Sound.get_buffer">Sound.get_buffer</a> - <font size=-1>acquires a buffer object for the sameples of the Sound.</font></td><td>acquires a buffer object for the sameples of the Sound.</td></tr>
 </table></small></ul>
 <p>Load a new sound buffer from a filename or from a python file object. Limited resampling will be performed to help the sample match the initialize arguments for the mixer. </p>
 <p>The Sound object represents actual sound sample data. Methods that change the state of the Sound object will the all instances of the Sound playback. </p>
 <p>Return the length of this Sound in seconds. </p>
 <!--COMMENTS:Sound.get_length--> &nbsp;<br> 
 <br></ul>
+
+
+<a name="Sound.get_buffer">
+<big><b>Sound.get_buffer</big></b><br><ul>
+  <i>acquires a buffer object for the sameples of the Sound.</i><br>
+  <tt>Sound.get_buffer(): return BufferProxy</tt><br>
+<p>Return a buffer object for the Sound samples. The buffer can be used for direct access and manipulation. </p>
+<p>New in pygame <tt>1.8</tt>. </p>
+<!--COMMENTS:Sound.get_buffer--> &nbsp;<br> 
+<br></ul>
 <br></ul>
 
 

File docs/ref/mouse.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/movie.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/music.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/overlay.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/pygame.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/rect.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/scrap.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/sndarray.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/sprite.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/surface.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;
   <tr><td><a href="surface.html#Surface.get_masks">Surface.get_masks</a> - <font size=-1>the bitmasks needed to convert between a color and a mapped integer</font></td><td>the bitmasks needed to convert between a color and a mapped integer</td></tr>
   <tr><td><a href="surface.html#Surface.get_shifts">Surface.get_shifts</a> - <font size=-1>the bit shifts needed to convert between a color and a mapped integer</font></td><td>the bit shifts needed to convert between a color and a mapped integer</td></tr>
   <tr><td><a href="surface.html#Surface.get_losses">Surface.get_losses</a> - <font size=-1>the significant bits used to convert between a color and a mapped integer</font></td><td>the significant bits used to convert between a color and a mapped integer</td></tr>
+  <tr><td><a href="surface.html#Surface.get_buffer">Surface.get_buffer</a> - <font size=-1>acquires a buffer object for the pixels of the Surface.</font></td><td>acquires a buffer object for the pixels of the Surface.</td></tr>
 </table></small></ul>
 <p><tt>A</tt> pygame Surface is used to represent any image. The Surface has a fixed resolution and pixel format. Surfaces with 8bit pixels use a color palette to map to 24bit color. </p>
 <p>Call <tt><a href="surface.html#pygame.Surface">pygame.Surface</a> - <font size=-1>pygame object for representing images</font></tt> to create a new image object. The Surface will be cleared to all black. The only required arguments are the sizes. With no additional arguments, the Surface will be created in a format that best matches the display Surface. </p>
   <i>fill Surface with a solid color</i><br>
   <tt>Surface.fill(color, rect=None, special_flags=0): return Rect</tt><br>
 <p>Fill the Surface with a solid color. If no rect argument is given the entire Surface will be filled. The rect argument will limit the fill to a specific area. The fill will also be contained by the Surface clip area. </p>
-<p>The color argument can be either an <tt>RGB</tt> sequence or a mapped color index. </p>
+<p>The color argument can be either a <tt>RGB</tt> sequence, a <tt>RGBA</tt> sequence or a mapped color index. If using <tt>RGBA</tt>, the Alpha <tt>(A</tt> part of <tt>RGBA)</tt> is ignored unless the surface uses per pixel alpha (Surface has the <tt>SRCALPHA</tt> flag). </p>
 <p>An optional special_flags is for passing in <tt>BLEND_ADD</tt>, <tt>BLEND_SUB</tt>, <tt>BLEND_MULT</tt>, <tt>BLEND_MIN</tt>, <tt>BLEND_MAX</tt> With other special blitting flags perhaps added in the future. </p>
 <p>This will return the affected Surface area. </p>
 <!--COMMENTS:Surface.fill--> &nbsp;<br> 
 <big><b>Surface.get_locked</big></b><br><ul>
   <i>test if the Surface is current locked</i><br>
   <tt>Surface.get_locked(): return bool</tt><br>
-<p>Returns True when the Surface is locked. It doesn't matter how many times the Surface is locked. </p>
+<p>Returns True when the Surface is locked. It doesn't matter how many times the Surface is locked. Surfaces that do not need locking (see mustlock()) will always return True. </p>
 <!--COMMENTS:Surface.get_locked--> &nbsp;<br> 
 <br></ul>
 
 <p>This value is not needed for normal Pygame usage. </p>
 <!--COMMENTS:Surface.get_losses--> &nbsp;<br> 
 <br></ul>
+
+
+<a name="Surface.get_buffer">
+<big><b>Surface.get_buffer</big></b><br><ul>
+  <i>acquires a buffer object for the pixels of the Surface.</i><br>
+  <tt>Surface.get_buffer(): return BufferProxy</tt><br>
+<p>Return a buffer object for the pixels of the Surface. The buffer can be used for direct pixel access and manipulation. </p>
+<p>This method implicitly locks the Surface. The lock will be released, once the returned BufferProxy object is deleted. </p>
+<p>New in pygame <tt>1.8</tt>. </p>
+<!--COMMENTS:Surface.get_buffer--> &nbsp;<br> 
+<br></ul>
 <br></ul>
 
 </body></html>

File docs/ref/surfarray.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/time.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;

File docs/ref/transform.html

 <a href=movie.html>Movie</a>&nbsp;||&nbsp;
 <a href=music.html>Music</a>&nbsp;||&nbsp;
 <a href=overlay.html>Overlay</a>&nbsp;||&nbsp;
+<a href=pixelarray.html>Pixelarray</a>&nbsp;||&nbsp;
 <a href=pygame.html>Pygame</a>&nbsp;||&nbsp;
 <a href=rect.html>Rect</a>&nbsp;||&nbsp;
 <a href=scrap.html>Scrap</a>&nbsp;||&nbsp;
   <tr><td><a href="transform.html#pygame.transform.scale2x">pygame.transform.scale2x</a> - <font size=-1>specialized image doubler</font></td><td>specialized image doubler</td></tr>
   <tr><td><a href="transform.html#pygame.transform.smoothscale">pygame.transform.smoothscale</a> - <font size=-1>scale a surface to an arbitrary size smoothly</font></td><td>scale a surface to an arbitrary size smoothly</td></tr>
   <tr><td><a href="transform.html#pygame.transform.chop">pygame.transform.chop</a> - <font size=-1>remove interior area of an image</font></td><td>remove interior area of an image</td></tr>
+  <tr><td><a href="transform.html#pygame.transform.laplacian">pygame.transform.laplacian</a> - <font size=-1>find edges in a surface</font></td><td>find edges in a surface</td></tr>
+  <tr><td><a href="transform.html#pygame.transform.average_surfaces">pygame.transform.average_surfaces</a> - <font size=-1>find the average surface from many surfaces.</font></td><td>find the average surface from many surfaces.</td></tr>
+  <tr><td><a href="transform.html#pygame.transform.threshold">pygame.transform.threshold</a> - <font size=-1>finds which, and how many pixels in a surface are within a threshold of a color.</font></td><td>finds which, and how many pixels in a surface are within a threshold of a color.</td></tr>
+  <tr><td>None</td><td></td></tr>
 </table></small></ul>
 <p><tt>A</tt> Surface transform is an operation that moves or resizes the pixels. All these functions take a Surface to operate on and return a new Surface with the results. </p>
 <p>Some of the transforms are considered destructive. These means every time they are performed they lose pixel data. Common examples of this are resizing and rotating. For this reason, it is better to retransform the original surface than to keep transforming an image multiple times. (For example, suppose you are animating a bouncing spring which expands and contracts. If you applied the size changes incrementally to the previous images, you would lose detail. Instead, always begin with the original image and scale to the desired <tt>size.)</tt> </p>
 <p>Extracts a portion of an image. All vertical and horizontal pixels surrounding the given rectangle area are removed. The resulting image is shrunken by the size of pixels removed. (The original image is not altered by this <tt>operation.)</tt> </p>
 <!--COMMENTS:pygame.transform.chop--> &nbsp;<br> 
 <br></ul>
+
+
+<a name="pygame.transform.laplacian">
+<big><b>pygame.transform.laplacian</big></b><br><ul>
+  <i>find edges in a surface</i><br>
+  <tt>pygame.transform.laplacian(Surface, DestSurface = None): return Surface</tt><br>
+<p>Finds the edges in a surface using the laplacian algorithm. </p>
+<!--COMMENTS:pygame.transform.laplacian--> &nbsp;<br> 
+<br></ul>
+
+
+<a name="pygame.transform.average_surfaces">
+<big><b>pygame.transform.average_surfaces</big></b><br><ul>
+  <i>find the average surface from many surfaces.</i><br>
+  <tt>pygame.transform.average_surfaces(Surfaces, DestSurface = None): return Surface</tt><br>
+<p>Takes a sequence of surfaces and returns a surface with average colors from each of the surfaces. </p>
+<!--COMMENTS:pygame.transform.average_surfaces--> &nbsp;<br> 
+<br></ul>
+
+
+<a name="pygame.transform.threshold">
+<big><b>pygame.transform.threshold</big></b><br><ul>
+  <i>finds which, and how many pixels in a surface are within a threshold of a color.</i><br>
+  <tt>pygame.transform.threshold(DestSurface, Surface, color, threshold = (0,0,0,0), diff_color = (0,0,0,0), change_return = True): return num_threshold_pixels</tt><br>
+<p>Finds which, and how many pixels in a surface are within a threshold of a color. </p>
+<p>It can set the destination surface where all of the pixels not within the threshold are changed to diff_color. </p>
+<p>Or it can be used to just count the number of pixels within the threshold if you set change_return to False. </p>
+<p>You can use a threshold of (r,g,b,a) where the r,g,b can have different thresholds. So you could use an r threshold of 40 and a blue threshold of 2 if you like. </p>
+<!--COMMENTS:pygame.transform.threshold--> &nbsp;<br> 
+<br></ul>
+
+
+<a name="">
+<big><b></big></b><br><ul>
+ &nbsp;<br> 
+<!--COMMENTS:--> &nbsp;<br> 
+<br></ul>
 <br></ul>
 
 </body></html>
 
 #include "pygame.h"
 #include "pygamedocs.h"
+#include "structmember.h"
 #include "bitmask.h"
 
 
     return mask
 */
 
+
+
+
 PyObject* mask_from_surface(PyObject* self, PyObject* args)
 {
-        //TODO:
 	bitmask_t *mask;
 	SDL_Surface* surf;
-        PyObject* surfobj;
-        PyMaskObject *maskobj;
 
-        int x, y, threshold;
-        Uint8 *pixels;
+    PyObject* surfobj;
+    PyMaskObject *maskobj;
 
-        SDL_PixelFormat *format;
-        Uint32 color;
-        Uint8 *pix;
-        Uint8 r, g, b, a;
+    int x, y, threshold;
+    Uint8 *pixels;
 
-        /* set threshold as 127 default argument. */
-        threshold = 127;
+    SDL_PixelFormat *format;
+    Uint32 color;
+    Uint8 *pix;
+    Uint8 r, g, b, a;
 
-        /* get the surface from the passed in arguments. 
-         *   surface, threshold
-         */
+    /* set threshold as 127 default argument. */
+    threshold = 127;
 
-        if (!PyArg_ParseTuple (args, "O!|i", &PySurface_Type, &surfobj, &threshold))
-            return NULL;
+    /* get the surface from the passed in arguments. 
+     *   surface, threshold
+     */
+
+    if (!PyArg_ParseTuple (args, "O!|i", &PySurface_Type, &surfobj, &threshold))
+        return NULL;
 
 	surf = PySurface_AsSurface(surfobj);
 
-        /* lock the surface, release the GIL. */
-        PySurface_Lock (surfobj);
+    /* lock the surface, release the GIL. */
+    PySurface_Lock (surfobj);
 
-        /* get the size from the surface, and create the mask. */
-        mask = bitmask_create(surf->w, surf->h);
 
-	if(!mask)
-	  return NULL; /*RAISE(PyExc_Error, "cannot create bitmask");*/
-        
-        
 
+    Py_BEGIN_ALLOW_THREADS;
 
-        /* TODO: this is the slow, but easy to code way.  Could make the loop 
-         *         just increment a pointer depending on the format.  
-         *         It's faster than in python anyhow.
-         */
-        pixels = (Uint8 *) surf->pixels;
-        format = surf->format;
 
-        for(y=0; y < surf->h; y++) {
-            for(x=0; x < surf->w; x++) {
-                switch (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;
+
+    /* get the size from the surface, and create the mask. */
+    mask = bitmask_create(surf->w, surf->h);
+
+
+	if(!mask) {
+        //Py_END_ALLOW_THREADS;
+        return NULL; /*RAISE(PyExc_Error, "cannot create bitmask");*/
+    }
+    
+
+
+    /* TODO: this is the slow, but easy to code way.  Could make the loop 
+     *         just increment a pointer depending on the format.  
+     *         It's faster than in python anyhow.
+     */
+    pixels = (Uint8 *) surf->pixels;
+    format = surf->format;
+
+    for(y=0; y < surf->h; y++) {
+        for(x=0; x < surf->w; x++) {
+            switch (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;
+            }
+
+
+            if (surf->flags & SDL_SRCCOLORKEY) {
+
+                SDL_GetRGBA (color, format, &r, &g, &b, &a);
+
+                /* no colorkey, so we check the threshold of the alpha */
+                if (a > threshold) {
+                    bitmask_setbit(mask, x, y);
                 }
-
-
-                if (surf->flags & SDL_SRCCOLORKEY) {
-
-                    SDL_GetRGBA (color, format, &r, &g, &b, &a);
-
-                    /* no colorkey, so we check the threshold of the alpha */
-                    if (a > threshold) {
-                        bitmask_setbit(mask, x, y);
-                    }
-                } else {
-                    /*  test against the colour key. */
-                    if (format->colorkey != color) {
-                        bitmask_setbit(mask, x, y);
-                    }
+            } else {
+                /*  test against the colour key. */
+                if (format->colorkey != color) {
+                    bitmask_setbit(mask, x, y);
                 }
             }
         }
+    }
 
-        /* unlock the surface, release the GIL.
-         */
-        PySurface_Unlock (surfobj);
 
-        /*create the new python object from mask*/        
-	maskobj = PyObject_New(PyMaskObject, &PyMask_Type);
-        if(maskobj)
-            maskobj->mask = mask;
+    Py_END_ALLOW_THREADS;
+
+    /* unlock the surface, release the GIL.
+     */
+    PySurface_Unlock (surfobj);
+
+    /*create the new python object from mask*/        
+    maskobj = PyObject_New(PyMaskObject, &PyMask_Type);
+    if(maskobj)
+        maskobj->mask = mask;
 
 
 	return (PyObject*)maskobj;
 
 
 
+/*
+
+def get_bounding_boxes(surf):
+    """
+    """
+    width, height = surf.get_width(), surf.get_height()
+
+    regions = []
+
+    # used pixels is Rects[y][x]
+    used_pixels = []
+    for y in xrange(height):
+        widthones = []
+        for x in xrange(width):
+            widthones.append(None)
+        used_pixels.append(widthones)
+
+
+    for y in xrange(height):
+        for x in xrange(width):
+            c = surf.get_at((x, y))
+            # if the pixel has been set.
+            if c[0]:
+                if not used_pixels[y][x]:
+                    used_pixels[y][x] = pygame.Rect(x,y,1,1)
+                    regions.append( used_pixels[y][x] )
+
+                aregion = used_pixels[y][x] 
+
+                # check other directions, clockwise.  mark a pixel as used if it is.
+                for dx, dy in [(0,-1), (1,-1), (1,0), (1,1), (0,1), (-1,1), (-1,0), (-1,-1)]:
+                    try:
+                        ax, ay = x+dx, y+dy
+                        if surf.get_at((ax,ay))[0]:
+                            if not used_pixels[ay][ax]:
+                                aregion.union_ip( pygame.Rect(ax,ay, 1, 1) )
+                            used_pixels[ay][ax] = aregion
+                    except:
+                        pass
+
+
+    return regions
+*/
+
+
+// returns an array of regions in regions which is 
+static GAME_Rect* get_bounding_rects(bitmask_t *mask, int *num_bounding_boxes) {
+
+    int x, y, p, i, n, width, height;
+    GAME_Rect **used_pixels;
+    GAME_Rect *a_used_pixels;
+    GAME_Rect *direction_used_pixels;
+    GAME_Rect *more_used_pixels;
+    GAME_Rect *regions;
+
+    GAME_Rect *aregion, *the_regions;
+    int num_regions;
+    int nx, ny, nh, nw, ay, ax;
+    int directions[8][2];
+
+
+    //for dx, dy in [(0,-1), (1,-1), (1,0), (1,1), (0,1), (-1,1), (-1,0), (-1,-1)]:
+
+    directions[0][0] = 0; directions[0][1] = -1;
+    directions[1][0] = 1; directions[1][1] = -1;
+    directions[2][0] = 1; directions[2][1] = 0;
+    directions[3][0] = 1; directions[3][1] = 1;
+    directions[4][0] = 0; directions[4][1] = 1;
+    directions[5][0] = -1; directions[5][1] = 1;
+    directions[6][0] = -1; directions[6][1] = 0;
+    directions[7][0] = -1; directions[7][1] = -1;
+
+
+
+    num_regions = 0;
+
+    height = mask->h;
+    width = mask->w;
+
+
+    /* used_pixels are pointers to rects held in the regions array.  */
+    used_pixels = (GAME_Rect**) malloc(sizeof(GAME_Rect*) * height * width);
+
+
+    for(y=0; y < height; y++) {
+        for(x=0; x < width; x++) {
+            //used_pixels[y][x] = (GAME_Rect*)NULL;
+            *((GAME_Rect **) (used_pixels + y * width) + x) = NULL;
+        }
+    }
+
+    regions = (GAME_Rect*) malloc(sizeof(GAME_Rect) * height * width);
+
+    the_regions = regions;
+
+    for(y=0; y < height; y++) {
+        for(x=0; x < width; x++) {
+            //
+            p = bitmask_getbit(mask, x, y);
+
+
+            if(p) {
+                /* a_used_pixels is the pointer used_pixels[y][x].  */
+                a_used_pixels = *((GAME_Rect **) (used_pixels + y * width) + x);
+
+                /*
+                if not used_pixels[y][x]:
+                    used_pixels[y][x] = pygame.Rect(x,y,1,1)
+                    regions.append( used_pixels[y][x] )
+
+                aregion = used_pixels[y][x] 
+
+                */
+                
+
+                if( !a_used_pixels ) {
+                    /* Add the pixels as a rect on the_regions */
+                    the_regions[num_regions].x = x;
+                    the_regions[num_regions].y = y;
+                    the_regions[num_regions].w = 1;
+                    the_regions[num_regions].h = 1;
+                    a_used_pixels = the_regions + num_regions;
+                    num_regions++;
+
+                }
+                aregion = a_used_pixels;
+
+                /* check other directions, clockwise.  mark a pixel as used if it is.  */
+
+                for(i=0; i < 8; i++) {
+
+                    ax = directions[i][0] + x;
+                    ay = directions[i][1] + y;
+                    
+                    /* if we are within the bounds of the mask, check it. */
+                    
+                    if(ax >=0 && ax < width && ay < height && ay >= 0) {
+                        
+                        
+                        /* printf("ax, ay: %d,%d\n", ax, ay);
+                        */
+
+                        if(bitmask_getbit(mask, ax, ay)) {
+                            /*
+                            if not used_pixels[ay][ax]:
+                                aregion.union_ip( pygame.Rect(ax,ay, 1, 1) )
+                            */
+                            direction_used_pixels = *((GAME_Rect **) (used_pixels + ay * width) + ax);
+                            if (!direction_used_pixels) {
+                                nx = MIN (aregion->x, ax);
+                                ny = MIN (aregion->y, ay);
+                                nw = MAX (aregion->x + aregion->w, ax + 1) - nx;
+                                nh = MAX (aregion->y + aregion->h, ay + 1) - ny;
+                                
+                                aregion->x = nx;
+                                aregion->y = ny;
+                                aregion->w = nw;
+                                aregion->h = nh;
+                            }
+                            /* used_pixels[ay][ax] = aregion */
+                            *((GAME_Rect **) (used_pixels + ay * width) + ax) = aregion;
+                        }
+                    }
+
+                }
+
+
+
+            }
+        }
+    }
+
+
+    *num_bounding_boxes = num_regions;
+
+
+    free(used_pixels);
+
+
+    return regions;
+}
+
+
+static PyObject* mask_get_bounding_rects(PyObject* self, PyObject* args)
+{
+    GAME_Rect *used_pixels;
+    GAME_Rect *regions;
+    GAME_Rect *aregion;
+    int num_bounding_boxes, i;
+    PyObject* ret;
+
+    PyObject* rect;
+
+
+
+	bitmask_t *mask = PyMask_AsBitmap(self);
+
+
+    ret = NULL;
+    num_bounding_boxes = 0;
+
+
+	if(!PyArg_ParseTuple(args, ""))
+		return NULL;
+
+    ret = PyList_New (0);
+    if (!ret)
+        return NULL;
+
+
+    Py_BEGIN_ALLOW_THREADS;
+
+    regions = get_bounding_rects(mask, &num_bounding_boxes);
+
+    Py_END_ALLOW_THREADS;
+
+
+    /* printf("num_bounding_boxes:%d\n", num_bounding_boxes); */
+
+
+    /* build a list of rects to return.  */
+    for(i=0; i < num_bounding_boxes; i++) {
+        aregion = regions + i;
+        /* printf("aregion x,y,w,h:%d,%d,%d,%d\n", aregion->x, aregion->y, aregion->w, aregion->h);
+        */
+
+        rect = PyRect_New4 ( aregion->x, aregion->y, aregion->w, aregion->h );
+        PyList_Append (ret, rect);
+        Py_DECREF (rect);
+    }
+
+    free(regions);
+
+
+	return ret;
+}
+
+
 
 
 static PyMethodDef maskobj_builtins[] =
 	{ "set_at", mask_set_at, METH_VARARGS, DOC_PYGAMEMASKSETAT },
 	{ "overlap", mask_overlap, METH_VARARGS, DOC_PYGAMEMASKOVERLAP },
 	{ "overlap_area", mask_overlap_area, METH_VARARGS, DOC_PYGAMEMASKOVERLAPAREA },
+	{ "get_bounding_rects", mask_get_bounding_rects, METH_VARARGS, DOC_PYGAMEMASKGETBOUNDINGRECTS },
 
 	{ NULL, NULL }
 };
   PyDict_SetItemString(dict, "MaskType", (PyObject *)&PyMask_Type);
   import_pygame_base ();
   import_pygame_surface ();
+  import_pygame_rect ();
 }
 

File src/mask.doc

 <END>
 
 
+get_bounding_rects
+Returns a list of bounding rects of regions of set pixels.
+Mask.get_bounding_rects() -> Rects
+
 <END>
+
+
+
+<END>

File src/pygamedocs.h

 
 #define DOC_PYGAMEMASKOVERLAPAREA "Mask.overlap_area(othermask, offset) -> numpixels\nReturns the number of overlapping 'pixels'."
 
+#define DOC_PYGAMEMASKGETBOUNDINGRECTS "Mask.get_bounding_rects() -> Rects\nReturns a list of bounding rects of regions of set pixels."
+
 #define DOC_ ""
 
 #define DOC_PYGAMEMIXER "pygame module for loading and playing sounds"
 
 #define DOC_PYGAMETRANSFORMCHOP "pygame.transform.chop(Surface, rect): return Surface\nremove interior area of an image"
 
+#define DOC_PYGAMETRANSFORMLAPLACIAN "pygame.transform.laplacian(Surface, DestSurface = None): return Surface\nfind edges in a surface"
+
+#define DOC_PYGAMETRANSFORMAVERAGESURFACES "pygame.transform.average_surfaces(Surfaces, DestSurface = None): return Surface\nfind the average surface from many surfaces."
+
+#define DOC_PYGAMETRANSFORMTHRESHOLD "pygame.transform.threshold(DestSurface, Surface, color, threshold = (0,0,0,0), diff_color = (0,0,0,0), change_return = True): return num_threshold_pixels\nfinds which, and how many pixels in a surface are within a threshold of a color."
+
+#define DOC_ ""
+

File src/surface.c

 
     }
 
-
     surface = SDL_CreateRGBSurface (flags, width, height, bpp, Rmask, Gmask,
                                     Bmask, Amask);
+
     if (!surface)
     {
         RAISE (PyExc_SDLError, SDL_GetError ());

File src/transform.c

 
 
 
+static int
+get_threshold (SDL_Surface *destsurf, SDL_Surface *surf, SDL_Surface *surf2, Uint32 color,  Uint32 threshold,  Uint32 diff_color, int change_return) {
+
+
+    int x, y;
+    Uint8 *pixels, *destpixels, *pixels2;
+    SDL_Rect sdlrect;
+
+
+    SDL_PixelFormat *format, *destformat, *format2;
+    Uint32 the_color, the_color2;
+    Uint8 *pix;
+    Uint8 r, g, b, a;
+    Uint8 dr, dg, db, da;
+    Uint8 tr, tg, tb, ta;
+
+    Uint8 c1r, c1g, c1b, c1a;
+    Uint8 c2r, c2g, c2b, c2a;
+
+
+    Uint8 *byte_buf;
+
+    int result;
+
+    int similar;
+
+    similar = 0;
+
+
+    pixels = (Uint8 *) surf->pixels;
+    format = surf->format;
+
+
+    SDL_GetRGBA (diff_color, format, &dr, &dg, &db, &da);
+    /*
+    printf("color:%d:   %d, %d, %d, %d,   change_return:%d: \n", diff_color, dr,dg,db,da, change_return);
+    */
+
+
+    if(change_return) {
+        sdlrect.x = sdlrect.y = 0;
+        sdlrect.w = destsurf->w;
+        sdlrect.h = destsurf->h;
+        result = SDL_FillRect (destsurf, &sdlrect, diff_color);
+    }
+
+
+
+    SDL_GetRGBA (color, format, &r, &g, &b, &a);
+
+/*
+    printf("color:%d:   %d, %d, %d, %d\n", color, r,g,b,a);
+*/
+
+    SDL_GetRGBA (threshold, format, &tr, &tg, &tb, &ta);
+
+
+
+
+
+
+/*
+    printf(":%d, %d, %d, %d\n", rgba_threshold[0], rgba_threshold[1], rgba_threshold[2], rgba_threshold[3]);
+    printf(":%d, %d, %d, %d\n", rgba_diff_color[0], rgba_diff_color[1], rgba_diff_color[2], rgba_diff_color[3]);
+    printf(":%d\n", change_return);
+*/
+
+
+    /* TODO: this is the slow, but easy to code way.  Could make the loop 
+     *         just increment a pointer depending on the format.  
+     *         It's faster than in python anyhow.
+     */
+    if(destsurf) {
+        destpixels = (Uint8 *) destsurf->pixels;
+        destformat = destsurf->format;
+    }
+
+    if(surf2) {
+        pixels2 = (Uint8 *) surf2->pixels;
+        format2 = surf2->format;
+    }
+
+
+
+    /*
+    printf("surf->w:%d, surf->h:%d\n", surf->w, surf->h);
+    printf(" ----- %d", surf2);
+    */
+
+
+
+
+
+    for(y=0; y < surf->h; y++) {
+        for(x=0; x < surf->w; x++) {
+            /* the_color = surf->get_at(x,y) */
+            switch (format->BytesPerPixel)
+            {
+            case 1:
+                the_color = (Uint32)*((Uint8 *) pixels + y * surf->pitch + x);
+                break;
+            case 2:
+                the_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
+                the_color = (pix[0]) + (pix[1] << 8) + (pix[2] << 16);
+        #else
+                the_color = (pix[2]) + (pix[1] << 8) + (pix[0] << 16);
+        #endif
+                break;
+            default:                  /* case 4: */
+                the_color = *((Uint32 *) (pixels + y * surf->pitch) + x);
+                break;
+            }
+
+            SDL_GetRGBA (the_color, format, &c1r, &c1g, &c1b, &c1a);
+
+
+            /*
+            See if we are using another surface or not.
+            If we are, get the other surfaces pixel.
+
+            Then test the threshold against that pixels color.
+            */
+
+            if(surf2) {
+                /* the_color2 = surf2->get_at(x,y) */
+
+                switch (format2->BytesPerPixel)
+                {
+                case 1:
+                    the_color2 = (Uint32)*((Uint8 *) pixels2 + y * surf2->pitch + x);
+                    break;
+                case 2:
+                    the_color2 = (Uint32)*((Uint16 *) (pixels2 + y * surf2->pitch) + x);
+                    break;
+                case 3:
+                    pix = ((Uint8 *) (pixels2 + y * surf2->pitch) + x * 3);
+            #if SDL_BYTEORDER == SDL_LIL_ENDIAN
+                    the_color2 = (pix[0]) + (pix[1] << 8) + (pix[2] << 16);
+            #else
+                    the_color2 = (pix[2]) + (pix[1] << 8) + (pix[0] << 16);
+            #endif
+                    break;
+                default:                  /* case 4: */
+                    the_color2 = *((Uint32 *) (pixels2 + y * surf2->pitch) + x);
+                    break;
+                }
+
+                SDL_GetRGBA (the_color2, format2, &c2r, &c2g, &c2b, &c2a);
+            }
+
+
+
+
+
+            /*
+            printf("hello!  %d:%d:%d:  tr:%d\n", cr, r, abs(cr - r), tr);
+            */
+
+            if ( !surf2 && ((abs(c1r - r) < tr) &
+                            (abs(c1g - g) < tg) & 
+                            (abs(c1b - b) < tb)) ) {
+                /*
+                printf("simiar\n");
+                */
+
+                /* this pixel is within the threshold. */
+                if (change_return) {
+                    /* destsurf->set_at((x,y), the_color) */
+
+
+                    switch (destformat->BytesPerPixel)
+                    {
+                    case 1:
+                        *((Uint8 *) destpixels + y * destsurf->pitch + x) = (Uint8) the_color;
+                        break;
+                    case 2:
+                        *((Uint16 *) (destpixels + y * destsurf->pitch) + x) = (Uint16) the_color;
+                        break;
+                    case 3:
+                        byte_buf = (Uint8 *) (destpixels + y * destsurf->pitch) + x * 3;
+#if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
+                        *(byte_buf + (destformat->Rshift >> 3)) = (Uint8) (the_color >> 16);
+                        *(byte_buf + (destformat->Gshift >> 3)) = (Uint8) (the_color >> 8);
+                        *(byte_buf + (destformat->Bshift >> 3)) = (Uint8) the_color;
+#else
+                        *(byte_buf + 2 - (destformat->Rshift >> 3)) = (Uint8) (the_color >> 16);
+                        *(byte_buf + 2 - (destformat->Gshift >> 3)) = (Uint8) (the_color >> 8);
+                        *(byte_buf + 2 - (destformat->Bshift >> 3)) = (Uint8) the_color;
+#endif
+                        break;
+                    default:                  /* case 4: */
+                        *((Uint32 *) (destpixels + y * destsurf->pitch) + x) = the_color;
+                        break;
+                    }
+                }
+
+
+
+                similar++;
+            } else if (surf2 && ((abs(c1r - c2r) < tr) &
+                                 (abs(c1g - c2g) < tg) & 
+                                 (abs(c1b - c2b) < tb))  ) {
+
+                /*
+                printf("in here!\n");
+                */
+
+                /* see if we are changing the return surface, 
+                     and how we want to change it.
+                */
+
+                if (change_return == 1) {
+                    /* destsurf->set_at((x,y), color)*/
+
+
+                    switch (destformat->BytesPerPixel)
+                    {
+                    case 1:
+                        *((Uint8 *) destpixels + y * destsurf->pitch + x) = (Uint8) color;
+                        break;
+                    case 2:
+                        *((Uint16 *) (destpixels + y * destsurf->pitch) + x) = (Uint16) color;
+                        break;
+                    case 3:
+                        byte_buf = (Uint8 *) (destpixels + y * destsurf->pitch) + x * 3;
+#if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
+                        *(byte_buf + (destformat->Rshift >> 3)) = (Uint8) (color >> 16);
+                        *(byte_buf + (destformat->Gshift >> 3)) = (Uint8) (color >> 8);
+                        *(byte_buf + (destformat->Bshift >> 3)) = (Uint8) color;
+#else
+                        *(byte_buf + 2 - (destformat->Rshift >> 3)) = (Uint8) (color >> 16);
+                        *(byte_buf + 2 - (destformat->Gshift >> 3)) = (Uint8) (color >> 8);
+                        *(byte_buf + 2 - (destformat->Bshift >> 3)) = (Uint8) color;
+#endif
+                        break;
+                    default:                  /* case 4: */
+                        *((Uint32 *) (destpixels + y * destsurf->pitch) + x) = color;
+                        break;
+                    }
+
+
+                    similar++;
+                }
+
+
+
+
+            }
+
+
+        }
+    }
+
+
+
+    return similar;
+}
+
+
+
+
+
+
+static PyObject* surf_threshold(PyObject* self, PyObject* arg)
+{
+	PyObject *surfobj, *surfobj2, *surfobj3;
+	SDL_Surface* surf, *destsurf, *surf2;
+	int bpp, change_return;
+    int num_threshold_pixels;
+
+
+    PyObject *rgba_obj_color, *rgba_obj_threshold, *rgba_obj_diff_color;
+    Uint8 rgba_color[4];
+    Uint8 rgba_threshold[4];
+    Uint8 rgba_diff_color[4];
+
+    Uint32 color;
+    Uint32 color_threshold;
+    Uint32 color_diff_color;
+
+    surf2 = destsurf = surf = NULL;
+
+    surfobj2 = NULL;
+    surfobj3 = NULL;
+
+
+
+    /* Set some defaults */
+    rgba_obj_threshold = NULL;
+    rgba_obj_diff_color = NULL;
+
+    num_threshold_pixels = 0;
+    change_return = 1;
+
+    rgba_threshold[0] = 0; rgba_threshold[1] = 0; rgba_threshold[2] = 0; rgba_threshold[4] = 255;
+    rgba_diff_color[0] = 0; rgba_diff_color[1] = 0; rgba_diff_color[2] = 0; rgba_diff_color[4] = 255;
+
+
+    /*get all the arguments*/
+    if (!PyArg_ParseTuple (arg, "O!O!O|OOiO!", &PySurface_Type, &surfobj, 
+                           &PySurface_Type, &surfobj2,
+                           &rgba_obj_color,  &rgba_obj_threshold, &rgba_obj_diff_color, 
+                           &change_return,
+                           &PySurface_Type, &surfobj3))
+        return NULL;
+
+
+    destsurf = PySurface_AsSurface (surfobj);
+    surf = PySurface_AsSurface (surfobj2);
+    if(surfobj3) {
+        surf2 = PySurface_AsSurface (surfobj3);
+    }
+
+
+
+    if (PyInt_Check (rgba_obj_color)) {
+        color = (Uint32) PyInt_AsLong (rgba_obj_color);
+    } else if (RGBAFromObj (rgba_obj_color, rgba_color)) {
+        color = SDL_MapRGBA (surf->format, rgba_color[0], rgba_color[1], rgba_color[2], rgba_color[3]);
+        /*printf("here I am! :%d:  %d, %d, %d, %d\n", color, rgba_color[0], rgba_color[1], rgba_color[2], rgba_color[3]);
+        */
+
+    } else {
+        return RAISE (PyExc_TypeError, "invalid color argument");
+    }
+
+
+
+    if(rgba_obj_threshold) {
+
+        if (PyInt_Check (rgba_obj_threshold))
+            color_threshold = (Uint32) PyInt_AsLong (rgba_obj_threshold);
+        else if (RGBAFromObj (rgba_obj_threshold, rgba_threshold))
+            color_threshold = SDL_MapRGBA (surf->format, rgba_threshold[0], rgba_threshold[1], rgba_threshold[2], rgba_threshold[3]);
+        else
+            return RAISE (PyExc_TypeError, "invalid threshold argument");
+
+    } else {
+        color_threshold = SDL_MapRGBA (surf->format, rgba_threshold[0], rgba_threshold[1], rgba_threshold[2], rgba_threshold[3]);
+    }
+
+    if(rgba_obj_diff_color) {
+
+        if (PyInt_Check (rgba_obj_diff_color))
+            color_diff_color = (Uint32) PyInt_AsLong (rgba_obj_diff_color);
+        else if (RGBAFromObj (rgba_obj_diff_color, rgba_diff_color))
+            color_diff_color = SDL_MapRGBA (surf->format, rgba_diff_color[0], rgba_diff_color[1], rgba_diff_color[2], rgba_diff_color[3]);
+        else
+            return RAISE (PyExc_TypeError, "invalid diff_color argument");
+    } else {
+        color_diff_color = SDL_MapRGBA (surf->format, rgba_diff_color[0], rgba_diff_color[1], rgba_diff_color[2], rgba_diff_color[3]);
+    }
+
+/*
+    printf(":%d, %d, %d, %d\n", rgba_color[0], rgba_color[1], rgba_color[2], rgba_color[3]);
+    printf(":%d, %d, %d, %d\n", rgba_threshold[0], rgba_threshold[1], rgba_threshold[2], rgba_threshold[3]);
+    printf(":%d, %d, %d, %d\n", rgba_diff_color[0], rgba_diff_color[1], rgba_diff_color[2], rgba_diff_color[3]);
+    printf(":%d\n", change_return);
+*/
+
+
+    bpp = surf->format->BytesPerPixel;
+    /*if(bpp < 3 || bpp > 4)
+		return RAISE(PyExc_ValueError, "Only 24-bit or 32-bit surfaces can be thresholded");
+    */
+
+	
+    PySurface_Lock(surfobj);
+    PySurface_Lock(surfobj2);
+
+    if(surfobj3) {
+        PySurface_Lock(surfobj3);
+    }
+    Py_BEGIN_ALLOW_THREADS;
+
+
+    num_threshold_pixels = get_threshold (destsurf, surf, surf2, color,  color_threshold,  color_diff_color, change_return);
+
+
+    Py_END_ALLOW_THREADS;
+
+    PySurface_Unlock(surfobj);
+    PySurface_Unlock(surfobj2);
+    if(surfobj3) {
+        PySurface_Unlock(surfobj3);
+    }
+
+
+
+    return PyInt_FromLong (num_threshold_pixels);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+
+TODO:
+add_4
+sub_4
+mul_4
+clamp_4
+
+*/
+
+
+#define SURF_GET_AT(p_color, p_surf, p_x, p_y, p_pixels, p_format, p_pix) \
+        switch (p_format->BytesPerPixel) \
+        { \
+        case 1: \
+            p_color = (Uint32)*((Uint8 *) (p_pixels) + (p_y) * p_surf->pitch + (p_x)); \
+            break; \
+        case 2: \
+            p_color = (Uint32)*((Uint16 *) ((p_pixels) + (p_y) * p_surf->pitch) + (p_x)); \
+            break; \
+        case 3: \
+            p_pix = ((Uint8 *) (p_pixels + (p_y) * p_surf->pitch) + (p_x) * 3); \
+            p_color = (SDL_BYTEORDER == SDL_LIL_ENDIAN) ? \
+                      (p_pix[0]) + (p_pix[1] << 8) + (p_pix[2] << 16) : \
+                      (p_pix[2]) + (p_pix[1] << 8) + (p_pix[0] << 16); \
+            break; \
+        default:                  /* case 4: */ \
+            p_color = *((Uint32 *) (p_pixels + (p_y) * p_surf->pitch) + (p_x)); \
+            break; \
+        } \
+
+
+
+#if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
+
+#define SURF_SET_AT(p_color, p_surf, p_x, p_y, p_pixels, p_format, p_byte_buf) \
+        switch (p_format->BytesPerPixel) \
+        { \
+        case 1: \
+            *((Uint8 *) p_pixels + (p_y) * p_surf->pitch + (p_x)) = (Uint8) p_color; \
+            break; \
+        case 2: \
+            *((Uint16 *) (p_pixels + (p_y) * p_surf->pitch) + (p_x)) = (Uint16) p_color; \
+            break; \
+        case 3: \
+            p_byte_buf = (Uint8 *) (p_pixels + (p_y) * p_surf->pitch) + (p_x) * 3; \
+            *(p_byte_buf + (p_format->Rshift >> 3)) = (Uint8) (p_color >> 16); \
+            *(p_byte_buf + (p_format->Gshift >> 3)) = (Uint8) (p_color >> 8); \
+            *(p_byte_buf + (p_format->Bshift >> 3)) = (Uint8) p_color; \
+            break; \
+        default:                   \
+            *((Uint32 *) (p_pixels + (p_y) * p_surf->pitch) + (p_x)) = p_color; \
+            break; \
+        } \
+
+#else
+
+#define SURF_SET_AT(p_color, p_surf, p_x, p_y, p_pixels, p_format, p_byte_buf) \
+        switch (p_format->BytesPerPixel) \
+        { \
+        case 1: \
+            *((Uint8 *) p_pixels + (p_y) * p_surf->pitch + (p_x)) = (Uint8) p_color; \
+            break; \
+        case 2: \
+            *((Uint16 *) (p_pixels + (p_y) * p_surf->pitch) + (p_x)) = (Uint16) p_color; \
+            break; \
+        case 3: \
+            p_byte_buf = (Uint8 *) (p_pixels + (p_y) * p_surf->pitch) + (p_x) * 3; \
+            *(p_byte_buf + 2 - (p_format->Rshift >> 3)) = (Uint8) (p_color >> 16); \
+            *(p_byte_buf + 2 - (p_format->Gshift >> 3)) = (Uint8) (p_color >> 8); \
+            *(p_byte_buf + 2 - (p_format->Bshift >> 3)) = (Uint8) p_color; \
+            break; \
+        default:                   \
+            *((Uint32 *) (p_pixels + (p_y) * p_surf->pitch) + (p_x)) = p_color; \
+            break; \
+        } \
+
+#endif
+
+
+
+
+
+
+
+
+/*
+number to use for missing samples
+*/
+#define LAPLACIAN_NUM 0xFFFFFFFF
+
+
+
+void laplacian(SDL_Surface *surf, SDL_Surface *destsurf) {
+
+    int ii;
+    int x,y,height,width;
+
+    Uint32 sample[9];
+    //Uint32 total[4];
+    int total[4];
+
+    Uint32 total2[4];
+    Uint32 total3[4];
+
+    Uint8 c1r, c1g, c1b, c1a;
+    //Uint32 c1r, c1g, c1b, c1a;
+    Uint8 acolor[4];
+
+    Uint32 the_color;
+
+    int atmp0;
+    int atmp1;
+    int atmp2;
+    int atmp3;
+
+    SDL_PixelFormat *format, *destformat, *format2;
+    Uint8 *pixels, *destpixels, *pixels2;
+    Uint8 *pix;
+    
+    Uint8 *byte_buf;
+    
+    
+    height = surf->h;
+    width = surf->w;
+
+
+    pixels = (Uint8 *) surf->pixels;
+    format = surf->format;
+
+    destpixels = (Uint8 *) destsurf->pixels;
+    destformat = destsurf->format;
+
+/*
+    -1 -1 -1
+    -1  8 -1
+    -1 -1 -1
+
+    col = (sample[4] * 8) - (sample[0] + sample[1] + sample[2] +
+                             sample[3] +             sample[5] + 
+                             sample[6] + sample[7] + sample[8])
+
+    [(-1,-1), (0,-1), (1,-1),     (-1,0), (0,0), (1,0),     (-1,1), (0,1), (1,1)]
+
+*/
+
+    for(y=0;y<height;y++) {
+        for(x=0;x<width;x++) {
+            
+            // Need to bounds check these accesses.
+
+            if(y > 0) {
+                if(x>0) {
+                    SURF_GET_AT(sample[0], surf, x+ -1, y+ -1, pixels, format, pix);
+                }
+                
+                SURF_GET_AT(sample[1], surf, x+  0, y+ -1, pixels, format, pix);
+                
+                if(x+1<width) {
+                    SURF_GET_AT(sample[2], surf, x+  1, y+ -1, pixels, format, pix);
+                }
+            } else {
+                sample[0] = LAPLACIAN_NUM;
+                sample[1] = LAPLACIAN_NUM;
+                sample[2] = LAPLACIAN_NUM;
+            }
+            
+            if(x>0) {
+                SURF_GET_AT(sample[3], surf, x+ -1, y+  0, pixels, format, pix);
+            } else {
+                sample[3] = LAPLACIAN_NUM;
+            }
+            
+            
+            //SURF_GET_AT(sample[4], surf, x+0 , y+0);
+            sample[4] = 0;
+
+            if(x+1<width) {
+                SURF_GET_AT(sample[5], surf, x+  1, y+  0, pixels, format, pix);
+            } else {
+                sample[5] = LAPLACIAN_NUM;
+            }
+
+            if(y+1 < height) {
+
+                if(x>0) {
+                    SURF_GET_AT(sample[6], surf, x+ -1, y+  1, pixels, format, pix);
+                }
+
+                SURF_GET_AT(sample[7], surf, x+  0, y+  1, pixels, format, pix);
+
+                if(x+1<width) {
+                    SURF_GET_AT(sample[8], surf, x+  1, y+  1, pixels, format, pix);
+                }
+            } else {
+                sample[6] = LAPLACIAN_NUM;
+                sample[7] = LAPLACIAN_NUM;
+                sample[8] = LAPLACIAN_NUM;
+            }
+            
+            
+            total[0] = 0; total[1] = 0; total[2] = 0; total[3] = 0;
+            
+            for(ii =0; ii<9; ii++) {
+                SDL_GetRGBA (sample[ii], format, &c1r, &c1g, &c1b, &c1a);
+                total[0] += c1r; total[1] += c1g; total[2] += c1b; total[3] += c1a;
+            }
+            
+            
+            SURF_GET_AT(sample[4], surf, x, y, pixels, format, pix);
+            
+            SDL_GetRGBA (sample[4], format, &c1r, &c1g, &c1b, &c1a);
+            
+            // cast on the right to a signed int, and then clamp to 0-255.
+
+            //atmp = c1r * 8
+            
+
+            atmp0 = c1r * 8;
+            acolor[0] = MIN(MAX(atmp0 - total[0], 0), 255);
+            atmp1 = c1g * 8;
+            acolor[1] = MIN(MAX(atmp1 - total[1], 0), 255);
+            atmp2 = c1b * 8;
+            acolor[2] = MIN(MAX(atmp2 - total[2], 0), 255);
+            atmp3 = c1a * 8;
+            acolor[3] = MIN(MAX(atmp3 - total[3], 0), 255);
+
+            //printf("%d;;%d;;%d;;  ", atmp0, acolor[0],total[0]);
+            
+            
+            //printf("%d,%d,%d,%d;;  \n", acolor[0], acolor[1], acolor[2], acolor[3]);
+            
+            //the_color = (Uint32)acolor;
+            //the_color = 0x00000000;
+            
+            
+            
+            // cast on the right to Uint32, and then clamp to 255.
+            
+            the_color = SDL_MapRGBA (surf->format, acolor[0], acolor[1], acolor[2], acolor[3]);
+
+
+
+
+            // set_at(destsurf, color, x,y);
+            
+            switch (destformat->BytesPerPixel)
+            {
+            case 1:
+                *((Uint8 *) destpixels + y * destsurf->pitch + x) = (Uint8) the_color;
+                break;
+            case 2:
+                *((Uint16 *) (destpixels + y * destsurf->pitch) + x) = (Uint16) the_color;
+                break;
+            case 3:
+                byte_buf = (Uint8 *) (destpixels + y * destsurf->pitch) + x * 3;
+#if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
+                *(byte_buf + (destformat->Rshift >> 3)) = (Uint8) (the_color >> 16);
+                *(byte_buf + (destformat->Gshift >> 3)) = (Uint8) (the_color >> 8);
+                *(byte_buf + (destformat->Bshift >> 3)) = (Uint8) the_color;
+#else
+                *(byte_buf + 2 - (destformat->Rshift >> 3)) = (Uint8) (the_color >> 16);
+                *(byte_buf + 2 - (destformat->Gshift >> 3)) = (Uint8) (the_color >> 8);
+                *(byte_buf + 2 - (destformat->Bshift >> 3)) = (Uint8) the_color;
+#endif
+                break;
+            default:                  
+                *((Uint32 *) (destpixels + y * destsurf->pitch) + x) = the_color;
+                break;
+            }
+
+
+
+        }
+    }
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+static PyObject*
+surf_laplacian (PyObject* self, PyObject* arg)
+{
+    PyObject *surfobj, *surfobj2;
+    SDL_Surface *surf;
+    SDL_Surface *newsurf;
+    int width, height;
+    surfobj2 = NULL;
+        
+    /*get all the arguments*/
+    if (!PyArg_ParseTuple (arg, "O!|O!", &PySurface_Type, &surfobj, 
+                           &PySurface_Type, &surfobj2))
+        return NULL;
+
+    surf = PySurface_AsSurface (surfobj);
+
+    /* if the second surface is not there, then make a new one. */
+
+    if (!surfobj2)
+    {
+        width = surf->w;
+        height = surf->h;
+
+        newsurf = newsurf_fromsurf (surf, width, height);
+
+        if (!newsurf)
+            return NULL;
+    }
+    else
+        newsurf = PySurface_AsSurface (surfobj2);
+
+    /* check to see if the size is the correct size. */
+    if (newsurf->w != (surf->w) || newsurf->h != (surf->h))
+        return RAISE (PyExc_ValueError, "Destination surface not the same size.");
+
+    /* check to see if the format of the surface is the same. */
+    if (surf->format->BytesPerPixel != newsurf->format->BytesPerPixel)
+        return RAISE (PyExc_ValueError, 
+                      "Source and destination surfaces need the same format.");
+
+    SDL_LockSurface (newsurf);
+    SDL_LockSurface (surf);
+
+    Py_BEGIN_ALLOW_THREADS;
+    laplacian (surf, newsurf);
+    Py_END_ALLOW_THREADS;
+
+    SDL_UnlockSurface (surf);
+    SDL_UnlockSurface (newsurf);
+
+    if (surfobj2)
+    {
+        Py_INCREF (surfobj2);
+        return surfobj2;
+    }
+    else
+        return PySurface_New (newsurf);
+}
+
+
+
+
+int average_surfaces(SDL_Surface **surfaces, int num_surfaces, SDL_Surface *destsurf) {
+    /*
+        returns the average surface from the ones given.
+
+        All surfaces need to be the same size.
+    */
+
+
+    Uint32 *accumulate;
+    Uint32 *the_idx;
+    Uint32 the_color;
+    SDL_Surface *surf;
+    int height, width, x, y, surf_idx;
+    Uint8 c1r, c1g, c1b;
+
+    float div_inv;
+
+    
+    SDL_PixelFormat *format, *destformat;
+    Uint8 *pixels, *destpixels;
+    Uint8 *pix;
+    Uint8 *byte_buf;
+    
+
+    if(!num_surfaces) { return 0; }
+    
+    height = surfaces[0]->h;
+    width = surfaces[0]->w;
+    
+    destpixels = (Uint8 *) destsurf->pixels;
+    destformat = destsurf->format; 
+
+
+    /* allocate an array to accumulate them all. */
+    accumulate = (Uint32 *) calloc(1, sizeof(Uint32) * height * width * 3 );
+
+    if(!accumulate) { return -1; }
+    
+    
+    /* add up the r,g,b from all the surfaces. */
+    
+    for(surf_idx=0;surf_idx < num_surfaces;surf_idx++) {
+        surf = surfaces[surf_idx];
+    
+        pixels = (Uint8 *) surf->pixels;
+        format = surf->format;
+    
+        the_idx = accumulate;
+        for(y=0;y<height;y++) {
+            for(x=0;x<width;x++) {
+                SURF_GET_AT(the_color, surf, x, y, pixels, format, pix);
+                SDL_GetRGB (the_color, format, &c1r, &c1g, &c1b);
+        
+                *(the_idx) += c1r;
+                *(the_idx + 1) += c1g;
+                *(the_idx + 2) += c1b;
+                the_idx += 3;
+            }
+        }
+    }
+    
+    
+    /* blit the accumulated array back to the destination surface. */
+    
+    
+    div_inv = 1. / (num_surfaces);
+    
+    the_idx = accumulate;
+    
+    for(y=0;y<height;y++) {
+        for(x=0;x<width;x++) {
+            
+            the_color = SDL_MapRGB (destformat, 
+                                    (Uint8) round(*(the_idx) * div_inv),
+                                    (Uint8) round(*(the_idx + 1) * div_inv),
+                                    (Uint8) round(*(the_idx + 2) * div_inv));
+            
+            SURF_SET_AT(the_color, destsurf, x, y, destpixels, destformat, byte_buf);
+            
+            the_idx += 3;
+        }
+    }
+    
+    
+    free(accumulate);
+    
+    return 1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+static PyObject*
+surf_average_surfaces (PyObject* self, PyObject* arg)
+{
+    PyObject *surfobj, *surfobj2;
+    SDL_Surface *surf;
+    SDL_Surface *newsurf;
+    SDL_Surface **surfaces;
+    int width, height;
+    int an_error;
+    size_t size, loop, loop_up_to;
+    
+    PyObject* list, *obj;
+    PyObject* ret = NULL;
+    
+    an_error = 0;
+
+
+    surfobj2 = NULL;
+
+    if (!PyArg_ParseTuple (arg, "O|O!", &list, &PySurface_Type, &surfobj2))
+        return NULL;
+
+    if (!PySequence_Check (list))
+        return RAISE (PyExc_TypeError, "Argument must be a sequence of surface objects.");
+
+
+    size = PySequence_Length (list); /*warning, size could be -1 on error?*/
+    
+    if(size < 1)
+        return RAISE (PyExc_TypeError, "Needs to be given at least one surface.");
+    
+    
+    /* Allocate an array of surface pointers. */
+    
+    surfaces = (SDL_Surface **) calloc(1, sizeof(SDL_Surface *) * size);
+    
+    if(!surfaces) {
+        return RAISE (PyExc_MemoryError, "Not enough memory to store surfaces.\n");
+    }
+    
+    
+    /* Iterate over 'surfaces' passed in. */
+    
+    
+    
+    /* need to get the first surface to see how big it is */
+    
+    loop = 0;
+
+
+    for (loop = 0; loop < size; ++loop)
+    {
+        
+        obj = PySequence_GetItem (list, loop);
+        
+        if(!obj) {
+            Py_XDECREF (obj);
+            ret = RAISE (PyExc_TypeError, "Needs to be a surface object.");
+            an_error = 1;
+            break;
+        }
+        
+
+        if (!PySurface_Check (obj)) {
+            Py_XDECREF (obj);
+            ret = RAISE (PyExc_TypeError, "Needs to be a surface object.");
+            an_error = 1;
+            break;
+        }
+        
+
+        surf = PySurface_AsSurface (obj);
+        
+        if(!surf) {
+            Py_XDECREF (obj);
+            ret = RAISE (PyExc_TypeError, "Needs to be a surface object.");
+            an_error = 1;
+            break;
+        }
+        
+
+        if(loop == 0) {
+            /* if the second surface is not there, then make a new one. */
+            if (!surfobj2) {
+        
+                width = surf->w;
+                height = surf->h;
+
+                newsurf = newsurf_fromsurf (surf, width, height);
+
+                if (!newsurf) {
+                    Py_XDECREF (obj);
+                    ret = RAISE (PyExc_ValueError, "Could not create new surface.");
+                    an_error = 1;
+                    break;
+                }
+            }
+            else
+                newsurf = PySurface_AsSurface (surfobj2);
+            
+            
+            /* check to see if the size is the correct size. */
+            if (newsurf->w != (surf->w) || newsurf->h != (surf->h)) {
+                Py_XDECREF (obj);
+                ret = RAISE (PyExc_ValueError, "Destination surface not the same size.");
+                an_error = 1;
+                break;
+            }
+            
+            /* check to see if the format of the surface is the same. */
+            if (surf->format->BytesPerPixel != newsurf->format->BytesPerPixel) {
+                Py_XDECREF (obj);
+                ret = RAISE (PyExc_ValueError, "Source and destination surfaces need the same format.");
+                an_error = 1;
+                break;
+            }
+        }
+        
+        
+        
+        /* Copy surface pointer, and also lock surface. */
+        SDL_LockSurface (surf);
+        surfaces[loop] = surf;
+
+        Py_DECREF (obj);
+    }
+    
+
+    loop_up_to = loop;
+    
+    if(!an_error) {
+        
+        /* Process images, get average surface. */
+        
+        SDL_LockSurface (newsurf);
+        
+        Py_BEGIN_ALLOW_THREADS;
+        average_surfaces (surfaces, size, newsurf);
+        Py_END_ALLOW_THREADS;
+        
+        SDL_UnlockSurface (newsurf);
+        
+        if (surfobj2)
+        {
+            Py_INCREF (surfobj2);
+            ret = surfobj2;
+        }
+        else {
+            ret = PySurface_New (newsurf);
+        }
+    } else {
+
+    }
+    
+    
+    
+    /* cleanup */
+    
+    /* unlock the surfaces we got up to. */
+    
+    for (loop = 0; loop < loop_up_to; loop++) {
+        if(surfaces[loop]) {
+            SDL_UnlockSurface (surfaces[loop]);
+        }
+    }
+    
+    free(surfaces);
+    
+    return ret;
+}
+
+
+
+
+
+
+
+
+
+
 
 
 
     { "chop", surf_chop, METH_VARARGS, DOC_PYGAMETRANSFORMCHOP },
     { "scale2x", surf_scale2x, METH_VARARGS, DOC_PYGAMETRANSFORMSCALE2X },
     { "smoothscale", surf_scalesmooth, METH_VARARGS, DOC_PYGAMETRANSFORMSMOOTHSCALE },
+    { "threshold", surf_threshold, METH_VARARGS, DOC_PYGAMETRANSFORMTHRESHOLD },
+    { "laplacian", surf_laplacian, METH_VARARGS, DOC_PYGAMETRANSFORMTHRESHOLD },
+    { "average_surfaces", surf_average_surfaces, METH_VARARGS, DOC_PYGAMETRANSFORMAVERAGESURFACES },
     
     { NULL, NULL, 0, NULL }
 };

File src/transform.doc

 resulting image is shrunken by the size of pixels removed.
 (The original image is not altered by this operation.)
 <END>
+
+
+
+laplacian
+find edges in a surface
+pygame.transform.laplacian(Surface, DestSurface = None): return Surface
+
+Finds the edges in a surface using the laplacian algorithm.
 <END>
+
+
+
+average_surfaces
+find the average surface from many surfaces.
+pygame.transform.average_surfaces(Surfaces, DestSurface = None): return Surface
+
+Takes a sequence of surfaces and returns a surface with average colors from each
+of the surfaces.
+<END>
+
+
+
+threshold
+finds which, and how many pixels in a surface are within a threshold of a color.
+pygame.transform.threshold(DestSurface, Surface, color, threshold = (0,0,0,0), diff_color = (0,0,0,0), change_return = True): return num_threshold_pixels
+
+Finds which, and how many pixels in a surface are within a threshold of a color.
+
+It can set the destination surface where all of the pixels not within the 
+threshold are changed to diff_color.
+
+Or it can be used to just count the number of pixels within the threshold if you set
+change_return to False.
+
+You can use a threshold of (r,g,b,a) where the r,g,b can have different thresholds. So
+you could use an r threshold of 40 and a blue threshold of 2 if you like.
+<END>
+
+
+
+
+
+
+
+<END>

File test/mask_test.py