Beispiel #1
0
    def setUp(self):
        super(TestImage, self).setUp()
        self.bg_color = (135, 90, 123)
        self.fill_color = (0, 160, 157)

        self.base64_1x1_png = b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYGAAAAAEAAH2FzhVAAAAAElFTkSuQmCC'
        self.base64_svg = base64.b64encode(b'<svg></svg>')
        self.base64_1920x1080_jpeg = tools.image_to_base64(
            Image.new('RGB', (1920, 1080)), 'JPEG')

        # Draw a red square in the middle of the image, this will be used to
        # verify crop is working. The border is going to be `self.bg_color` and
        # the middle is going to be `self.fill_color`.

        # horizontal image (border is left/right)
        image = Image.new('RGB', (1920, 1080), color=self.bg_color)
        offset = (image.size[0] - image.size[1]) / 2
        draw = ImageDraw.Draw(image)
        draw.rectangle(xy=[(offset, 0),
                           (image.size[0] - offset, image.size[1])],
                       fill=self.fill_color)
        self.base64_1920x1080_png = tools.image_to_base64(image, 'PNG')

        # vertical image (border is top/bottom)
        image = Image.new('RGB', (1080, 1920), color=self.bg_color)
        offset = (image.size[1] - image.size[0]) / 2
        draw = ImageDraw.Draw(image)
        draw.rectangle(xy=[(0, offset),
                           (image.size[0], image.size[1] - offset)],
                       fill=self.fill_color)
        self.base64_1080x1920_png = tools.image_to_base64(image, 'PNG')
Beispiel #2
0
    def setUp(self):
        super(TestImage, self).setUp()
        self.bg_color = (135, 90, 123)
        self.fill_color = (0, 160, 157)

        self.base64_1x1_png = b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYGAAAAAEAAH2FzhVAAAAAElFTkSuQmCC'
        self.base64_svg = base64.b64encode(b'<svg></svg>')
        self.base64_1920x1080_jpeg = tools.image_to_base64(Image.new('RGB', (1920, 1080)), 'JPEG')

        # Draw a red square in the middle of the image, this will be used to
        # verify crop is working. The border is going to be `self.bg_color` and
        # the middle is going to be `self.fill_color`.

        # horizontal image (border is left/right)
        image = Image.new('RGB', (1920, 1080), color=self.bg_color)
        offset = (image.size[0] - image.size[1]) / 2
        draw = ImageDraw.Draw(image)
        draw.rectangle(xy=[
            (offset, 0),
            (image.size[0] - offset, image.size[1])
        ], fill=self.fill_color)
        self.base64_1920x1080_png = tools.image_to_base64(image, 'PNG')

        # vertical image (border is top/bottom)
        image = Image.new('RGB', (1080, 1920), color=self.bg_color)
        offset = (image.size[1] - image.size[0]) / 2
        draw = ImageDraw.Draw(image)
        draw.rectangle(xy=[
            (0, offset),
            (image.size[0], image.size[1] - offset)
        ], fill=self.fill_color)
        self.base64_1080x1920_png = tools.image_to_base64(image, 'PNG')
