0

So I have an image (16x16):

image = Image.open("image.png")

And I convert it into pygame image:

mode = image.mode
data = image.tobytes()
py_image = pygame.image.fromstring(data, (64, 64), mode)

And it gives me this error:

ValueError: String length does not equal format and resolution size
martineau
  • 119,623
  • 25
  • 170
  • 301
Yenz1
  • 84
  • 1
  • 9
  • Can't be sure, but I'm almost sure `mode` is probably not corresponding to the bytes given by `tobytes()`. Most likely the `mode` is `RGBA` and the data is given in `RGB`. Altho that might be an assumption that isn't correct. Some light on the topic: https://stackoverflow.com/questions/33244928/how-to-display-pil-image-with-pygame – Torxed Jun 17 '20 at 15:56
  • Perhaps `imgage.tobytes("raw", mode)` would ensure correct formatting? – Torxed Jun 17 '20 at 16:11
  • tostring() has been removed and image.tobytes("raw", mode) doesn't work. – Yenz1 Jun 17 '20 at 16:37
  • Check my post, as it contains some debugging information to diagnose your issue. Your code should work fine, as does mine below (proof of output). So your problem isn't with the code, it's with the image **most** likely. Check how to debug it and let me know what the output of `print(Image.open())` is :) – Torxed Jun 17 '20 at 16:39
  • There's your answer, `16x16` pixels, not `64x64` as you're trying to create/import. This function **isn't for scaling**, it's for direct import of data. – Torxed Jun 17 '20 at 16:49

1 Answers1

2

The problem is that fromstring() doesn't do what you think it does, it doesn't scale images. It can only source a data-stream into the original data-stream size. So if you're inputting 16x16 pixels of data, that's the size fromstring() will require in order to create a image from a string/bytes stream.

This is how that function is intended to function:

from PIL import Image
print(Image.open("test.png"))

And it should give you:

<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=64x64 at 0x2FCB6B8>

Where the size and modes are important. You should also use this as input vectors for fromstring() since the size might change.

The following works perfectly fine for me:

from PIL import Image
import pygame

pygame.init()

gameDisplay = pygame.display.set_mode((800, 600))

image = Image.open("test.png")
mode = image.mode
data = image.tobytes('raw', mode)
py_image = pygame.image.fromstring(data, image.size, mode)

exit = False
while not exit:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit = True

    gameDisplay.fill((255, 255, 255))
    gameDisplay.blit(py_image, (10, 10))

    pygame.display.update()

pygame.quit()

And produces:

enter image description here


If you want to convert a small image, into a larger one. You'll first need to create a blank template in which you can read the data in to. Here I'll create a blank (white) image of 64x64 pixels, and transplant/merge a smaller 16x16 image into the bigger one at position 0, 0.

source = Image.open("test.png")
canvas = Image.new('RGB', (64,64), (255, 255, 255))
canvas.paste(source, (0, 0))

You can then proceed to use the image as per normal. Altho, this won't scale it, it will only give you a larger canvas to work with. If you want to scale an image, you should use pygame.transform.scale or PIL scale the image.

Torxed
  • 22,866
  • 14
  • 82
  • 131
  • I know that my image is 16x16 and not 64x64 but it needs to be because it will be just displaying image while the image is being modified. (it will be preview) No matter the size of the image I want to display all images the same size. (there are also different sized images) – Yenz1 Jun 17 '20 at 16:46
  • 1
    @Yenz1 I mean, that's not what you'r question is asking. You're asking why you're getting the error. This is why. If you want to create a blank image and then transplant your image onto the bigger image (or scale it), that's a completely different question mate. – Torxed Jun 17 '20 at 16:50
  • Oh, sorry for wasting your time. – Yenz1 Jun 17 '20 at 16:52
  • 2
    @Yenz1 I added a example of what you're actually asking. Which is, "How do I paste a small image into a larger one and then import it into Pygame" :) See the edit at the bottom. In the example, I used a `16x16` source image, and pasted it onto `canvas` which is a `64x64` blank white image. – Torxed Jun 17 '20 at 16:54