def test_compression_results_in_identical_files(self): with python_utils.open_file( os.path.join( feconf.TESTS_DATA_DIR, 'compressed_image.jpg'), 'rb', encoding=None) as f: correct_compressed_image = f.read() correct_height, correct_width = ( image_services.get_image_dimensions(correct_compressed_image)) compressed_image = ( image_services.compress_image(self.jpeg_raw_image, 0.5)) # In order to make sure the images are the same, the function needs to # open and save the image specifically using PIL since the "golden # image" (image that we compare the compressed image to) is saved using # PIL. This applies a slight quality change that won't appear unless we # save it using PIL. temp_image = Image.open(io.BytesIO(compressed_image)) image_format = temp_image.format with io.BytesIO() as output: temp_image.save(output, format=image_format) compressed_image_content = output.getvalue() height, width = image_services.get_image_dimensions( compressed_image_content) self.assertEqual(correct_height, height) self.assertEqual(correct_width, width) image1 = Image.open(io.BytesIO(correct_compressed_image)).convert('RGB') image2 = Image.open(io.BytesIO(compressed_image_content)).convert('RGB') diff = ImageChops.difference(image1, image2) # Function diff.getbbox() returns a bounding box on all islands or # regions of non-zero pixels. In other words, if we have a bounding # box, there will be areas that are not 0 in the difference meaning # that the 2 images are not equal. self.assertFalse(diff.getbbox())
def test_compress_image_returns_correct_dimensions(self): compressed_image = ( image_services.compress_image(self.jpeg_raw_image, 0.5)) height, width = ( image_services.get_image_dimensions(compressed_image)) self.assertEqual(self.TEST_IMAGE_HEIGHT * 0.5, height) self.assertEqual(self.TEST_IMAGE_WIDTH * 0.5, width)
def test_compress_image_on_prod_mode_with_small_image_size(self): with python_utils.open_file( os.path.join(feconf.TESTS_DATA_DIR, 'img.png'), mode='rb', encoding=None) as f: original_image_content = f.read() with self.swap(constants, 'DEV_MODE', False): fs = fs_domain.AbstractFileSystem( fs_domain.GcsFileSystem( feconf.ENTITY_TYPE_EXPLORATION, self.EXPLORATION_ID)) self.assertFalse(fs.isfile('image/%s' % self.FILENAME)) self.assertFalse( fs.isfile('image/%s' % self.COMPRESSED_IMAGE_FILENAME)) self.assertFalse(fs.isfile('image/%s' % self.MICRO_IMAGE_FILENAME)) fs_services.save_original_and_compressed_versions_of_image( self.FILENAME, 'exploration', self.EXPLORATION_ID, original_image_content, 'image', True) self.assertTrue(fs.isfile('image/%s' % self.FILENAME)) self.assertTrue( fs.isfile('image/%s' % self.COMPRESSED_IMAGE_FILENAME)) self.assertTrue(fs.isfile('image/%s' % self.MICRO_IMAGE_FILENAME)) original_image_content = fs.get( 'image/%s' % self.FILENAME) compressed_image_content = fs.get( 'image/%s' % self.COMPRESSED_IMAGE_FILENAME) micro_image_content = fs.get( 'image/%s' % self.MICRO_IMAGE_FILENAME) self.assertEqual( image_services.get_image_dimensions( original_image_content), (32, 32)) self.assertEqual( image_services.get_image_dimensions( compressed_image_content), (25, 25)) self.assertEqual( image_services.get_image_dimensions( micro_image_content), (22, 22))
def map(model): # pylint: disable=too-many-return-statements if model.deleted: yield ('SUCCESS - DELETED', model.username) return if model.username is None: yield ('SUCCESS - NOT REGISTERED', model.username) return if model.profile_picture_data_url is None: yield ('FAILURE - MISSING PROFILE PICTURE', model.username) return try: profile_picture_binary = utils.convert_png_data_url_to_binary( model.profile_picture_data_url) except Exception: yield ('FAILURE - INVALID PROFILE PICTURE DATA URL', model.username) return if imghdr.what(None, h=profile_picture_binary) != 'png': yield ('FAILURE - PROFILE PICTURE NOT PNG', model.username) return try: # Load the image to retrieve dimensions for later verification. height, width = image_services.get_image_dimensions( profile_picture_binary) except Exception: yield ('FAILURE - CANNOT LOAD PROFILE PICTURE', model.username) return if ( height != user_services.GRAVATAR_SIZE_PX or width != user_services.GRAVATAR_SIZE_PX ): yield ( 'FAILURE - PROFILE PICTURE NON STANDARD DIMENSIONS - %s,%s' % ( height, width ), model.username ) return yield ('SUCCESS', model.username)
def get_filename_with_dimensions(old_filename, exp_id): """Gets the filename with dimensions of the image file in it. Args: old_filename: str. Name of the file whose dimensions need to be calculated. exp_id: str. Exploration id. Returns: str. The new filename of the image file. """ file_system_class = fs_services.get_entity_file_system_class() fs = fs_domain.AbstractFileSystem( file_system_class(feconf.ENTITY_TYPE_EXPLORATION, exp_id)) filepath = 'image/%s' % old_filename try: content = fs.get(filepath.encode('utf-8')) height, width = image_services.get_image_dimensions(content) except IOError: height = 120 width = 120 new_filename = regenerate_image_filename_using_dimensions( old_filename, height, width) return new_filename
def test_image_dimensions_are_output_correctly(self): height, width = (image_services.get_image_dimensions( self.jpeg_raw_image)) self.assertEqual(self.TEST_IMAGE_HEIGHT, height) self.assertEqual(self.TEST_IMAGE_WIDTH, width)