Ejemplo n.º 1
0
    def _parse_file(file, filename):
        if not file:
            file = open(filename, 'rb')

        header = AsepriteHeader(file)
        if header.magic_number != '0xa5e0':
            raise ImageDecodeException("Does not appear to be a valid ASEprite file.")

        if header.color_depth not in (8, 16, 32):
            raise ImageDecodeException("Invalid color depth.")

        global PALETTE_INDEX
        PALETTE_INDEX = header.palette_index

        frames = []
        for _ in range(header.num_frames):
            frame_size = _unpack(DWORD, file)
            magic_number = hex(_unpack(WORD, file))
            if magic_number != '0xf1fa':
                raise ImageDecodeException("Malformed frame. File may be corrupted.")
            num_chunks = _unpack(WORD, file)
            duration = _unpack(WORD, file)
            _zero = _unpack(BYTE * 6, file)
            header_size = struct.calcsize(DWORD + WORD * 3 + BYTE * 6)
            data = file.read(frame_size - header_size)
            frames.append(Frame(num_chunks, duration, header, data))

        # Layers chunk is in the first frame:
        layers = frames[0].layers
        pitch = len('RGBA') * header.width

        file.close()

        return header, frames, layers, pitch
Ejemplo n.º 2
0
def _unpack(fmt, file):
    """Unpack little endian bytes fram a file-like object. """
    size = struct.calcsize(fmt)
    data = file.read(size)
    if len(data) < size:
        raise ImageDecodeException('Unexpected EOF')
    return struct.unpack("<" + fmt, data)[0]
Ejemplo n.º 3
0
 def __init__(self, data):
     if len(data) < self.get_size():
         raise ImageDecodeException('Not a DDS file')
     items = struct.unpack(self.get_format(), data)
     for field, value in itertools.zip_longest(self._fields,
                                               items,
                                               fillvalue=None):
         setattr(self, field[0], value)
Ejemplo n.º 4
0
Archivo: gif.py Proyecto: pyzh/pyglet
def read_graphic_control_extension(file, stream, graphics_scope):
    # 23. Graphic control extension
    (block_size, fields, delay_time, transparent_color_index,
     terminator) = unpack('BBHBB', file)
    if block_size != 4:
        raise ImageDecodeException('Incorrect block size')

    if delay_time:
        # Follow Firefox/Mac behaviour: use 100ms delay for any delay
        # less than 10ms.
        if delay_time <= 1:
            delay_time = 10
        graphics_scope.delay = float(delay_time) / 100
Ejemplo n.º 5
0
def pil_open(filename, autocrop=False):

    with _loader.file(filename) as file:
        try:
            image = PIL.Image.open(file)
            if autocrop:
                return pil_autocrop(image)

            image.load()
            return image

        except Exception as e:
            raise ImageDecodeException('PIL cannot read %r: %s' %
                                       (filename or file, e))
Ejemplo n.º 6
0
def _loader_pil_load(filename, autocrop=False):

    image = pil_open(filename, autocrop)

    try:
        image = image.transpose(PIL.Image.FLIP_TOP_BOTTOM)
    except Exception as e:
        raise ImageDecodeException('PIL failed to transpose %r: %s' %
                                   (filename or file, e))

    # Convert bitmap and palette images to component
    if image.mode in ('1', 'P'):
        image = image.convert()

    if image.mode not in ('L', 'LA', 'RGB', 'RGBA'):
        raise ImageDecodeException('Unsupported mode "%s"' % image.mode)

    width, height = image.size

    # tostring is deprecated, replaced by tobytes in Pillow (PIL fork)
    # (1.1.7) PIL still uses it
    image_data_fn = getattr(image, "tobytes", getattr(image, "tostring"))
    return pyglet.image.ImageData(width, height, image.mode, image_data_fn())
Ejemplo n.º 7
0
def get_image_data(image):
    """
    Retrieve image data from a PIL Image so it can be loaded into a Pyglet image.
    Returns the data wrapped in a Pyglet ImageData object.
    """
    image = image.transpose(Image.FLIP_TOP_BOTTOM)

    # Convert bitmap and palette images to component
    if image.mode in ('1', 'P'):
        image = image.convert()

    if image.mode not in ('L', 'LA', 'RGB', 'RGBA'):
        raise ImageDecodeException('Unsupported mode "%s"' % image.mode)
    width, height = image.size

    return ImageData(width, height, image.mode, image.tostring())
