I'm new to pyglet. I'd like to change a pixel from black to white at each on_draw iteration. So after 1000 iterations, there should be exactly 1000 white pixels in the window. However, I'd like to avoid calling 1000 draw operations in on_draw for that. So I'd like to create an image, do an RGB putpixel on the image, and blit the image to the screen. How can I do that? The pyglet documentation, the examples and the source code aren't too helpful on this.
Since no one gave a really good answer to this.
I'll place one here:
import pyglet
from random import randint
width, height = 500, 500
window = pyglet.window.Window(width=width, height=height)
image = pyglet.image.SolidColorImagePattern((255,255,255,255)).create_image(width, height)
data = image.get_image_data().get_data('RGB', width*3)
new_image = b''
for i in range(0, len(data), 3):
pixel = bytes([randint(0,255)]) + bytes([randint(0,255)]) + bytes([randint(0,255)])
new_image += pixel
image.set_data('RGB', width*3, new_image)
#window.event
def on_draw():
window.clear()
image.blit(0, 0)
pyglet.app.run()
Essentially, what this does is it creates a white image, that in itself can be drawn in the window. But seeing as we want to do putpixel, i've modified every pixel in the white image as a demo.
Can be used in junction with:
https://pythonhosted.org/pyglet/api/pyglet.image.ImageData-class.html#get_region
Which can be used to optemize the image manipulation further.
This is too late to help you, but there are ways to do this. For example, blit_into, which modifies a loaded image:
import pyglet
window = pyglet.window.Window(600, 600)
background = pyglet.resource.image('my600x600blackbackground.bmp')
pix = pyglet.resource.image('singlewhitepixel.bmp').get_image_data()
def update(dt):
background.blit_into(pix, x, y, 0) #specify x and y however you want
#window.event
def on_draw():
window.clear()
background.blit(0,0)
pyglet.clock.schedule(update, 1.0/30) #30 frames per second
pyglet.app.run()
It seems there is no easy way to do this in pyglet. So I've given up on using pyglet.
Related
I'm currently working on a little project in which I'm trying to generate a random image of a set size with a set palette. Everything generates fine and dandy, but zooming in on the image shows the pixels are interpolated in a way that doesn't look great. I would prefer if the pixels had hard edges, as with nearest neighbor interpolation. How would I go about doing that? See code below:
#!/usr/bin/env
import random
from PIL import Image
colors = ["#ffffff", "#898d90", "#000000", "#cf0530", "#2450a4", "#7eed56", "#ffd635", "#6134e1",
"#ffa800", "#6d482f", "#ff3881", "#51e9f4", "#fff8b8", "#94b3ff", "#158d62", "#515252" ]
def main():
size = width, height = 128, 128
image = Image.new( "RGB", size)
fillRand(image, size)
image.show()
del image
def randColor():
color = random.choice(colors)
return color
def hex_to_rgb(hex):
return tuple(int(hex.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))
def fillRand(image, size):
for x in range(size[0]):
for y in range(size[1]):
pixel_access_object = image.load()
pixel_access_object[x,y] = (hex_to_rgb(randColor()))
if ( __name__ == "__main__"):
main()
Thank you in advance!
P.S. - Python isn't my main language and I'm rusty in general, so apologies if my code is wack.
I think that's a problem with your image viewer. I used ImageGlass, and there the pixels have crisp edges. A possible solution would be to make your pixels bigger, so you color 16x16 pixels the same color, instead of one. Then the interpolation woulden't be as visible.
So, couple hours ago I found Pyglet best for me for rendering gif animations, so I', new in this. My problem is that the animated gif renders at its original size in fullscreen window, I need to make it match, but I can't figure out how I should do this, any help? My code:
import sys
import pyglet
from pyglet.window import Platform
if len(sys.argv) > 1:
animation = pyglet.image.load_animation(sys.argv[1])
bin = pyglet.image.atlas.TextureBin()
animation.add_to_texture_bin(bin)
else:
animation = pyglet.resource.animation('gaben.gif')
sprite = pyglet.sprite.Sprite(animation)
screen = Platform().get_default_display().get_default_screen()
window = pyglet.window.Window(width=screen.width, height=screen.height)
window.set_fullscreen(True)
pyglet.gl.glClearColor(1, 1, 1, 1)
#window.event
def on_draw():
window.clear()
sprite.draw()
pyglet.app.run()
The result what I get
The easiest way is to use the sprite object's .scale.
It has the ability to scale the image in proportion to it's original dimensions and you don't need to worry about mapping data or filling in pixel-gaps if you resize the image yourself some how.
To help you get going, this is a simple example of a implementation:
(And it looks like this: https://youtu.be/Ly61VvTZnCU)
import pyglet
from pyglet.window import Platform
monitor = Platform().get_default_display().get_default_screen()
sprite = pyglet.sprite.Sprite(pyglet.resource.animation('anim.gif'))
H_ratio = max(sprite.height, monitor.height) / min(sprite.height, monitor.height)
W_ratio = max(sprite.width, monitor.width) / min(sprite.width, monitor.width)
sprite.scale = min(H_ratio, W_ratio) # sprite.scale = 2 would double the size.
# We'll upscale to the lowest of width/height
# to not go out of bounds. Whichever
# value hits the screen edges first essentially.
window = pyglet.window.Window(width=monitor.width, height=monitor.height, fullscreen=True)
pyglet.gl.glClearColor(1, 1, 1, 1)
#window.event
def on_draw():
window.clear()
sprite.draw()
pyglet.app.run()
I removed some of your code for demo/testing purposes.
The code is by no means perfect, but it will hopefully give you an insight as to how this works).
I'm new to Pyglet (and stackoverflow) and cannot seem to find out how to resize images.
'pipe.png' is the image that I am trying to adjust the size of.
With this code, the image is not fully shown because the window size is too small.
I would like to adjust the size of the image so that it fits inside of the window.
The current size of 'pipe.png' is 100x576.
import pyglet
window = pyglet.window.Window()
pyglet.resource.path = ["C:\\"]
pipe = pyglet.resource.image('pipe.png')
pyglet.resource.reindex()
#window.event
def on_draw():
window.clear()
pipe.blit(0, 0)
pyglet.app.run()
EDIT:
I ended up finding out the answer here:
http://pyglet.org/doc-current/programming_guide/image.html#simple-image-blitting
The solution is:
imageWidth = 100
imageHeight = 100
imageName.width = imageWidth
imageName.height = imageHeight
This would adjust to image size to display as 100x100
Came across of this oldie, so for whoever lone ranger that ends up here juast as I did. Changing .width and .height won't do much in many cases (or at all these days?).
In order to successfully change a image resolution, you need to modify it's .scale attribute.
Here's a snippet of code that I use to resize a image:
from pyglet.gl import *
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
image = pyglet.image.load('test.png')
height, width = 800, 600 # Desired resolution
# the min() and max() mumbo jumbo is to honor the smallest requested resolution.
# this is because the smallest resolution given is the limit of say
# the window-size that the image will fit in, there for we can't honor
# the largest resolution or else the image will pop outside of the region.
image.scale = min(image.height, height)/max(image.height, height)), max(min(width, image.width)/max(width, image.width)
# Usually not needed, and should not be tampered with,
# but for a various bugs when using sprite-inheritance on a user-defined
# class, these values will need to be updated manually:
image.width = width
image.height = height
image.texture.width = width
image.texture.height = height
I'm using Pyglet and I have a little that includes an object moving over a background. Both of them are represented by images (png and jpg).
I've created a non-fullscreen window with size 800x600 and it works fine, but when I toggle to fullscreen... background and object have the same size as before and the rest of the screen is filled with black (empty color).
What I want to do is to "scale" the images or change the resolution when I toggle fullscreen mode.
I've read the documentation, but I can't find the answer to this.
I know that with Pygame, this problem solves itself automatically (if you change the window size, everything rescales automatically)... but how do you do this with pyglet?
This is my relevant code:
import pyglet
WIDTH = 800
HEIGHT = 600
working_dir = '/where/i/have/my/images/'
window = pyglet.window.Window(WIDTH, HEIGHT)
background = pyglet.image.load(working_dir + 'background.jpg')
flying_thing = pyglet.image.load(working_dir + 'flying_thing.png')
#window.event
def on_draw():
window.clear()
background.blit(0, 0)
flying_thing.blit(WIDTH // 2, HEIGHT // 2)
#window.event
def on_key_press(symbol, modifiers):
if symbol == pyglet.window.key.SPACE:
window.set_fullscreen(not window.fullscreen)
pyglet.app.run()
You can try this code changing working_dir, background.jpg and flying_thing.png to a working directory of yours and two images in it.
I didn't tried, but from pyglet docs, blit supports width and height. Its signature is
blit(self, x, y, z=0, width=None, height=None)
Have you tried using
background.blit(width=window.width, height=windows.height)
instead? (I'm not sure the window.width changes on full_screen, let's see...).
This answer can also be relevant to your question: https://stackoverflow.com/a/11183462/931303.
I have a 200x200px image in pygame that I'd like to slice in half, so the 2 shapes would be 100x200px. Afterwards, I'd like to blit the 2 new images on the screen with a set amount of pixels in between them. How would an image be split/cropped in such a way?
EDIT - Fixed! I managed to figure this out by myself from using pygame.transform.chop() and pygame.transform.rotate(). Thanks for the help, though. I know a little more thanks to the help of Tankor Smash.
You don't need to create two images, just use one and blit it twice:
origin1 = (0,0)
separation = 20
# Load the image
img = pygame.image.load(image_path)
width, height = img.get_width()/2, img.get_height()
origin2 = origin1[0] + width + separation, origin1[1]
# Blit first half
source_area = pygame.Rect((0,0), (width, height))
screen.blit(img, origin1, source_area)
# Blit second half
source_area = pygame.Rect((width,0), (width, height))
screen.blit(img, origin2, source_area)
I believe you'd be better using PIL, here http://www.pythonware.com/products/pil/
But if you were to use Pygame, it'd be something along the lines of creating a surface with the image on it, then blitting one half of the surface to a part of the screen, then the other half at another.
#load the image to a surface
img =pygame.image.load(path)
#create a rect half the width of the image
half_rect = pygame.rect(img.width/2, img.height/2)
#blit first half
main_screen.blit((0,0), rect, img)
#blit second half
main_screen.blit((image.width+10,0),rect, img)
Now that's pseudocode, but that's how I'd do it, roughly
The other method is to use subsurfaces http://www.pygame.org/docs/ref/surface.html#Surface.subsurface
If you have many sprites on one sheet, you can use it as a spritesheet : http://www.pygame.org/wiki/Spritesheet?parent=CookBook