Exemplo n.º 1
0
def stream_to_array(stream, width, height, color_type, bit_depth, interlace=0):
    # `stream` is 1-d numpy array with dytpe np.uint8 containing the
    # data from one or more IDAT or fdAT chunks.
    #
    # This function converts `stream` to a numpy array.

    img_color_dim, img_dtype = img_color_format(color_type, bit_depth)
    if img_color_dim == 1:
        img_shape = (height, width)
    else:
        img_shape = (height, width, img_color_dim)
    img = np.empty(img_shape, dtype=img_dtype)

    if interlace == 1:
        passes = numpngw._interlace_passes(img)
    else:
        passes = [img]

    pass_start_index = 0
    for a in passes:
        if a.size == 0:
            continue
        pass_height, pass_width = a.shape[:2]
        ncols, rembits = divmod(pass_width*bit_depth, 8)
        ncols += rembits > 0

        if bit_depth < 8:
            bytes_per_pixel = 1  # Not really, but we need 1 here for later.
            data_bytes_per_line = ncols
        else:
            # nchannels is a map from color_type to the number of color
            # channels (e.g. an RGB image has three channels).
            nchannels = {0: 1, 2: 3, 3: 1, 4: 2, 6: 4}
            bytes_per_channel = bit_depth // 8
            bytes_per_pixel = bytes_per_channel * nchannels[color_type]
            data_bytes_per_line = bytes_per_pixel * pass_width

        data_width = data_bytes_per_line // bytes_per_pixel

        pass_end_index = (pass_start_index +
                          pass_height * (data_bytes_per_line + 1))
        shp = (pass_height, data_bytes_per_line + 1)
        lines = stream[pass_start_index:pass_end_index].reshape(shp)
        pass_start_index = pass_end_index

        prev = np.zeros((data_width, bytes_per_pixel), dtype=np.uint8)
        shp = (pass_height, data_width, bytes_per_pixel)
        p = np.empty(shp, dtype=np.uint8)
        for k in range(lines.shape[0]):
            line_filter_type = lines[k, 0]
            filtered = lines[k, 1:].reshape(-1, bytes_per_pixel)
            if line_filter_type == 0:
                p[k] = filtered
            elif line_filter_type == 1:
                p[k] = numpngw._filter1inv(filtered, prev)
            elif line_filter_type == 2:
                p[k] = numpngw._filter2inv(filtered, prev)
            elif line_filter_type == 3:
                p[k] = numpngw._filter3inv(filtered, prev)
            elif line_filter_type == 4:
                p[k] = numpngw._filter4inv(filtered, prev)
            else:
                raise ValueError('invalid filter type: %i' %
                                 (line_filter_type,))
            prev = p[k]

        # As this point, p has data type uint8 and has shape
        # (height, width, bytes_per_pixel).
        # 16 bit components of the pixel are stored in big-endian format.

        uint8to16 = np.array([256, 1], dtype=np.uint16)

        if color_type == 0:
            # grayscale
            if bit_depth == 16:
                pass_img = p.dot(uint8to16)
            elif bit_depth == 8:
                pass_img = p[:, :, 0]
            else:  # bit_depth is 1, 2 or 4.
                pass_img = numpngw._unpack(p.reshape(pass_height, -1),
                                           bitdepth=bit_depth,
                                           width=pass_width)

        elif color_type == 2:
            # RGB
            if bit_depth == 16:
                # Combine high and low bytes to 16-bit values.
                shp = (pass_height, pass_width, 3, 2)
                pass_img = p.reshape(shp).dot(uint8to16)
            else:  # bit_depth is 8.
                pass_img = p

        elif color_type == 3:
            # indexed
            if bit_depth < 8:
                pass_img = numpngw._unpack(p[:, :, 0], bitdepth=bit_depth,
                                           width=pass_width)
            else:
                pass_img = p[:, :, 0]

        elif color_type == 4:
            # grayscale with alpha
            if bit_depth == 16:
                # Combine high and low bytes to 16-bit values.
                shp = (pass_height, pass_width, 2, 2)
                pass_img = p.reshape(shp).dot(uint8to16)
            else:  # bit_depth is 8.
                pass_img = p

        elif color_type == 6:
            # RGBA
            if bit_depth == 16:
                # Combine high and low bytes to 16-bit values.
                shp = (pass_height, pass_width, 4, 2)
                pass_img = p.reshape(shp).dot(uint8to16)
            else:  # bit_depth is 8.
                pass_img = p

        else:
            raise RuntimeError('invalid color type %r' % (color_type,))

        a[...] = pass_img

    return img
