pygame find a solution to stop pupil overflow outside Eye - python

i try to create ellipse eye with pygame, and i have problem: my pupils overflow over eyes :
and I search to get this result
my code is like this :
self.lastrect = self.display.fill((0,0,0),self.lastrect)
leftEye = pygame.draw.ellipse(self.display, (255, 255, 255), [int(self.startx -self.startx/2-self.eyeRadius),int(self.starty-self.eyeRadius*self.eyeRatio), self.eyeWidth,self.eyeHeight], 0)
rightEye = pygame.draw.ellipse(self.display, (255, 255, 255), [int(self.startx +self.startx/2-self.eyeRadius),int(self.starty-self.eyeRadius*self.eyeRatio), self.eyeWidth,self.eyeHeight], 0)
leftPupil = self.display.blit(self.pupil,(self.x-self.startx/2-self.rad,self.y-self.rad))
rightPupil = self.display.blit(self.pupil,(self.x+self.startx/2-self.rad,self.y-self.rad))
pygame.display.update([leftPupil,leftEye,rightPupil,rightEye,self.lastrect])
can you help me to find a solution to stop pupil's overflow outside Eye ?

While there's no doubt that masks would be the better way, I would do something different (and dumber). In short is that I would give the screen a white backround, blit the pupil, AND THEN blit the face (in your picture it is the black background without the eye slots. This may sound confusing so think about creating the same exact image but with a white background.
However, there are a lot of negatives to this if you apply it to a program with other shapes and images so you'll want to probably stick with masking anyways. But this could work

I made it like this :
mask = pygame.Surface(self.size, pygame.SRCALPHA)
mask.fill((254, 195, 172))
pygame.draw.ellipse(mask, (0, 0, 0), [
self.leftEllipseX, self.leftEllipseY, self.eyeWidth, self.eyeHeight], 0)
pygame.draw.ellipse(mask, (0, 0, 0), [
self.rightEllipseX, self.rightEllipseY, self.eyeWidth, self.eyeHeight], 0)
self.display.blit(mask, (0, 0), None, pygame.BLEND_RGB_MAX)

Related

How to get the Difference blending mode?

I'm trying to make a night effect for my game in Pygame. So I'm gonna blit a black image on the screen then, change its blending mode to Difference just like in Photoshop in order to make the screen look darker. However, I still don't know how to do that as I haven't used the blending modes in Pygame yet. Any help ?
The blending mode can be changed by setting the optional special_flags argument of pygame.Surface.blit:
blit(source, dest, area=None, special_flags=0) -> Rect
[...]
New in pygame 1.8: Optional special_flags: BLEND_ADD, BLEND_SUB, BLEND_MULT, BLEND_MIN, BLEND_MAX.
New in pygame 1.8.1: Optional special_flags: BLEND_RGBA_ADD, BLEND_RGBA_SUB, BLEND_RGBA_MULT, BLEND_RGBA_MIN, BLEND_RGBA_MAX, BLEND_RGB_ADD, BLEND_RGB_SUB, BLEND_RGB_MULT, BLEND_RGB_MIN, BLEND_RGB_MAX.
New in pygame 1.9.2: Optional special_flags: BLEND_PREMULTIPLIED
New in pygame 2.0.0: Optional special_flags: BLEND_ALPHA_SDL2 [...]
e.g.:
screen.blit(image, (x, y), special_flags = pygame.BLEND_RGBA_SUB)
Unfortunately, Pygame doesn't have a blending mode that gives the absolute difference of 2 images. However it can be achieved with
MAX(SUB(image1, imgage2), SUB(image2, image1))
e.g.:
image1 = pygame.image.load('image2.png')
image2 = pygame.image.load('image1.png')
temp_image = image1.copy()
temp_image.blit(image2, (0, 0), special_flags = pygame.BLEND_RGBA_SUB)
final_image = image2.copy()
final_image.blit(image1, (0, 0), special_flags = pygame.BLEND_RGBA_SUB)
final_image.blit(temp_image, (0, 0), special_flags = pygame.BLEND_RGBA_MAX)

Is there a way to change the Python Imaging Library (PIL)'s default fill color?

