async def test_should_be_ok_but_150x150(self): response = await self.async_fetch("/unsafe/200x200/grayscale.jpg") engine = Engine(self.context) engine.load(response.body, ".jpg") expect(response.code).to_equal(200) expect(response.headers["Content-Type"]).to_equal("image/jpeg") expect(engine.size).to_equal((150, 150))
def test_load_image_with_metadata(self): engine = Engine(self.context) with open(join(STORAGE_PATH, "Christophe_Henner_-_June_2016.jpg"), "rb") as image_file: buffer = image_file.read() engine.load(buffer, None) image = engine.image expect(image.format).to_equal("JPEG") expect(engine.metadata).Not.to_be_null() expect(engine.metadata.__class__.__name__).to_equal("ImageMetadata") # read the xmp tags xmp_keys = engine.metadata.xmp_keys expect(len(xmp_keys)).to_equal(44) expect("Xmp.aux.LensSerialNumber" in xmp_keys).to_be_true() width = engine.metadata["Xmp.aux.LensSerialNumber"].value expect(width).to_equal("0000c139be") # read EXIF tags exif_keys = engine.metadata.exif_keys expect(len(exif_keys)).to_equal(37) expect("Exif.Image.Software" in exif_keys).to_be_true() expect(engine.metadata["Exif.Image.Software"].value).to_equal( "Adobe Photoshop Lightroom 4.4 (Macintosh)") # read IPTC tags iptc_keys = engine.metadata.iptc_keys expect(len(iptc_keys)).to_equal(6) expect("Iptc.Application2.DateCreated" in iptc_keys).to_be_true() expect( engine.metadata["Iptc.Application2.DateCreated"].value).to_equal( [datetime.date(2016, 6, 23)])
def test_load_image_with_metadata(self): engine = Engine(self.context) with open(join(STORAGE_PATH, 'BlueSquare.jpg'), 'r') as im: buffer = im.read() engine.load(buffer, None) image = engine.image expect(image.format).to_equal('JPEG') expect(engine.metadata).Not.to_be_null() expect(engine.metadata.__class__.__name__).to_equal('ImageMetadata') # read the xmp tags xmp_keys = engine.metadata.xmp_keys expect(len(xmp_keys)).to_equal(27) expect('Xmp.tiff.ImageWidth' in xmp_keys).to_be_true() width = engine.metadata[b'Xmp.tiff.ImageWidth'].value expect(width).to_equal(360) # read EXIF tags exif_keys = engine.metadata.exif_keys expect(len(exif_keys)).to_equal(17) expect('Exif.Image.Orientation' in exif_keys).to_be_true() expect(engine.metadata[b'Exif.Image.Orientation'].value).to_equal(1) # read IPTC tags iptc_keys = engine.metadata.iptc_keys expect(len(iptc_keys)).to_equal(4) expect('Iptc.Application2.Keywords' in iptc_keys).to_be_true() expect(engine.metadata[b'Iptc.Application2.Keywords'].value).to_equal( ['XMP', 'Blue Square', 'test file', 'Photoshop', '.jpg'] )
def test_should_be_ok_when_orientation_exif(self): response = self.fetch( '/unsafe/10_years_of_Wikipedia_by_Guillaume_Paumier.jpg') expect(response.code).to_equal(200) engine = Engine(self.context) engine.load(response.body, '.jpg') expect(engine.size).to_equal((4052, 3456))
def test_should_be_ok_but_150x150(self): response = self.fetch('/unsafe/200x200/grayscale.jpg') engine = Engine(self.context) engine.load(response.body, '.jpg') expect(response.code).to_equal(200) expect(response.headers['Content-Type']).to_equal('image/jpeg') expect(engine.size).to_equal((150, 150))
def test_load_image_with_metadata(self): engine = Engine(self.context) with open(join(STORAGE_PATH, 'Christophe_Henner_-_June_2016.jpg'), 'r') as im: buffer = im.read() engine.load(buffer, None) image = engine.image expect(image.format).to_equal('JPEG') expect(engine.metadata).Not.to_be_null() expect(engine.metadata.__class__.__name__).to_equal('ImageMetadata') # read the xmp tags xmp_keys = engine.metadata.xmp_keys expect(len(xmp_keys)).to_equal(44) expect('Xmp.aux.LensSerialNumber' in xmp_keys).to_be_true() width = engine.metadata[b'Xmp.aux.LensSerialNumber'].value expect(width).to_equal('0000c139be') # read EXIF tags exif_keys = engine.metadata.exif_keys expect(len(exif_keys)).to_equal(37) expect('Exif.Image.Software' in exif_keys).to_be_true() expect(engine.metadata[b'Exif.Image.Software'].value).to_equal('Adobe Photoshop Lightroom 4.4 (Macintosh)') # read IPTC tags iptc_keys = engine.metadata.iptc_keys expect(len(iptc_keys)).to_equal(6) expect('Iptc.Application2.DateCreated' in iptc_keys).to_be_true() expect(engine.metadata[b'Iptc.Application2.DateCreated'].value).to_equal( [datetime.date(2016, 6, 23)] )
def test_not_imported_cv2_failed_to_convert_tif_to_png(self, mockLogError): engine = Engine(self.context) with open(join(STORAGE_PATH, 'gradient_8bit.tif'), 'r') as im: buffer = im.read() returned_buffer = engine.convert_tif_to_png(buffer) expect(mockLogError.called).to_be_true() expect(buffer).to_equal(returned_buffer)
def test_convert_tif_16bit_per_channel_lsb_to_png(self): engine = Engine(self.context) with open(join(STORAGE_PATH, 'gradient_lsb_16bperchannel.tif'), 'r') as im: buffer = im.read() expect(buffer).not_to_equal(None) engine.convert_tif_to_png(buffer) expect(engine.extension).to_equal('.png')
def test_should_be_ok_but_150x150(self): response = self.fetch("/unsafe/200x200/wellsford.jpg") engine = Engine(self.context) engine.load(response.body, ".jpg") expect(response.code).to_equal(200) expect(response.headers["Content-Type"]).to_equal("image/jpeg") expect(engine.size).to_equal((150, 150))
async def test_can_read_image_svg_with_px_units_and_convert_png(self): response = await self.async_fetch("/unsafe/Commons-logo.svg") expect(response.code).to_equal(200) expect(response.body).to_be_png() engine = Engine(self.context) engine.load(response.body, ".png") expect(engine.size).to_equal((1024, 1376))
def test_can_read_image_svg_with_px_units_and_convert_png(self): response = self.fetch('/unsafe/escudo.svg') expect(response.code).to_equal(200) expect(response.body).to_be_png() engine = Engine(self.context) engine.load(response.body, '.png') expect(engine.size).to_equal((1080, 1080))
def test_can_read_image_svg_with_inch_units_and_convert_png(self): response = self.fetch('/unsafe/Commons-logo-inches.svg') expect(response.code).to_equal(200) expect(response.body).to_be_png() engine = Engine(self.context) engine.load(response.body, '.png') expect(engine.size).to_equal((2000, 2600))
async def test_should_return_original_image_size_with_normalize(self): response = await self.async_fetch( "/unsafe/filters:format(jpeg)/weird_normalize_error.jpg") engine = Engine(self.context) engine.load(response.body, ".jpg") expect(response.code).to_equal(200) expect(response.headers["Content-Type"]).to_equal("image/jpeg") expect(engine.size).to_equal((159, 239))
async def test_should_return_original_image_size(self): response = await self.async_fetch( "/unsafe/filters:format(jpeg)/very-small-jpeg.jpg") engine = Engine(self.context) engine.load(response.body, ".jpg") expect(response.code).to_equal(200) expect(response.headers["Content-Type"]).to_equal("image/jpeg") expect(engine.size).to_equal((100, 100))
def test_load_tif_8bit_per_channel(self): engine = Engine(self.context) with open(join(STORAGE_PATH, 'gradient_8bit.tif'), 'r') as im: buffer = im.read() expect(buffer).not_to_equal(None) engine.load(buffer, None) final_bytes = BytesIO(engine.read()) im = Image.open(final_bytes) expect(im.format).to_equal('PNG') expect(im.size).to_equal((100, 100))
def test_load_tif_8bit_per_channel(self): engine = Engine(self.context) with open(join(STORAGE_PATH, "gradient_8bit.tif"), "rb") as image_file: buffer = image_file.read() expect(buffer).not_to_equal(None) engine.load(buffer, None) final_bytes = BytesIO(engine.read()) image_file = Image.open(final_bytes) expect(image_file.format).to_equal("PNG") expect(image_file.size).to_equal((100, 100))
def test_load_tif_8bit_per_channel(self): engine = Engine(self.context) with open(join(STORAGE_PATH, 'gradient_8bit.tif'), 'rb') as im: buffer = im.read() expect(buffer).not_to_equal(None) engine.load(buffer, None) final_bytes = BytesIO(engine.read()) im = Image.open(final_bytes) expect(im.format).to_equal('PNG') expect(im.size).to_equal((100, 100))
def test_compare_image_data_and_mode(engine): pil_engine = PileEngine(get_context()) with open(join(STORAGE_PATH, "1bit.png"), "rb") as image_file: buffer = image_file.read() assert buffer is not None engine.load(buffer, ".png") pil_engine.load(buffer, ".png") pil_mode, pil_data = pil_engine.image_data_as_rgb() mode, data = engine.image_data_as_rgb() assert mode == pil_mode assert len(data) == len(pil_data) assert data[:100] == pil_data[:100] assert data[-100:] == pil_data[-100:]
class GetImageWithAutoWebP(BaseContext): def get_app(self): cfg = Config(SECURITY_KEY='ACME-SEC') cfg.LOADER = "thumbor.loaders.file_loader" cfg.FILE_LOADER_ROOT_PATH = storage_path cfg.AUTO_WEBP = True importer = Importer(cfg) importer.import_modules() server = ServerParameters(8889, 'localhost', 'thumbor.conf', None, 'info', None) server.security_key = 'ACME-SEC' ctx = Context(server, cfg, importer) application = ThumborServiceApp(ctx) self.engine = PILEngine(ctx) return application def topic(self): response = self.get('/unsafe/image.jpg', headers={"Accept": 'image/webp,*/*;q=0.8'}) return (response.code, response.body) def should_be_webp(self, response): code, image_buffer = response expect(code).to_equal(200) image = self.engine.create_image(image_buffer) expect(image.format.lower()).to_equal('webp')
def image_fixture(http_path, image_filename): this_dir = os.path.abspath(os.path.dirname(__file__)) fixtures_dir = os.path.join(this_dir, 'test_fixtures') if not os.path.exists(fixtures_dir): os.mkdir(fixtures_dir) image_path = os.path.join(fixtures_dir, image_filename) if not os.path.exists(image_path): urlretrieve(http_path + image_filename, image_path) context = mock.Mock(request=mock.Mock(focal_points=[])) engine = PilEngine(context) context.modules.engine = engine with open(image_path) as f: engine.load(f.read(), None) return context
class GetImageWithAutoWebP(BaseContext): def get_app(self): cfg = Config(SECURITY_KEY='ACME-SEC') cfg.LOADER = "thumbor.loaders.file_loader" cfg.FILE_LOADER_ROOT_PATH = storage_path cfg.AUTO_WEBP = True importer = Importer(cfg) importer.import_modules() server = ServerParameters(8889, 'localhost', 'thumbor.conf', None, 'info', None) server.security_key = 'ACME-SEC' ctx = Context(server, cfg, importer) application = ThumborServiceApp(ctx) self.engine = PILEngine(ctx) return application def topic(self): return self.get('/unsafe/image.jpg', headers={ "Accept": 'image/webp,*/*;q=0.8' }) def should_be_webp(self, response): expect(response.code).to_equal(200) expect(response.headers).to_include('Vary') expect(response.headers['Vary']).to_include('Accept') image = self.engine.create_image(response.body) expect(image.format.lower()).to_equal('webp')
def test_should_preserve_png_transparency(self): engine = Engine(self.context) with open(join(STORAGE_PATH, "paletted-transparent.png"), "rb") as image_file: buffer = image_file.read() engine.load(buffer, "png") expect(engine.original_mode).to_equal("P") engine.resize(200, 150) img = Image.open(BytesIO(engine.read(".png"))) expect(img.mode).to_equal("P") expect(img.format.lower()).to_equal("png") transparent_pixels_count = sum( img.convert("RGBA").split()[3] # Get alpha channel .point( lambda x: 0 if x else 1) # return 1 if pixel is transparent, 0 otherwise .getdata()) # Image has total of 200x150=30000 pixels. Most of them should be transparent expect(transparent_pixels_count).to_be_greater_than(19000)
def test_resize_truncated_image(self): engine = Engine(self.context) with open(join(STORAGE_PATH, 'BlueSquare_truncated.jpg'), 'r') as im: buffer = im.read() engine.load(buffer, '.jpg') engine.resize(10, 10) mode, _ = engine.image_data_as_rgb() expect(mode).to_equal('RGB')
def test_convert_should_preserve_palette_mode(self): engine = Engine(self.context) with open(join(STORAGE_PATH, '256_color_palette.png'), 'r') as im: buffer = im.read() engine.load(buffer, '.png') engine.resize(10, 10) mode, _ = engine.image_data_as_rgb() expect(mode).to_equal('P')
def test_convert_png_1bit_to_png(self): engine = Engine(self.context) with open(join(STORAGE_PATH, '1bit.png'), 'r') as im: buffer = im.read() engine.load(buffer, '.png') engine.resize(10, 10) mode, _ = engine.image_data_as_rgb() expect(mode).to_equal('RGBA')
def test_resize_truncated_image(self): engine = Engine(self.context) with open(join(STORAGE_PATH, "BlueSquare_truncated.jpg"), "rb") as image_file: buffer = image_file.read() engine.load(buffer, ".jpg") engine.resize(10, 10) mode, _ = engine.image_data_as_rgb() expect(mode).to_equal("RGB")
def test_can_set_resampling_filter(self): to_test = { "LANCZOS": Image.LANCZOS, "NEAREST": Image.NEAREST, "BiLinear": Image.BILINEAR, "bicubic": Image.BICUBIC, "garbage": Image.LANCZOS, } if hasattr(Image, "HAMMING"): to_test["HAMMING"] = Image.HAMMING for setting, expected in to_test.items(): cfg = Config(PILLOW_RESAMPLING_FILTER=setting) engine = Engine(Context(config=cfg)) expect(engine.get_resize_filter()).to_equal(expected) cfg = Config() engine = Engine(Context(config=cfg)) expect(engine.get_resize_filter()).to_equal(Image.LANCZOS)
def test_convert_png_1bit_to_png(self): engine = Engine(self.context) with open(join(STORAGE_PATH, '1bit.png'), 'r') as im: buffer = im.read() engine.load(buffer, '.png') engine.resize(10, 10) mode, _ = engine.image_data_as_rgb() expect(mode).to_equal( 'P' ) # Note that this is not a true 1bit image, it's 8bit in black/white.
def test_convert_should_preserve_palette_mode(self): engine = Engine(self.context) with open(join(STORAGE_PATH, "256_color_palette.png"), "rb") as image_file: buffer = image_file.read() engine.load(buffer, ".png") expect(engine.original_mode).to_equal("P") engine.resize(10, 10) mode, _ = engine.image_data_as_rgb() expect(mode).to_equal("RGB") final_bytes = BytesIO(engine.read()) mode = Image.open(final_bytes).mode expect(mode).to_equal("P")
def test_convert_png_1bit_to_png(self): engine = Engine(self.context) with open(join(STORAGE_PATH, '1bit.png'), 'r') as im: buffer = im.read() engine.load(buffer, '.png') engine.resize(10, 10) mode, _ = engine.image_data_as_rgb() expect(mode).to_equal('P') # Note that this is not a true 1bit image, it's 8bit in black/white.
def test_convert_png_1bit_to_png(self): engine = Engine(self.context) with open(join(STORAGE_PATH, "1bit.png"), "rb") as image_file: buffer = image_file.read() engine.load(buffer, ".png") expect(engine.original_mode).to_equal( "P" ) # Note that this is not a true 1bit image, it's 8bit in black/white. engine.resize(10, 10) mode, _ = engine.image_data_as_rgb() expect(mode).to_equal("RGB") final_bytes = BytesIO(engine.read()) mode = Image.open(final_bytes).mode expect(mode).to_equal("P")
def get_app(self): cfg = Config(SECURITY_KEY='ACME-SEC') cfg.LOADER = "thumbor.loaders.file_loader" cfg.FILE_LOADER_ROOT_PATH = storage_path cfg.AUTO_WEBP = True importer = Importer(cfg) importer.import_modules() server = ServerParameters(8889, 'localhost', 'thumbor.conf', None, 'info', None) server.security_key = 'ACME-SEC' ctx = Context(server, cfg, importer) application = ThumborServiceApp(ctx) self.engine = PILEngine(ctx) return application
def test_can_set_resampling_filter(self): to_test = { 'LANCZOS': Image.LANCZOS, 'NEAREST': Image.NEAREST, 'BiLinear': Image.BILINEAR, 'bicubic': Image.BICUBIC, 'garbage': Image.LANCZOS, } if hasattr(Image, 'HAMMING'): to_test['HAMMING'] = Image.HAMMING for setting, expected in to_test.items(): cfg = Config(PILLOW_RESAMPLING_FILTER=setting) engine = Engine(Context(config=cfg)) expect(engine.get_resize_filter()).to_equal(expected) cfg = Config() engine = Engine(Context(config=cfg)) expect(engine.get_resize_filter()).to_equal(Image.LANCZOS)
def test_should_preserve_png_transparency(self): engine = Engine(self.context) with open(join(STORAGE_PATH, 'paletted-transparent.png'), 'r') as im: buffer = im.read() engine.load(buffer, 'png') expect(engine.original_mode).to_equal('P') engine.resize(200, 150) img = Image.open(BytesIO(engine.read('.png'))) expect(img.mode).to_equal('P') expect(img.format.lower()).to_equal('png') transparent_pixels_count = sum(img.convert('RGBA') .split()[3] # Get alpha channel .point(lambda x: 0 if x else 1) # return 1 if pixel is transparent, 0 otherwise .getdata()) # Image has total of 200x150=30000 pixels. Most of them should be transparent expect(transparent_pixels_count).to_be_greater_than(19000)
def test_should_be_ok_without_orientation_exif(self): response = self.fetch('/unsafe/20x20.jpg') expect(response.code).to_equal(200) engine = Engine(self.context) engine.load(response.body, '.jpg') expect(engine.size).to_equal((20, 20))
def test_should_be_ok_when_orientation_exif(self): response = self.fetch('/unsafe/10_years_of_Wikipedia_by_Guillaume_Paumier.jpg') expect(response.code).to_equal(200) engine = Engine(self.context) engine.load(response.body, '.jpg') expect(engine.size).to_equal((4052, 3456))
def test_should_be_ok_when_orientation_exif(self): response = self.fetch('/unsafe/Landscape_8.jpg') expect(response.code).to_equal(200) engine = Engine(self.context) engine.load(response.body, '.jpg') expect(engine.size).to_equal((600, 450))
def test_load_image(self): engine = Engine(self.context) with open(join(STORAGE_PATH, 'image.jpg'), 'r') as im: buffer = im.read() image = engine.create_image(buffer) expect(image.format).to_equal('JPEG')
def test_convert_tif_8bit_per_channel_to_png(self): engine = Engine(self.context) with open(join(STORAGE_PATH, "gradient_8bit.tif"), "r") as im: buffer = im.read() engine.convert_tif_to_png(buffer) expect(engine.extension).to_equal(".png")