misc: autoconvert HEIC files (#88586) #1308

Merged
fpeters merged 1 commits from wip/88586-heic-auto-convert into main 2024-03-29 08:33:10 +01:00
3 changed files with 55 additions and 6 deletions

View File

@ -592,3 +592,23 @@ def test_file_download_url_on_wrong_field(pub):
resp = resp.form.submit('submit').follow() # -> submit
formdata = formdef.data_class().select()[0]
app.get(formdata.get_url() + 'files/1/', status=404)
def test_file_auto_convert_heic(pub):
FormDef.wipe()
formdef = FormDef()
formdef.name = 'test'
formdef.fields = [fields.FileField(id='0', label='field label')]
formdef.store()
formdef.data_class().wipe()
with open(os.path.join(os.path.dirname(__file__), '..', 'image.heic'), 'rb') as fd:
upload = Upload('image.heic', fd.read(), 'image/heic')
resp = get_app(pub).get('/test/')
resp.forms[0]['f0$file'] = upload
resp = resp.forms[0].submit('submit') # -> validation
resp = resp.forms[0].submit('submit') # -> submit
resp = resp.follow()
assert resp.click('image.jpeg').follow().content_type == 'image/jpeg'
assert b'JFIF' in resp.click('image.jpeg').follow().body

BIN
tests/image.heic Normal file

Binary file not shown.

View File

@ -29,6 +29,7 @@ import mimetypes
import os
import random
import re
import subprocess
import sys
import tempfile
import time
@ -1047,12 +1048,6 @@ class FileWithPreviewWidget(CompositeWidget):
self.value.content_type = filetype
if self.max_file_size and hasattr(self.value, 'file_size'):
Review

Je déplace la vérification de la taille après la possible transformation du fichier.

Je déplace la vérification de la taille après la possible transformation du fichier.
# validate file size
if self.value.file_size > self.max_file_size_bytes:
self.set_error(_('over file size limit (%s)') % self.max_file_size)
return
if self.file_type:
# validate file type
accepted_file_types = []
@ -1098,6 +1093,40 @@ class FileWithPreviewWidget(CompositeWidget):
) or filetype in blacklisted_file_types:
self.set_error(_('forbidden file type'))
if self.value.content_type in ('image/heic', 'image/heif') and not get_publisher().has_site_option(
'do-no-transform-heic-files'
Review

Je ne pense pas que ça serve mais au cas où quelqu'un demanderait à un moment de laisser les HEIC passer le flag est déjà là.

Je ne pense pas que ça serve mais au cas où quelqu'un demanderait à un moment de laisser les HEIC passer le flag est déjà là.
):
# convert HEIC files to JPEG
try:
with open(self.value.fp.name, 'rb') as fd:
# libheic will automatically switch image orientation so we need to remove
# EXIF profile to avoid it being applied a second time.
# (graphicsmagick >= 1.3.41 have heif:ignore-transformations=false to avoid
# that).
Review

Il y a 1.3.40 dans bookworm donc on doit faire avec.

Il y a 1.3.40 dans bookworm donc on doit faire avec.
rc = subprocess.run(
['gm', 'convert', '+profile', '"*"', 'HEIC:-', 'JPEG:-'],
input=fd.read(),
capture_output=True,
check=True,
)
from wcs.fields.file import FileField
self.value = FileField.convert_value_from_anything(
{
'content': rc.stdout,
'filename': os.path.splitext(self.value.base_filename)[0] + '.jpeg',
'content_type': 'image/jpeg',
}
)
except subprocess.CalledProcessError:
pass
if self.max_file_size and hasattr(self.value, 'file_size'):
# validate file size
if self.value.file_size > self.max_file_size_bytes:
self.set_error(_('over file size limit (%s)') % self.max_file_size)
tnoel marked this conversation as resolved
Review

Ici on pourrait se retrouver avec une conversion qui a fait grossir le fichier, et l'utilisateur averti ne comprendrait pas le pépin. Il s'agirait de dire qu'il y a eu conversion parce que le format HEIC n'est pas pris en charge nativement... Genre,

if convert_from_heic:
  self.set_error(_('over file size limit (%s) (after JPEG conversion , HEIC is not supported)') % self.max_file_size)

Ceci étant je me dis que l'utilisateur non averti ne va rien comprendre à ce message d'erreur...

Je ne valide donc pas, mais si tu penses que ça va juste embrouiller la plupart des personnes, je n'insisterai pas.

Ici on pourrait se retrouver avec une conversion qui a fait grossir le fichier, et l'utilisateur averti ne comprendrait pas le pépin. Il s'agirait de dire qu'il y a eu conversion parce que le format HEIC n'est pas pris en charge nativement... Genre, if convert_from_heic: self.set_error(_('over file size limit (%s) (after JPEG conversion , HEIC is not supported)') % self.max_file_size) Ceci étant je me dis que l'utilisateur non averti ne va rien comprendre à ce message d'erreur... Je ne valide donc pas, mais si tu penses que ça va juste embrouiller la plupart des personnes, je n'insisterai pas.
Review

Ceci étant je me dis que l'utilisateur non averti ne va rien comprendre à ce message d'erreur...

Oui je pense que c'est compliqué à comprendre et comme en local la conversion jpeg réduisait la taille je ne m'inquièterais pas.

> Ceci étant je me dis que l'utilisateur non averti ne va rien comprendre à ce message d'erreur... Oui je pense que c'est compliqué à comprendre et comme en local la conversion jpeg réduisait la taille je ne m'inquièterais pas.
return
class EmailWidget(StringWidget):
HTML_TYPE = 'email'