예제 #1
0
def parse_ffdb(bytes_array: BytesArray,
               image_info: ImageInfo):  #   таблицы квантования
    ff_db_indexes = bytes_array.find_all_pairs("ff", "db")
    if ff_db_indexes == -1:
        raise BadMarkerException

    header_size = 3
    zig_zag = ZigZag()
    for ff_db_index in ff_db_indexes:
        ff_db_index += SECTION_TITLE_SIZE
        header = bytes_array[ff_db_index:ff_db_index + header_size]
        ff_db_size = int(header[0] + header[1], 16)

        ff_db_data = bytes_array[ff_db_index:ff_db_index + ff_db_size]
        ff_db_data_index = 0
        values_length = int(ff_db_data[ff_db_data_index + 2][0], 16)
        if values_length != 0:
            raise BadQuantizationValuesLength

        quantization_table_id = int(ff_db_data[ff_db_data_index + 2][1], 16)

        quantization_table_index = ff_db_data_index + 3
        quantization_arr = ff_db_data[quantization_table_index:]

        quantization_table = zig_zag.zig_zag_order(quantization_arr)
        image_info.add_quantization_table(
            QuantizationTable(quantization_table_id, quantization_table))
예제 #2
0
def parse_ffda(bytes_array: BytesArray,
               image_info: ImageInfo):  # start of scan
    ffda_data = bytes_array.read_from_one_pair_to_other("ffda", "ffd9")
    header_length = int(
        ffda_data[2] + ffda_data[3], 16
    )  #   в первых ьдвух байтах длина только для заголовочной части а не для всей секции

    ffda_header_data = ffda_data[SECTION_TITLE_SIZE:header_length]
    ffda_header_index = 0
    amount_of_components = int(ffda_header_data[ffda_header_index + 2], 16)
    if amount_of_components != 3:
        raise BadComponentsAmountException

    components_index = ffda_header_index + 3

    for i in range(0, amount_of_components):

        component_id = int(ffda_header_data[components_index], 16)
        dc_table_id = int(ffda_header_data[components_index + 1][1])
        ac_table_id = int(ffda_header_data[components_index + 1][0])

        component = image_info.get_component_by_id(component_id)
        component.dc_haff_table_id = dc_table_id
        component.ac_haff_table_id = ac_table_id

        components_index += 2

    # берем данные и переводим в двоичную строку(0111010...)
    coded_data = ffda_data[(header_length + 2):]
    coded_data_binary = hex_to_binary(coded_data)
    parse_channels(image_info, coded_data_binary)
예제 #3
0
def quantization(image_info: ImageInfo):
    for comp in image_info.components:
        quantization_table_id = comp.quantization_table_id
        quantization_table = image_info.get_quantization_table_by_id(
            quantization_table_id)
        for i, block in enumerate(comp.array_of_blocks):
            comp.array_of_blocks[i] = multiply_2d_matrixes(
                block, quantization_table.table)
예제 #4
0
def parse_channels(image_info: ImageInfo, coded_data_binary: str):
    y_comp_index = 1
    cb_comp_index = 2
    cr_comp_index = 3

    y_component = image_info.get_component_by_id(y_comp_index)
    cb_component = image_info.get_component_by_id(cb_comp_index)
    cr_component = image_info.get_component_by_id(cr_comp_index)

    arr_for_index = [0]
    y_amount, cb_amount, cr_amount = 0, 0, 0
    counter = 0
    try:
        while y_amount < y_component.blocks_amount and\
                cb_amount < cb_component.blocks_amount and cr_amount < cr_component.blocks_amount:
            for i in range(0, y_component.k_ratio):
                if y_amount >= y_component.blocks_amount:
                    break

                parse_channel(coded_data_binary, y_component, image_info,
                              arr_for_index)
                y_amount += 1
                counter += 1

            for j in range(0, cb_component.k_ratio):
                if cb_amount >= cb_component.blocks_amount:
                    break
                parse_channel(coded_data_binary, cb_component, image_info,
                              arr_for_index)
            for k in range(0, cr_component.k_ratio):
                if cr_amount >= cr_component.blocks_amount:
                    break
                parse_channel(coded_data_binary, cr_component, image_info,
                              arr_for_index)

    except EndException:
        pass

    length_of_data = len(coded_data_binary)
    length_index = arr_for_index[0]
    if arr_for_index[0] != len(coded_data_binary) - 1:
        print("length_of_data: " + str(length_of_data) + " length_index: " +
              str(length_index))

    for comp in image_info.components:
        comp.substract_dc()
