def decode(self): data = self.read() array = Bitset() for ch in data: array.push(ch) filename = self.filename.split('.')[:-1] filename = '.'.join(filename) with open('decoded_' + filename, 'wb') as file: for i in array.chunks(str(array), 8): int_value = int(i, base=2) bin_array = struct.pack('B', int_value) file.write(bin_array) if self.verbose: import os os.system('diff {} {}'.format(filename, 'decoded_' + filename))
def __init__(self, filename, verbose=True, table=[]): super(LempelZiv, self).__init__() self.filename = filename self.verbose = verbose self.bitarray = Bitset() self.bitarray.verbose = self.verbose self.bitarray.name = self.filename + '.lzv' self.table = table if self.filename: with open(self.filename, 'rb') as file: self.bitarray.fromfile(file) self.data = self.bitarray.to01() else: self.data = _options.text
def __init__(self, filename): super(CustomJpeg, self).__init__() self.filename = filename # 0 is to read as grayscale self.figure = cv2.imread(self.filename, 0) # generate image RGB -> YCbCr self.figure_ycbcr = cv2.cvtColor( cv2.imread(self.filename), cv2.COLOR_BGR2YCR_CB) # got each element from YCbCr self.y, self.cb, self.cr = self._split_channel_(self.figure_ycbcr) if not _options.output: self.output_filename = self.filename.replace( self.filename.split('.')[-1], 'cjpeg') else: self.output_filename = _options.output if self.figure is None: raise FileNotFound(self.filename) self.shape = self.figure.shape self.pixs = _options.size self.scrambled = np.array([]) self.bitarray = Bitset() self.bitarray.name = self.output_filename self.bitarray.verbose = False
def __init__(self, filename, verbose=True, mode='bin'): """Initialize the object.""" super(HuffmanCompactor, self).__init__() self.filename = filename self.mode = mode self.verbose = verbose self.bitarray = Bitset() self.bitarray.verbose = self.verbose self.dict_table = {}
class CustomJpeg(object): """docstring for CustomJpeg""" def __init__(self, filename): super(CustomJpeg, self).__init__() self.filename = filename # 0 is to read as grayscale self.figure = cv2.imread(self.filename, 0) # generate image RGB -> YCbCr self.figure_ycbcr = cv2.cvtColor( cv2.imread(self.filename), cv2.COLOR_BGR2YCR_CB) # got each element from YCbCr self.y, self.cb, self.cr = self._split_channel_(self.figure_ycbcr) if not _options.output: self.output_filename = self.filename.replace( self.filename.split('.')[-1], 'cjpeg') else: self.output_filename = _options.output if self.figure is None: raise FileNotFound(self.filename) self.shape = self.figure.shape self.pixs = _options.size self.scrambled = np.array([]) self.bitarray = Bitset() self.bitarray.name = self.output_filename self.bitarray.verbose = False def encode(self, output=''): """encode de file""" # will be only one block if True in (self.pixs > np.array(self.figure.shape)): self.pixs = min(self.figure.shape) import warnings warnings.simplefilter("always") warnings.warn('size updated to {}'.format( self.pixs), Warning) self.blocks_split() self.output = self.scrambled.copy() for i in range(len(self.scrambled)): self.output[i] = CustomJpeg._customDCT_(self.scrambled[i]) self.quantize() self.output = self._blocks_merge_( self.output, self.figure.shape, self.pixs) def save(self): # save if len(self.bitarray) > 0: self.bitarray.to_file() def size(self): return int(len(self.bitarray) / 8) def quantize(self): """ Quantize the output to write into the file""" # start value to DC DC = 0 for block in self.output: list_block = self.zig_zag(block) # [new DC] = [first] - [old DC] DC = list_block[0] - DC # lets format the list like the outpush shows in: # http://www.pcs-ip.eu/index.php/main/edu/8 bits = [] # first stage bits.append(DC) zero_counts = 0 for value in list_block[1:]: if value == 0: zero_counts += 1 if zero_counts == 10: bits.append([zero_counts, value]) zero_counts = 0 else: bits.append([zero_counts, value]) zero_counts = 0 # second stage bit_size = len('{:b}'.format(abs(bits[0]))) bits[0] = [[bit_size], bits[0]] for bit in range(1, len(bits)): bit_size = len('{:b}'.format(abs(bits[bit][1]))) bits[bit][0] = [bits[bit][0], bit_size] # third stage for bit in range(len(bits)): value = bits[bit][-1] # using U1 if value < 0: binary = '{:b}'.format(((1 << 16) + value) - 1) else: binary = '{:b}'.format(value) # cut the string bit_size = bits[bit][0][-1] binary = binary[-bit_size:] bits[bit][-1] = binary # four stage (huffman) bits[0][0] = huffman_dc[bits[0][0][0]] self.bitarray.push(bits[0][0]) if '-' in bits[0][1]: bits[0][1] = int(bits[0][1], 2) self.bitarray.push(bits[0][1]) for bit in range(1, len(bits)): bits[bit][0] = huffman_luminance[str(bits[bit][0])] self.bitarray.push(bits[bit][0]) self.bitarray.push(bits[bit][1]) # its ready! def blocks_merge(self): """merge splited image into one""" self.figure = CustomJpeg._blocks_merge_( self.scrambled, self.figure.shape, self.pixs ) def blocks_split(self): """split a image into NxN blocks. N=self.pixs""" self.scrambled = CustomJpeg._blocks_split_( self.figure, self.pixs) def show(self, name=''): """show the figure""" if name == '': name = self.output_filename cv2.imshow(name, self.figure) cv2.waitKey(0) def write(self): """write the bitarray to a file""" if not len(self.bitarray): raise EmptyFile(self.bitarray.name) self.bitarray.to_file() @staticmethod def _split_channel_(img): channels = [] for ch in range(img.shape[-1]): channels.append(img[..., ch]) return channels @staticmethod def _concatenate_channels_(ch1, ch2, ch3): assert ch1.ndim == 2 and ch2.ndim == 2 and ch3.ndim == 2 rgb = (ch1[..., np.newaxis], ch2[..., np.newaxis], ch3[..., np.newaxis]) return np.concatenate(rgb, axis=-1) @staticmethod def _customDCT_(block): """applying DCT in a macroblock""" imf = np.float32(block) / 255.0 # float conversion/scale dst = cv2.dct(imf) # the dct img = np.uint8(dst) * 255.0 return img @staticmethod def _blocks_merge_(scrambled, shape, pixs=8): no_rows, no_cols = shape rows_n = int((no_rows / pixs) * pixs) cols_n = int((no_cols / pixs) * pixs) figure = np.zeros(shape, scrambled.dtype) next_block = 0 # reassemble the blocks for row in range(rows_n - pixs + 1): for col in range(cols_n - pixs + 1): if (row % pixs == 0 and col % pixs == 0): cur_block = scrambled[next_block].copy() next_block += 1 figure[row:row + pixs, col:col + pixs] = cur_block return figure @staticmethod def _blocks_split_(figure, pixs=8): scrambled = figure.copy() no_rows, no_cols = scrambled.shape rows_n = int((no_rows / pixs) * pixs) cols_n = int((no_cols / pixs) * pixs) scrambled = cv2.resize(scrambled, (cols_n, rows_n)) allBlocks = [] # for loops to extract all blocks for row in range(rows_n - pixs + 1): for col in range(cols_n - pixs + 1): if (row % pixs == 0 and col % pixs == 0): block = scrambled[row:row + pixs, col:col + pixs].copy() allBlocks.append(block) return np.array(allBlocks, dtype=figure.dtype) @staticmethod def zig_zag(figure): """return the zig-zag of a block don't edit original block """ if figure.shape[0] != figure.shape[1]: raise Exception('Block sould be square') n = figure.shape[0] output = np.array([], dtype=figure.dtype) def move(i, j): """inside method""" if j < (n - 1): return max(0, i - 1), j + 1 else: return i + 1, j x, y = 0, 0 for v in figure.flatten(): output = np.append(output, figure[y][x]) if (x + y) & 1: x, y = move(x, y) else: y, x = move(y, x) return output
class LempelZiv(object): """docstring for LempelZiv""" def __init__(self, filename, verbose=True, table=[]): super(LempelZiv, self).__init__() self.filename = filename self.verbose = verbose self.bitarray = Bitset() self.bitarray.verbose = self.verbose self.bitarray.name = self.filename + '.lzv' self.table = table if self.filename: with open(self.filename, 'rb') as file: self.bitarray.fromfile(file) self.data = self.bitarray.to01() else: self.data = _options.text def encode(self): position = 0 offset = 1 output = '' self.table = list(set(self.data)) self.table.sort() while position + offset <= len(self.data): print('\r{:0.2f} '.format(100 * (position + offset) / len(self.data)), end='') buff = self.data[position:position + offset] if not buff in self.table: self.table.append(buff) output += str( self.table.index(self.data[position:position + offset - 1])) position += offset - 1 offset = 1 else: offset += 1 output += str(self.table.index(self.data[position:position + offset])) print(self.table) with open(self.filename + '.table', "w") as f: json.dump(self.table, f) self.bitarray.push(output) self.bitarray.to_file() self.data = output return output def decode(self): table_file = self.filename.split('.')[:-1] table_file = '.'.join(table_file) + '.table' with open(table_file) as json_file: self.dict_table = json.load(json_file) with open(table_file.replace('.table', '.lzv'), 'rb') as file: self.bitarray.fromfile(file) self.bitarray = self.bitarray.to01() def __str__(self): return self.data
class HuffmanCompactor(object): """docstring for Huffman Compactor.""" def __init__(self, filename, verbose=True, mode='bin'): """Initialize the object.""" super(HuffmanCompactor, self).__init__() self.filename = filename self.mode = mode self.verbose = verbose self.bitarray = Bitset() self.bitarray.verbose = self.verbose self.dict_table = {} def encoding(self): self.txt = open(self.filename, "rb",).read() self.symb2freq = defaultdict(int) self.symb2freq[256] = 0 for ch in self.txt: self.symb2freq[ch] += 1 if not len(self.symb2freq): raise IndexError('Input is empty, no magic here...') self.bitarray.name = self.filename.split('/')[-1] + '.huff' def build_table(self): """Create the Huffman table of the given dict mapping symbols.""" self.encoding() heap = [[wt, [sym, ""]] for sym, wt in self.symb2freq.items()] heapify(heap) while len(heap) > 1: lo = heappop(heap) hi = heappop(heap) for pair in lo[1:]: pair[1] = '0' + pair[1] for pair in hi[1:]: pair[1] = '1' + pair[1] heappush(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:]) self.table = sorted(heappop(heap)[1:], key=lambda p: (len(p[-1]), p)) for item in self.table: self.dict_table[item[0]] = item[1] return self.table def build_array(self): if not self.dict_table: self.build_table() for ch in self.txt: self.bitarray.extend(self.dict_table[ch]) def write(self): if not len(self.bitarray): self.build_array() with open(self.filename.split('/')[-1] + '.table', "w") as f: json.dump(self.dict_table, f) self.bitarray.extend(self.dict_table[256]) self.bitarray.to_file() def read(self): table_file = self.filename.split('.')[:-1] table_file = '.'.join(table_file) + '.table' with open(table_file) as json_file: self.dict_table = json.load(json_file) with open(table_file.replace('.table', '.huff'), 'rb') as file: self.bitarray.fromfile(file) self.bitarray = self.bitarray.to01() decoded = '' data = '' count = len(self.bitarray) while decoded != '256': size = len(self.bitarray) if self.verbose: print('\r%3.2f' % (100 * (1 - (size / count))), end='') # need to be paralelized for i in range(0, len(self.dict_table['256']) + 1): sym = self.bitarray[:i] try: decoded = list(self.dict_table.keys() )[list(self.dict_table.values()).index(sym)] if decoded == '256': if self.verbose: print('\r100.00') return data data += chr(int(decoded)) self.bitarray = self.bitarray[i:] break except: pass # '01' in a.values() # check presence # list(a.keys())[list(a.values()).index(0)] # get symb def decode(self): data = self.read() array = Bitset() for ch in data: array.push(ch) filename = self.filename.split('.')[:-1] filename = '.'.join(filename) with open('decoded_' + filename, 'wb') as file: for i in array.chunks(str(array), 8): int_value = int(i, base=2) bin_array = struct.pack('B', int_value) file.write(bin_array) if self.verbose: import os os.system('diff {} {}'.format(filename, 'decoded_' + filename)) def __str__(self): """Format the output preatty.""" out = "Symbol Weight\tHuffman Code\n" for p in self.table: out += '\r{}'.format([p[0]]).ljust(13) out += '{}\t'.format(self.symb2freq[p[0]]).rjust(5) out += '{}\n'.format(p[1]).ljust(20) return out
class LempelZiv(object): """docstring for LempelZiv""" def __init__(self, filename, verbose=True, table=[]): super(LempelZiv, self).__init__() self.filename = filename self.verbose = verbose self.bitarray = Bitset() self.bitarray.verbose = self.verbose self.bitarray.name = self.filename + '.lzv' self.table = table if self.filename: with open(self.filename, 'rb') as file: self.bitarray.fromfile(file) self.data = self.bitarray.to01() else: self.data = _options.text def encode(self): position = 0 offset = 1 output = '' self.table = list(set(self.data)) self.table.sort() while position + offset <= len(self.data): print('\r{:0.2f} '.format( 100 * (position + offset) / len(self.data)), end='') buff = self.data[position:position + offset] if not buff in self.table: self.table.append(buff) output += str(self.table.index( self.data[position:position + offset - 1])) position += offset - 1 offset = 1 else: offset += 1 output += str(self.table.index( self.data[position:position + offset])) print(self.table) with open(self.filename + '.table', "w") as f: json.dump(self.table, f) self.bitarray.push(output) self.bitarray.to_file() self.data = output return output def decode(self): table_file = self.filename.split('.')[:-1] table_file = '.'.join(table_file) + '.table' with open(table_file) as json_file: self.dict_table = json.load(json_file) with open(table_file.replace('.table', '.lzv'), 'rb') as file: self.bitarray.fromfile(file) self.bitarray = self.bitarray.to01() def __str__(self): return self.data