Beispiel #3
0
    def test_16_image_process_format(self):
        """Test the format parameter of image_process."""

        image = tools.base64_to_image(
            tools.image_process(self.base64_1920x1080_jpeg,
                                output_format='PNG'))
        self.assertEqual(image.format, 'PNG', "change format to PNG")

        image = tools.base64_to_image(
            tools.image_process(self.base64_1x1_png, output_format='JpEg'))
        self.assertEqual(image.format, 'JPEG',
                         "change format to JPEG (case insensitive)")

        image = tools.base64_to_image(
            tools.image_process(self.base64_1920x1080_jpeg,
                                output_format='BMP'))
        self.assertEqual(image.format, 'PNG',
                         "change format to BMP converted to PNG")

        self.base64_image_1080_1920_rgba = tools.image_to_base64(
            Image.new('RGBA', (108, 192)), 'PNG')
        image = tools.base64_to_image(
            tools.image_process(self.base64_image_1080_1920_rgba,
                                output_format='jpeg'))
        self.assertEqual(image.format, 'JPEG',
                         "change format PNG with RGBA to JPEG")

        # pass quality to force the image to be processed
        self.base64_image_1080_1920_tiff = tools.image_to_base64(
            Image.new('RGB', (108, 192)), 'TIFF')
        image = tools.base64_to_image(
            tools.image_process(self.base64_image_1080_1920_tiff, quality=95))
        self.assertEqual(image.format, 'JPEG', "unsupported format to JPEG")
    def setUp(self):
        super(TestImage, self).setUp()
        self.bg_color = (135, 90, 123)
        self.fill_color = (0, 160, 157)

        self.base64_1x1_png = b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGNgYGAAAAAEAAH2FzhVAAAAAElFTkSuQmCC'
        self.base64_svg = base64.b64encode(b'<svg></svg>')
        self.base64_1920x1080_jpeg = tools.image_to_base64(
            Image.new('RGB', (1920, 1080)), 'JPEG')
        # The following image contains a tag `Lens Info` with a value of `3.99mm f/1.8`
        # This particular tag 0xa432 makes the `exif_transpose` method fail in 5.4.1 < Pillow < 7.2.0
        self.base64_exif_jpg = b"""/9j/4AAQSkZJRgABAQAAAQABAAD/4QDQRXhpZgAATU0AKgAAAAgABgESAAMAAAABAAYAAAEaAAUA
                                  AAABAAAAVgEbAAUAAAABAAAAXgEoAAMAAAABAAEAAAITAAMAAAABAAEAAIdpAAQAAAABAAAAZgAA
                                  AAAAAAABAAAAAQAAAAEAAAABAAWQAAAHAAAABDAyMzGRAQAHAAAABAECAwCgAAAHAAAABDAxMDCg
                                  AQADAAAAAf//AACkMgAFAAAABAAAAKgAAAAAAAABjwAAAGQAAAGPAAAAZAAAAAkAAAAFAAAACQAA
                                  AAX/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx
                                  NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy
                                  MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAADAAYDASIAAhEBAxEB/8QAHwAAAQUBAQEB
                                  AQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1Fh
                                  ByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZ
                                  WmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG
                                  x8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAEC
                                  AwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHB
                                  CSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0
                                  dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX
                                  2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigD//2Q=="""

        # Draw a red square in the middle of the image, this will be used to
        # verify crop is working. The border is going to be `self.bg_color` and
        # the middle is going to be `self.fill_color`.

        # horizontal image (border is left/right)
        image = Image.new('RGB', (1920, 1080), color=self.bg_color)
        offset = (image.size[0] - image.size[1]) / 2
        draw = ImageDraw.Draw(image)
        draw.rectangle(xy=[(offset, 0),
                           (image.size[0] - offset, image.size[1])],
                       fill=self.fill_color)
        self.base64_1920x1080_png = tools.image_to_base64(image, 'PNG')

        # vertical image (border is top/bottom)
        image = Image.new('RGB', (1080, 1920), color=self.bg_color)
        offset = (image.size[1] - image.size[0]) / 2
        draw = ImageDraw.Draw(image)
        draw.rectangle(xy=[(0, offset),
                           (image.size[0], image.size[1] - offset)],
                       fill=self.fill_color)
        self.base64_1080x1920_png = tools.image_to_base64(image, 'PNG')
Beispiel #5
0
 def test_12_image_process_verify_resolution(self):
     """Test the verify_resolution parameter of image_process."""
     res = tools.image_process(self.base64_1920x1080_jpeg, verify_resolution=True)
     self.assertNotEqual(res, False, "size ok")
     base64_image_excessive = tools.image_to_base64(Image.new('RGB', (45001, 1000)), 'PNG')
     with self.assertRaises(ValueError, msg="size excessive"):
         tools.image_process(base64_image_excessive, verify_resolution=True)
Beispiel #6
0
 def test_12_image_process_verify_resolution(self):
     """Test the verify_resolution parameter of image_process."""
     res = tools.image_process(self.base64_1920x1080_jpeg,
                               verify_resolution=True)
     self.assertNotEqual(res, False, "size ok")
     base64_image_excessive = tools.image_to_base64(
         Image.new('RGB', (45001, 1000)), 'PNG')
     with self.assertRaises(ValueError, msg="size excessive"):
         tools.image_process(base64_image_excessive, verify_resolution=True)
