hydrus/include/HydrusFileHandling.py

337 lines
9.0 KiB
Python
Raw Normal View History

2015-03-25 22:04:19 +00:00
import gc
2013-08-07 22:25:18 +00:00
import hashlib
import hsaudiotag
import hsaudiotag.auto
import hsaudiotag.flac
import hsaudiotag.mpeg
import hsaudiotag.ogg
2013-07-17 20:56:13 +00:00
import HydrusAudioHandling
import HydrusConstants as HC
import HydrusDocumentHandling
2013-07-24 20:26:00 +00:00
import HydrusExceptions
2013-07-17 20:56:13 +00:00
import HydrusFlashHandling
import HydrusImageHandling
import HydrusVideoHandling
import os
2015-03-25 22:04:19 +00:00
import tempfile
2015-10-21 21:53:10 +00:00
import threading
2013-07-17 20:56:13 +00:00
import traceback
2014-05-21 21:37:35 +00:00
import cStringIO
2015-03-25 22:04:19 +00:00
import subprocess
import HydrusData
2013-07-17 20:56:13 +00:00
# Mime
2015-03-25 22:04:19 +00:00
header_and_mime = [
( 0, '\xff\xd8', HC.IMAGE_JPEG ),
( 0, 'GIF87a', HC.IMAGE_GIF ),
( 0, 'GIF89a', HC.IMAGE_GIF ),
( 0, '\x89PNG', HC.IMAGE_PNG ),
( 0, 'BM', HC.IMAGE_BMP ),
( 0, 'CWS', HC.APPLICATION_FLASH ),
( 0, 'FWS', HC.APPLICATION_FLASH ),
( 0, 'FLV', HC.VIDEO_FLV ),
( 0, '%PDF', HC.APPLICATION_PDF ),
( 0, 'PK\x03\x04', HC.APPLICATION_ZIP ),
( 0, 'hydrus encrypted zip', HC.APPLICATION_HYDRUS_ENCRYPTED_ZIP ),
( 4, 'ftypmp4', HC.VIDEO_MP4 ),
2015-07-01 22:02:07 +00:00
( 4, 'ftypisom', HC.VIDEO_MP4 ),
( 4, 'ftypM4V', HC.VIDEO_MP4 ),
2015-03-25 22:04:19 +00:00
( 0, 'fLaC', HC.AUDIO_FLAC ),
( 0, '\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C', HC.UNDETERMINED_WM )
]
def ConvertAbsPathToPortablePath( abs_path ):
if abs_path == '': return None
try: return os.path.relpath( abs_path, HC.BASE_DIR )
except: return abs_path
2013-07-17 20:56:13 +00:00
2015-03-25 22:04:19 +00:00
def CleanUpTempPath( os_file_handle, temp_path ):
2015-08-12 20:35:24 +00:00
try:
os.close( os_file_handle )
except OSError:
gc.collect()
try:
os.close( os_file_handle )
except OSError:
print( 'Could not close the temporary file ' + temp_path )
return
2015-05-06 20:26:18 +00:00
2015-08-12 20:35:24 +00:00
try:
os.remove( temp_path )
2015-05-06 20:26:18 +00:00
except OSError:
2015-03-25 22:04:19 +00:00
2015-05-06 20:26:18 +00:00
gc.collect()
2015-03-25 22:04:19 +00:00
2015-08-12 20:35:24 +00:00
try:
os.remove( temp_path )
except OSError:
print( 'Could not delete the temporary file ' + temp_path )
2015-03-25 22:04:19 +00:00
def CopyFileLikeToFileLike( f_source, f_dest ):
2015-10-21 21:53:10 +00:00
for block in HydrusData.ReadFileLikeAsBlocks( f_source ): f_dest.write( block )
2015-03-25 22:04:19 +00:00
2014-05-21 21:37:35 +00:00
def GenerateThumbnail( path, dimensions = HC.UNSCALED_THUMBNAIL_DIMENSIONS ):
mime = GetMime( path )
if mime in HC.IMAGES:
pil_image = HydrusImageHandling.GeneratePILImage( path )
HydrusImageHandling.EfficientlyThumbnailPILImage( pil_image, dimensions )
f = cStringIO.StringIO()
if pil_image.mode == 'P' and pil_image.info.has_key( 'transparency' ):
pil_image.save( f, 'PNG', transparency = pil_image.info[ 'transparency' ] )
elif pil_image.mode == 'RGBA': pil_image.save( f, 'PNG' )
else:
pil_image = pil_image.convert( 'RGB' )
pil_image.save( f, 'JPEG', quality=92 )
f.seek( 0 )
thumbnail = f.read()
f.close()
else:
2014-06-25 20:37:06 +00:00
( size, mime, width, height, duration, num_frames, num_words ) = GetFileInfo( path )
2014-05-21 21:37:35 +00:00
2014-06-25 20:37:06 +00:00
cropped_dimensions = HydrusImageHandling.GetThumbnailResolution( ( width, height ), dimensions )
2014-05-21 21:37:35 +00:00
2014-06-25 20:37:06 +00:00
renderer = HydrusVideoHandling.VideoRendererFFMPEG( path, mime, duration, num_frames, cropped_dimensions )
2014-05-21 21:37:35 +00:00
2014-06-25 20:37:06 +00:00
numpy_image = renderer.read_frame()
2014-05-21 21:37:35 +00:00
2014-06-25 20:37:06 +00:00
pil_image = HydrusImageHandling.GeneratePILImageFromNumpyImage( numpy_image )
2014-05-21 21:37:35 +00:00
2014-06-25 20:37:06 +00:00
f = cStringIO.StringIO()
pil_image.save( f, 'JPEG', quality=92 )
f.seek( 0 )
thumbnail = f.read()
2014-05-21 21:37:35 +00:00
2014-06-25 20:37:06 +00:00
f.close()
2014-05-21 21:37:35 +00:00
return thumbnail
2015-03-25 22:04:19 +00:00
def GetExtraHashesFromPath( path ):
h_md5 = hashlib.md5()
h_sha1 = hashlib.sha1()
h_sha512 = hashlib.sha512()
with open( path, 'rb' ) as f:
2015-10-21 21:53:10 +00:00
for block in HydrusData.ReadFileLikeAsBlocks( f ):
2015-03-25 22:04:19 +00:00
h_md5.update( block )
h_sha1.update( block )
h_sha512.update( block )
md5 = h_md5.digest()
sha1 = h_sha1.digest()
sha512 = h_sha512.digest()
return ( md5, sha1, sha512 )
2014-06-25 20:37:06 +00:00
def GetFileInfo( path ):
2013-07-17 20:56:13 +00:00
2013-08-07 22:25:18 +00:00
info = os.lstat( path )
size = info[6]
2013-07-17 20:56:13 +00:00
2013-07-24 20:26:00 +00:00
if size == 0: raise HydrusExceptions.SizeException( 'File is of zero length!' )
2013-07-17 20:56:13 +00:00
2013-08-07 22:25:18 +00:00
mime = GetMime( path )
2013-07-17 20:56:13 +00:00
2013-07-24 20:26:00 +00:00
if mime not in HC.ALLOWED_MIMES: raise HydrusExceptions.MimeException( 'Filetype is not permitted!' )
2013-07-17 20:56:13 +00:00
width = None
height = None
duration = None
num_frames = None
num_words = None
if mime in HC.IMAGES:
2014-05-14 20:46:38 +00:00
( ( width, height ), duration, num_frames ) = HydrusImageHandling.GetImageProperties( path )
2013-07-17 20:56:13 +00:00
elif mime == HC.APPLICATION_FLASH:
2013-08-07 22:25:18 +00:00
( ( width, height ), duration, num_frames ) = HydrusFlashHandling.GetFlashProperties( path )
2013-07-17 20:56:13 +00:00
elif mime == HC.VIDEO_FLV:
2013-08-07 22:25:18 +00:00
( ( width, height ), duration, num_frames ) = HydrusVideoHandling.GetFLVProperties( path )
2014-06-25 20:37:06 +00:00
elif mime in ( HC.VIDEO_WMV, HC.VIDEO_MP4, HC.VIDEO_MKV, HC.VIDEO_WEBM ):
2014-04-30 21:31:40 +00:00
2014-06-25 20:37:06 +00:00
( ( width, height ), duration, num_frames ) = HydrusVideoHandling.GetFFMPEGVideoProperties( path )
2014-04-30 21:31:40 +00:00
2013-08-07 22:25:18 +00:00
elif mime == HC.APPLICATION_PDF: num_words = HydrusDocumentHandling.GetPDFNumWords( path )
elif mime == HC.AUDIO_MP3: duration = HydrusAudioHandling.GetMP3Duration( path )
elif mime == HC.AUDIO_OGG: duration = HydrusAudioHandling.GetOGGVorbisDuration( path )
elif mime == HC.AUDIO_FLAC: duration = HydrusAudioHandling.GetFLACDuration( path )
2013-08-14 20:21:49 +00:00
elif mime == HC.AUDIO_WMA: duration = HydrusAudioHandling.GetWMADuration( path )
2013-07-17 20:56:13 +00:00
return ( size, mime, width, height, duration, num_frames, num_words )
2013-08-07 22:25:18 +00:00
def GetHashFromPath( path ):
h = hashlib.sha256()
2013-08-14 20:21:49 +00:00
with open( path, 'rb' ) as f:
2013-08-07 22:25:18 +00:00
2015-10-21 21:53:10 +00:00
for block in HydrusData.ReadFileLikeAsBlocks( f ): h.update( block )
2013-08-07 22:25:18 +00:00
2014-11-12 23:33:13 +00:00
return h.digest()
2013-08-07 22:25:18 +00:00
def GetMime( path ):
2013-07-17 20:56:13 +00:00
2013-08-14 20:21:49 +00:00
with open( path, 'rb' ) as f:
2013-07-17 20:56:13 +00:00
2013-08-07 22:25:18 +00:00
f.seek( 0 )
2013-07-17 20:56:13 +00:00
2013-08-07 22:25:18 +00:00
bit_to_check = f.read( 256 )
for ( offset, header, mime ) in header_and_mime:
offset_bit_to_check = bit_to_check[ offset: ]
2013-08-14 20:21:49 +00:00
if offset_bit_to_check.startswith( header ):
if mime == HC.UNDETERMINED_WM:
try:
( ( width, height ), duration, num_frames ) = HydrusVideoHandling.GetCVVideoProperties( path )
return HC.VIDEO_WMV
except: pass # we'll catch wma later
else: return mime
2013-07-17 20:56:13 +00:00
2014-04-30 21:31:40 +00:00
try:
mime = HydrusVideoHandling.GetMatroskaOrWebm( path )
return mime
except: pass
2013-08-07 22:25:18 +00:00
hsaudio_object = hsaudiotag.auto.File( path )
2013-07-17 20:56:13 +00:00
2013-08-07 22:25:18 +00:00
if hsaudio_object.valid:
if type( hsaudio_object.original ) == hsaudiotag.mpeg.Mpeg: return HC.AUDIO_MP3
elif type( hsaudio_object.original ) == hsaudiotag.flac.FLAC: return HC.AUDIO_FLAC
elif type( hsaudio_object.original ) == hsaudiotag.ogg.Vorbis: return HC.AUDIO_OGG
2013-08-14 20:21:49 +00:00
elif type( hsaudio_object.original ) == hsaudiotag.wma.WMADecoder: return HC.AUDIO_WMA
2013-08-07 22:25:18 +00:00
2013-07-17 20:56:13 +00:00
2013-08-07 22:25:18 +00:00
return HC.APPLICATION_UNKNOWN
2015-03-25 22:04:19 +00:00
def GetTempFile(): return tempfile.TemporaryFile()
def GetTempFileQuick(): return tempfile.SpooledTemporaryFile( max_size = 1024 * 1024 * 4 )
def GetTempPath(): return tempfile.mkstemp( prefix = 'hydrus' )
def IsImage( mime ): return mime in ( HC.IMAGE_JPEG, HC.IMAGE_GIF, HC.IMAGE_PNG, HC.IMAGE_BMP )
def LaunchDirectory( path ):
2015-10-21 21:53:10 +00:00
def do_it():
2015-06-17 20:01:41 +00:00
2015-10-21 21:53:10 +00:00
if HC.PLATFORM_WINDOWS:
os.startfile( path )
else:
if HC.PLATFORM_OSX: cmd = [ 'open' ]
elif HC.PLATFORM_LINUX: cmd = [ 'xdg-open' ]
cmd.append( path )
process = subprocess.Popen( cmd, startupinfo = HydrusData.GetSubprocessStartupInfo() )
process.wait()
process.communicate()
2015-06-17 20:01:41 +00:00
2015-03-25 22:04:19 +00:00
2015-10-28 21:29:05 +00:00
thread = threading.Thread( target = do_it )
thread.daemon = True
thread.start()
2015-10-21 21:53:10 +00:00
2015-03-25 22:04:19 +00:00
def LaunchFile( path ):
2015-10-21 21:53:10 +00:00
def do_it():
2015-06-17 20:01:41 +00:00
2015-10-21 21:53:10 +00:00
if HC.PLATFORM_WINDOWS:
os.startfile( path )
else:
if HC.PLATFORM_OSX: cmd = [ 'open' ]
elif HC.PLATFORM_LINUX: cmd = [ 'xdg-open' ]
cmd.append( path )
process = subprocess.Popen( cmd, startupinfo = HydrusData.GetSubprocessStartupInfo() )
process.wait()
process.communicate()
2015-03-25 22:04:19 +00:00
2015-10-21 21:53:10 +00:00
2015-10-28 21:29:05 +00:00
thread = threading.Thread( target = do_it )
thread.daemon = True
thread.start()
2013-07-17 20:56:13 +00:00