]> vgcfreebox.myrthtech.pt Git - ue-ccd-compressaodeimagensbinarias.git/blob - lz78/lz_78_rle.py
second version delivered to teacher
[ue-ccd-compressaodeimagensbinarias.git] / lz78 / lz_78_rle.py
1 import sys
2 import struct
3
4 ########################################################################################
5 # Apenas comprimir
6 #
7 # python lz_78_rle.py <caminho_para_o_ficheiro_original>
8 #
9 #
10 # Os ficheiros gerados ficarão na mesma pasta que o script
11 ########################################################################################
12
13 def rle_transform(bitstream):
14 sequencia = []
15 pixel_atual = '0' # Começa sempre com o pixel 0 conforme enunciado
16 contador = 0
17
18 for bit in bitstream:
19 if bit == pixel_atual:
20 if contador == 255: # Limite de 8 bits
21 sequencia.append(255)
22 sequencia.append(0) # Troço de 0 do outro pixel para continuar no mesmo [cite: 41]
23 contador = 1
24 else:
25 contador += 1
26 else:
27 sequencia.append(contador)
28 pixel_atual = bit
29 contador = 1
30 sequencia.append(contador)
31 return sequencia
32
33 def lz78_compression(image_data):
34 dictionary = {0: []}
35 output = []
36 symbol = []
37
38 for i in image_data:
39 temp = symbol + [i]
40 dict_values = list(dictionary.values())
41 if temp in dict_values:
42 symbol = temp
43 else:
44 if not symbol:
45 output.append([0, i])
46 dictionary[len(dictionary)] = [i]
47 else:
48 idx = dict_values.index(symbol)
49 output.append([idx, i])
50 dictionary[len(dictionary)] = symbol + [i]
51 symbol = []
52
53 if symbol:
54 idx = list(dictionary.values()).index(symbol)
55 output.append([idx, -1])
56 return output
57
58 def clean_image_data(image_data):
59
60 clean_text = ""
61
62 for line in image_data:
63 line = line.strip()
64 line = line.replace(" ", "")
65 if not line or line.startswith('#'):
66 continue
67 clean_text += line
68
69 return clean_text
70
71 def chunkstring(string, length):
72 return [string[i : length+i] for i in range(0, len(string), length)]
73
74
75 with open(sys.argv[1], "r") as image:
76 lines = image.readlines()
77 image_size = lines[1].split()
78
79 if lines[0].strip() != 'P1':
80 raise ValueError("This is not a pbm file")
81
82 clean_text = clean_image_data(lines[2:]) #Limpa os espaços em branco para comprimir melhor
83
84 clean_text = rle_transform(clean_text)
85
86 output = lz78_compression(clean_text)
87
88 print(f"Output: {output}\n")
89
90 #Compressão em texto (human-readable)
91 with open(sys.argv[1] + "_compressed", "w") as save_file:
92 save_file.write(f"{output} \n{image_size[0]} {image_size[1]}")
93
94 #Compressão em binário (compressão "a sério")
95 with open(sys.argv[1] + ".bin", "wb") as save_file:
96 largura = int(image_size[0])
97 altura = int(image_size[1])
98 save_file.write(struct.pack('II', largura, altura))
99
100 for indice, val in output:
101 simbolo_byte = val if val != -1 else 255
102 save_file.write(struct.pack('HB', indice, simbolo_byte))