Exemple #1
0
def _read_metadata(handle):
    block_count = lib.heif_image_handle_get_number_of_metadata_blocks(
        handle, ffi.NULL)
    if block_count == 0:
        return

    metadata = []
    ids = ffi.new('heif_item_id[]', block_count)
    lib.heif_image_handle_get_list_of_metadata_block_IDs(
        handle, ffi.NULL, ids, block_count)
    for i in range(len(ids)):
        metadata_type = lib.heif_image_handle_get_metadata_type(handle, ids[i])
        metadata_type = ffi.string(metadata_type).decode()
        data_length = lib.heif_image_handle_get_metadata_size(handle, ids[i])
        p_data = ffi.new('char[]', data_length)
        error = lib.heif_image_handle_get_metadata(handle, ids[i], p_data)
        if error.code != 0:
            raise HeifError(code=error.code,
                            subcode=error.subcode,
                            message=ffi.string(error.message).decode())
        data_buffer = ffi.buffer(p_data, data_length)
        data = bytes(data_buffer)
        if metadata_type == 'Exif':
            # skip TIFF header, first 4 bytes
            data = data[4:]
        metadata.append({'type': metadata_type, 'data': data})

    return metadata
Exemple #2
0
def _read_heif_image(img, height):
    p_stride = ffi.new('int *')
    p_data = lib.heif_image_get_plane_readonly(img, heif_channel_interleaved,
                                               p_stride)
    stride = p_stride[0]

    data_length = height * stride
    data_buffer = ffi.buffer(p_data, data_length)
    data = bytes(data_buffer)

    return data
Exemple #3
0
def _read_heif_context(ctx, d, apply_transformations):
    error = lib.heif_context_read_from_memory(ctx, d, len(d), ffi.NULL)
    if error.code != 0:
        raise HeifError(code=error.code,
                        subcode=error.subcode,
                        message=ffi.string(error.message).decode())

    p_handle = ffi.new('struct heif_image_handle **')
    error = lib.heif_context_get_primary_image_handle(ctx, p_handle)
    if error.code != 0:
        raise HeifError(code=error.code,
                        subcode=error.subcode,
                        message=ffi.string(error.message).decode())
    handle = p_handle[0]

    try:
        result = _read_heif_handle(handle, apply_transformations)
    except:
        raise
    finally:
        lib.heif_image_handle_release(handle)
    return result
Exemple #4
0
def _read_heif_handle(handle, apply_transformations):
    alpha = lib.heif_image_handle_has_alpha_channel(handle)
    mode = 'RGB' if alpha == 0 else 'RGBA'

    p_img = ffi.new('struct heif_image **')
    p_options = lib.heif_decoding_options_alloc()
    if apply_transformations == False:
        p_options.ignore_transformations = 1
    error = lib.heif_decode_image(
        handle, p_img, heif_colorspace_RGB, heif_chroma_interleaved_RGB
        if mode == 'RGB' else heif_chroma_interleaved_RGBA, p_options)
    lib.heif_decoding_options_free(p_options)
    if error.code != 0:
        raise HeifError(code=error.code,
                        subcode=error.subcode,
                        message=ffi.string(error.message).decode())
    img = p_img[0]

    width = lib.heif_image_handle_get_width(handle)
    height = lib.heif_image_handle_get_height(handle)
    size = (width, height)

    try:
        data = _read_heif_image(img, height)
    except:
        raise
    finally:
        lib.heif_image_release(img)

    metadata = _read_metadata(handle)
    color_profile = _read_color_profile(handle)

    heif_file = HeifFile(mode=mode,
                         size=size,
                         data=data,
                         metadata=metadata,
                         color_profile=color_profile)
    return heif_file
Exemple #5
0
def _read_color_profile(handle):
    profile_type = lib.heif_image_handle_get_color_profile_type(handle)
    if profile_type == heif_color_profile_type_not_present:
        return

    color_profile = {'type': 'unknown', 'data': None}
    if profile_type == heif_color_profile_type_nclx:
        color_profile['type'] = 'nclx'
    elif profile_type == heif_color_profile_type_rICC:
        color_profile['type'] = 'rICC'
    elif profile_type == heif_color_profile_type_prof:
        color_profile['type'] = 'prof'
    data_length = lib.heif_image_handle_get_raw_color_profile_size(handle)
    p_data = ffi.new('char[]', data_length)
    error = lib.heif_image_handle_get_raw_color_profile(handle, p_data)
    if error.code != 0:
        raise HeifError(code=error.code,
                        subcode=error.subcode,
                        message=ffi.string(error.message).decode())
    data_buffer = ffi.buffer(p_data, data_length)
    data = bytes(data_buffer)
    color_profile['data'] = data

    return color_profile