Beispiel #7
0
    def test_16_image_process_format(self):
        """Test the format parameter of image_process."""

        image = tools.base64_to_image(tools.image_process(self.base64_1920x1080_jpeg, output_format='PNG'))
        self.assertEqual(image.format, 'PNG', "change format to PNG")

        image = tools.base64_to_image(tools.image_process(self.base64_1x1_png, output_format='JpEg'))
        self.assertEqual(image.format, 'JPEG', "change format to JPEG (case insensitive)")

        image = tools.base64_to_image(tools.image_process(self.base64_1920x1080_jpeg, output_format='BMP'))
        self.assertEqual(image.format, 'PNG', "change format to BMP converted to PNG")

        self.base64_image_1080_1920_rgba = tools.image_to_base64(Image.new('RGBA', (108, 192)), 'PNG')
        image = tools.base64_to_image(tools.image_process(self.base64_image_1080_1920_rgba, output_format='jpeg'))
        self.assertEqual(image.format, 'JPEG', "change format PNG with RGBA to JPEG")

        self.base64_image_1080_1920_tiff = tools.image_to_base64(Image.new('RGB', (108, 192)), 'TIFF')
        image = tools.base64_to_image(tools.image_process(self.base64_image_1080_1920_tiff))
        self.assertEqual(image.format, 'JPEG', "unsupported format to JPEG")
Beispiel #8
0
    def test_13_image_process_quality(self):
        """Test the quality parameter of image_process."""

        # CASE: PNG RGBA doesn't apply quality, just optimize
        image = tools.image_to_base64(Image.new('RGBA', (1080, 1920)), 'PNG')
        res = tools.image_process(image)
        self.assertLessEqual(len(res), len(image))

        # CASE: PNG RGB doesn't apply quality, just optimize
        image = tools.image_to_base64(Image.new('P', (1080, 1920)), 'PNG')
        res = tools.image_process(image)
        self.assertLessEqual(len(res), len(image))

        # CASE: JPEG optimize + reduced quality
        res = tools.image_process(self.base64_1920x1080_jpeg)
        self.assertLessEqual(len(res), len(self.base64_1920x1080_jpeg))

        # CASE: GIF doesn't apply quality, just optimize
        image = tools.image_to_base64(Image.new('RGB', (1080, 1920)), 'GIF')
        res = tools.image_process(image)
        self.assertLessEqual(len(res), len(image))
Beispiel #9
0
    def test_13_image_process_quality(self):
        """Test the quality parameter of image_process."""

        # CASE: PNG RGBA doesn't apply quality, just optimize
        image = tools.image_to_base64(Image.new('RGBA', (1080, 1920)), 'PNG')
        res = tools.image_process(image)
        self.assertLessEqual(len(res), len(image))

        # CASE: PNG RGB doesn't apply quality, just optimize
        image = tools.image_to_base64(Image.new('P', (1080, 1920)), 'PNG')
        res = tools.image_process(image)
        self.assertLessEqual(len(res), len(image))

        # CASE: JPEG optimize + reduced quality
        res = tools.image_process(self.base64_1920x1080_jpeg)
        self.assertLessEqual(len(res), len(self.base64_1920x1080_jpeg))

        # CASE: GIF doesn't apply quality, just optimize
        image = tools.image_to_base64(Image.new('RGB', (1080, 1920)), 'GIF')
        res = tools.image_process(image)
        self.assertLessEqual(len(res), len(image))
Beispiel #10
0
 def test_parse_company_colors_grayscale(self):
     """Grayscale images with transparency - make sure the color extraction does not crash"""
     self.company.write({
         'primary_color': '#ff0080',
         'secondary_color': '#00ff00',
         'logo': self.company_imgs['overwatch']['img'],
         'paperformat_id': self.env.ref('base.paperformat_us').id,
     })
     with Form(self.env['base.document.layout']) as doc_layout:
         with Image.open(os.path.join(dir_path, 'logo_ci.png'), 'r') as img:
             base64_img = image_to_base64(img, 'PNG')
             doc_layout.logo = base64_img
         self.assertNotEqual(None, doc_layout.primary_color)
Beispiel #11
0
    def test_15_image_process_colorize(self):
        """Test the colorize parameter of image_process."""

        # verify initial condition
        image_rgba = Image.new('RGBA', (1, 1))
        self.assertEqual(image_rgba.mode, 'RGBA')
        self.assertEqual(image_rgba.getpixel((0, 0)), (0, 0, 0, 0))
        base64_rgba = tools.image_to_base64(image_rgba, 'PNG')

        # CASE: color random, color has changed
        image = tools.base64_to_image(tools.image_process(base64_rgba, colorize=True))
        self.assertEqual(image.mode, 'P')
        self.assertNotEqual(image.getpixel((0, 0)), (0, 0, 0))
Beispiel #12
0
    def test_15_image_process_colorize(self):
        """Test the colorize parameter of image_process."""

        # verify initial condition
        image_rgba = Image.new('RGBA', (1, 1))
        self.assertEqual(image_rgba.mode, 'RGBA')
        self.assertEqual(image_rgba.getpixel((0, 0)), (0, 0, 0, 0))
        base64_rgba = tools.image_to_base64(image_rgba, 'PNG')

        # CASE: color random, color has changed
        image = tools.base64_to_image(
            tools.image_process(base64_rgba, colorize=True))
        self.assertEqual(image.mode, 'RGB')
        self.assertNotEqual(image.getpixel((0, 0)), (0, 0, 0))
