def compress(img_path: str, b: int, out_path: str) -> str: """ Compresses an image into a format with bits to represent each channel. Saves the image and returns the path to compressed output image specified by the out_path. Parameters: ---------- img_path: str (file path to a .png image) b: int in [1, 8] out_path: str (file path to the compressed png image) Returns: ------- compressed_img : str (file path to the image with each channel compressed to b bits, same as out_path) Examples: ------- >>> imageCompress.compress("..//image.png", b = 5, "..//compressed_image.png") >>> "..//compressed_image.png" """ if type(img_path) != str: raise TypeError( "Input image path type not correct, make sure you are passing a string!" ) if type(out_path) != str: raise TypeError( "Output path type not correct, make sure you are passing a string!" ) if type(b) != int: raise TypeError("b should be a positive integer <= 8!") if b <= 0: raise ValueError( "b should be a positive integer greater than 0 and less than 9!") if b > 8: raise ValueError("b should be a positive integer <= 8!") min_size_img = compression( img_path, 1, os.path.join((os.path.dirname(os.path.abspath(img_path))), "1.png")) desired_size_img = compression( img_path, b, os.path.join((os.path.dirname(os.path.abspath(img_path))), "2.png")) if image_size(min_size_img) > image_size(img_path): os.remove(min_size_img) os.remove(desired_size_img) raise Exception("The image is already compressed") elif image_size(desired_size_img) > image_size(img_path): os.remove(min_size_img) os.remove(desired_size_img) raise Exception("Choose a smaller b to compress the image.") else: os.remove(min_size_img) os.remove(desired_size_img) return compression(img_path, b, out_path)
def compress(img_path, b, out_path): """ Compresses an image into a format with bits to represent each channel. Parameters: ---------- img_path: str (file path to a .png image) b: int in [1, 8] out_path: str (file path to the compressed png image) Returns: ------- compressed_img : str (file path to the image with each channel compressed to b bits, same as out_path) """ if type(img_path) != str or type(out_path) != str: raise TypeError( "Image path not correct, make sure you are passing a string!") if type(b) != int: raise TypeError("b should be a positive integer <= 8!") if b <= 0 or b > 8: raise ValueError("b should be a positive integer <= 8!") min_size_img = compression( img_path, 1, os.path.join((os.path.dirname(os.path.abspath(img_path))), "1.png")) desired_size_img = compression( img_path, b, os.path.join((os.path.dirname(os.path.abspath(img_path))), "2.png")) if image_size(min_size_img) > image_size(img_path): os.remove(min_size_img) os.remove(desired_size_img) raise Exception("The image is already compressed") elif image_size(desired_size_img) > image_size(img_path): os.remove(min_size_img) os.remove(desired_size_img) raise Exception("Choose a smaller b to compress the image.") else: os.remove(min_size_img) os.remove(desired_size_img) return compression(img_path, b, out_path)
def test_size_type(self): ''' Function to test that a TypeError is raised when invalid type is passed in as image ''' with pytest.raises(TypeError): image_size(imread(img_path)) with pytest.raises(TypeError): image_size(True) with pytest.raises(TypeError): image_size(123) with pytest.raises(TypeError): image_size(12.2)
def test_compress_size(self): ''' Function to test that the size of the compressed image is correct ''' compressed_img = compress(img_path, 3, outpath) assert image_size(compressed_img) < 7 / 8 * image_size(img_path) compressed_img = compress(img_path, 1, outpath) assert image_size(compressed_img) < 5 / 8 * image_size(img_path) compressed_img = compress(img_path, 6, outpath) assert image_size(compressed_img) <= 8 / 8 * image_size(img_path) compressed_img = compress(img_path, 8, outpath) assert image_size(compressed_img) <= image_size(img_path)
def test_size_output(self): ''' Function to test that correct size is returned ''' assert image_size(img_path) <= 1.1 * imread(img_path).nbytes