-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
156 lines (123 loc) · 5.01 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
########## JPEG Compression ##########
# Author: amirhnajafiz
# Email: [email protected]
# Year: 2022
# Version: 0.1
######################################
# utils package
# ================
from utils.image import *
from utils.convert import rgb2ycbcr
# ================
# quantization package
# ================
from quantization.sampling import sample
from quantization.quantization import quantize
from quantization.zigzag import get_zigzags
# ================
# huffman package
# ================
from huffman.huffman import freq, do_huffman
# ================
# RLC package
# ================
from rlc.rlc import rlc_coding
# ================
# python libraries
# ================
import numpy as np
import os
import time
from datetime import datetime
import pickle
# ================
# Global Variables
# ================
INPUT_DIR = 'in'
OUTPUT_DIR = 'out'
# ================
if __name__ == "__main__":
# check the output directory
if not os.path.exists(OUTPUT_DIR):
os.mkdir(OUTPUT_DIR)
print(f'[OK][{datetime.now().strftime("%m/%d/%Y, %H:%M:%S")}] Begin ...')
# get the input file
path = input("[Enter the file path] > ")
# reading the image into an array
start_time = time.time()
pix, width, height = read_image_file(os.path.join(INPUT_DIR, path))
print(f'[OK] Input file: {os.path.join(INPUT_DIR, path)}')
print(f'[OK] Image read: {width}x{height}')
# converting to YCrCb
start_time = time.time()
pix = rgb2ycbcr(pix)
print(f'[OK][{time.time() - start_time}s] Convert to YCrCb: {pix.shape}')
# showing the YCrCb image
create_image(pix).show()
y = np.zeros((height, width), np.float32) + pix[:, :, 0]
cr = np.zeros((height, width), np.float32) + pix[:, :, 1]
cb = np.zeros((height, width), np.float32) + pix[:, :, 2]
# size of the image in bits before compression
totalNumberOfBitsWithoutCompression = len(y) * len(y[0]) * 8 + len(cb) * len(cb[0]) * 8 + len(cr) * len(cr[0]) * 8
print(f'[INFO] Total input: {np.round(totalNumberOfBitsWithoutCompression / 1024, 5)} kb')
# sampleing
start_time = time.time()
y, cr, cb = sample(y, cr, cb)
print(f'[OK][{time.time() - start_time}s] Chroma subsampling')
# quantizing
start_time = time.time()
y, cr, cb, ws = quantize(y, cr, cb)
print(f'[OK][{time.time() - start_time}s] Quantized')
# zigzags
start_time = time.time()
y, cr, cb = get_zigzags(y, cr, cb, ws)
print(f'[OK][{time.time() - start_time}s] Performing ZigZag iteration')
start_time = time.time()
# find the run length encoding for each channel
# then get the frequency of each component in order to form a Huffman dictionary
"""
for Y, calculate the RLC coding
and perform the huffman coding on it.
"""
yEncoded = rlc_coding(y)
yHuffman = do_huffman(freq(yEncoded))
"""
for Cr, calculate the RLC coding
and perform the huffman coding on it.
"""
crEncoded = rlc_coding(cr)
crHuffman = do_huffman(freq(crEncoded))
"""
for Cb, calculate the RLC coding
and perform the huffman coding on it.
"""
cbEncoded = rlc_coding(cb)
cbHuffman = do_huffman(freq(cbEncoded))
print(f'[OK][{time.time() - start_time}s] Huffman coding')
# saving encodeds
with open(os.path.join(OUTPUT_DIR, "encode_" + path.split('.')[0] + ".pickle"), "wb") as myFile:
pickle.dump(yEncoded, myFile, protocol=pickle.HIGHEST_PROTOCOL)
pickle.dump(crEncoded, myFile, protocol=pickle.HIGHEST_PROTOCOL)
pickle.dump(cbEncoded, myFile, protocol=pickle.HIGHEST_PROTOCOL)
# saving huffman trees
with open(os.path.join(OUTPUT_DIR, "htrees_" + path.split('.')[0] + ".pickle"), "wb") as myFile:
pickle.dump(yHuffman, myFile, protocol=pickle.HIGHEST_PROTOCOL)
pickle.dump(crHuffman, myFile, protocol=pickle.HIGHEST_PROTOCOL)
pickle.dump(cbHuffman, myFile, protocol=pickle.HIGHEST_PROTOCOL)
print('[OK] Output files created')
# calculate the number of bits to transmit for each channel
# and write them to an output file
yBitsToTransmit, crBitsToTransmit, cbBitsToTransmit = str(), str(), str()
with open(os.path.join(OUTPUT_DIR, path.split('.')[0] + ".asfh"), "w") as file:
for value in yEncoded:
yBitsToTransmit += yHuffman[value]
for value in crEncoded:
crBitsToTransmit += crHuffman[value]
for value in cbEncoded:
cbBitsToTransmit += cbHuffman[value]
file.write(yBitsToTransmit + "\n" + crBitsToTransmit + "\n" + cbBitsToTransmit)
# total number of bites after compression
totalNumberOfBitsAfterCompression = len(yBitsToTransmit) + len(crBitsToTransmit) + len(cbBitsToTransmit)
print(f'[INFO] Compressed image size: {np.round(totalNumberOfBitsAfterCompression / 1024, 5)} kb')
print(f'[INFO] Compression Ratio: {np.round(totalNumberOfBitsWithoutCompression / totalNumberOfBitsAfterCompression, 3)}')
print(f'[OK][{datetime.now().strftime("%m/%d/%Y, %H:%M:%S")}] Done')