I am writing a program to compress an image using Huffman encoding, and I need to write the data structure and the byte file. After that, I have to read/decode it. I realize that my read and write is very slow.
I think in writetree() I need to write either width, height, compress bits and the tree data structure. I am not sure we can combine it or not.
And another part, I think I use too many for loops so it is very slow in a very long string.
from PIL import Image
import numpy as np
import json
import sys, string
trim = ('0', ('127', '255'))
width = 4
height = 4
longstring = "1100100111001101011110010011010110101111001001101011010111100100110101101011"
def decode (tree, str) :
output = ""
list = []
p = tree
count = 0
for bit in str :
if bit == '0' : p = p[0] # Head up the left branch
else : p = p[1] # or up the right branch
if type(p) == type("") :
output += p # found a character. Add to output
list.append(int(p))
p = tree # and restart for next character
return list
def writetree(tree,height, width,compress):
with open('structure.txt', 'w') as outfile:
json.dump(trim, outfile)
outfile.close()
f = open("info.txt", "w")
f.write(str(height)+"\n")
f.write(str(width)+"\n")
f.write(str(compress)+"\n")
f.close()
def readtree():
with open('structure.txt') as json_file:
data = json.load(json_file)
k = open("info.txt", "r")
heightread = k.readline().strip("\n")
widthread = k.readline().strip("\n")
compressread = k.readline().strip("\n")
json_file.close()
k.close()
return tuple(data), int(heightread), int(widthread), int(compressread)
def writefile():
print("Write file")
with open('file', 'wb') as f:
bit_strings = [longstring[i:i + 8] for i in range(0, len(longstring), 8)]
byte_list = [int(b, 2) for b in bit_strings]
print(byte_list)
realsize = len(bytearray(byte_list))
print('Compress number of bits: ', len(longstring))
writetree(trim,height,width,len(longstring))
f.write(bytearray(byte_list))
f.close()
def readfile():
print("Read file")
byte_list = []
longbin = ""
with open('file', 'rb') as f:
value = f.read(1)
while value != b'':
byte_list.append(ord(value))
value = f.read(1)
print(byte_list)
for a in byte_list[:-1]:
longbin = longbin + '{0:08b}'.format(a)
trim_read, height_read, width_read , compress_read = readtree()
sodu = compress_read%8
'''
because the this string is split 8 bits at the time, and the current compress_read is 76
so the sodu is 4. I have to convert the last byte_list into 4bits not 8 bits
'''
if sodu == 0:
longbin = longbin + '{0:08b}'.format(byte_list[-1])
elif sodu == 1:
longbin = longbin + '{0:01b}'.format(byte_list[-1])
elif sodu == 2:
longbin = longbin + '{0:02b}'.format(byte_list[-1])
elif sodu == 3:
longbin = longbin + '{0:03b}'.format(byte_list[-1])
elif sodu == 4:
longbin = longbin + '{0:04b}'.format(byte_list[-1])
elif sodu == 5:
longbin = longbin + '{0:05b}'.format(byte_list[-1])
elif sodu == 6:
longbin = longbin + '{0:06b}'.format(byte_list[-1])
elif sodu == 7:
longbin = longbin + '{0:07b}'.format(byte_list[-1])
print(longbin)
print("Decode/ show image:")
pixels = decode(trim_read, longbin)
it = iter(pixels)
pixels = list(zip(it,it,it))
#print(pixels)
image_out = Image.new("RGB", (width_read, height_read))
image_out.putdata(pixels)
#image_out.show()
writefile()
readfile()