Ejemplo n.º 8
0
def read(file):
    """Read a GIF file stream.

    :rtype: GIFStream
    """
    # 17. Header
    signature = file.read(3)
    version = file.read(3)
    if signature != b'GIF':
        raise ImageDecodeException('Not a GIF stream')

    stream = GIFStream()

    # 18. Logical screen descriptor
    (logical_screen_width,
     logical_screen_height,
     fields,
     background_color_index,
     pixel_aspect_ratio) = unpack('HHBBB', file)
    global_color_table_flag = fields & 0x80
    global_color_table_size = fields & 0x7

    # 19. Global color table
    if global_color_table_flag:
        global_color_table = file.read(6 << global_color_table_size)

    # <Data>*
    graphics_scope = GraphicsScope()
    block_type = read_byte(file)

    while block_type != LABEL_TRAILER:
        if block_type == LABEL_IMAGE_DESCRIPTOR:
            read_table_based_image(file, stream, graphics_scope)
            graphics_scope = GraphicsScope()
        elif block_type == LABEL_EXTENSION_INTRODUCER:
            extension_block_type = read_byte(file)
            if extension_block_type == LABEL_GRAPHIC_CONTROL_EXTENSION:
                read_graphic_control_extension(file, stream, graphics_scope)
            else:
                skip_data_sub_blocks(file)
        else:
            # Skip bytes until a valid start character is found
            print(block_type)
            pass
        block_type = read_byte(file)

    return stream
Ejemplo n.º 9
0
    def _blend_pixels(bottom, top, mode):
        # Iterate over the arrays in chunks of 4 (RGBA):
        bottom_iter = _chunked_iter(bottom, 4)
        top_iter = _chunked_iter(top, 4)

        if mode == 'Normal':
            final_array = []
            # If RGB values are > 0, use the top pixel.
            for bottom_pixel, top_pixel in zip(bottom_iter, top_iter):
                if sum(top_pixel[:3]) > 0:
                    final_array.extend(top_pixel)
                else:
                    final_array.extend(bottom_pixel)
            return bytes(final_array)

        # TODO: implement additional blend modes
        else:
            raise ImageDecodeException('Unsupported blend mode.')
Ejemplo n.º 10
0
Archivo: gif.py Proyecto: pyzh/pyglet
def read_byte(file):
    data = file.read(1)
    if not len(data):
        raise ImageDecodeException('Unexpected EOF')
    return ord(data)
Ejemplo n.º 11
0
Archivo: gif.py Proyecto: pyzh/pyglet
def unpack(format, file):
    size = struct.calcsize(format)
    data = file.read(size)
    if len(data) < size:
        raise ImageDecodeException('Unexpected EOF')
    return struct.unpack(format, data)