Exemplo n.º 2
0
def stream_to_array_old(stream, width, height, color_type, bit_depth):
    # `stream` is 1-d numpy array with dytpe np.uint8 containing the
    # data from one or more IDAT or fdAT chunks.
    #
    # This function converts `stream` to a numpy array.

    ncols, rembits = divmod(width*bit_depth, 8)
    ncols += rembits > 0

    if bit_depth < 8:
        bytes_per_pixel = 1  # Not really, but we need 1 here for later.
        data_bytes_per_line = ncols
    else:
        # nchannels is a map from color_type to the number of color
        # channels (e.g. an RGB image has three channels).
        nchannels = {0: 1, 2: 3, 3: 1, 4: 2, 6: 4}
        bytes_per_channel = bit_depth // 8
        bytes_per_pixel = bytes_per_channel * nchannels[color_type]
        data_bytes_per_line = bytes_per_pixel * width

    data_width = data_bytes_per_line / bytes_per_pixel

    lines = stream.reshape(height, data_bytes_per_line + 1)

    prev = np.zeros((data_width, bytes_per_pixel), dtype=np.uint8)
    p = np.empty((height, data_width, bytes_per_pixel), dtype=np.uint8)
    for k in range(lines.shape[0]):
        line_filter_type = lines[k, 0]
        filtered = lines[k, 1:].reshape(-1, bytes_per_pixel)
        if line_filter_type == 0:
            p[k] = filtered
        elif line_filter_type == 1:
            p[k] = numpngw._filter1inv(filtered, prev)
        elif line_filter_type == 2:
            p[k] = numpngw._filter2inv(filtered, prev)
        elif line_filter_type == 3:
            p[k] = numpngw._filter3inv(filtered, prev)
        elif line_filter_type == 4:
            p[k] = numpngw._filter4inv(filtered, prev)
        else:
            raise ValueError('invalid filter type: %i' % (line_filter_type,))
        prev = p[k]

    # As this point, p has data type uint8 and has shape
    # (height, width, bytes_per_pixel).
    # 16 bit components of the pixel are stored in big-endian format.

    uint8to16 = np.array([256, 1], dtype=np.uint16)

    if color_type == 0:
        # grayscale
        if bit_depth == 16:
            img = p.dot(uint8to16)
        elif bit_depth == 8:
            img = p[:, :, 0]
        else:  # bit_depth is 1, 2 or 4.
            img = numpngw._unpack(p.reshape(height, -1),
                                  bitdepth=bit_depth, width=width)

    elif color_type == 2:
        # RGB
        if bit_depth == 16:
            # Combine high and low bytes to 16-bit values.
            img = p.reshape(height, width, 3, 2).dot(uint8to16)
        else:  # bit_depth is 8.
            img = p

    elif color_type == 3:
        # indexed
        img = p[:, :, 0]

    elif color_type == 4:
        # grayscale with alpha
        if bit_depth == 16:
            # Combine high and low bytes to 16-bit values.
            img = p.reshape(height, width, 2, 2).dot(uint8to16)
        else:  # bit_depth is 8.
            img = p

    elif color_type == 6:
        # RGBA
        if bit_depth == 16:
            # Combine high and low bytes to 16-bit values.
            img = p.reshape(height, width, 4, 2).dot(uint8to16)
        else:  # bit_depth is 8.
            img = p

    else:
        raise RuntimeError('invalid color type %r' % (color_type,))

    return img
