Support AVIF image format

See https://jakearchibald.com/2020/avif-has-landed
merge-requests/8/head
Bob Mottram 2020-09-09 16:09:38 +01:00
parent 717a62d397
commit e12b6483c3
9 changed files with 53 additions and 15 deletions

View File

@ -722,7 +722,7 @@ def htmlEditBlog(mediaInstance: bool, translate: {},
editBlogImageSection += \
' <input type="file" id="attachpic" name="attachpic"'
editBlogImageSection += \
' accept=".png, .jpg, .jpeg, .gif, .webp, ' + \
' accept=".png, .jpg, .jpeg, .gif, .webp, .avif, ' + \
'.mp4, .webm, .ogv, .mp3, .ogg">'
editBlogImageSection += ' </div>'

View File

@ -737,6 +737,7 @@ def saveMediaInFormPOST(mediaBytes, debug: bool,
'jpeg': 'image/jpeg',
'gif': 'image/gif',
'webp': 'image/webp',
'avif': 'image/avif',
'mp4': 'video/mp4',
'ogv': 'video/ogv',
'mp3': 'audio/mpeg',
@ -771,7 +772,7 @@ def saveMediaInFormPOST(mediaBytes, debug: bool,
break
# remove any existing image files with a different format
extensionTypes = ('png', 'jpg', 'jpeg', 'gif', 'webp')
extensionTypes = ('png', 'jpg', 'jpeg', 'gif', 'webp', 'avif')
for ex in extensionTypes:
if ex == detectedExtension:
continue

View File

@ -254,6 +254,7 @@ class PubServer(BaseHTTPRequestHandler):
if path.endswith('.png') or \
path.endswith('.jpg') or \
path.endswith('.gif') or \
path.endswith('.avif') or \
path.endswith('.webp'):
return True
return False
@ -2522,6 +2523,8 @@ class PubServer(BaseHTTPRequestHandler):
mediaFilename = mediaFilenameBase + '.gif'
if self.headers['Content-type'].endswith('webp'):
mediaFilename = mediaFilenameBase + '.webp'
if self.headers['Content-type'].endswith('avif'):
mediaFilename = mediaFilenameBase + '.avif'
with open(mediaFilename, 'wb') as avFile:
avFile.write(mediaBytes)
if debug:
@ -3552,6 +3555,9 @@ class PubServer(BaseHTTPRequestHandler):
if 'image/webp' in self.headers['Accept']:
favType = 'image/webp'
favFilename = 'favicon.webp'
if 'image/avif' in self.headers['Accept']:
favType = 'image/avif'
favFilename = 'favicon.avif'
# custom favicon
faviconFilename = baseDir + '/' + favFilename
if not os.path.isfile(faviconFilename):
@ -3848,6 +3854,8 @@ class PubServer(BaseHTTPRequestHandler):
mediaFileType = 'image/gif'
elif mediaFilename.endswith('.webp'):
mediaFileType = 'image/webp'
elif mediaFilename.endswith('.avif'):
mediaFileType = 'image/avif'
elif mediaFilename.endswith('.mp4'):
mediaFileType = 'video/mp4'
elif mediaFilename.endswith('.ogv'):
@ -3890,6 +3898,8 @@ class PubServer(BaseHTTPRequestHandler):
mediaImageType = 'jpeg'
elif emojiFilename.endswith('.webp'):
mediaImageType = 'webp'
elif emojiFilename.endswith('.avif'):
mediaImageType = 'avif'
else:
mediaImageType = 'gif'
with open(emojiFilename, 'rb') as avFile:
@ -3974,6 +3984,11 @@ class PubServer(BaseHTTPRequestHandler):
'image/webp',
mediaBinary, None,
callingDomain)
elif mediaFilename.endswith('.avif'):
self._set_headers_etag(mediaFilename,
'image/avif',
mediaBinary, None,
callingDomain)
else:
# default to jpeg
self._set_headers_etag(mediaFilename,
@ -6965,7 +6980,7 @@ class PubServer(BaseHTTPRequestHandler):
GETstartTime, GETtimings: {}) -> bool:
"""Show a background image
"""
for ext in ('webp', 'gif', 'jpg', 'png'):
for ext in ('webp', 'gif', 'jpg', 'png', 'avif'):
for bg in ('follow', 'options', 'login'):
# follow screen background image
if path.endswith('/' + bg + '-background.' + ext):
@ -7028,6 +7043,8 @@ class PubServer(BaseHTTPRequestHandler):
mediaFileType = 'jpeg'
elif mediaFilename.endswith('.webp'):
mediaFileType = 'webp'
elif mediaFilename.endswith('.avif'):
mediaFileType = 'avif'
else:
mediaFileType = 'gif'
with open(mediaFilename, 'rb') as avFile:
@ -7075,6 +7092,8 @@ class PubServer(BaseHTTPRequestHandler):
mediaImageType = 'jpeg'
elif avatarFile.endswith('.gif'):
mediaImageType = 'gif'
elif avatarFile.endswith('.avif'):
mediaImageType = 'avif'
else:
mediaImageType = 'webp'
with open(avatarFilename, 'rb') as avFile:
@ -7819,6 +7838,7 @@ class PubServer(BaseHTTPRequestHandler):
if self.path == '/login.png' or \
self.path == '/login.gif' or \
self.path == '/login.webp' or \
self.path == '/login.avif' or \
self.path == '/login.jpeg' or \
self.path == '/login.jpg' or \
self.path == '/qrcode.png':
@ -9005,6 +9025,8 @@ class PubServer(BaseHTTPRequestHandler):
mediaFileType = 'image/gif'
elif checkPath.endswith('.webp'):
mediaFileType = 'image/webp'
elif checkPath.endswith('.avif'):
mediaFileType = 'image/avif'
elif checkPath.endswith('.mp4'):
mediaFileType = 'video/mp4'
elif checkPath.endswith('.ogv'):
@ -9079,6 +9101,7 @@ class PubServer(BaseHTTPRequestHandler):
if filename.endswith('.png') or \
filename.endswith('.jpg') or \
filename.endswith('.webp') or \
filename.endswith('.avif') or \
filename.endswith('.gif'):
if self.server.debug:
print('DEBUG: POST media removing metadata')

View File

@ -32,8 +32,6 @@
--font-size-pgp-key2: 8px;
--font-size-tox: 16px;
--font-size-tox2: 8px;
--text-entry-foreground: #ccc;
--text-entry-background: #111;
--time-color: #aaa;
--time-vertical-align: 4px;
--button-text: #FFFFFF;

View File

@ -56,7 +56,7 @@ def getImageHash(imageFilename: str) -> str:
def isMedia(imageFilename: str) -> bool:
permittedMedia = ('png', 'jpg', 'gif', 'webp',
permittedMedia = ('png', 'jpg', 'gif', 'webp', 'avif',
'mp4', 'ogv', 'mp3', 'ogg')
for m in permittedMedia:
if imageFilename.endswith('.' + m):
@ -84,7 +84,7 @@ def getAttachmentMediaType(filename: str) -> str:
"""
mediaType = None
imageTypes = ('png', 'jpg', 'jpeg',
'gif', 'webp')
'gif', 'webp', 'avif')
for mType in imageTypes:
if filename.endswith('.' + mType):
return 'image'
@ -143,7 +143,7 @@ def attachMedia(baseDir: str, httpPrefix: str, domain: str, port: int,
return postJson
fileExtension = None
acceptedTypes = ('png', 'jpg', 'gif', 'webp',
acceptedTypes = ('png', 'jpg', 'gif', 'webp', 'avif',
'mp4', 'webm', 'ogv', 'mp3', 'ogg')
for mType in acceptedTypes:
if imageFilename.endswith('.' + mType):

View File

@ -122,6 +122,8 @@ def postMessageToOutbox(messageJson: {}, postToNickname: str,
fileExtension = 'gif'
elif mediaTypeStr.endswith('webp'):
fileExtension = 'webp'
elif mediaTypeStr.endswith('avif'):
fileExtension = 'avif'
elif mediaTypeStr.endswith('audio/mpeg'):
fileExtension = 'mp3'
elif mediaTypeStr.endswith('ogg'):

View File

@ -801,7 +801,7 @@ def setThemeImages(baseDir: str, name: str) -> None:
backgroundNames = ('login', 'shares', 'delete', 'follow',
'options', 'block', 'search', 'calendar')
extensions = ('webp', 'gif', 'jpg', 'png')
extensions = ('webp', 'gif', 'jpg', 'png', 'avif')
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for acct in dirs:

View File

@ -51,7 +51,7 @@ def removeAvatarFromCache(baseDir: str, actorStr: str) -> None:
"""Removes any existing avatar entries from the cache
This avoids duplicate entries with differing extensions
"""
avatarFilenameExtensions = ('png', 'jpg', 'gif', 'webp')
avatarFilenameExtensions = ('png', 'jpg', 'gif', 'webp', 'avif')
for extension in avatarFilenameExtensions:
avatarFilename = \
baseDir + '/cache/avatars/' + actorStr + '.' + extension

View File

@ -230,6 +230,11 @@ def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
'Accept': 'image/webp'
}
avatarImageFilename = avatarImagePath + '.webp'
elif avatarUrl.endswith('.avif') or '.avif?' in avatarUrl:
sessionHeaders = {
'Accept': 'image/avif'
}
avatarImageFilename = avatarImagePath + '.avif'
else:
return None
@ -304,7 +309,7 @@ def getPersonAvatarUrl(baseDir: str, personUrl: str, personCache: {},
actorStr = personJson['id'].replace('/', '-')
avatarImagePath = baseDir + '/cache/avatars/' + actorStr
imageExtension = ('png', 'jpg', 'jpeg', 'gif', 'webp')
imageExtension = ('png', 'jpg', 'jpeg', 'gif', 'webp', 'avif')
for ext in imageExtension:
if os.path.isfile(avatarImagePath + '.' + ext):
return '/avatars/' + actorStr + '.' + ext
@ -1064,7 +1069,7 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str,
domain: str, port: int, httpPrefix: str) -> str:
"""Shows the edit profile screen
"""
imageFormats = '.png, .jpg, .jpeg, .gif, .webp'
imageFormats = '.png, .jpg, .jpeg, .gif, .webp, .avif'
pathOriginal = path
path = path.replace('/inbox', '').replace('/outbox', '')
path = path.replace('/shares', '')
@ -1621,6 +1626,9 @@ def htmlLogin(translate: {}, baseDir: str, autocomplete=True) -> str:
elif os.path.isfile(baseDir + '/accounts/login.webp'):
loginImage = 'login.webp'
loginImageFilename = baseDir + '/accounts/' + loginImage
elif os.path.isfile(baseDir + '/accounts/login.avif'):
loginImage = 'login.avif'
loginImageFilename = baseDir + '/accounts/' + loginImage
if not loginImageFilename:
loginImageFilename = baseDir + '/accounts/' + loginImage
@ -1965,13 +1973,13 @@ def htmlNewPost(mediaInstance: bool, translate: {},
newPostImageSection += \
' <input type="file" id="attachpic" name="attachpic"'
newPostImageSection += \
' accept=".png, .jpg, .jpeg, .gif, .webp">\n'
' accept=".png, .jpg, .jpeg, .gif, .webp, .avif">\n'
else:
newPostImageSection += \
' <input type="file" id="attachpic" name="attachpic"'
newPostImageSection += \
' accept=".png, .jpg, .jpeg, .gif, .webp, .mp4, ' + \
'.webm, .ogv, .mp3, .ogg">\n'
' accept=".png, .jpg, .jpeg, .gif, ' + \
'.webp, .avif, .mp4, .webm, .ogv, .mp3, .ogg">\n'
newPostImageSection += ' </div>\n'
scopeIcon = 'scope_public.png'
@ -3623,11 +3631,13 @@ def getPostAttachmentsAsHtml(postJsonObject: {}, boxName: str, translate: {},
if mediaType == 'image/png' or \
mediaType == 'image/jpeg' or \
mediaType == 'image/webp' or \
mediaType == 'image/avif' or \
mediaType == 'image/gif':
if attach['url'].endswith('.png') or \
attach['url'].endswith('.jpg') or \
attach['url'].endswith('.jpeg') or \
attach['url'].endswith('.webp') or \
attach['url'].endswith('.avif') or \
attach['url'].endswith('.gif'):
if attachmentCtr > 0:
attachmentStr += '<br>'
@ -4922,6 +4932,10 @@ def htmlTimeline(defaultTimeline: str,
bannerFile = 'banner.gif'
bannerFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/' + bannerFile
if not os.path.isfile(bannerFilename):
bannerFile = 'banner.avif'
bannerFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/' + bannerFile
if not os.path.isfile(bannerFilename):
bannerFile = 'banner.webp'