hydrus/hydrus/core/HydrusClipHandling.py

179 lines
4.7 KiB
Python

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()
db = None
c = None
try:
( db, c ) = GetSQLiteDB( path, sqlite_temp_path )
( png_bytes, ) = c.execute( 'SELECT ImageData FROM CanvasPreview;' ).fetchone()
with open( temp_path, 'wb' ) as f:
f.write( png_bytes )
finally:
if c is not None:
c.close()
if db is not None:
db.close()
HydrusTemp.CleanUpTempPath( os_file_handle, sqlite_temp_path )
def GetClipProperties( path ):
( os_file_handle, sqlite_temp_path ) = HydrusTemp.GetTempPath()
db = None
c = None
try:
( db, c ) = GetSQLiteDB( path, sqlite_temp_path )
( 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 None:
num_frames = None
duration_ms = None
else:
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:
if c is not None:
c.close()
if db is not None:
db.close()
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, so no PNG thumb could be extracted!' )
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 )