179 lines
4.7 KiB
Python
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 )
|
|
|