Exemplo n.º 3
0
def stream_to_array(stream, width, height, color_type, bit_depth, interlace=0):
    # `stream` is 1-d numpy array with dytpe np.uint8 containing the
    # data from one or more IDAT or fdAT chunks.
    #
    # This function converts `stream` to a numpy array.

    img_color_dim, img_dtype = img_color_format(color_type, bit_depth)
    if img_color_dim == 1:
        img_shape = (height, width)
    else:
        img_shape = (height, width, img_color_dim)
    img = np.empty(img_shape, dtype=img_dtype)

    if interlace == 1:
        passes = numpngw._interlace_passes(img)
    else:
        passes = [img]

    pass_start_index = 0
    for a in passes:
        if a.size == 0:
            continue
        pass_height, pass_width = a.shape[:2]
        ncols, rembits = divmod(pass_width*bit_depth, 8)
        ncols += rembits > 0

        if bit_depth < 8:
            bytes_per_pixel = 1  # Not really, but we need 1 here for later.
            data_bytes_per_line = ncols
        else:
            # nchannels is a map from color_type to the number of color
            # channels (e.g. an RGB image has three channels).
            nchannels = {0: 1, 2: 3, 3: 1, 4: 2, 6: 4}
            bytes_per_channel = bit_depth // 8
            bytes_per_pixel = bytes_per_channel * nchannels[color_type]
            data_bytes_per_line = bytes_per_pixel * pass_width

        data_width = data_bytes_per_line // bytes_per_pixel

        pass_end_index = (pass_start_index +
                          pass_height * (data_bytes_per_line + 1))
        shp = (pass_height, data_bytes_per_line + 1)
        lines = stream[pass_start_index:pass_end_index].reshape(shp)
        pass_start_index = pass_end_index

        prev = np.zeros((data_width, bytes_per_pixel), dtype=np.uint8)
        shp = (pass_height, data_width, bytes_per_pixel)
        p = np.empty(shp, dtype=np.uint8)
        for k in range(lines.shape[0]):
            line_filter_type = lines[k, 0]
            filtered = lines[k, 1:].reshape(-1, bytes_per_pixel)
            if line_filter_type == 0:
                p[k] = filtered
            elif line_filter_type == 1:
                p[k] = numpngw._filter1inv(filtered, prev)
            elif line_filter_type == 2:
                p[k] = numpngw._filter2inv(filtered, prev)
            elif line_filter_type == 3:
                p[k] = numpngw._filter3inv(filtered, prev)
            elif line_filter_type == 4:
                p[k] = numpngw._filter4inv(filtered, prev)
            else:
                raise ValueError('invalid filter type: %i' %
                                 (line_filter_type,))
            prev = p[k]

        # As this point, p has data type uint8 and has shape
        # (height, width, bytes_per_pixel).
        # 16 bit components of the pixel are stored in big-endian format.

        uint8to16 = np.array([256, 1], dtype=np.uint16)

        if color_type == 0:
            # grayscale
            if bit_depth == 16:
                pass_img = p.dot(uint8to16)
            elif bit_depth == 8:
                pass_img = p[:, :, 0]
            else:  # bit_depth is 1, 2 or 4.
                pass_img = numpngw._unpack(p.reshape(pass_height, -1),
                                           bitdepth=bit_depth,
                                           width=pass_width)

        elif color_type == 2:
            # RGB
            if bit_depth == 16:
                # Combine high and low bytes to 16-bit values.
                shp = (pass_height, pass_width, 3, 2)
                pass_img = p.reshape(shp).dot(uint8to16)
            else:  # bit_depth is 8.
                pass_img = p

        elif color_type == 3:
            # indexed
            if bit_depth < 8:
                pass_img = numpngw._unpack(p[:, :, 0], bitdepth=bit_depth,
                                           width=pass_width)
            else:
                pass_img = p[:, :, 0]

        elif color_type == 4:
            # grayscale with alpha
            if bit_depth == 16:
                # Combine high and low bytes to 16-bit values.
                shp = (pass_height, pass_width, 2, 2)
                pass_img = p.reshape(shp).dot(uint8to16)
            else:  # bit_depth is 8.
                pass_img = p

        elif color_type == 6:
            # RGBA
            if bit_depth == 16:
                # Combine high and low bytes to 16-bit values.
                shp = (pass_height, pass_width, 4, 2)
                pass_img = p.reshape(shp).dot(uint8to16)
            else:  # bit_depth is 8.
                pass_img = p

        else:
            raise RuntimeError('invalid color type %r' % (color_type,))

        a[...] = pass_img

    return img
