Split Image in Pygame - python

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

Related

Pygame change image colour but preserve transparency

I've got a function that takes an image and adjusts all of the RGB values by a given amount:
def colour(self,img,col):
img = self.my_image.copy()
col = (col[0],col[1],col[2],0)
img.fill(col, None, pygame.BLEND_RGBA_ADD)
return img
I want to apply this to a partially transparent image. But when I apply this to the image, the transparent pixels become coloured. I want these pixels to stay transparent, but any opaque pixels to be coloured as normal. Is there any way I can do this, without having to loop through every pixel and check if each one is transparent before adjusting it? Thanks
fill treats the color to be solid. You have to use blit.
Create a transparent image the size of the source image and fill it with the color. Finally, mix both images:
def colour(self, img, col):
img = self.my_image.copy()
color_img = pygame.Surface(img.get_size(), pygame.SRCALPHA)
color_img.fill((col[0], col[1], col[2], 0))
img.blit(color_img, (0, 0), special_flags = pygame.BLEND_RGBA_ADD)
return img
See also Is it possible to change sprite colours in Pygame?

How do i properly rescale an image on PyGame without it being badly cropped?

I'm trying to rescale an image on pygame but it instead crops the image, I'm just looking to change the pixel width and height of the image.
I used pygame.transform.scale and used 1900, 600 as the parameters, the original image is a 1920x1080
mainmenu = pygame.image.load("Main_Menu.png")
mainmenu = pygame.transform.scale(mainmenu, (1900,600))
screen.blit(background, (0, 0))
I expected the image to be rescaled to a 1900x600 image but it instead output a badly cropped image in the 1900x600 format.
You've to use pygame.transform.smoothscale() rather than pygame.transform.scale().
Use convert() or convert_alpha() to convert the surface to a surface with a with proper pixel format
mainmenu = pygame.image.load("Main_Menu.png")
mainmenu = pygame.transform.smoothscale(mainmenu.convert_alpha(), (1900,600))
screen.blit(background, (0, 0))
While scale() does a scaling operation, which is as fast as possible, smoothscale() scales smoothly and calculates area averages of the colors which cover the pixels.

Pygame image used as screen then final transformed to screen

I want to be able to stretch a screen without needing to stretch each image individually.
I have a image I use as the screen, then when I have the final product I transform the image to the size of the screen and blit it to the screen.
But the images blit onto the main image do not transform with the main image, and comes out as its first size.
You can find the current version here:
https://gist.github.com/gideonjvisser/eca7506f483c51edf93c/
Here's the script:
import pygame
from pygame.locals import Color
chosen_resolution = (400,200)
screen = pygame.display.set_mode(chosen_resolution)
screen_rect = screen.get_rect()
in_game_resolution = (800,600)
screen_image = pygame.Surface(in_game_resolution)
screen_image_rect = screen_image.get_rect()
image_on_in_game = pygame.image.load("image.png").convert_alpha()
image_on_in_game = pygame.transform.scale(image_on_in_game, (469,669)) #to fit on in_game_resolution
print screen_rect
print screen_image_rect
while(True):
screen_image.fill(Color('white'))
screen_image.blit(image_on_in_game, (0,0))
screen_image = pygame.transform.scale(screen_image, chosen_resolution)
screen.blit(screen_image, (0,0))
pygame.display.flip()
This code almost works. The issue is that, in your while loop, you overwrite your static resolution intermediate surface with the scaled version. Try replacing the while loop with this:
while True:
screen_image.fill(Color('white'))
screen_image.blit(image_on_in_game, (0,0))
screen.blit(pygame.transform.scale(screen_image, chosen_resolution), (0,0))
pygame.display.flip()
Now the pre-scaled buffer should remain the right size and actually be scaled to fit the real screen's size.

PIL selection of coordinates to make an image

I am wanting to create an image from a selection of coordinates i have. So I want each coordinate to be set a particular size and colour say black and 2X2, and then place it at the particular pixel it represents.
How will i go about this?
Will the function putpixel, work for what I want to do?
Thanks in advance
Doing this with putpixel will be inconvenient but not impossible. Since you say you want to make dots of more than a single pixel, it would be better to use ImageDraw.rectangle() or ellipse() instead.
For example:
import Image
import ImageDraw
img = Image.new("RGB", (400,400), "white")
draw = ImageDraw.Draw(img)
coords = [(100,70), (220, 310), (200,200)]
dotSize = 2
for (x,y) in coords:
draw.rectangle([x,y,x+dotSize-1,y+dotSize-1], fill="black")
img.show()

putpixel with pyglet

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.

Categories