[FIX] base: do not crash if uploading a grayscale image

Behavior before the fix:

Uploading a grayscale image with transparency in the company logo field
of the document layout causes a crash:

```
  File "/data/build/odoo/addons/web/models/base_document_layout.py", line 89, in _compute_logo_colors
    wizard.logo_primary_color, wizard.logo_secondary_color = wizard_for_image._parse_logo_colors()
  File "/data/build/odoo/addons/web/models/base_document_layout.py", line 191, in _parse_logo_colors
    color[1][2] > white_threshold) and color[1][3] > 0:
Exception

...
IndexError: tuple index out of range
```

To reproduce, use the `logo_ci.png` image included in the unit test
data and load it in the document layout (under General Settings).

The system does not detect that the image does not have color
information and attempts to read the R,G,B values (but the image only
has 2 values per pixel: the grayscale value and the alpha)

Versions affected: 13, 14

Behavior after the fix:

The image is loaded correctly (arguably, there is not a lot of interest
in detecting the primary color of a grayscale image, but the script
still returns a (gray) value which is preferrable to a traceback)

opw-2352394

closes odoo/odoo#59498

X-original-commit: 6d6e48f34f850fa533ce00532ada0e3464c8144b
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Signed-off-by: Nicolas Galler <nicocrm@users.noreply.github.com>
This commit is contained in:
Nicolas Galler
2020-10-08 10:59:54 +00:00
parent 6504ac9e90
commit e6fccbae92
3 changed files with 16 additions and 3 deletions
+2 -3
View File
@@ -179,9 +179,8 @@ class BaseDocumentLayout(models.TransientModel):
w = int(50 * base_w / base_h)
h = 50
# Converts to RGBA if no alpha detected
image_converted = image.convert(
'RGBA') if 'A' not in image.getbands() else image
# Converts to RGBA (if already RGBA, this is a noop)
image_converted = image.convert('RGBA')
image_resized = image_converted.resize((w, h))
colors = []
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

@@ -194,6 +194,20 @@ class TestBaseDocumentLayout(TestBaseDocumentLayoutHelpers):
doc_layout.secondary_color = doc_layout.logo_secondary_color
self.assertColors(doc_layout, self.company_imgs['sweden']['colors'])
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)
# /!\ This case is NOT supported, and probably not supportable
# res.partner resizes manu-militari the image it is given
# so res.company._get_logo differs from res.partner.[default image]