Ejemplo n.º 12
0
    def decode(self, file, filename):
        if not file:
            file = open(filename, 'rb')
        bytes = file.read()
        buffer = ctypes.c_buffer(bytes)

        if bytes[:2] != 'BM':
            raise ImageDecodeException(
                'Not a Windows bitmap file: %r' % (filename or file))

        file_header = to_ctypes(buffer, 0, BITMAPFILEHEADER)
        bits_offset = file_header.bfOffBits
        info_header_offset = ctypes.sizeof(BITMAPFILEHEADER)
        info_header = to_ctypes(buffer, info_header_offset, BITMAPINFOHEADER)
        palette_offset = info_header_offset + info_header.biSize

        if info_header.biSize < ctypes.sizeof(BITMAPINFOHEADER):
            raise ImageDecodeException(
                'Unsupported BMP type: %r' % (filename or file))

        width = info_header.biWidth
        height = info_header.biHeight
        if width <= 0  or info_header.biPlanes != 1:
            raise ImageDecodeException(
                'BMP file has corrupt parameters: %r' % (filename or file))
        pitch_sign = height < 0 and -1 or 1
        height = abs(height)

        compression = info_header.biCompression
        if compression not in (BI_RGB, BI_BITFIELDS):
            raise ImageDecodeException(
                'Unsupported compression: %r' % (filename or file))

        clr_used = 0
        bitcount = info_header.biBitCount
        if bitcount == 1:
            pitch = (width + 7) // 8
            bits_type = ctypes.c_ubyte
            decoder = decode_1bit
        elif bitcount == 4:
            pitch = (width + 1) // 2
            bits_type = ctypes.c_ubyte
            decoder = decode_4bit
        elif bitcount == 8:
            bits_type = ctypes.c_ubyte
            pitch = width
            decoder = decode_8bit
        elif bitcount == 16:
            pitch = width * 2
            bits_type = ctypes.c_uint16
            decoder = decode_bitfields
        elif bitcount == 24:
            pitch = width * 3
            bits_type = ctypes.c_ubyte
            decoder = decode_24bit
        elif bitcount == 32:
            pitch = width * 4
            if compression == BI_RGB:
                decoder = decode_32bit_rgb
                bits_type = ctypes.c_ubyte
            elif compression == BI_BITFIELDS:
                decoder = decode_bitfields
                bits_type = ctypes.c_uint32
            else:
                raise ImageDecodeException(
                    'Unsupported compression: %r' % (filename or file))
        else:
            raise ImageDecodeException(
                'Unsupported bit count %d: %r' % (bitcount, filename or file))

        pitch = (pitch + 3) & ~3
        packed_width = pitch // ctypes.sizeof(bits_type)

        if bitcount < 16 and compression == BI_RGB:
            clr_used = info_header.biClrUsed or (1 <<  bitcount)
            palette = to_ctypes(buffer, palette_offset, RGBQUAD * clr_used)
            bits = to_ctypes(buffer, bits_offset,
                             bits_type * packed_width * height)
            return decoder(bits, palette, width, height, pitch, pitch_sign)
        elif bitcount >= 16 and compression == BI_RGB:
            bits = to_ctypes(buffer, bits_offset,
                             bits_type * (packed_width * height))
            return decoder(bits, None, width, height, pitch, pitch_sign)
        elif compression == BI_BITFIELDS:
            if info_header.biSize >= ctypes.sizeof(BITMAPV4HEADER):
                info_header = to_ctypes(buffer, info_header_offset,
                                        BITMAPV4HEADER)
                r_mask = info_header.bV4RedMask
                g_mask = info_header.bV4GreenMask
                b_mask = info_header.bV4BlueMask
            else:
                fields_offset = info_header_offset + \
                    ctypes.sizeof(BITMAPINFOHEADER)
                fields = to_ctypes(buffer, fields_offset, RGBFields)
                r_mask = fields.red
                g_mask = fields.green
                b_mask = fields.blue
            class _BitsArray(ctypes.LittleEndianStructure):
                _pack_ = 1
                _fields_ = [
                    ('data', bits_type * packed_width * height),
                ]
            bits = to_ctypes(buffer, bits_offset, _BitsArray).data
            return decoder(bits, r_mask, g_mask, b_mask,
                           width, height, pitch, pitch_sign)
Ejemplo n.º 13
0
def to_ctypes(buffer, offset, type):
    if offset + ctypes.sizeof(type) > len(buffer):
        raise ImageDecodeException('BMP file is truncated')
    ptr = ptr_add(ctypes.pointer(buffer), offset)
    return ctypes.cast(ptr, ctypes.POINTER(type)).contents
Ejemplo n.º 14
0
    def decode(self, file, filename):
        header = file.read(DDSURFACEDESC2.get_size())
        desc = DDSURFACEDESC2(header)
        if desc.dwMagic != b'DDS ' or desc.dwSize != 124:
            raise ImageDecodeException('Invalid DDS file (incorrect header).')

        width = desc.dwWidth
        height = desc.dwHeight
        mipmaps = 1

        if desc.dwFlags & DDSD_DEPTH:
            raise ImageDecodeException('Volume DDS files unsupported')

        if desc.dwFlags & DDSD_MIPMAPCOUNT:
            mipmaps = desc.dwMipMapCount

        if desc.ddpfPixelFormat.dwSize != 32:
            raise ImageDecodeException(
                'Invalid DDS file (incorrect pixel format).')

        if desc.dwCaps2 & DDSCAPS2_CUBEMAP:
            raise ImageDecodeException('Cubemap DDS files unsupported')

        if not desc.ddpfPixelFormat.dwFlags & DDPF_FOURCC:
            raise ImageDecodeException(
                'Uncompressed DDS textures not supported.')

        has_alpha = desc.ddpfPixelFormat.dwRGBAlphaBitMask != 0

        selector = (desc.ddpfPixelFormat.dwFourCC, has_alpha)
        if selector not in _compression_formats:
            raise ImageDecodeException('Unsupported texture compression %s' %
                                       desc.ddpfPixelFormat.dwFourCC)

        dformat, decoder = _compression_formats[selector]
        if dformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
            block_size = 8
        else:
            block_size = 16

        datas = []
        w, h = width, height
        for i in range(mipmaps):
            if not w and not h:
                break
            if not w:
                w = 1
            if not h:
                h = 1
            size = ((w + 3) // 4) * ((h + 3) // 4) * block_size
            data = file.read(size)
            datas.append(data)
            w >>= 1
            h >>= 1

        image = CompressedImageData(width, height, dformat, datas[0],
                                    'GL_EXT_texture_compression_s3tc', decoder)
        level = 0
        for data in datas[1:]:
            level += 1
            image.set_mipmap_data(level, data)

        return image