Example #1
0
def dqt(flag, name, popper, print_details=False):
    """
    DQT
    :return:
    """
    DQT = {}
    length = read_bytes(popper, 2)
    content = read_bytes(popper, length - 2, False)
    Pq = (content[0] & 0xf0) >> 4
    Tq = content[0] & 0x0f
    table = content[1:]
    if print_details:
        idx_seg = 1
        idx_seg = print_bytes(length, idx_seg, 2)
        print('\t\t\t\t\t\t\t\t', 'Length = {length}'.format(length=length))
        idx_seg = print_bytes(content[:1], idx_seg)
        print(
            '\t\t\t\t\t\t\t\t', '(Pq,Tq)',
            '高四位Pq为量化表的数据精确度,Pq=0时,Q0~Qn的值为8位,Pq=1时,Qt的值为16位,Tq表示量化表的编号,为0~3。在基本系统中,Pq=0,Tq=0~1,也就是说最多有两个量化表。'
        )
        print('\t\t\t\t\t\t\t\t', '(Pq,Tq)=(%d,%d)' % (Pq, Tq))
        print_bytes(table, idx_seg)
    table = decode_dqt(table, Pq, print_details)

    DQT['flag'] = flag
    DQT['name'] = name
    DQT['length'] = length
    DQT['content'] = content
    DQT['Pq'] = Pq
    DQT['Tq'] = Tq
    DQT['table'] = table
    return DQT
Example #2
0
def sos(flag, name):
    SOS = {}
    length = read_bytes(2)
    content = read_bytes(length - 2, False)
    idx_seg = 1
    idx_seg = print_bytes(length, idx_seg, 2)
    print('\t\t\t\t\t\t\t\t', 'Length = {length}'.format(length=length))
    print_bytes(content, idx_seg)
    Ns = content[0]
    CsTdas = []
    for c in range(Ns):
        Csn = content[1 + c * 2]
        TdnTan = content[2 + c * 2]
        CsTdas.append([Csn, TdnTan])
    Ss = content[7]
    Se = content[8]
    AhAl = content[9]
    Ah = (AhAl & 0xf0) >> 4
    Al = AhAl & 0x0f

    SOS['flag'] = flag
    SOS['name'] = name
    SOS['length'] = length
    SOS['Ns'] = Ns
    SOS['CsTdas'] = CsTdas
    SOS['Ss'] = Ss
    SOS['Se'] = Se
    SOS['Ah'] = Ah
    SOS['Al'] = Al

    for k in SOS:
        print('\t\t', '%8s' % k, '\t', SOS[k])

    SOS['content'] = content
    return SOS
Example #3
0
def app_0(flag, name):
    """
    APP 0
    :return:
    """
    length = read_bytes(2)
    content = read_bytes(length - 2, False)
    idx_seg = 1
    idx_seg = print_bytes(length, idx_seg, 2)
    print('\t\t\t\t\t\t\t\t', 'Length = {length}'.format(length=length))
    idx_seg = print_bytes(content, idx_seg)

    identifier = bytes_2_int(content[:5])
    version = bytes_2_int(content[5:7])
    units = content[7]
    x_density = bytes_2_int(content[8:10])
    y_density = bytes_2_int(content[10:12])
    x_thumbnail = content[12]
    y_thumbnail = content[13]
    print('''    {length:#06X}\tLength\t{length}
    {identifier:#012X}\tIdentifier\t{identifier_b}
    {version:#06X}\tVersion
    {units:#04X}\tUnits\t零时表示未指定,为1表示英寸,为2表示厘米
    {x_density:#06X}\tx_density\t{x_density}
    {y_density:#06X}\ty_density\t{y_density}
    {x_thumbnail:#04X}\tx_thumbnail\t{x_thumbnail}
    {y_thumbnail:#04X}\ty_thumbnail\t{y_thumbnail}'''.format(
        length=length,
        identifier=identifier,
        identifier_b=identifier.to_bytes(5, 'big'),
        version=version,
        units=units,
        x_density=x_density,
        y_density=y_density,
        x_thumbnail=x_thumbnail,
        y_thumbnail=y_thumbnail,
    ))
    # remain = length - 16
    # if remain > 0:
    #     remain = read_bytes(remain, False)
    #     print(remain)
    # else:
    #     remain = b''
    remain = content[12:]

    return {
        'flag': flag,
        'name': name,
        'length': length,
        'identifier': identifier,
        'version': version,
        'units': units,
        'x_density': x_density,
        'y_density': y_density,
        'x_thumbnail': x_thumbnail,
        'y_thumbnail': y_thumbnail,
        'data': remain,
        'content': content
    }