예제 #5
0
def parse_ffc0(bytes_array: BytesArray,
               image_info: ImageInfo):  #   Информация о картинке(р - ры)
    ff_c0_index = bytes_array.find_pair("ff", "c0")
    if ff_c0_index == -1:
        ff_c0_index = bytes_array.find_pair("ff", "c2")
        # raise NotBaseMethodOfCodingException

    header_index = ff_c0_index + SECTION_TITLE_SIZE
    ff_db_size = int(bytes_array[header_index] + bytes_array[header_index + 1],
                     16)
    ff_c0_data = bytes_array[header_index:header_index + ff_db_size]
    ff_db_data_index = 0
    channel_dimension = int(ff_c0_data[ff_db_data_index + 2], 16)
    if channel_dimension != 8:
        raise BadDimensionException

    image_size_index = ff_db_data_index + 3

    image_height = int(
        ff_c0_data[image_size_index] + ff_c0_data[image_size_index + 1], 16)
    image_width = int(
        ff_c0_data[image_size_index + 2] + ff_c0_data[image_size_index + 3],
        16)
    image_info.width = image_width
    image_info.height = image_height

    channels_amount_index = ff_db_data_index + 7
    channels_amount = int(ff_c0_data[channels_amount_index], 16)
    if channels_amount != 3:
        raise BadChannelsAmountException
    image_info.channels_amount = channels_amount

    channel_data_size = 3
    channel_info_index = channels_amount_index + 1
    max_horizontal_thinning = 0
    max_vertical_thinning = 0
    for i in range(0, channels_amount):
        channel_data = ff_c0_data[channel_info_index:channel_info_index +
                                  channel_data_size]
        component_id = int(channel_data[0], 16)
        horizontal_thinning = int(channel_data[1][0], 16)
        vertical_thinning = int(channel_data[1][1], 16)
        k_ratio = 1
        if component_id == 1:
            k_ratio = horizontal_thinning * vertical_thinning
            max_horizontal_thinning = horizontal_thinning
            max_vertical_thinning = vertical_thinning
        horizontal_thinning = max_horizontal_thinning // horizontal_thinning
        vertical_thinning = max_vertical_thinning // vertical_thinning
        quantization_table_id = int(channel_data[2], 16)
        image_info.add_component(
            Component(component_id, horizontal_thinning, vertical_thinning,
                      quantization_table_id, image_info.width,
                      image_info.height, k_ratio))

        channel_info_index += 3
    image_info.set_new_size()
예제 #6
0
def parse_fffe(bytes_array: BytesArray,
               image_info: ImageInfo):  #   комментарий
    ff_ee_start = 2
    if bytes_array[ff_ee_start] + bytes_array[ff_ee_start + 1] != 'fffe' \
            or bytes_array[ff_ee_start] + bytes_array[ff_ee_start + 1] != 'ffe0':
        # raise BadMarkerException
        pass

    ff_ee_header_size = 2
    comment = bytes_array.read_n_bytes(ff_ee_start + SECTION_TITLE_SIZE,
                                       ff_ee_header_size)
    comment = comment[2:]
    image_info.comment = comment
예제 #7
0
def y_cb_cr_to_rgb(image_info: ImageInfo):
    y_comp_index = 1
    cb_comp_index = 2
    cr_comp_index = 3

    y_component = image_info.get_component_by_id(y_comp_index)
    cb_component = image_info.get_component_by_id(cb_comp_index)
    cr_component = image_info.get_component_by_id(cr_comp_index)

    rgb_components_array = []
    if y_component.k_ratio == 4 and cb_component.k_ratio == 1 and cr_component.k_ratio == 1:
        convert_by_blocks(y_component, cb_component, cr_component,
                          rgb_components_array, 1)
    elif y_component.k_ratio == 1 and cb_component.k_ratio == 1 and cr_component.k_ratio == 1:
        for i in range(0, y_component.blocks_amount):
            rgb_component = convert_ycbcr_to_rgb(
                y_component.array_of_blocks[i],
                cb_component.array_of_blocks[i],
                cr_component.array_of_blocks[i], 0, 2)

            rgb_components_array.append(rgb_component)
    else:
        raise BadComponentsAmountException
    return rgb_components_array
