import sqlite3 from hydrus.core import HydrusExceptions from hydrus.core import HydrusTemp def ExtractDBPNGToPath( path, temp_path ): ( os_file_handle, sqlite_temp_path ) = HydrusTemp.GetTempPath() try: ( db, c ) = GetSQLiteDB( path, sqlite_temp_path ) try: ( png_bytes, ) = c.execute( 'SELECT ImageData FROM CanvasPreview;' ).fetchone() with open( temp_path, 'wb' ) as f: f.write( png_bytes ) finally: c.close() db.close() except: raise HydrusExceptions.NoThumbnailFileException() finally: HydrusTemp.CleanUpTempPath( os_file_handle, sqlite_temp_path ) def GetClipProperties( path ): ( os_file_handle, sqlite_temp_path ) = HydrusTemp.GetTempPath() num_frames = None duration_ms = None try: ( db, c ) = GetSQLiteDB( path, sqlite_temp_path ) try: ( width_float, height_float, canvas_unit, canvas_dpi_float ) = c.execute( 'SELECT CanvasWidth, CanvasHeight, CanvasUnit, CanvasResolution FROM Canvas;' ).fetchone() if c.execute( 'SELECT 1 FROM sqlite_master WHERE name = "TimeLine";' ).fetchone() is not None: try: result = c.execute( 'SELECT StartFrame, FrameRate, EndFrame from TimeLine;' ).fetchone() if result is not None: ( start_frame_float, framerate_float, end_frame_float ) = result num_frames = int( end_frame_float - start_frame_float ) if framerate_float == 0: framerate_float = 24.0 duration_s = num_frames / framerate_float duration_ms = duration_s * 1000 except: pass finally: c.close() db.close() finally: HydrusTemp.CleanUpTempPath( os_file_handle, sqlite_temp_path ) # ok the deal here is that width and height is in the canvas units, which might be mm or inches instead of pixels # the 'resolution' however is always in DPI lmaaaoooooo, so to get pixels we just have to normalise to that unit_conversion_multiplier = 1 if canvas_unit == 0: # width and height are in pixels unit_conversion_multiplier = 1 elif canvas_unit == 1: # cm cm_in_an_inch = 2.54 unit_conversion_multiplier = canvas_dpcm_float = canvas_dpi_float / cm_in_an_inch elif canvas_unit == 2: # mm mm_in_an_inch = 25.4 unit_conversion_multiplier = canvas_dpmm_float = canvas_dpi_float / mm_in_an_inch elif canvas_unit == 3: # inches unit_conversion_multiplier = canvas_dpi_float elif canvas_unit == 5: # pt, lmao points_in_an_inch = 72 unit_conversion_multiplier = canvas_dpp_float = canvas_dpi_float / points_in_an_inch return ( ( round( width_float * unit_conversion_multiplier ), round( height_float * unit_conversion_multiplier ) ), duration_ms, num_frames ) def GetSQLiteDB( path, sqlite_temp_path ): with open( path, 'rb' ) as f: clip_bytes = f.read() SQLITE_START = b'SQLite format 3' try: i = clip_bytes.index( SQLITE_START ) except IndexError: raise HydrusExceptions.DamagedOrUnusualFileException( 'This clip file had no internal SQLite file!' ) sqlite_bytes = clip_bytes[ i : ] with open( sqlite_temp_path, 'wb' ) as f: f.write( sqlite_bytes ) try: db = sqlite3.connect( sqlite_temp_path, isolation_level = None, detect_types = sqlite3.PARSE_DECLTYPES ) c = db.cursor() except: raise HydrusExceptions.DamagedOrUnusualFileException( 'This clip file seemed to have an invalid internal SQLite file!' ) return ( db, c )