Example #4
0
def dht(flag, name, popper, print_details=False):
    DHT = {}
    length = read_bytes(popper, 2)
    content = read_bytes(popper, length - 2, False)
    if print_details:
        idx_seg = 1
        idx_seg = print_bytes(length, idx_seg, 2)
        print('\t\t\t\t\t\t\t\t', 'Length = {length}'.format(length=length))
        print_bytes(content, idx_seg)
    TcTh = content[0]
    Tc = (TcTh & 0xf0) >> 4
    Th = TcTh & 0x0f

    cnts = dict(zip(range(1, 17), content[1:17]))

    vals = content[17:]
    vals_cur = 0
    codes = {}
    code_val = 0
    for k in cnts:
        # print(k, cnts[k])
        for cnt in range(cnts[k]):
            # print('\t', (bin(val), k))

            # # codes[code]={len,value}
            # codes[val] = {'len':k,'val':vals[vals_cur]}

            # # codes[(code,len)]=value
            codes[(code_val, k)] = vals[vals_cur]
            vals_cur += 1
            code_val += 1
        code_val <<= 1
        # print()

    DHT['flag'] = flag
    DHT['name'] = name
    DHT['length'] = length
    DHT['Tc'] = Tc
    DHT['Th'] = Th
    DHT['table'] = codes

    if print_details:
        for k in DHT:
            if k == 'table':
                print_huf_codes(DHT['table'], print_details)
            else:
                print('\t\t', '%8s' % k, '\t', DHT[k])

    DHT['content'] = content
    return DHT
Example #5
0
def app_n(flag, name):
    """
    APP N
    :return:
    """
    APP_N = {}
    length = read_bytes(2)
    content = read_bytes(length - 2, False)
    idx_seg = 1
    idx_seg = print_bytes(length, idx_seg, 2)
    print('\t\t\t\t\t\t\t\t', 'Length = {length}'.format(length=length))
    print_bytes(content, idx_seg)
    APP_N['flag'] = flag
    APP_N['name'] = name
    APP_N['length'] = length
    APP_N['content'] = content
    return APP_N
Example #6
0
def sof_0(flag, name, popper, print_details=False):
    """
    SOF0
    :return:
    """
    SOF0 = {}
    length = read_bytes(popper, 2)
    content = read_bytes(popper, length - 2, False)
    if print_details:
        idx_seg = 1
        idx_seg = print_bytes(length, idx_seg, 2)
        print('\t\t\t\t\t\t\t\t', 'Length = {length}'.format(length=length))
        print_bytes(content, idx_seg)
    P = content[0]
    Y = bytes_2_int(content[1:3])
    X = bytes_2_int(content[3:5])
    Nf = content[5]
    Tqs = []
    for c in range(Nf):
        # 成分编号
        Cn = content[6 + c * 3]
        # 水平垂直采样因子
        HnVn = content[7 + c * 3]
        # 量化表编号
        Tqn = content[8 + c * 3]

        Tqs.append([Cn, HnVn, Tqn])

    SOF0['flag'] = flag
    SOF0['name'] = name
    SOF0['length'] = length
    SOF0['P'] = P
    SOF0['Y'] = Y
    SOF0['X'] = X
    SOF0['Nf'] = Nf
    SOF0['Tqs'] = Tqs
    if print_details:
        print('\tSOF0')
        for k in SOF0:
            print('\t\t', '%8s' % k, '\t', SOF0[k])
    SOF0['content'] = content
    return SOF0