Beispiel #13
0
 def test_parse_company_colors_grayscale(self):
     """Grayscale images with transparency"""
     self.company.write({
         'primary_color':
         '#ff0080',
         'secondary_color':
         '#00ff00',
         'paperformat_id':
         self.env.ref('base.paperformat_us').id,
     })
     with Form(self.env['base.document.layout']) as doc_layout:
         with Image.open(os.path.join(dir_path, 'logo_ci.png'), 'r') as img:
             base64_img = image_to_base64(img, 'PNG')
             doc_layout.logo = base64_img
         self.assertEqual('#8d8d8d', doc_layout.primary_color)
Beispiel #14
0
 def _set_images(self):
     for fname in self._get_images_for_test():
         fname_split = fname.split('.')
         if not fname_split[0] in _file_cache:
             with Image.open(os.path.join(dir_path, fname), 'r') as img:
                 base64_img = image_to_base64(img, 'JPEG')
                 primary, secondary = self.env['base.document.layout'].create(
                     {})._parse_logo_colors(base64_img)
                 _img = frozendict({
                     'img': base64_img,
                     'colors': {
                         'primary_color': primary,
                         'secondary_color': secondary,
                     },
                 })
                 _file_cache[fname_split[0]] = _img
     self.company_imgs = frozendict(_file_cache)
 def _get_exif_colored_square_b64(self, orientation, colors, size):
     image = Image.new('RGB', (size, size), color=self.bg_color)
     draw = ImageDraw.Draw(image)
     # Paint the colors on the 4 corners, to be able to test which colors
     # move on which corners.
     draw.rectangle(xy=[(0, 0), (size // 2, size // 2)],
                    fill=colors[0])  # top/left
     draw.rectangle(xy=[(size // 2, 0), (size, size // 2)],
                    fill=colors[1])  # top/right
     draw.rectangle(xy=[(0, size // 2), (size // 2, size)],
                    fill=colors[2])  # bottom/left
     draw.rectangle(xy=[(size // 2, size // 2), (size, size)],
                    fill=colors[3])  # bottom/right
     # Set the proper exif tag based on orientation params.
     exif = b'Exif\x00\x00II*\x00\x08\x00\x00\x00\x01\x00\x12\x01\x03\x00\x01\x00\x00\x00' + bytes(
         [orientation]) + b'\x00\x00\x00\x00\x00\x00\x00'
     # The image image is saved with the exif tag.
     return tools.image_to_base64(image, 'JPEG', exif=exif)
Beispiel #16
0
def image2jpg(env, content):
    if not content:
        return False
    if isinstance(content, str):
        content = content.encode('ascii')

    config_size = env['ir.config_parameter'].sudo().get_param(
        'acrux_image_resize', 500)
    if config_size == 'original':
        size = (0, 0)
    else:
        size = (min(int(config_size), 1024), min(int(config_size), 1024))
    try:
        ret = image_process(content,
                            size=size,
                            quality=80,
                            output_format='JPEG')
    except IOError as _e:
        image_stream = io.BytesIO(codecs.decode(content, 'base64'))
        image = Image.open(image_stream)
        if image.mode == 'P':
            if 'transparency' in image.info:
                alpha = image.convert('RGBA').split()[-1]
                bg = Image.new("RGBA", image.size, (255, 255, 255, 255))
                bg.paste(image, mask=alpha)
            image = image.convert('RGB')
        opt = {'format': 'JPEG', 'optimize': True, 'quality': 80}
        # stream = io.BytesIO()
        # image.save(stream, **opt)

        to_base64 = image_to_base64(image, **opt)
        ret = image_process(to_base64,
                            size=size,
                            quality=80,
                            output_format='JPEG')
    except Exception as _e:
        ret = False
        _logger.error('Could not convert image to JPG.')

    return ret
Beispiel #17
0
    def test_01_website_favicon(self):
        """The goal of this test is to make sure the favicon is correctly
        handled on the website."""

        # Test setting an Ico file directly, done through create
        Website = self.env['website']

        website = Website.create({
            'name': 'Test Website',
            'favicon': Website._default_favicon(),
        })

        image = base64_to_image(website.favicon)
        self.assertEqual(image.format, 'ICO')

        # Test setting a JPEG file that is too big, done through write
        bg_color = (135, 90, 123)
        image = Image.new('RGB', (1920, 1080), color=bg_color)
        website.favicon = image_to_base64(image, 'JPEG')
        image = base64_to_image(website.favicon)
        self.assertEqual(image.format, 'ICO')
        self.assertEqual(image.size, (256, 256))
        self.assertEqual(image.getpixel((0, 0)), bg_color)
Beispiel #18
0
    def test_10_image_autoresize(self):
        Attachment = self.env['ir.attachment']
        img_bin = io.BytesIO()
        dir_path = os.path.dirname(os.path.realpath(__file__))
        with Image.open(os.path.join(dir_path, 'odoo.jpg'), 'r') as logo:
            img = Image.new('RGB', (4000, 2000), '#4169E1')
            img.paste(logo)
            img.save(img_bin, 'JPEG')

        img_encoded = image_to_base64(img, 'JPEG')
        img_bin = img_bin.getvalue()

        fullsize = 124.99

        ####################################
        ### test create/write on 'datas'
        ####################################
        attach = Attachment.with_context(image_no_postprocess=True).create({
            'name':
            'image',
            'datas':
            img_encoded,
        })
        self.assertApproximately(attach.datas,
                                 fullsize)  # no resize, no compression

        attach = attach.with_context(image_no_postprocess=False)
        attach.datas = img_encoded
        self.assertApproximately(attach.datas,
                                 12.06)  # default resize + default compression

        # resize + default quality (80)
        self.env['ir.config_parameter'].set_param(
            'base.image_autoresize_max_px', '1024x768')
        attach.datas = img_encoded
        self.assertApproximately(attach.datas, 3.71)

        # resize + quality 50
        self.env['ir.config_parameter'].set_param(
            'base.image_autoresize_quality', '50')
        attach.datas = img_encoded
        self.assertApproximately(attach.datas, 3.57)

        # no resize + no quality implicit
        self.env['ir.config_parameter'].set_param(
            'base.image_autoresize_max_px', '0')
        attach.datas = img_encoded
        self.assertApproximately(attach.datas, fullsize)

        # Check that we only compress quality when we resize. We avoid to compress again during a new write.
        # no resize + quality -> should have no effect
        self.env['ir.config_parameter'].set_param(
            'base.image_autoresize_max_px', '10000x10000')
        self.env['ir.config_parameter'].set_param(
            'base.image_autoresize_quality', '50')
        attach.datas = img_encoded
        self.assertApproximately(attach.datas, fullsize)

        ####################################
        ### test create/write on 'raw'
        ####################################

        # reset default ~ delete
        self.env['ir.config_parameter'].search([
            ('key', 'ilike', 'base.image_autoresize%')
        ]).unlink()

        attach = Attachment.with_context(image_no_postprocess=True).create({
            'name':
            'image',
            'raw':
            img_bin,
        })
        self.assertApproximately(attach.raw,
                                 fullsize)  # no resize, no compression

        attach = attach.with_context(image_no_postprocess=False)
        attach.raw = img_bin
        self.assertApproximately(attach.raw,
                                 12.06)  # default resize + default compression

        # resize + default quality (80)
        self.env['ir.config_parameter'].set_param(
            'base.image_autoresize_max_px', '1024x768')
        attach.raw = img_bin
        self.assertApproximately(attach.raw, 3.71)

        # resize + no quality
        self.env['ir.config_parameter'].set_param(
            'base.image_autoresize_quality', '0')
        attach.raw = img_bin
        self.assertApproximately(attach.raw, 4.09)

        # resize + quality 50
        self.env['ir.config_parameter'].set_param(
            'base.image_autoresize_quality', '50')
        attach.raw = img_bin
        self.assertApproximately(attach.raw, 3.57)

        # no resize + no quality implicit
        self.env['ir.config_parameter'].set_param(
            'base.image_autoresize_max_px', '0')
        attach.raw = img_bin
        self.assertApproximately(attach.raw, fullsize)
Beispiel #19
0
 def test_01_image_to_base64(self):
     """Test that a PIL image is correctly saved as base64."""
     image = Image.new('RGB', (1, 1))
     image_base64 = tools.image_to_base64(image, 'PNG')
     self.assertEqual(image_base64, self.base64_1x1_png)
Beispiel #20
0
 def test_01_image_to_base64(self):
     """Test that a PIL image is correctly saved as base64."""
     image = Image.new('RGB', (1, 1))
     image_base64 = tools.image_to_base64(image, 'PNG')
     self.assertEqual(image_base64, self.base64_1x1_png)