Exemplo n.º 4
0
def stream_to_array(stream, width, height, color_type, bit_depth):
    # `stream` is 1-d numpy array with dytpe np.uint8 containing the
    # data from one or more IDAT or fdAT chunks.
    # This function assumes that the PNG filter type is 0.
    #
    # This function converts `stream` to an array.

    # nchannels is a map from color_type to the number of color
    # channels (e.g. an RGB image has three channels).
    nchannels = {0: 1, 2: 3, 3: 1, 4: 2, 6: 4}

    ncols, rembits = divmod(width*bit_depth, 8)
    ncols += rembits > 0
    lines = stream.reshape(height, nchannels[color_type]*ncols + 1)
    expected_col0 = np.zeros(height, dtype=np.uint8)
    assert_array_equal(lines[:, 0], expected_col0)
    p = lines[:, 1:]

    uint8to16 = np.array([256, 1], dtype=np.uint16)

    if color_type == 0:
        # grayscale
        if bit_depth == 16:
            img = p.reshape(-1, p.shape[1]//2, 2).dot(uint8to16)
        elif bit_depth == 8:
            img = p
        else:  # bit_depth is 1, 2 or 4.
            img = numpngw._unpack(p, bitdepth=bit_depth, width=width)

    elif color_type == 2:
        # RGB
        if bit_depth == 16:
            # Combine high and low bytes to 16-bit values.
            img1 = p.reshape(-1, p.shape[1]//2, 2).dot(uint8to16)
            # Reshape to (height, width, 3)
            img = img1.reshape(height, -1, 3)
        else:  # bit_depth is 8.
            # Reshape to (height, width, 3)
            img = p.reshape(height, -1, 3)

    elif color_type == 3:
        # indexed
        img = p.reshape(height, -1)

    elif color_type == 4:
        # grayscale with alpha
        if bit_depth == 16:
            # Combine high and low bytes to 16-bit values.
            img1 = p.reshape(-1, p.shape[1]//2, 2).dot(uint8to16)
            # Reshape to (height, width, 2)
            img = img1.reshape(height, -1, 2)
        else:  # bit_depth is 8.
            # Reshape to (height, width, 2)
            img = p.reshape(height, -1, 2)

    elif color_type == 6:
        # RGBA
        if bit_depth == 16:
            # Combine high and low bytes to 16-bit values.
            img1 = p.reshape(-1, p.shape[1]//2, 2).dot(uint8to16)
            # Reshape to (height, width, 4)
            img = img1.reshape(height, -1, 4)
        else:  # bit_depth is 8.
            # Reshape to (height, width, 3)
            img = p.reshape(height, -1, 4)

    else:
        raise RuntimeError('invalid color type %r' % (color_type,))

    return img
Exemplo n.º 5
0
def stream_to_array_old(stream, width, height, color_type, bit_depth):
    # `stream` is 1-d numpy array with dytpe np.uint8 containing the
    # data from one or more IDAT or fdAT chunks.
    #
    # This function converts `stream` to a numpy array.

    ncols, rembits = divmod(width*bit_depth, 8)
    ncols += rembits > 0

    if bit_depth < 8:
        bytes_per_pixel = 1  # Not really, but we need 1 here for later.
        data_bytes_per_line = ncols
    else:
        # nchannels is a map from color_type to the number of color
        # channels (e.g. an RGB image has three channels).
        nchannels = {0: 1, 2: 3, 3: 1, 4: 2, 6: 4}
        bytes_per_channel = bit_depth // 8
        bytes_per_pixel = bytes_per_channel * nchannels[color_type]
        data_bytes_per_line = bytes_per_pixel * width

    data_width = data_bytes_per_line / bytes_per_pixel

    lines = stream.reshape(height, data_bytes_per_line + 1)

    prev = np.zeros((data_width, bytes_per_pixel), dtype=np.uint8)
    p = np.empty((height, data_width, bytes_per_pixel), dtype=np.uint8)
    for k in range(lines.shape[0]):
        line_filter_type = lines[k, 0]
        filtered = lines[k, 1:].reshape(-1, bytes_per_pixel)
        if line_filter_type == 0:
            p[k] = filtered
        elif line_filter_type == 1:
            p[k] = numpngw._filter1inv(filtered, prev)
        elif line_filter_type == 2:
            p[k] = numpngw._filter2inv(filtered, prev)
        elif line_filter_type == 3:
            p[k] = numpngw._filter3inv(filtered, prev)
        elif line_filter_type == 4:
            p[k] = numpngw._filter4inv(filtered, prev)
        else:
            raise ValueError('invalid filter type: %i' % (line_filter_type,))
        prev = p[k]

    # As this point, p has data type uint8 and has shape
    # (height, width, bytes_per_pixel).
    # 16 bit components of the pixel are stored in big-endian format.

    uint8to16 = np.array([256, 1], dtype=np.uint16)

    if color_type == 0:
        # grayscale
        if bit_depth == 16:
            img = p.dot(uint8to16)
        elif bit_depth == 8:
            img = p[:, :, 0]
        else:  # bit_depth is 1, 2 or 4.
            img = numpngw._unpack(p.reshape(height, -1),
                                  bitdepth=bit_depth, width=width)

    elif color_type == 2:
        # RGB
        if bit_depth == 16:
            # Combine high and low bytes to 16-bit values.
            img = p.reshape(height, width, 3, 2).dot(uint8to16)
        else:  # bit_depth is 8.
            img = p

    elif color_type == 3:
        # indexed
        img = p[:, :, 0]

    elif color_type == 4:
        # grayscale with alpha
        if bit_depth == 16:
            # Combine high and low bytes to 16-bit values.
            img = p.reshape(height, width, 2, 2).dot(uint8to16)
        else:  # bit_depth is 8.
            img = p

    elif color_type == 6:
        # RGBA
        if bit_depth == 16:
            # Combine high and low bytes to 16-bit values.
            img = p.reshape(height, width, 4, 2).dot(uint8to16)
        else:  # bit_depth is 8.
            img = p

    else:
        raise RuntimeError('invalid color type %r' % (color_type,))

    return img