Example #7
0
def read_scan(SCAN=True, show_img=True, print_data=False, print_decode=False):
    global cur
    _img = img[cur:]
    cur = len(img)

    # print('data old:')
    # print_bytes(_img, 1)
    # save_bytes(_img, 1)

    # replace 0xff00 and 0xffd9
    _cur = 0
    scan = b''
    while _cur < len(_img):
        i = _img[_cur]
        if i == 0xff:
            i_next = _img[_cur + 1]
            if i_next == 0xd9:
                print(hex((i << 8) | i_next))
                break
            elif i_next == 0x00:
                # print('Warn! 0xFF00 @cur', _cur + 1)
                scan += i.to_bytes(1, 'big')
                _cur += 2
                continue
            elif i_next == 0xff:
                print('Warn! 0xFFFF @cur', _cur + 1)
                _cur += 1
                continue
            elif i_next in range(0xd0, 0xd8):
                # TODO 0XD0--0XD7,组成RSTn标记,需要忽视整个RSTn标记,即不对当前0XFF和紧接着的0XDn两个字节进行译码,并按RST标记的规则调整译码变量;???
                scan += i.to_bytes(1, 'big')
                raise Exception('Unimpled')

        else:
            scan += i.to_bytes(1, 'big')

        _cur += 1

    # save_bytes(scan, 1)

    Y_DC_Huffman_table_id = (headers[0xda][0]['CsTdas'][0][1] >> 4) | 0x00
    Y_AC_Huffman_table_id = (headers[0xda][0]['CsTdas'][0][1] & 0x0f) | 0x10
    U_DC_Huffman_table_id = (headers[0xda][0]['CsTdas'][1][1] >> 4) | 0x00
    U_AC_Huffman_table_id = (headers[0xda][0]['CsTdas'][1][1] & 0x0f) | 0x10
    V_DC_Huffman_table_id = (headers[0xda][0]['CsTdas'][2][1] >> 4) | 0x00
    V_AC_Huffman_table_id = (headers[0xda][0]['CsTdas'][2][1] & 0x0f) | 0x10
    table_ids = [(Y_DC_Huffman_table_id, Y_AC_Huffman_table_id),
                 (U_DC_Huffman_table_id, U_AC_Huffman_table_id),
                 (V_DC_Huffman_table_id, V_AC_Huffman_table_id)]
    DHTs = {}
    for _dht in headers[0xc4]:
        DHTs[(_dht['Tc'] << 4) | _dht['Th']] = _dht  # ['table']
        if print_decode:
            print_dht(_dht)
    if print_data:
        print('data:')
        print_bytes(scan, 1)
    if not SCAN:
        return
    if print_data:
        print_stream(scan)

    # get H123,V123
    sof0_Tqs = headers[0xc0][0]['Tqs']
    colors_tqs = {}
    for tq in sof0_Tqs:
        # tq[0]-颜色分量号,-1映射到012
        colors_tqs[tq[0] - 1] = {}
        # 水平和垂直采样因子
        colors_tqs[tq[0] - 1]['H'] = tq[1] >> 4
        colors_tqs[tq[0] - 1]['V'] = tq[1] & 0x0f
        # MCU 中 data unit(s) 的数量
        colors_tqs[tq[0] -
                   1]['DUC'] = colors_tqs[tq[0] - 1]['H'] * colors_tqs[tq[0] -
                                                                       1]['V']
        # 量化表编号
        colors_tqs[tq[0] - 1]['QTable'] = tq[2]

    prev = 0
    DC = True
    got = True
    RLE_val = False
    code_len = 0

    # todo convert to numpy
    MCUs = []
    mcu = {0: [], 1: [], 2: []}
    data_unit = []

    in_mcu = True
    mcu_idx = 0
    current_color = 0
    data_unit_idx = 0

    # 差分编码
    diff = [0, 0, 0]

    for i in scan:
        ii = i | (prev << 8)
        for a in reversed(range(8)):
            code_len += 1
            t = (ii >> a)
            # print(t, bin(t))
            if RLE_val:
                if code_len >= val_len:
                    ii &= (0xff >> (8 - a))
                    # hit the val
                    RLE_val = decode_b(code_len, t)
                    if print_decode:
                        print('RLE', bin(t)[2:].zfill(code_len), RLE_val)
                    data_unit.append(RLE_val)
                    code_len = 0
                    RLE_val = False
                    if len(data_unit) >= 64:
                        DC = True
                        data_unit_idx += 1
                        # # # todo 差分编码矫正
                        # # Dc_n = Diff_n-1 + Diff_n
                        # tmp = data_unit[0]
                        # data_unit[0] += diff[current_color]
                        # diff[current_color] = tmp

                        # Dc_n = Dc_n-1 + Diff_n
                        data_unit[0] += diff[current_color]
                        diff[current_color] = data_unit[0]

                        mcu[current_color].append(data_unit)
                        data_unit = []
                        if data_unit_idx >= colors_tqs[current_color]['DUC']:
                            if print_decode:
                                print('---Color', colors_YCrCb[current_color],
                                      'end')
                            current_color += 1
                            current_color %= 3
                            data_unit_idx = 0
                            if current_color == 0:
                                # todo big image - do add to img sync
                                mcu = convert_mcu(mcu, colors_tqs)
                                MCUs.append(mcu)
                                if print_decode:
                                    print('===MCU', mcu_idx, ' end')
                                mcu = {0: [], 1: [], 2: []}
                                mcu_idx += 1
                                in_mcu = True
                continue
            if got:
                got = False
                if DC:
                    table = DHTs[table_ids[current_color][0]]
                else:
                    table = DHTs[table_ids[current_color][1] | 0x10]
            # if t in table['table'] and code_len == table['table'][t]['len']:
            if (t, code_len) in table['table']:
                # hit the huffman code
                got = True
                # val = table['table'][(t, code_len)]['val']
                val = table['table'][(t, code_len)]
                if DC:
                    if in_mcu and current_color == 0:
                        if print_decode:
                            print('===MCU', mcu_idx, '===')
                        in_mcu = False
                    if print_decode:
                        print('---Col', colors_YCrCb[current_color],
                              '---data unit', data_unit_idx, '---')
                        print('DC:', end=' ')
                        print('hcode',
                              bin(t)[2:].zfill(code_len), 'val',
                              '{v:#04X}, {v}'.format(v=val))
                    if val == 0:
                        # DC = True
                        # print('Color', colors[current_color], 'end')
                        # current_color += 1
                        # current_color %= 3

                        DC = False
                        val_len = val
                        RLE_val = False
                        # todo dc=0 : append 0
                        data_unit.append(RLE_val)
                    else:
                        DC = False
                        val_len = val
                        RLE_val = True
                else:
                    # AC
                    if print_decode:
                        print('AC:', end=' ')
                        print('hcode',
                              bin(t)[2:].zfill(code_len), 'val',
                              '{v:#04X}, {v}'.format(v=val))
                    if val == 0:
                        DC = True
                        data_unit_idx += 1
                        rest_z = 64 - len(data_unit)
                        if rest_z > 0:
                            data_unit += [0] * rest_z

                        # # todo 差分编码矫正
                        # tmp = data_unit[0]
                        # data_unit[0] += diff[current_color]
                        # diff[current_color] = tmp

                        data_unit[0] += diff[current_color]
                        diff[current_color] = data_unit[0]

                        mcu[current_color].append(data_unit)
                        data_unit = []
                        if data_unit_idx >= colors_tqs[current_color]['DUC']:
                            if print_decode:
                                print('---Color', colors_YCrCb[current_color],
                                      'end')
                            current_color += 1
                            current_color %= 3
                            data_unit_idx = 0
                            if current_color == 0:
                                # todo big image - do add to img sync
                                mcu = convert_mcu(mcu, colors_tqs)
                                MCUs.append(mcu)
                                if print_decode:
                                    print('===MCU', mcu_idx, ' end')
                                mcu = {0: [], 1: [], 2: []}
                                mcu_idx += 1
                                in_mcu = True
                    else:
                        zero_cnt = val >> 4
                        if print_decode:
                            print('\tzero cnt:', zero_cnt)
                        data_unit += ([0] * zero_cnt)
                        val_len = val & 0x0f
                        # todo 应该是0xF0才会到这里,假设16个0后面一定会有AC编码
                        if val_len == 0:
                            RLE_val = False
                            # todo debug AC code == 0xF0 ? zero_cnt=15,+0?
                            data_unit.append(0)

                        else:
                            RLE_val = True

                # print('hcode',bin(t)[2:].zfill(table['table'][t]['len']))
                # print('hcode', bin(t)[2:].zfill(table['table'][(t, code_len)]),'val','{v:#04X}, {v}'.format(v=val))
                ii &= (0xff >> (8 - a))
                code_len = 0
        prev = ii

    # print('===================\nMCUs')
    # print(MCUs)
    img_show = merge_mcus(MCUs, colors_tqs, headers[0xc0][0])
    img_show = crop_image(img_show, headers[0xc0][0])
    if show_img:
        plt_mcu(img_show)
    return img_show