diff --git a/hydrus/core/HydrusConstants.py b/hydrus/core/HydrusConstants.py index 80329c46..d40ac979 100644 --- a/hydrus/core/HydrusConstants.py +++ b/hydrus/core/HydrusConstants.py @@ -761,7 +761,7 @@ MIMES_THAT_MAY_HAVE_AUDIO = tuple( list( MIMES_THAT_DEFINITELY_HAVE_AUDIO ) + li ARCHIVES = { APPLICATION_ZIP, APPLICATION_HYDRUS_ENCRYPTED_ZIP, APPLICATION_RAR, APPLICATION_7Z } -MIMES_WITH_THUMBNAILS = set( IMAGES ).union( ANIMATIONS ).union( VIDEO ).union( { APPLICATION_FLASH, APPLICATION_CLIP, APPLICATION_PSD } ) +MIMES_WITH_THUMBNAILS = set( IMAGES ).union( ANIMATIONS ).union( VIDEO ).union( { APPLICATION_FLASH, APPLICATION_CLIP, APPLICATION_PSD, APPLICATION_KRITA } ) FILES_THAT_CAN_HAVE_ICC_PROFILE = { IMAGE_JPEG, IMAGE_PNG, IMAGE_GIF, IMAGE_TIFF } diff --git a/hydrus/core/HydrusFileHandling.py b/hydrus/core/HydrusFileHandling.py index 42b077eb..4e722428 100644 --- a/hydrus/core/HydrusFileHandling.py +++ b/hydrus/core/HydrusFileHandling.py @@ -4,6 +4,7 @@ import struct from hydrus.core import HydrusAudioHandling from hydrus.core import HydrusClipHandling +from hydrus.core import HydrusKritaHandling from hydrus.core import HydrusConstants as HC from hydrus.core import HydrusData from hydrus.core import HydrusDocumentHandling @@ -154,7 +155,28 @@ def GenerateThumbnailBytes( path, target_resolution, mime, duration, num_frames, HydrusTemp.CleanUpTempPath( os_file_handle, temp_path ) + + elif mime == HC.APPLICATION_KRITA: + ( os_file_handle, temp_path ) = HydrusTemp.GetTempPath() + + try: + + HydrusKritaHandling.ExtractZippedImageToPath( path, temp_path ) + + thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( temp_path, target_resolution, HC.IMAGE_PNG, clip_rect = clip_rect ) + + except Exception as e: + + thumb_path = os.path.join( HC.STATIC_DIR, 'krita.png' ) + + thumbnail_bytes = HydrusImageHandling.GenerateThumbnailBytesFromStaticImagePath( thumb_path, target_resolution, HC.IMAGE_PNG, clip_rect = clip_rect ) + + finally: + + HydrusTemp.CleanUpTempPath( os_file_handle, temp_path ) + + elif mime == HC.APPLICATION_FLASH: ( os_file_handle, temp_path ) = HydrusTemp.GetTempPath() @@ -316,6 +338,10 @@ def GetFileInfo( path, mime = None, ok_to_look_for_hydrus_updates = False ): ( ( width, height ), duration, num_frames ) = HydrusClipHandling.GetClipProperties( path ) + elif mime == HC.APPLICATION_KRITA: + + ( width, height ) = HydrusKritaHandling.GetKraProperties( path ) + elif mime == HC.APPLICATION_FLASH: ( ( width, height ), duration, num_frames ) = HydrusFlashHandling.GetFlashProperties( path ) diff --git a/hydrus/core/HydrusKritaHandling.py b/hydrus/core/HydrusKritaHandling.py new file mode 100644 index 00000000..94def9e0 --- /dev/null +++ b/hydrus/core/HydrusKritaHandling.py @@ -0,0 +1,93 @@ + +from hydrus.core import HydrusExceptions +from hydrus.core import HydrusTemp + +import zipfile +import re + +KRITA_FILE_THUMB = "preview.png" +KRITA_FILE_MERGED = "mergedimage.png" + + +def ExtractSingleFileFromZip( path_to_zip, filename_to_extract, extract_into_file_path ): + + with zipfile.ZipFile( path_to_zip ) as zip_handle: + + with zip_handle.open( filename_to_extract ) as reader: + + with open( extract_into_file_path, "wb" ) as writer: + + writer.write( reader.read() ) + + +def ExtractZippedImageToPath( path_to_zip, temp_path_file ): + + try: + + ExtractSingleFileFromZip( path_to_zip, KRITA_FILE_MERGED, temp_path_file ) + + return + + except KeyError: + + pass + + + try: + + ExtractSingleFileFromZip( path_to_zip, KRITA_FILE_THUMB, temp_path_file ) + + except KeyError: + + raise HydrusExceptions.DamagedOrUnusualFileException( f'This krita file had no {KRITA_FILE_MERGED} or {KRITA_FILE_THUMB}, so no PNG thumb could be extracted!' ) + + +# TODO: animation and frame stuff which is also in the maindoc.xml +def GetKraProperties( path ): + + ( os_file_handle, maindoc_xml ) = HydrusTemp.GetTempPath() + + DOCUMENT_INFO_FILE = "maindoc.xml" + + # TODO: probably actually parse the xml instead of using regex + FIND_KEY_VALUE = re.compile(r"([a-z\-\_]+)\s*=\s*['\"]([^'\"]+)", re.IGNORECASE) + + width = None + height = None + + try: + + ExtractSingleFileFromZip( path, DOCUMENT_INFO_FILE, maindoc_xml ) + + with open(maindoc_xml, "r") as reader: + + for line in reader: + + for match in FIND_KEY_VALUE.findall( line ): + + key, value = match + + if key == "width" and value.isdigit(): + + width = int(value) + + if key == "height" and value.isdigit(): + + height = int(value) + + if width is not None and height is not None: + + break + + except KeyError: + + raise HydrusExceptions.DamagedOrUnusualFileException( f'This krita file had no {DOCUMENT_INFO_FILE}, so no information could be extracted!' ) + + finally: + + HydrusTemp.CleanUpTempPath( os_file_handle, maindoc_xml ) + + return width, height + + +