Search code examples
pythonpython-3.xpygamepygame2

How to output pygame.image.save to a variable instead of a file?


I want to send a pygame.surface.Surface to another computer using socket library. I tried using pygame.image.tostring but it took 900kb, but when I used pygame.image.save and I used jpg format it only took 45kb. But the problem is pygame.image.save output it to a file and pygame.image.load only accepts file, and it slows my program because I need bytes object and reading and writing a file 32 times per second will kill the cpu. What sould I do to transform a pygame.surface.Surface to a bytes but in jpg format without reading and writing files 32 times per second?
(It doesn't need to be jpg format but I want it take least possible bytes)


Solution

  • An alternative option would be to use zlib to compress the string:

    import zlib
    
    image_str = pygame.image.tostring(my_image)
    compressed_image_str = zlib.compress(image_str)
    

    Or save the image to an io.BytesIO object with pygame.image.save():

    import io
    
    temp_io = io.BytesIO()
    pygame.image.save(my_surface, temp_io, "JPEG")
    

    Another option is to use PLI Image and io.BytesIO, which gives you more flexibility in choosing the format:

    from PIL import Image
    import io
    
    pil_string_image = pygame.image.tostring(my_surface, "RGB", False)
    pli_image = Image.frombytes('RGB', my_surface.get_size(), pil_string_image, 'raw')
    temp_io = io.BytesIO()
    pli_image.save(temp_io, format="JPEG")