]> vgcfreebox.myrthtech.pt Git - ue-ccd-compressaodeimagensbinarias.git/blob - lz78/lz_78_2x2.py
second version delivered to teacher
[ue-ccd-compressaodeimagensbinarias.git] / lz78 / lz_78_2x2.py
1 import sys
2 import struct
3
4 ########################################################################################
5 # Apenas comprimir
6 #
7 # python lz_78_2x2.py <caminho_para_o_ficheiro_original>
8 #
9 #
10 # Os ficheiros gerados ficarão na mesma pasta que o script
11 ########################################################################################
12
13 def lz78_compression(image):
14 dictionary = {0: ""}
15 output = []
16 symbol = ""
17
18 for i in image:
19 if (symbol + i) in dictionary.values():
20 symbol += i
21 else:
22 if symbol == "":
23 output.append([0, i])
24 dictionary[len(dictionary)] = i
25 else:
26 idx = list(dictionary.keys())[list(dictionary.values()).index(symbol)]
27 output.append([idx, i])
28 dictionary[len(dictionary)] = symbol + i
29 symbol = ""
30
31 if symbol != "":
32 idx = list(dictionary.keys())[list(dictionary.values()).index(symbol)]
33 output.append([idx, ""])
34
35 return output, dictionary
36
37 def clean_image_data(image_data):
38 clean_text = ""
39 for line in image_data:
40 line = line.strip().replace(" ", "")
41 if not line or line.startswith('#'):
42 continue
43 clean_text += line
44 return clean_text
45
46 def chunkstring(string, length):
47 return [string[i : length+i] for i in range(0, len(string), length)]
48
49 def get_blocks(bitstream, largura, altura):
50 matriz = [bitstream[i*largura:(i+1)*largura] for i in range(altura)]
51 # Padding
52 if largura % 2 != 0:
53 matriz = [linha + '0' for linha in matriz]
54 largura += 1
55 if altura % 2 != 0:
56 matriz.append('0' * largura)
57 altura += 1
58
59 blocos = []
60 for r in range(0, altura, 2):
61 for c in range(0, largura, 2):
62 bloco = matriz[r][c] + matriz[r][c+1] + matriz[r+1][c] + matriz[r+1][c+1]
63 blocos.append(bloco)
64 return blocos, largura, altura
65
66
67 with open(sys.argv[1], "r") as image:
68 lines = image.readlines()
69 image_size = lines[1].split()
70
71 if lines[0].strip() != 'P1':
72 raise ValueError("This is not a pbm file")
73
74 largura_orig = int(image_size[0])
75 altura_orig = int(image_size[1])
76
77 clean_text = clean_image_data(lines[2:])
78
79 image_blocks, largura_pad, altura_pad = get_blocks(clean_text, largura_orig, altura_orig)
80
81 output, dic = lz78_compression(image_blocks)
82
83 with open(sys.argv[1] + "_compressed", "w") as save_file:
84 save_file.write(f"{output}\n{largura_orig} {altura_orig} {largura_pad} {altura_pad}")
85
86 with open(sys.argv[1] + ".bin", "wb") as save_file:
87 save_file.write(struct.pack('IIII', largura_orig, altura_orig, largura_pad, altura_pad))
88 for indice, simbolo in output:
89 simbolo_val = int(simbolo, 2) if simbolo != "" else 16
90 save_file.write(struct.pack('HB', indice, simbolo_val))