Pour l'évolution de mon projet TAO-MKV, je cherche à convertir des sous-titres HDMV/PGS (ou .sup) en .srt .
J'arrive à extraire les horodatages de l'hexadécimale (reste la mise en forme dans le fichier .srt)
Le problème c'est d'extraire les bitmap ( 1 sous-titre vers une image" png, bmp ou jpeg...)
Quelqu'un pourrait m'aider à comprendre la structure des PGS et le décodage des .bmp RLE?
(extraire un bloc de sous-titre qui est en hexadecimal vers une image "png jpg etc..." qui sera lu via OCR).
L'OCR est déjà opérationnel sous ça dernière version.
J'ai fait ce code pour lire l'hexa d'un sous-titre et le rendre plus compréhensif.
#include <Array.au3>
#include <file.au3>
#include <MsgBoxConstants.au3>
#include <String.au3>
;~ INFOS ==========================================================================================================
;~ ### http://blog.thescorpius.com/index.php/2017/07/15/presentation-graphic-stream-sup-files-bluray-subtitle-format/ ###
;~ TIMES = 0x16
;~ SIZE = 0x17
;~ PALETTE = 0x14
;~ BITMAP = 0x15
;~ END = 0x80
;~================================================================================================================
Global $ligne, $retour, $nb
Local $hFile=FileOpen("CHEMIN \subtitle.sup",$FO_BINARY)
Dim $Tableau = StringSplit ( FileRead($hFile) , "5047" , 1 )
;~ ############### sépare les blocs / pas obligatoire #############
For $i = 0 to UBound($Tableau) -1
If StringLen($Tableau[$i]) = 22 Then _ArrayInsert ($Tableau,$i +1,"")
Next
;~ ##################################################################
For $i = 0 to UBound($Tableau) -1
;~ ################ remplace les lignes HEXADECIMALE par le nom de la fonction ########################################
;~ If StringMid ($Tableau[$i], 17, 2) = 15 Then $Tableau[$i] = "bitmap" ;
;~ If StringMid ($Tableau[$i], 17, 2) = 17 Then $Tableau[$i] = "taille" ;
;~ If StringMid ($Tableau[$i], 17, 2) = 14 Then $Tableau[$i] = "palette" ;
;~ If StringMid ($Tableau[$i], 17, 2) = 80 Then $Tableau[$i] = StringMid ($Tableau[$i], 17, 2) & " fin" ;
;~ ############################################################################################################
;~ ############## First Segment: PCS (0x16)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 16 Then ; pour récupérer l'horodatage et le convertir en temps lisible en texte
horodatage($Tableau[$i] , $retour)
ConsoleWrite("First Segment: PCS (0x16)" & @CRLF & _
"Presentation Time (PTS): " & $retour & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: PCS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) &" bytes" & @CRLF & _
"Width: " & Dec( StringMid ($Tableau[$i], 23, 4)) & @CRLF & _
"Height: " & Dec( StringMid ($Tableau[$i], 27, 4)) & @CRLF & _
"Frame rate: " & StringMid ($Tableau[$i], 31, 2) & @CRLF & _
"Composition Number: " & dec(StringMid ($Tableau[$i], 33, 4)) & @CRLF & _
"Composition State: Epoch Start " & StringMid ($Tableau[$i], 37, 2) & @CRLF & _
"Palette Update Flag: " & StringMid ($Tableau[$i], 39, 2) & @CRLF & _
"Palette ID: " & StringMid ($Tableau[$i], 41, 2) & @CRLF & _
"Number of Composition Objects: " & StringMid ($Tableau[$i], 43, 2) & @CRLF & _
"Object ID: " & StringMid ($Tableau[$i], 45, 2) & @CRLF & _
"Window ID: " & StringMid ($Tableau[$i], 47, 2) & @CRLF & _
"Object Cropped Flag: " & StringMid ($Tableau[$i], 49, 4) & @CRLF & _
"Object Horizontal Position: " & Dec( StringMid ($Tableau[$i], 53, 4)) & @CRLF & _
"Object Vertical Position: " & Dec( StringMid ($Tableau[$i], 57, 4)) & @CRLF & @CRLF )
$Tableau[$i] = $retour & " --> "
EndIf
;~ ############## Second Segment: WDS (0x17)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 17 Then
ConsoleWrite("Second Segment: WDS (0x17)" & @CRLF & _
"Presentation Time (PTS): " & StringMid ($Tableau[$i], 1, 8) & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: WDS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) & " bytes" & @CRLF & _
"Number of Windows: " & StringMid ($Tableau[$i], 23, 1) & @CRLF & _
"Window ID: " & StringMid ($Tableau[$i], 25, 2) & @CRLF & _
"Window Horizontal Position: " & Dec( StringMid ($Tableau[$i], 27, 4)) & @CRLF & _
"Window Vertical Position: " & Dec( StringMid ($Tableau[$i], 31, 4)) & @CRLF & _
"Window Width: " & Dec( StringMid ($Tableau[$i], 35, 4)) & @CRLF & _
"Window Height " & Dec( StringMid ($Tableau[$i], 39, 4)) & @CRLF & _
"Window ID: " & StringMid ($Tableau[$i], 43, 2) & @CRLF & _
"Window Horizontal Position: " & Dec( StringMid ($Tableau[$i], 45, 4)) & @CRLF & _
"Window Vertical Position: " & Dec( StringMid ($Tableau[$i], 49, 4)) & @CRLF & _
"Window Width: " & Dec( StringMid ($Tableau[$i], 53, 4)) & @CRLF & _
"Window Height " & Dec( StringMid ($Tableau[$i], 47, 4)) & @CRLF & @CRLF )
EndIf
;~ ############## Third Segment: PDS (0x14)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 14 Then
ConsoleWrite("Third Segment: PDS (0x14)" & @CRLF & _
"Presentation Time (PTS): " & StringMid ($Tableau[$i], 1, 8) & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: PDS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) & " bytes" & @CRLF & _
"Palette ID: " & StringMid ($Tableau[$i], 23, 2) & @CRLF & _
"Palette Version: " & StringMid ($Tableau[$i], 25, 2) & @CRLF & _
"le reste: " & StringMid ($Tableau[$i], 27) & @CRLF & @CRLF )
EndIf
;~ ############## Fourth Segment: ODS (0x15)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 15 Then ; pour récupérer les infos sur le bitmap du sous-titre
ConsoleWrite("Fourth Segment: ODS (0x15)" & @CRLF & _
"Presentation Time (PTS): " & StringMid ($Tableau[$i], 1, 8) & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: PDS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) & @CRLF & _
"Object ID: " & StringMid ($Tableau[$i], 23, 4) & @CRLF & _
"Object Version Number: " & StringMid ($Tableau[$i], 27, 2) & @CRLF & _
"Last in sequence flag: First and last sequence " & StringMid ($Tableau[$i], 29, 2) & @CRLF & _
"Object Data Length: " & Dec( StringMid ($Tableau[$i], 31, 6)) & @CRLF & _
"Width: " & Dec( StringMid ($Tableau[$i], 37, 4)) & @CRLF & _
"Height: " & Dec( StringMid ($Tableau[$i], 41, 4)) & @CRLF & _
"Object Data encodé en RLE: " & StringMid ($Tableau[$i], 45) & @CRLF & @CRLF )
EndIf
;~ ############## Fifth Segment: END (0x80)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 80 Then ConsoleWrite("########################### fin du bloc #####################################################################################################" & @CRLF & @CRLF)
Next
_ArrayDisplay($Tableau)
;~ ############# création de horodatage #################
Func horodatage($ligne, ByRef $retour)
$ligne = StringLeft ($ligne, 8) ; récuperation des hexa temps
Local $dec = Dec ($ligne)
Local $sec = ($dec/90)/1000
$heure = Int($sec / 3600)
$minute = Int(($sec - $heure * 3600) / 60)
$seconde = $sec - $heure * 3600 - $minute * 60
$MS = StringRight ( ($dec/90), 3 )
ConsoleWrite( StringFormat('%02d:%02d:%02d:%03d', $heure, $minute, $seconde,$MS) & @CRLF)
$retour = StringFormat('%02d:%02d:%02d:%03d', $heure, $minute, $seconde,$MS)
EndFunc
;~ #######################################################
#include <file.au3>
#include <MsgBoxConstants.au3>
#include <String.au3>
;~ INFOS ==========================================================================================================
;~ ### http://blog.thescorpius.com/index.php/2017/07/15/presentation-graphic-stream-sup-files-bluray-subtitle-format/ ###
;~ TIMES = 0x16
;~ SIZE = 0x17
;~ PALETTE = 0x14
;~ BITMAP = 0x15
;~ END = 0x80
;~================================================================================================================
Global $ligne, $retour, $nb
Local $hFile=FileOpen("CHEMIN \subtitle.sup",$FO_BINARY)
Dim $Tableau = StringSplit ( FileRead($hFile) , "5047" , 1 )
;~ ############### sépare les blocs / pas obligatoire #############
For $i = 0 to UBound($Tableau) -1
If StringLen($Tableau[$i]) = 22 Then _ArrayInsert ($Tableau,$i +1,"")
Next
;~ ##################################################################
For $i = 0 to UBound($Tableau) -1
;~ ################ remplace les lignes HEXADECIMALE par le nom de la fonction ########################################
;~ If StringMid ($Tableau[$i], 17, 2) = 15 Then $Tableau[$i] = "bitmap" ;
;~ If StringMid ($Tableau[$i], 17, 2) = 17 Then $Tableau[$i] = "taille" ;
;~ If StringMid ($Tableau[$i], 17, 2) = 14 Then $Tableau[$i] = "palette" ;
;~ If StringMid ($Tableau[$i], 17, 2) = 80 Then $Tableau[$i] = StringMid ($Tableau[$i], 17, 2) & " fin" ;
;~ ############################################################################################################
;~ ############## First Segment: PCS (0x16)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 16 Then ; pour récupérer l'horodatage et le convertir en temps lisible en texte
horodatage($Tableau[$i] , $retour)
ConsoleWrite("First Segment: PCS (0x16)" & @CRLF & _
"Presentation Time (PTS): " & $retour & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: PCS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) &" bytes" & @CRLF & _
"Width: " & Dec( StringMid ($Tableau[$i], 23, 4)) & @CRLF & _
"Height: " & Dec( StringMid ($Tableau[$i], 27, 4)) & @CRLF & _
"Frame rate: " & StringMid ($Tableau[$i], 31, 2) & @CRLF & _
"Composition Number: " & dec(StringMid ($Tableau[$i], 33, 4)) & @CRLF & _
"Composition State: Epoch Start " & StringMid ($Tableau[$i], 37, 2) & @CRLF & _
"Palette Update Flag: " & StringMid ($Tableau[$i], 39, 2) & @CRLF & _
"Palette ID: " & StringMid ($Tableau[$i], 41, 2) & @CRLF & _
"Number of Composition Objects: " & StringMid ($Tableau[$i], 43, 2) & @CRLF & _
"Object ID: " & StringMid ($Tableau[$i], 45, 2) & @CRLF & _
"Window ID: " & StringMid ($Tableau[$i], 47, 2) & @CRLF & _
"Object Cropped Flag: " & StringMid ($Tableau[$i], 49, 4) & @CRLF & _
"Object Horizontal Position: " & Dec( StringMid ($Tableau[$i], 53, 4)) & @CRLF & _
"Object Vertical Position: " & Dec( StringMid ($Tableau[$i], 57, 4)) & @CRLF & @CRLF )
$Tableau[$i] = $retour & " --> "
EndIf
;~ ############## Second Segment: WDS (0x17)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 17 Then
ConsoleWrite("Second Segment: WDS (0x17)" & @CRLF & _
"Presentation Time (PTS): " & StringMid ($Tableau[$i], 1, 8) & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: WDS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) & " bytes" & @CRLF & _
"Number of Windows: " & StringMid ($Tableau[$i], 23, 1) & @CRLF & _
"Window ID: " & StringMid ($Tableau[$i], 25, 2) & @CRLF & _
"Window Horizontal Position: " & Dec( StringMid ($Tableau[$i], 27, 4)) & @CRLF & _
"Window Vertical Position: " & Dec( StringMid ($Tableau[$i], 31, 4)) & @CRLF & _
"Window Width: " & Dec( StringMid ($Tableau[$i], 35, 4)) & @CRLF & _
"Window Height " & Dec( StringMid ($Tableau[$i], 39, 4)) & @CRLF & _
"Window ID: " & StringMid ($Tableau[$i], 43, 2) & @CRLF & _
"Window Horizontal Position: " & Dec( StringMid ($Tableau[$i], 45, 4)) & @CRLF & _
"Window Vertical Position: " & Dec( StringMid ($Tableau[$i], 49, 4)) & @CRLF & _
"Window Width: " & Dec( StringMid ($Tableau[$i], 53, 4)) & @CRLF & _
"Window Height " & Dec( StringMid ($Tableau[$i], 47, 4)) & @CRLF & @CRLF )
EndIf
;~ ############## Third Segment: PDS (0x14)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 14 Then
ConsoleWrite("Third Segment: PDS (0x14)" & @CRLF & _
"Presentation Time (PTS): " & StringMid ($Tableau[$i], 1, 8) & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: PDS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) & " bytes" & @CRLF & _
"Palette ID: " & StringMid ($Tableau[$i], 23, 2) & @CRLF & _
"Palette Version: " & StringMid ($Tableau[$i], 25, 2) & @CRLF & _
"le reste: " & StringMid ($Tableau[$i], 27) & @CRLF & @CRLF )
EndIf
;~ ############## Fourth Segment: ODS (0x15)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 15 Then ; pour récupérer les infos sur le bitmap du sous-titre
ConsoleWrite("Fourth Segment: ODS (0x15)" & @CRLF & _
"Presentation Time (PTS): " & StringMid ($Tableau[$i], 1, 8) & @CRLF & _
"Decoding Time (DTS): " & StringMid ($Tableau[$i], 9, 8) & @CRLF & _
"Segment Type: PDS " & StringMid ($Tableau[$i], 17, 2) & @CRLF & _
"Segment Size: " & Dec( StringMid ($Tableau[$i], 19, 4)) & @CRLF & _
"Object ID: " & StringMid ($Tableau[$i], 23, 4) & @CRLF & _
"Object Version Number: " & StringMid ($Tableau[$i], 27, 2) & @CRLF & _
"Last in sequence flag: First and last sequence " & StringMid ($Tableau[$i], 29, 2) & @CRLF & _
"Object Data Length: " & Dec( StringMid ($Tableau[$i], 31, 6)) & @CRLF & _
"Width: " & Dec( StringMid ($Tableau[$i], 37, 4)) & @CRLF & _
"Height: " & Dec( StringMid ($Tableau[$i], 41, 4)) & @CRLF & _
"Object Data encodé en RLE: " & StringMid ($Tableau[$i], 45) & @CRLF & @CRLF )
EndIf
;~ ############## Fifth Segment: END (0x80)
;~ ########################################
If StringMid ($Tableau[$i], 17, 2) = 80 Then ConsoleWrite("########################### fin du bloc #####################################################################################################" & @CRLF & @CRLF)
Next
_ArrayDisplay($Tableau)
;~ ############# création de horodatage #################
Func horodatage($ligne, ByRef $retour)
$ligne = StringLeft ($ligne, 8) ; récuperation des hexa temps
Local $dec = Dec ($ligne)
Local $sec = ($dec/90)/1000
$heure = Int($sec / 3600)
$minute = Int(($sec - $heure * 3600) / 60)
$seconde = $sec - $heure * 3600 - $minute * 60
$MS = StringRight ( ($dec/90), 3 )
ConsoleWrite( StringFormat('%02d:%02d:%02d:%03d', $heure, $minute, $seconde,$MS) & @CRLF)
$retour = StringFormat('%02d:%02d:%02d:%03d', $heure, $minute, $seconde,$MS)
EndFunc
;~ #######################################################
Vous pouvez prendre les vôtres aussi.
Merci d'avance