Using Pyglet to scale gif to screen - python

Anyone can bring some clarity to my code as to why when I attempt to scale my gif to full screen half the screen is white while the other is the gif(animation)? This is using the Pyglet python module.
Here's my code along with an image of the issue:
'Load animation'
animation = pyglet.image.load_animation('Goober#13427G.gif')
animSprite = pyglet.sprite.Sprite(animation)
# 'Scale image to screen *harcoded*'
# animSprite.scale_x = 3.2
# animSprite.scale_y = 1.71
' Get display and create a fullscreen window while scaling gif to screen'
display = pyglet.canvas.Display()
screen = display.get_screens()
H_ratio = max(animSprite.height, screen[1].height) / min(animSprite.height, screen[1].height)
W_ratio = max(animSprite.width, screen[1].width) / min(animSprite.width, screen[1].width)
animSprite.scale = min(H_ratio, W_ratio)
window = pyglet.window.Window(width=screen[1].width, height=screen[1].height, fullscreen=True, screen=screen[1])
r, g, b, alpha = 1, 1, 1, .5
pyglet.gl.glClearColor(r, g, b, alpha)
#window.event
def on_draw():
window.clear()
animSprite.draw()
pyglet.app.run()
```[Gif with second half of screen to the right is white][1]
[1]: https://i.stack.imgur.com/JsbJy.jpg

Try scaling each axis.
animSprite.scale_x = W_ratio
animSprite.scale_y = H_ratio

Related

Pyglet render into texture

I'm writing a drawing program using pyglet, and I want to be able to have the image being created as separate from the window's buffer (for instance, the image could be larger than the window, or may want to draw to this image at a different rate than the main window is being re-drawn). I want to be able to draw into this off-screen image, then display it in the window, but pyglet doesn't allow drawing to anything else than a window. Is there any simple way I can do this?
I've tried creating a second hidden pyglet window, but this gets rendered at the same rate as the main window which I definitely don't want.
The closest I found was Pyglet draw text into texture, but the code there isn't complete, and also no longer works as the opengl version used by pyglet has moved on.
The following code works for me, perhaps someone else can improve on my answer:
import pyglet
from pyglet.gl import *
from ctypes import byref
W, H = 800, 600
image = pyglet.image.create(W, H)
texture = image.get_texture()
window = pyglet.window.Window(width=W, height=H)
fbo_id = gl.GLuint(0)
glGenFramebuffers(1, byref(fbo_id))
glBindFramebuffer(GL_FRAMEBUFFER, fbo_id)
glBindTexture(GL_TEXTURE_2D, texture.id)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.id, 0)
rect1 = pyglet.shapes.Rectangle(0, 0, W, H, (255, 0, 0) )
rect2 = pyglet.shapes.Rectangle(W//4, H//4, W//2, H//2, (0, 0, 255) )
label = pyglet.text.Label("Hello World", font_name="Times New Roman", font_size=36,
x=W//2, y=H//2, anchor_x="center", anchor_y="center")
rect1.draw()
rect2.draw()
label.draw()
#window.event
def on_mouse_drag(x, y, dx, dy, xxx, modifiers):
glBindFramebuffer(GL_FRAMEBUFFER, fbo_id)
line = pyglet.shapes.Line(x-dx, y-dy, x, y, 3, (0, 255, 255))
line.draw()
#window.event
def on_draw():
glBindFramebuffer(GL_FRAMEBUFFER, 0)
window.clear()
texture.blit(0, 0)
pyglet.app.run()

Pyglet displaying text over image

I am trying to display some text over an image using the pyglet library. However, I keep getting this "Texture Region" popping up instead of the actual text I included..Hoping someone can help.
SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
# width of window
width = 900
# height of window
height = 900
# caption i.e title of the window
title = "E MAJOR"
# creating a window
window = pyglet.window.Window(width, height, title)
# text
text = "E MAJOR"
# creating label with following properties
# font = cooper
# position = 250, 150
# anchor position = center
label = pyglet.text.Label("E MAJOR",
font_name='Cooper',
color=(255,255,255,255),
font_size=36,
x=425,
y=50,
anchor_x='center',
anchor_y='center')
# creating a batch
batch = pyglet.graphics.Batch()
# loading geeksforgeeks image
image = pyglet.image.load('e-major.png')
# creating sprite object
# it is instance of an image displayed on-screen
sprite = pyglet.sprite.Sprite(image, x=100, y=25)
# on draw event
#window.event
def on_draw():
# clear the window
window.clear()
# draw the image on screen
sprite.draw()
# draw the label
label.draw()
# key press event
#window.event
def on_key_press(symbol, modifier):
# key "C" get press
if symbol == key.C:
# printing the message
print("Key : C is pressed")
# image for icon
img = image = pyglet.resource.image("e-major.png")
# setting image as icon
window.set_icon(img)
# loading image resource
value = pyglet.resource.image("e-major.png")
# setting text of label
label.text = str(value)
# start running the application
pyglet.app.run()
Looks like getting rid of
# setting text of label
label.text = str(value)
fixed this issue

Image in Button tkinter

I am having a problem in making a login image to a button. I have succeeded in making the image with a transparent background, but I can't succeed to make the button with transparent background.
I attached a screenshot that shows what I mean. The upper 'login' is a image (with transparent background), the lower is Login button but there is a white background around it. I want to make a button with transparent background.
self.login_image = Image.open('images/LoginButton.png')
self.login_image = ImageTk.PhotoImage(self.login_image)
self.main_screen_canvas.create_image(700, 300, image=self.login_image)
self.login_button = Button(self.main_screen_canvas, borderwidth=0, image=self.login_image)
self.login_button.place(x=300,y=400)
What should I do?
BackgroundImage
LoginButtonImage
Here's how to do what I was suggesting in the comment which uses the technique shown in another answer of mine to simulate a tkinter Button on a Canvas that has a transparent image placed on it (instead of text).
One issue I ran into was that fact that your 2421 × 1210 pixel background image was larger than my screen. To deal with it I added a fitrect() helper function to determine a new smaller size for it that would fit. I wrote it a long time ago, but have found it handy to have around many times (like now). Note that in the code ll and ur refer to the lower-left and upper-right corners of the rectangles involved.
Here's the resulting code:
from PIL import Image, ImageTk
import tkinter as tk
class CanvasButton:
""" Create left mouse button clickable canvas image object.
The x, y coordinates are relative to the top-left corner of the canvas.
"""
flash_delay = 100 # Milliseconds.
def __init__(self, canvas, x, y, image_source, command, state=tk.NORMAL):
self.canvas = canvas
if isinstance(image_source, str):
self.btn_image = tk.PhotoImage(file=image_source)
else:
self.btn_image = image_source
self.canvas_btn_img_obj = canvas.create_image(x, y, anchor='nw', state=state,
image=self.btn_image)
canvas.tag_bind(self.canvas_btn_img_obj, "<ButtonRelease-1>",
lambda event: (self.flash(), command()))
def flash(self):
self.set_state(tk.HIDDEN)
self.canvas.after(self.flash_delay, self.set_state, tk.NORMAL)
def set_state(self, state):
""" Change canvas button image's state.
Normally, image objects are created in state tk.NORMAL. Use value
tk.DISABLED to make it unresponsive to the mouse, or use tk.HIDDEN to
make it invisible.
"""
self.canvas.itemconfigure(self.canvas_btn_img_obj, state=state)
def fitrect(r1_ll_x, r1_ll_y, r1_ur_x, r1_ur_y, r2_ll_x, r2_ll_y, r2_ur_x, r2_ur_y):
""" Find the largest rectangle that will fit within rectangle r2 that has
rectangle r1's aspect ratio.
Note: Either the width or height of the resulting rect will be
identical to the corresponding dimension of rect r2.
"""
# Calculate aspect ratios of rects r1 and r2.
deltax1, deltay1 = (r1_ur_x - r1_ll_x), (r1_ur_y - r1_ll_y)
deltax2, deltay2 = (r2_ur_x - r2_ll_x), (r2_ur_y - r2_ll_y)
aspect1, aspect2 = (deltay1 / deltax1), (deltay2 / deltax2)
# Compute size of resulting rect depending on which aspect ratio is bigger.
if aspect1 > aspect2:
result_ll_y, result_ur_y = r2_ll_y, r2_ur_y
delta = deltay2 / aspect1
result_ll_x = r2_ll_x + (deltax2 - delta) / 2.0
result_ur_x = result_ll_x + delta
else:
result_ll_x, result_ur_x = r2_ll_x, r2_ur_x
delta = deltax2 * aspect1
result_ll_y = r2_ll_y + (deltay2 - delta) / 2.0
result_ur_y = result_ll_y + delta
return result_ll_x, result_ll_y, result_ur_x, result_ur_y
def btn_clicked():
""" Prints to console a message every time the button is clicked """
print("Button Clicked")
background_image_path = 'background_image.jpg'
button_image_path = 'button_image.png'
root = tk.Tk()
root.update_idletasks()
background_img = Image.open(background_image_path) # Must use PIL for JPG images.
scrnwidth, scrnheight = root.winfo_screenwidth(), root.winfo_screenheight()
bgrdwidth, bgrdheight = background_img.size
border_width, border_height = 20, 20 # Allow room for window's decorations.
# Determine a background image size that will fit on screen with a border.
bgr_ll_x, bgr_ll_y, bgr_ur_x, bgr_ur_y = fitrect(
0, 0, bgrdwidth, bgrdheight,
0, 0, scrnwidth-border_width, scrnheight-border_height)
bgr_width, bgr_height = int(bgr_ur_x-bgr_ll_x), int(bgr_ur_y-bgr_ll_y)
# Resize background image to calculated size.
background_img = ImageTk.PhotoImage(background_img.resize((bgr_width, bgr_height)))
# Create Canvas same size as fitted background image.
canvas = tk.Canvas(root, bd=0, highlightthickness=0, width=bgr_width, height=bgr_height)
canvas.pack(fill=tk.BOTH)
# Put background image on Canvas.
background = canvas.create_image(0, 0, anchor='nw', image=background_img)
# Put CanvasButton on Canvas centered at the bottom.
button_img = tk.PhotoImage(file=button_image_path)
btn_x, btn_y = (bgr_width/2), (bgr_height-button_img.height())
canvas_btn1 = CanvasButton(canvas, btn_x, btn_y, button_img, btn_clicked)
root.mainloop()
And here's the result of running it:

Pyglet ignores alpha channel

I'm trying to make a level editor for a game I'm writing in Python using Pyglet. I want to be able to modify the darkness of any block I place. As such, I have added a darkness attribute to the Block class. Here is that class:
class Block:
def __init__(self, name, image, wall):
self.name = name
self.image = image
self.wall = wall
self.darkness = 0
def set_darkness(self, darkness):
self.darkness = darkness
def draw(self, x, y):
self.image.blit(x, y)
pyglet.graphics.draw(4, GL_QUADS, ('v2i', (x, y, x + block_width, y, x + block_width, y + block_height, x, y + block_width)), ('c4B', (0, 0, 0, self.darkness) * 4))
I am trying to darken an image by drawing a black rectangle on top of it, and then adjusting the transparency of that rectangle. However, no matter what I set self.darkness to in __init__, the rectangle continues to be completely opaque.
I tried enabling color blending with pyglet.gl by adding this code to the top of my program:
from pyglet.gl import *
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
This changed nothing. I also tried using Pyglet's SolidColorImagePattern class to create a black rectangle with the alpha channel set to self.darkness, but that also did nothing. How do I make this rectangle transparent?
For any OpenGL instruction, a valid and current OpenGL Context is of need. Of course pyglet provides an OpenGL context, but the context is created and made current when the pyglet (OpenGL) window is created (see pyglet.window).
Create the window, before setting up Blending to solve the issue:
from pyglet.gl import *
window = pyglet.window.Window(400, 400, "OpenGL window")
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

Python Drawing Portion of Image When Mouse Hover

My question relates to Python GTK
I have an image -a JPG - which I draw onto a drawing area. I want to reveal a portion of the image -say a 10pix by 10 px square -only where the mouse pointer is currently at. Everything 10 x 10 px square away from the mouse should hidden i.e. black.
I'm am new to PyGtk please can anyone help?
Thanks
#!/usr/bin/python
import os
import sys
import gtk
MASK_COLOR = 0x000000
def composite(source, start_x=345, start_y=345):
width = 50
height = 50
alpha = 255
dest = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8 ,800,800)
dest.fill(MASK_COLOR)
source.composite(dest,
start_x,
start_y,
width,
height,
0,
0,
1,
1,
gtk.gdk.INTERP_NEAREST,
alpha)
return dest
def it_moved(widget, event, window, masked, original):
r = window.get_display().get_window_at_pointer()
masked.set_from_pixbuf(composite(original.get_pixbuf(), r[1], r[2]))
return True
if __name__ == '__main__':
window = gtk.Window()
eb = gtk.EventBox()
original = gtk.Image()
original.set_from_file(sys.argv[1])
masked = gtk.Image()
masked.set_from_pixbuf(composite(original.get_pixbuf()))
eb.add(masked)
eb.set_property('events', gtk.gdk.POINTER_MOTION_MASK)
eb.connect('motion_notify_event', it_moved, window, masked, original)
window.add(eb)
window.set_size_request(800,800)
window.show_all()
gtk.main()
This should do something like you describe. I chose to show a 50x50 area since yours was kinda small to see under the pointer. I didn't hide that either.

Categories