Start adding HEIF support
This commit is contained in:
parent
50e5482740
commit
2887be614c
|
@ -718,6 +718,12 @@ APPLICATION_KRITA = 55
|
|||
IMAGE_SVG = 56
|
||||
APPLICATION_XCF = 57
|
||||
APPLICATION_GZIP = 58
|
||||
IMAGE_HEIF = 59
|
||||
IMAGE_HEIF_SEQUENCE = 60
|
||||
IMAGE_HEIC = 61
|
||||
IMAGE_HEIC_SEQUENCE = 62
|
||||
IMAGE_AVIF = 63
|
||||
IMAGE_AVIF_SEQUENCE = 64
|
||||
APPLICATION_OCTET_STREAM = 100
|
||||
APPLICATION_UNKNOWN = 101
|
||||
|
||||
|
@ -738,6 +744,12 @@ SEARCHABLE_MIMES = {
|
|||
IMAGE_TIFF,
|
||||
IMAGE_ICON,
|
||||
IMAGE_SVG,
|
||||
IMAGE_HEIF,
|
||||
IMAGE_HEIF_SEQUENCE,
|
||||
IMAGE_HEIC,
|
||||
IMAGE_HEIC_SEQUENCE,
|
||||
IMAGE_AVIF,
|
||||
IMAGE_AVIF_SEQUENCE,
|
||||
APPLICATION_FLASH,
|
||||
VIDEO_AVI,
|
||||
VIDEO_FLV,
|
||||
|
@ -787,12 +799,18 @@ IMAGES = {
|
|||
IMAGE_BMP,
|
||||
IMAGE_WEBP,
|
||||
IMAGE_TIFF,
|
||||
IMAGE_ICON
|
||||
IMAGE_ICON,
|
||||
IMAGE_HEIF,
|
||||
IMAGE_HEIC,
|
||||
IMAGE_AVIF,
|
||||
}
|
||||
|
||||
ANIMATIONS = {
|
||||
IMAGE_GIF,
|
||||
IMAGE_APNG
|
||||
IMAGE_APNG,
|
||||
IMAGE_HEIF_SEQUENCE,
|
||||
IMAGE_HEIC_SEQUENCE,
|
||||
IMAGE_AVIF_SEQUENCE,
|
||||
}
|
||||
|
||||
AUDIO = {
|
||||
|
@ -853,7 +871,13 @@ for ( general_mime_type, mimes_in_type ) in general_mimetypes_to_mime_groups.ite
|
|||
|
||||
mimes_to_general_mimetypes[ mime ] = general_mime_type
|
||||
|
||||
|
||||
PIL_HEIF_MIMES = {
|
||||
IMAGE_HEIF,
|
||||
IMAGE_HEIF_SEQUENCE,
|
||||
IMAGE_HEIC,
|
||||
IMAGE_HEIC_SEQUENCE,
|
||||
IMAGE_AVIF,
|
||||
}
|
||||
|
||||
MIMES_THAT_DEFINITELY_HAVE_AUDIO = tuple( [ APPLICATION_FLASH ] + list( AUDIO ) )
|
||||
MIMES_THAT_MAY_HAVE_AUDIO = tuple( list( MIMES_THAT_DEFINITELY_HAVE_AUDIO ) + list( VIDEO ) )
|
||||
|
@ -862,11 +886,11 @@ ARCHIVES = { APPLICATION_ZIP, APPLICATION_HYDRUS_ENCRYPTED_ZIP, APPLICATION_RAR,
|
|||
|
||||
MIMES_WITH_THUMBNAILS = set( IMAGES ).union( ANIMATIONS ).union( VIDEO ).union( { IMAGE_SVG, APPLICATION_FLASH, APPLICATION_CLIP, APPLICATION_PSD, APPLICATION_KRITA } )
|
||||
|
||||
FILES_THAT_CAN_HAVE_ICC_PROFILE = { IMAGE_JPEG, IMAGE_PNG, IMAGE_GIF, IMAGE_TIFF }
|
||||
FILES_THAT_CAN_HAVE_ICC_PROFILE = { IMAGE_JPEG, IMAGE_PNG, IMAGE_GIF, IMAGE_TIFF }.union( PIL_HEIF_MIMES )
|
||||
|
||||
FILES_THAT_CAN_HAVE_EXIF = { IMAGE_JPEG, IMAGE_TIFF, IMAGE_PNG, IMAGE_WEBP }
|
||||
FILES_THAT_CAN_HAVE_EXIF = { IMAGE_JPEG, IMAGE_TIFF, IMAGE_PNG, IMAGE_WEBP }.union( PIL_HEIF_MIMES )
|
||||
# images and animations that PIL can handle
|
||||
FILES_THAT_CAN_HAVE_HUMAN_READABLE_EMBEDDED_METADATA = { IMAGE_JPEG, IMAGE_PNG, IMAGE_BMP, IMAGE_WEBP, IMAGE_TIFF, IMAGE_ICON, IMAGE_GIF, IMAGE_APNG }
|
||||
FILES_THAT_CAN_HAVE_HUMAN_READABLE_EMBEDDED_METADATA = { IMAGE_JPEG, IMAGE_PNG, IMAGE_BMP, IMAGE_WEBP, IMAGE_TIFF, IMAGE_ICON, IMAGE_GIF, IMAGE_APNG }.union( PIL_HEIF_MIMES )
|
||||
|
||||
FILES_THAT_CAN_HAVE_PIXEL_HASH = set( IMAGES ).union( { IMAGE_GIF } )
|
||||
FILES_THAT_HAVE_PERCEPTUAL_HASH = set( IMAGES )
|
||||
|
@ -887,6 +911,12 @@ mime_enum_lookup = {
|
|||
'image/tiff' : IMAGE_TIFF,
|
||||
'image/x-icon' : IMAGE_ICON,
|
||||
'image/svg+xml': IMAGE_SVG,
|
||||
'image/heif' : IMAGE_HEIF,
|
||||
'image/heif-sequence' : IMAGE_HEIF_SEQUENCE,
|
||||
'image/heic' : IMAGE_HEIC,
|
||||
'image/heic-sequence' : IMAGE_HEIC_SEQUENCE,
|
||||
'image/avif' : IMAGE_AVIF,
|
||||
'image/avif-sequence' : IMAGE_AVIF_SEQUENCE,
|
||||
'image/vnd.microsoft.icon' : IMAGE_ICON,
|
||||
'image' : IMAGES,
|
||||
'application/x-shockwave-flash' : APPLICATION_FLASH,
|
||||
|
@ -950,6 +980,12 @@ mime_string_lookup = {
|
|||
IMAGE_TIFF : 'tiff',
|
||||
IMAGE_ICON : 'icon',
|
||||
IMAGE_SVG : 'svg',
|
||||
IMAGE_HEIF: 'heif',
|
||||
IMAGE_HEIF_SEQUENCE: 'heif sequence',
|
||||
IMAGE_HEIC: 'heic',
|
||||
IMAGE_HEIC_SEQUENCE: 'heic sequence',
|
||||
IMAGE_AVIF: 'avif',
|
||||
IMAGE_AVIF_SEQUENCE: 'avif sequence',
|
||||
APPLICATION_FLASH : 'flash',
|
||||
APPLICATION_OCTET_STREAM : 'application/octet-stream',
|
||||
APPLICATION_YAML : 'yaml',
|
||||
|
@ -1014,6 +1050,12 @@ mime_mimetype_string_lookup = {
|
|||
IMAGE_TIFF : 'image/tiff',
|
||||
IMAGE_ICON : 'image/x-icon',
|
||||
IMAGE_SVG : 'image/svg+xml',
|
||||
IMAGE_HEIF: 'image/heif',
|
||||
IMAGE_HEIF_SEQUENCE: 'image/heif-sequence',
|
||||
IMAGE_HEIC: 'image/heic',
|
||||
IMAGE_HEIC_SEQUENCE: 'image/heic-sequence',
|
||||
IMAGE_AVIF: 'image/avif',
|
||||
IMAGE_AVIF_SEQUENCE: 'image/avif-sequence',
|
||||
APPLICATION_FLASH : 'application/x-shockwave-flash',
|
||||
APPLICATION_OCTET_STREAM : 'application/octet-stream',
|
||||
APPLICATION_YAML : 'application/x-yaml',
|
||||
|
@ -1079,6 +1121,12 @@ mime_ext_lookup = {
|
|||
IMAGE_TIFF : '.tiff',
|
||||
IMAGE_ICON : '.ico',
|
||||
IMAGE_SVG : '.svg',
|
||||
IMAGE_HEIF: 'heif',
|
||||
IMAGE_HEIF_SEQUENCE: 'heifs',
|
||||
IMAGE_HEIC: 'heic',
|
||||
IMAGE_HEIC_SEQUENCE: 'heics',
|
||||
IMAGE_AVIF: 'avif',
|
||||
IMAGE_AVIF_SEQUENCE: 'avifs',
|
||||
APPLICATION_FLASH : '.swf',
|
||||
APPLICATION_OCTET_STREAM : '.bin',
|
||||
APPLICATION_YAML : '.yaml',
|
||||
|
|
|
@ -79,6 +79,21 @@ headers_and_mime.extend( [
|
|||
( ( ( 0, b'\x52\x61\x72\x21\x1A\x07\x01\x00' ), ), HC.APPLICATION_RAR ),
|
||||
( ( ( 0, b'\x1f\x8b' ), ), HC.APPLICATION_GZIP ),
|
||||
( ( ( 0, b'hydrus encrypted zip' ), ), HC.APPLICATION_HYDRUS_ENCRYPTED_ZIP ),
|
||||
( ( ( 4, b'ftypavif' ), ), HC.IMAGE_AVIF ),
|
||||
( ( ( 4, b'ftypavis' ), ), HC.IMAGE_AVIF_SEQUENCE ),
|
||||
( ( ( 4, b'ftypmif1' ), ( 16, b'avif' ), ), HC.IMAGE_AVIF ),
|
||||
( ( ( 4, b'ftypmif1' ), ( 20, b'avif' ), ), HC.IMAGE_AVIF ),
|
||||
( ( ( 4, b'ftypmif1' ), ( 24, b'avif' ), ), HC.IMAGE_AVIF ),
|
||||
( ( ( 4, b'ftypheic' ), ), HC.IMAGE_HEIC ),
|
||||
( ( ( 4, b'ftypheix' ), ), HC.IMAGE_HEIC ),
|
||||
( ( ( 4, b'ftypheim' ), ), HC.IMAGE_HEIC ),
|
||||
( ( ( 4, b'ftypheis' ), ), HC.IMAGE_HEIC ),
|
||||
( ( ( 4, b'ftyphevc' ), ), HC.IMAGE_HEIC_SEQUENCE ),
|
||||
( ( ( 4, b'ftyphevx' ), ), HC.IMAGE_HEIC_SEQUENCE ),
|
||||
( ( ( 4, b'ftyphevm' ), ), HC.IMAGE_HEIC_SEQUENCE ),
|
||||
( ( ( 4, b'ftyphevs' ), ), HC.IMAGE_HEIC_SEQUENCE ),
|
||||
( ( ( 4, b'ftypmif1' ), ), HC.IMAGE_HEIF ),
|
||||
( ( ( 4, b'ftypsf1' ), ), HC.IMAGE_HEIF_SEQUENCE ),
|
||||
( ( ( 4, b'ftypmp4' ), ), HC.UNDETERMINED_MP4 ),
|
||||
( ( ( 4, b'ftypisom' ), ), HC.UNDETERMINED_MP4 ),
|
||||
( ( ( 4, b'ftypM4V' ), ), HC.UNDETERMINED_MP4 ),
|
||||
|
@ -102,7 +117,7 @@ def GenerateThumbnailBytes( path, target_resolution, mime, duration, num_frames,
|
|||
target_resolution = ( 128, 128 )
|
||||
|
||||
|
||||
if mime in ( HC.IMAGE_JPEG, HC.IMAGE_PNG, HC.IMAGE_GIF, HC.IMAGE_WEBP, HC.IMAGE_TIFF, HC.IMAGE_ICON ): # not apng atm
|
||||
if mime in { HC.IMAGE_JPEG, HC.IMAGE_PNG, HC.IMAGE_GIF, HC.IMAGE_WEBP, HC.IMAGE_TIFF, HC.IMAGE_ICON }.union( HC.PIL_HEIF_MIMES ): # not apng atm
|
||||
|
||||
try:
|
||||
|
||||
|
@ -353,7 +368,7 @@ def GetFileInfo( path, mime = None, ok_to_look_for_hydrus_updates = False ):
|
|||
has_audio = False
|
||||
|
||||
|
||||
if mime in ( HC.IMAGE_JPEG, HC.IMAGE_PNG, HC.IMAGE_GIF, HC.IMAGE_WEBP, HC.IMAGE_TIFF, HC.IMAGE_ICON ):
|
||||
if mime in { HC.IMAGE_JPEG, HC.IMAGE_PNG, HC.IMAGE_GIF, HC.IMAGE_WEBP, HC.IMAGE_TIFF, HC.IMAGE_ICON }.union( HC.PIL_HEIF_MIMES ):
|
||||
|
||||
( ( width, height ), duration, num_frames ) = HydrusImageHandling.GetImageProperties( path, mime )
|
||||
|
||||
|
|
|
@ -26,6 +26,12 @@ from PIL import ImageFile as PILImageFile
|
|||
from PIL import Image as PILImage
|
||||
from PIL import ImageCms as PILImageCms
|
||||
|
||||
from pillow_heif import register_heif_opener
|
||||
from pillow_heif import register_avif_opener
|
||||
|
||||
register_heif_opener(thumbnails=False)
|
||||
register_avif_opener(thumbnails=False)
|
||||
|
||||
from hydrus.core import HydrusConstants as HC
|
||||
from hydrus.core import HydrusData
|
||||
from hydrus.core import HydrusExceptions
|
||||
|
@ -79,7 +85,7 @@ warnings.simplefilter( 'ignore', PILImage.DecompressionBombError )
|
|||
OLD_PIL_MAX_IMAGE_PIXELS = PILImage.MAX_IMAGE_PIXELS
|
||||
PILImage.MAX_IMAGE_PIXELS = None # this turns off decomp check entirely, wew
|
||||
|
||||
PIL_ONLY_MIMETYPES = { HC.IMAGE_GIF, HC.IMAGE_ICON }
|
||||
PIL_ONLY_MIMETYPES = { HC.IMAGE_GIF, HC.IMAGE_ICON }.union( HC.PIL_HEIF_MIMES )
|
||||
|
||||
try:
|
||||
|
||||
|
@ -817,8 +823,8 @@ def GetResolutionNumPy( numpy_image ):
|
|||
|
||||
def GetResolutionAndNumFramesPIL( path, mime ):
|
||||
|
||||
pil_image = GeneratePILImage( path, dequantize = False )
|
||||
|
||||
pil_image = GeneratePILImage( path, dequantize = False )
|
||||
|
||||
( x, y ) = pil_image.size
|
||||
|
||||
if mime == HC.IMAGE_GIF: # some jpegs came up with 2 frames and 'duration' because of some embedded thumbnail in the metadata
|
||||
|
@ -1222,6 +1228,8 @@ def RawOpenPILImage( path ) -> PILImage.Image:
|
|||
pil_image = PILImage.open( path )
|
||||
|
||||
except Exception as e:
|
||||
|
||||
print(e)
|
||||
|
||||
raise HydrusExceptions.DamagedOrUnusualFileException( 'Could not load the image--it was likely malformed!' )
|
||||
|
||||
|
|
Loading…
Reference in New Issue