I'm currently using Python Imaging Library's (PIL) transform with EXTENT function to allow users to do some basic editing of images i.e. simple zoom in / zoom out, x and y-axis offsets, set background color, rotation etc
And so one problem is that they are able to zoom out or offset enough so that parts of the final output image goes beyond the bounds of the source image. When this happens, PIL fills this portion with a black color
Does anybody know if there's a way to set a custom fill color rather than the black default or has any suggestions on ways to get around this? Much appreciated
I was originally thinking of pre-pasting an alpha layer to where the bounds are exceeded but this seems to get complicated quite quickly..
[Edit] Maybe this will help. So, do something like (don't pay too much attention to the exact integers ) ...
image2 = image1.transform((600, 400), Image.EXTENT, (0, 0, 1200, 800))
draw = ImageDraw.Draw(image2)
# Fill in rectangle below the real image
draw.rectangle( (0, 50, 1200, 600), fill=(255, 150, 0))
# Fill in rectangle to the right of the real image
draw.rectangle( (100, 0, 800, 50), fill=(150, 255, 0))
del draw
image2.save(SAVE_NAME)

How to make a circle semi-transparent in pygame?

I'm somewhat new to pygame and trying to figure out how to make a circle semi-transparent. The trick however is that the background for the circle also has to be transparent. Here is the code I'm talking about:
size = 10
surface = pygame.Surface(size, size), pygame.SRCALPHA, 32)
pygame.draw.circle(
surface,
pygame.Color("black"),
(int(size/2), int(size/2)),
int(size/2), 2)
I tried using surface.set_alpha(127) but that didn't work. I'm assuming because the surface is already transparent.
Any help is appreciated.
A couple things. First, your surface definition should crash, as it missing a parenthesis. It should be:
surface = pygame.Surface((size, size), pygame.SRCALPHA, 32)
I assume that somewhere later in your code, you have something to the effect of:
mainWindow.blit(surface, (x, y))
pygame.display.update() #or flip
Here is your real problem:
>>> import pygame
>>> print pygame.Color("black")
(0, 0, 0, 255)
Notice that 255 at the end. That means that pygame.Color("black") returns a fully opaque color. Whereas (0, 0, 0, 0) would be fully transparent. If you want to set the transparency, define the color directly. That would make your draw function look like:
pygame.draw.circle(
surface,
(0, 0, 0, transparency),
(int(size/2), int(size/2)),
int(size/2), 2)

Fill pygame font with custom pattern

I'm currently working on a (first) project in Python/Pygame and I'm trying to display text with a pattern overlay. The pattern consists vertical lines (1 pixel width), 2 alternating colors .
I'm creating this pattern using pygame.draw.line(), and I can create rectangles with a custom function I created. But now I want this pattern on my font.
I'm new to Python and am wondering: is there a way to create some sort of mask so that the pattern will appear on the font characters only, not outside of them? I've searched the web for some time but cannot find anything.
Many thanks in advance!
You could make use of the different blend modes to get the effect you desire.
Here's a simple example (where t.bmp is the image with your pattern, but of course you can just use any other surface):
import pygame
pygame.init()
screen = pygame.display.set_mode((490, 160))
font = pygame.font.SysFont('Arial', 150)
pattern = pygame.image.load('t.bmp').convert()
text = font.render('FooBar', True, (255, 255, 255), (0, 0, 0))
pattern.blit(text, (0, 0), special_flags = pygame.BLEND_MULT)
screen.blit(pattern, (0, 0))
pygame.display.flip();
while True:
if pygame.event.get(pygame.QUIT):
break
Result:

Python PIL Editing Pixels versus ImageDraw.point

I am working on an image-generation program, and I have an issue trying to directly edit the pixels of an image.
My original method, which works, was simply:
image = Image.new('RGBA', (width, height), background)
drawing_image = ImageDraw.Draw(image)
# in some loop that determines what to draw and at what color
drawing_image.point((x, y), color)
This works fine, but I thought directly editing pixels might be slightly faster. I plan on using "very" high resolutions (maybe 10000px by 10000px), so even a slight decrease in time per pixel will be a large decrease overall.
I tried using this:
image = Image.new('RGBA', (width, height), background)
pixels = image.load()
# in some loop that determines what to draw and at what color
pixels[x][y] = color # note: color is a hex-formatted string, i.e "#00FF00"
This gives me an error:
Traceback (most recent call last):
File "my_path\my_file.py", line 100, in <module>
main()
File "my_path\my_file.py", line 83, in main
pixels[x][y] = color
TypeError: argument must be sequence of length 2
How does the actual pixels[x][y] work? I seem to be missing a fundamental concept here (I've never worked with directly editing pixels prior to this), or at least just not understanding what arguments are required. I even tried pixels[x][y] = (0, 0, 0), but that raised the same error.
In addition, is there a faster way to edit the pixels? I've heard that using the pixels[x][y] = some_color is faster than drawing to the image, but I'm open to any other faster method.
Thanks in advance!
You need to pass a tuple index as pixels[(x, y)] or simply pixels[x, y], for example:
#-*- coding: utf-8 -*-
#!python
from PIL import Image
width = 4
height = 4
background = (0, 0, 0, 255)
image = Image.new("RGBA", (width, height), background)
pixels = image.load()
pixels[0, 0] = (255, 0, 0, 255)
pixels[0, 3] = (0, 255, 0, 255)
pixels[3, 3] = (0, 0, 255, 255)
pixels[3, 0] = (255, 255, 255, 255)
image.save("image.png")

Categories