예제 #8
0
def merge_rgb_blocks(rgb_components_array: [], image_info: ImageInfo):
    y_comp_index = 1

    y_component = image_info.get_component_by_id(y_comp_index)
    m_cols = 0
    m_rows = 0
    if y_component.k_ratio == 4:
        m_cols = int(y_component.horizontal_blocks / (y_component.k_ratio / 2))
        m_rows = int(y_component.vertical_blocks / (y_component.k_ratio / 2))
    elif y_component.k_ratio == 1:
        m_cols = int(y_component.horizontal_blocks)
        m_rows = int(y_component.vertical_blocks)

    rows = []
    for i in range(0, m_rows):
        #filling one row of matrixes
        one_row = []
        for j in range(0, m_cols):
            first = rgb_components_array.pop(0)
            one_row.append(first)
        while len(one_row) > 1:
            first = one_row.pop(0)
            second = one_row.pop(0)
            first_second_conc = append_right(first, second)

            new_arr = []
            new_arr.append(first_second_conc)
            for mass in one_row:
                new_arr.append(mass)

            one_row = new_arr

        rows.append(one_row[0])

    result_matrix = rows
    while len(result_matrix) > 1:
        first = result_matrix.pop(0)
        second = result_matrix.pop(0)
        first_second_conc = append_down(first, second)

        new_arr = []
        new_arr.append(first_second_conc)
        for mass in result_matrix:
            new_arr.append(mass)
        result_matrix = new_arr

    result_matrix = np.asarray(result_matrix[0], dtype=np.uint8)
    return result_matrix
예제 #9
0
def decode_image(file_name: str) -> ():
    with open(file_name, "rb") as f:
        img = f.read()
        bytes_array = BytesArray(img)
        image_info = ImageInfo()  # для результата

        parse_ffd8(bytes_array)
        parse_fffe(bytes_array, image_info)
        parse_ffdb(bytes_array, image_info)
        parse_ffc0(bytes_array, image_info)
        parse_ffc4(bytes_array, image_info)
        parse_ffda(bytes_array, image_info)
        quantization(image_info)
        i_dct(image_info)
        rgb_components_array = y_cb_cr_to_rgb(image_info)
        result_matrix = merge_rgb_blocks(rgb_components_array, image_info)
        result_matrix = cut_image(result_matrix)
        return result_matrix, image_info
예제 #10
0
        parse_ffc4(bytes_array, image_info)
        parse_ffda(bytes_array, image_info)
        quantization(image_info)
        i_dct(image_info)
        rgb_components_array = y_cb_cr_to_rgb(image_info)
        result_matrix = merge_rgb_blocks(rgb_components_array, image_info)
        result_matrix = cut_image(result_matrix)
        return result_matrix, image_info


if __name__ == "__main__":
    cur_path = os.path.dirname(__file__)
    with open(cur_path + "/images/vodopad.jpg", "rb") as f:
        img = f.read()
        bytes_array = BytesArray(img)
        image_info = ImageInfo()  #   для результата

        parse_ffd8(bytes_array)
        parse_fffe(bytes_array, image_info)
        parse_ffdb(bytes_array, image_info)
        parse_ffc0(bytes_array, image_info)
        parse_ffc4(bytes_array, image_info)
        parse_ffda(bytes_array, image_info)
        quantization(image_info)
        i_dct(image_info)
        rgb_components_array = y_cb_cr_to_rgb(image_info)
        result_matrix = merge_rgb_blocks(rgb_components_array, image_info)
        result_matrix = cut_image(result_matrix)
        imshow(result_matrix)
        plt.show()