Pyglet blit a texture region onto a texture - python

I would like to create a single texture from multiple smaller texture regions.
What I'm trying is:
import pyglet
import pyglet.gl as gl
large_texture = pyglet.image.Texture(width=800,
height=600,
target=gl.GL_TEXTURE_2D,
id=0)
texture = pyglet.resource.texture("assets/my_image.png")
region = texture.get_region(0, 0, 32, 32)
region_2 = texture.get_region(0, 32, 32, 32)
large_texture.blit_into(region.get_image_data(), x=0, y=0, z=0)
large_texture.blit_into(region_2.get_image_data(), x=0, y=32, z=0)
I was expecting that this would place the two texture regions onto the large_texture, but instead, I get this error:
pyglet.gl.lib.GLException: b'invalid value'
Is there something obvious that I am missing, or what (if any) is the correct way to achieve this?

You aren't actually creating a texture right now.
large_texture = pyglet.image.Texture(width=800,
height=600,
target=gl.GL_TEXTURE_2D,
id=0)
Is just declaring a Python object (usually used internally by Pyglet).
The actual texture creation is done in the create method: large_texture = pyglet.image.Texture.create(width=800, height=600)
Once you do that, it should work.

Related

Why does my create_rectangle disappears after specifying these points using tkinter?

I wanted to create a transparent box with a red outline between these two specified points at (614, 162) and (759, 306). However, it returns me an invisible or no box at all. But for (100, 50) and (160, 100), the box is visible.
import tkinter as tkr
app = tkr.Tk()
app.title("AI Cashier")
app.geometry("1366x768")
app.wm_attributes("-transparentcolor", "white")
app.config(bg = "White")
can = tkr.Canvas(app,bg = "White",highlightthickness = 0)
can.create_rectangle(100,50,160,100,outline = "red", width = 2)
can.pack()
app.mainloop()
Could anyone explain to me because I'm still new to tkinter. Or is it a bug?
Why does my create_rectangle disappears after specifying these points using tkinter?
It is because the canvas is only a couple hundred pixels wide and tall, so you are drawing outside the visible area of the canvas.
A simple fix for the code in the question is to make the canvas bigger. You can either give it an explicit width and height (eg: can = tkr.Canvas(..., width=800, height=400)), or force the canvas to fill the window (eg: can.pack(fill='both', expand=True')). In either of those cases, the image will be visible.

Kivy Interpolation on Canvas

I am new to kivy and python. I am trying to have an texture (256x256) shown pixelated through my canvas, but it is blurred, and through some googling i think it is interpolated? I want it to show the pixels with sharp edging and not blurred. It also blends in color from surrounding tiles in the texture when i use texture.get_region(...) to select one tile (64x64) and display that, so i get a border from the other tiles in my new texture. I guess i am just really bad at reading Kivy's documentation.
texture = Image('template.png').texture //getting texture
topright = texture.get_region(64, 64, 64, 64) //Selecting a specific Tile
with self.canvas:
Rectangle(texture = texture, pos = self.pos, size = (512,512))
Set
texture.mag_filter = 'nearest'
texture.min_filter = 'nearest'
You might only need one of these, I don't remember, but you can test and see the doc at http://kivy.org/docs/api-kivy.graphics.texture.html

How Do You Resize an Image in Python Using Pyglet

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

Pyglet: How to change resolution when you go fullscreen?

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.

Why glDrawpixels does not render my transparent background?

I want to render font in opengl with transparent background.
The main problem is that my background is always opaque black !
here is my code :
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
font = ImageFont.truetype("/usr/share/fonts/truetype/wqy/wqy-microhei.ttc", 16)
textsize = font.getsize(u"当前运行列表")
im = Image.new("RGB",textsize,"#000")
draw = ImageDraw.Draw(im)
transparent_area = (0,0,im.size[0],im.size[1])
mask=Image.new('L', im.size, color=0)
drawmask = ImageDraw.Draw(mask)
drawmask.rectangle(transparent_area, fill=0)
im.putalpha(mask)
draw.text((0,0), u"当前运行列表", font=font, fill="red")
#im.save('render.png')
ix, iy, image = im.size[0], im.size[1], im.tostring("raw", "RGBA", 0, -1)
glDrawPixels(ix,iy,GL_RGBA,GL_UNSIGNED_BYTE,image)
Cheers, it is not fully clear what are you trying to acheive. You could either be trying to have a transparent font rendered over some other OpenGL geometry, or maybe you want to render contents of the window using OpenGL and make parts of the window transparent (so you can see windows behind it).
To make window transparent, you need to use:
// Set WS_EX_LAYERED on this window
SetWindowLong(hwnd,
GWL_EXSTYLE,
GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
// Make this window transparent
int transparentColor = RGB(x, y, z);
SetLayeredWindowAttributes(hwnd, transparentColor, 255, LWA_COLORKEY);
This enables so called color keying on the window, that means anything that is rendered using RGB(x, y, z) gets transparent, and the window is not visible in these parts. Note that this transparency is binary, it is either fully transparent or fully opaque. Also, you need to be using GDI to render to your window. That means either do not use OpenGL at all, and use function like BitBlt() or StretchBlt() instead, or use OpenGL to render into a P-buffer (or into a FBO, framebuffer object), then use glReadPixels() to copy the output, and then use BitBlt() again to display the results using GDI. In your case where you are trying to render a piece of text, you might be better off without using OpenGL.
So, in your example you could make black color transparent, i.e. x = y = z = 0, do not use OpenGL, and create a device independent bitmap (DIB) instead using CreateDIBSection(), fill it with image instead of passing it to glDrawPixels() and render to window using BitBlt().
added this at beginning
glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE )
glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE )
glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 )
glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 )
glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 )
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 )

Categories