Does Blender have a method to a get PNG-formatted bytearray for an image via Python? In Blender's Python, I can get the raw bytes that make up an image into a bytearray, like so:

    image = bpy.data.images[0]  # Pick any valid image you like.
    pixels = bytearray([int(p * 255) for p in image.pixels])


But, instead of raw pixel data, I would like to get a bytearray containing all the bytes of a PNG-format image.  This can be compressed or uncompressed PNG, but I need the bytes to represent a valid PNG format as if for saving to a file, not raw pixel data.  Ideally I'd like to get these bytes without actually saving them to disk, and without modifying the user's image if possible (for example they may think the image is a JPG or something).  How can I do this?  Does Blender have a PNG data format helper function that I could use without disturbing the user's image?  If not, is there a code snippet that will convert Blender's internal image representation to PNG format?
I got this working based on Python code from Stack Overflow here.

Here's the version of that code adapted to work inside stock Blender 2.77a:

import base64
import zlib
import struct

def img_to_png(blender_image):
    width = blender_image.size[0]
    height = blender_image.size[1]
    buf = bytearray([int(p * 255) for p in blender_image.pixels])

    # reverse the vertical line order and add null bytes at the start
    width_byte_4 = width * 4
    raw_data = b''.join(b'\x00' + buf[span:span + width_byte_4]
                        for span in range((height - 1) * width_byte_4, -1, - width_byte_4))

    def png_pack(png_tag, data):
        chunk_head = png_tag + data
        return (struct.pack("!I", len(data)) +
                chunk_head +
                struct.pack("!I", 0xFFFFFFFF &amp; zlib.crc32(chunk_head)))

    png_bytes = b''.join([
        b'\x89PNG\r\n\x1a\n',
        png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
        png_pack(b'IDAT', zlib.compress(raw_data, 9)),
        png_pack(b'IEND', b'')])

    return 'data:image/png;base64,' + base64.b64encode(png_bytes).decode()


Example usage:

print(img_to_png(bpy.data.images[0]))


This will print out a PNG-format data-URI of the image, regardless of what format the image is within Blender, and without altering the user's image.  I suggest using a very small image to test with, so the test output is not overwhelming when printed to the console.