先發兩個主題討論
1. NTSC <-> PAL 長寬解析值轉換
2. Avisynth 的filter 解碼
其實也沒什麼高深
只是近來看了一些問題帖得到的經驗
先來講 1.
最近看了兩個主題才知道這也是有點學問的
先來看個人做的一個多功能Avisynth腳本
===================================
###########################################################
## 此腳本效果是加上字幕於黑邊上 ##
## 原始影像分辨率需大於 PAL_W*PAL_H,否則會有變形之結果 ##
###########################################################
sClip=avisource("test.avi") #.BilinearResize(512,384) ##測試用
#sClip.Width=512 ##註示用
#sClip.Height=384 ##註示用
## 使用者调整參數 ##
FontSize=20 #字幕大小
SubtitleT= "上字幕"#上字幕
SubtitleB= "test.ssa"#下字幕(文字請勿使用 \ ),亦可填寫的是字幕檔案(此時請註上路徑比如 c:\test.aas)
PAL_W= 352 #水平分辨率,請盡量使用4的倍數
PAL_H= 288 #垂直分辨率,請盡量使用4的倍數
mux_mode="add" #合成模式
BorderRevision=0 #寬度裁減修正值
## 尚未用到的使用者參數 ##
SubtitleFirst_frame=0#字幕顯示的開始"時間"(請以frame編號填寫),預設值 0
SubtitleLast_frame=framecount(sClip)-1 #字幕顯示的結束"時間"(請以frame編號填寫),預設值 framecount(sClip)-1
####################
## A 11:9 = 1.222222
## B 12:9 = 1.333333
## 銀幕寬不變時,
## A->B 要先在A時減少水平分辨率才可以一比一轉換,
## B->A 則反過來在B時增加水平分辨率,
## 反過來說就是一比一轉換後要乘以修正值A->B 是A/B,B->A 是B/A。
## PAR = DAR * (水平分辨率/垂直分辨率)
## 此例PAR 等於 Float(PAL_W)/PAL_H * Float(sClip.Width)/sClip.Height
## 當想使用PAL <-> NTSC 轉換時請除去下方 #PN# ※用於在TV看片時
#PN#sDAR= Float(sClip.Width)/sClip.Height
#PN#dDAR= Float(PAL_W)/PAL_H
#PN#PAR= (sDAR==dDAR) ? 1 : ((sDARNew_H= PAL_H-((BorderRevision+FontSize)*2) #=248
## for resize filter 作修正
temp= New_H % 4
New_H= (temp == 0) ? New_H : New_H-temp
New_W= Float(New_H)/sClip.Height *sClip.Width
#PN# *PAR## for resize filter 作修正
temp= Ceil(New_W) % 4
New_W= (temp == 0) ? New_W : New_W-temp #=332
b= Ceil((PAL_W-New_W)/2)
#return sClip.subtitle(string(PAR)) ##除錯用
## X= b
## Y= FontSize
## 製作一個空的黑色Clip ##
MainP=NullClip(sClip, sClip.Framecount).BilinearResize(PAL_W,PAL_H).ConvertToYUY2
## 调整原影像使字幕夾擊它 ##
nClip=sClip.BilinearResize(New_W, New_H).ConvertToYUY2
#c=Layer(AudioDub(MainP,sClip), nClip, mux_mode, 255, X, Y)
c=Layer(AudioDub(MainP,sClip), nClip, mux_mode, 255, b,FontSize+BorderRevision)
## 加上下字幕 ##
c= (SubtitleT=="") ? c : c.Subtitle(SubtitleT, font="Arial", size=FontSize, align=8)
return (SubtitleB=="")||(Findstr(SubtitleB,"\")>0) ? Get_Sub_File(c,"",SubtitleB,"Auto") : c.Subtitle(SubtitleB, font="華康細圓", size=FontSize-2,align=2)
function NullClip(clip "template", Int "Len")
{
Len = Default(Len, 0)
return Blackness(template, length= Len)
}
#EX: Get_Sub_File(Video, File_Path, File_Name, Subtitle_Style)
Function Get_Sub_File (clip v, String F_P, String F_N, String S_S) {
Loadplugin("VSfilter.dll")
Function Auto_Subtitle_Load (String A_Sub_Name) {
A_Sub_Style =
\ Exist(A_Sub_Name + "IDX") ? "IDX" :
\ Exist(A_Sub_Name + "SRT") ? "SRT" :
\ Exist(A_Sub_Name + "SSA") ? "SSA" :
\ Exist(A_Sub_Name + "ASS") ? "ASS" :
\ Exist(A_Sub_Name + "SMI") ? "SMI" : "NOS"
return A_Sub_Style
}
## 求Subtitle 檔名、副檔名##
S_S_FrontNameChrNum = Get_File_Name_Info(S_S, ".")
F_N_FrontNameChrNum = Get_File_Name_Info(F_N, ".") #Findstr
S_N_Temp = LeftStr(F_N, F_N_FrontNameChrNum)
Sub_Style =
\ (UCase(S_S) == "AUTO") ?
\ Auto_Subtitle_Load(F_P + S_N_Temp) :
\ (S_S_FrontNameChrNum != 0) ?
\ UCase(RightStr(S_S, 3)) :
\ UCase(S_S)
Sub_Name =
\ (S_S_FrontNameChrNum == 0) ?
\ F_P + S_N_Temp + Sub_Style :
\ (Findstr(S_S, ":") > 0) ?
\ S_S :
\ F_P + S_S
## Subtitle File存在 #######
Temp_Sub_IDX = (Sub_Style == "IDX") ? v.VobSub(Sub_Name) : nop
Temp_Sub_SRT = (Sub_Style == "SRT") ? v.TextSub(Sub_Name) : nop
Temp_Sub_SSA = (Sub_Style == "SSA") ? v.TextSub(Sub_Name) : nop
Temp_Sub_ASS = (Sub_Style == "ASS") ? v.TextSub(Sub_Name) : nop
Temp_Sub_SMI = (Sub_Style == "SMI") ? v.TextSub(Sub_Name) : nop
#Temp_Sub_ = (Sub_Style == "") ? v.ConvertToRGB.VD_Subtitler(Sub_Name) : nop
Temp_Sub_NOS = (Sub_Style == "NOS") ? v : nop
File_Subtitle = (Sub_Style <> "") ? Eval("Temp_Sub_"+ Sub_Style) : v
return(File_Subtitle) #string().Subtitle(Sub_Name)
}
#EX: Get_File_Name_Info(StrS, "name") m:\abc.avi
Function Get_File_Name_Info (String ExWork_Movie_File, String Path_Or_Name) {
Function Do_GetStr (String ExWork_Movie_File, Int Str_Len_Num, Int Str_FilePath_necessary_word_Num, String Path_Or_Name) {
F_Str_Num = Str_Len_Num - Str_FilePath_necessary_word_Num + 1
F_Str = LeftStr(ExWork_Movie_File, F_Str_Num)
B_Str_Num = Str_FilePath_necessary_word_Num - 1
B_Str = RightStr(ExWork_Movie_File, B_Str_Num)
Return (Path_Or_Name == "PATH"?F_Str:(Path_Or_Name == "NAME")?B_Str:"")
}
Path_Or_Name = UCase(Path_Or_Name)
Str_Len_Num = StrLen(ExWork_Movie_File)
Str_FilePath_necessary_word_Num = Findstr(RevStr(ExWork_Movie_File), "\")
Str_FrontNameChrNum = (Findstr(RevStr(ExWork_Movie_File), ".") > 0)? Str_Len_Num - Findstr(RevStr(ExWork_Movie_File), ".") + 1 : 0
Return_Word =
\ (Str_FilePath_necessary_word_Num != 0) ?
\ Do_GetStr(ExWork_Movie_File, Str_Len_Num, Str_FilePath_necessary_word_Num, Path_Or_Name) : 0
return ((Path_Or_Name == ".")? Str_FrontNameChrNum : Return_Word)
}
===================================
這個腳本與主題 1. 所要探討的就是New_W及New_H
分別代表 轉換後的水平及垂直分辨率
見蓝字體
我們知道雖然有這麼個公式 PAR = DAR * (水平分辨率/垂直分辨率)
但對本例實際的應用不高
我們要講的是:
大家都知道
垂直解析度(分辨率)比水平解析度 來的小因此在轉換時大多希望寧可
捨去 水平 進而維持 垂直 不變此時就會形成一個反相的轉換概念(如下圖)與實際的狀況相反
假設 源高以sH,源寬以sW 表示
因此實際應用上欲達到 設定新高(H),求得新寬(W)
可以得到一個公式
W=h*sW*[轉換比值]
這裡的 h=H/sH 為 新高 對 源高 的增減百分比
當W:H=sW:sH 時 [轉換比值]=1
當W:H≠sW:sH 時 [轉換比值]=(W/H)與(sW/sH)相除
至於誰除以誰:
當 W/H 比 sW/sH 大時為 (W/H) / (sW/sH),反之 (sW/sH) / (W/H)
相互轉換後的結果
<->