TCAX 字幕特效制作工具官方论坛 | ASS | TCAS | Python | Aegisub | Lua

标题: 像素字按照贝塞尔曲线形状扩散(修正定位偏差) [打印本页]

作者: milkyjing    时间: 2012-4-24 12:00:37     标题: 像素字按照贝塞尔曲线形状扩散(修正定位偏差)

执行此例子可能需要新模块 gdiFont.rar (6.37 KB, 下载次数: 4491)
解压后放到TCAX根目录下, 或者是当前特效工程目录下.
完整特效工程 bezier_pixels.rar (93.58 KB, 下载次数: 4627)
  1. from tcaxPy import *
  2. from gdiFont import *

  3. def tcaxPy_Init():
  4.     global _Fs
  5.     global _FD          # 一帧的持续时间, 约40毫秒
  6.     global _Spacing     # 字体间距
  7.     global GdiFont         # 首要字体
  8.     _Fs = GetVal(val_FontSize)
  9.     _FD = 1000 / GetVal(val_FXFPS)
  10.     _Spacing = GetVal(val_Spacing)
  11.     GdiFont = gfInitFont(GetVal(val_FontFaceName), _Fs, _Spacing, GetVal(val_SpaceScale), 0, False)

  12. def tcaxPy_Fin():
  13.     gfFinFont(GdiFont)

  14. def tcaxPy_Main(_i, _j, _n, _start, _end, _elapk, _k, _x, _y, _a, _txt):
  15.     ASS_BUF  = []        # 保存ASS特效
  16.     TCAS_BUF = []        # 保存TCAS特效
  17.     ##### 主要特效编写操作 ####
  18.     dx = _x - int((_a + _Spacing) / 2 + 0.5)     # 一个固定操作, 将an5的坐标转换为an7
  19.     dy = _y - int(_Fs / 2 + 0.5)                 # ASS特效默认采用an5坐标, TCAS特效则采用an7坐标
  20.     points = gfGetPoints(GdiFont, _txt)
  21.     pt_num = len(points)
  22.     dx = _x - int((_a + _Spacing) / 2 + 0.5)
  23.     dy = _y - int(_Fs / 2 + 0.5)
  24.     inix = dx - randint(15, 30)
  25.     tab_posx = (inix + randint(-40, 40), inix + randint(-130, 130), inix + randint(-130, 130), inix + randint(-40, 40))
  26.     tab_posy = (dy + _Fs + randint(-15, 20), _y + randint(-100, 100), _y + randint(-110, 110), dy + randint(-15, 20))
  27.     maxi = int(tab_posy[0] - tab_posy[3]) + 90
  28.     pos_cur = Bezier3(maxi, tab_posx[0] + randint(-15, 15), tab_posy[0], tab_posx[3] + randint(-15, 15), tab_posy[3], tab_posx[1] + randint(-20, 20), tab_posy[1], tab_posx[2] + randint(-20, 20), tab_posy[2])
  29.     bucle = max(pt_num, maxi)
  30.     for part in range(bucle):
  31.         indice_text = randint(0, pt_num - 1)
  32.         indice_pos = randint(0, maxi - 1)
  33.         x = dx + points[indice_text][0]
  34.         y = dy + points[indice_text][1]
  35.         x_fin = pos_cur[indice_pos][0]
  36.         y_fin = pos_cur[indice_pos][1]
  37.         rand_ini = randint(50, 400)
  38.         ts = _end - 30 + _j * 2.5
  39.         te = ts + 65 + _j * 2.5
  40.         rand_end = 10 * (te - ts)
  41.         EFT = move(x, y, x_fin, y_fin, rand_ini, rand_end) + fad(70, 0) + color1('0337C1') + fsc(125, 125) + shad(0) + bord(0) + alpha(255 - points[indice_text][2]) + t(alpha(255) + fsc(50, 50))
  42.         ass_main(ASS_BUF, SubL(ts, te, 0, Pix_Style), EFT, PixPt())
  43.     ##### 将结果返回给tcax进行处理 #####
  44.     return (ASS_BUF, TCAS_BUF)
复制代码


附件: gdiFont.rar (2012-4-24 12:01:23, 6.37 KB) / 下载次数 4491
http://tcax.org/forum.php?mod=attachment&aid=NTI5fDA3YjU4ZmQ2fDE3MTQ2MTQzNDd8MHww

附件: bezier_pixels.rar (2012-4-24 12:01:23, 93.58 KB) / 下载次数 4627
http://tcax.org/forum.php?mod=attachment&aid=NTI4fDkyZGU4NmUzfDE3MTQ2MTQzNDd8MHww
作者: youkaze    时间: 2012-4-24 12:44:12

果断牛奶大的这个写的有艺术感一点 咱的有点僵硬嗯
作者: 忘却の小伊    时间: 2012-4-24 13:15:19

奶大有新技术了~~!!
作者: 忘却の小伊    时间: 2012-4-27 23:36:19

能给点注释么...
看着很头疼啊...
作者: milkyjing    时间: 2012-4-28 13:40:34

忘却の小伊 发表于 2012-4-27 23:36
能给点注释么...
看着很头疼啊...

原理基本同, http://www.tcax.org/forum.php?mod=viewthread&tid=178

需要解释的地方, 直接提出吧...
作者: 渣渣疯子    时间: 2012-4-29 18:16:39

没时间,没时间,被折腾,被折腾。。。怨念啊o(一︿一+)o
作者: usfsaf    时间: 2012-6-8 14:28:18

请问:但凡套用外置py脚本,修改字幕的颜色必须是在该py脚本内部编辑么?还是根据不同情况分别来修改相应tcc文件和ass样式也可达到效果呢?
作者: milkyjing    时间: 2012-6-8 16:55:18

usfsaf 发表于 2012-6-8 14:28
请问:但凡套用外置py脚本,修改字幕的颜色必须是在该py脚本内部编辑么?还是根据不同情况分别来修改相应tc ...

修改tcc的值会体现在 GetVal(val_1C), GetVal(val_2C) 等处。。

所以,如果你的py脚本中调用了这些值,而不是具体的某个颜色,比如"FF00FF",则,修改tcc也可以达到修改颜色的效果
作者: usfsaf    时间: 2012-6-8 21:59:37

milkyjing 发表于 2012-6-8 16:55
修改tcc的值会体现在 GetVal(val_1C), GetVal(val_2C) 等处。。

所以,如果你的py脚本中调用了这些值, ...

感谢milkyjing !
1.看来是优先级决定,先看py是否具体到某色,如是直接修改py完事;如否则看tcc了;只是区分颜色函数和颜色变量咱还没那个水平,还得磨。
2.还是这个特效算法,改白色及全语句适用后压了几次都发现:每句特效都是整行唱完后才出来一下,时间很短,(单k值卡拉OK同步是正常的),k值是单文字的,不知问题何在?修改的部分tcc如下:
# mode configuration
< inherit ass header = false >
< k mode = syllable >
< text layout = horizontal >
< tcaxpy init = true >
< tcaxpy user = false >
< tcaxpy fin = false >


# py settings
< py file = bezier_pixels.py >     < beg line = 1 >    < end line = 0 >
# main settings

< k-timed ass file = test_k.ass >
< font file = 汉仪小隶书简.TTF>    < font face id = 1 >    < font size = 65 >
< fx width = 1920 >    < fx height = 1080 >    < fx fps = 23.976 >
< alignment = 1 >
< x offset = 30>    < y offset = 20 >
< spacing = 0 >    < space scale = 1.0 >

作者: milkyjing    时间: 2012-6-8 22:21:01

usfsaf 发表于 2012-6-8 21:59
感谢milkyjing !
1.看来是优先级决定,先看py是否具体到某色,如是直接修改py完事;如否则看tcc了;只是 ...

Re2: 这个效果就是这样子的。。。不是完整的卡拉OK特效(只是一个组成部分而已)
作者: usfsaf    时间: 2012-6-8 22:24:49

也再疑惑是不是这样的呢,果然啊,那是要和内置的开场和存在并用么?
作者: 爱雪音MiKu    时间: 2013-2-18 20:11:55

呜咕。。。    points = gfGetPoints(GdiFont, _txt)
                     pt_num = len(points)                      这2句是将文字的像素转换成点0.0?
这里inix = dx - randint(15, 30)定义有什么用处0.0?
作者: milkyjing    时间: 2013-2-18 20:15:31

爱雪音MiKu 发表于 2013-2-18 20:11
呜咕。。。    points = gfGetPoints(GdiFont, _txt)
                     pt_num = len(points)          ...

隨機定義一個初始位置
作者: 爱雪音MiKu    时间: 2013-2-18 20:24:23

milkyjing 发表于 2013-2-18 20:15
隨機定義一個初始位置

呜咕      maxi = int(tab_posy[0] - tab_posy[3]) + 90    这句是获取移动的点的坐标0.0?   呜咕。。为什么是[0][3]不是应该写[0][1]吗。。偶试了改成1感觉没什么变化。。后面的那个+90是做什么的?。。让整个移动的坐标再加90?  
作者: 爱雪音MiKu    时间: 2013-2-19 15:30:27

  1. from tcaxPy import *
  2. from gdiFont import *

  3. def tcaxPy_Init():
  4.     global _Fs
  5.     global _FD          # 一帧的持续时间, 约40毫秒
  6.     global _Spacing     # 字体间距
  7.     global GdiFont         # 首要字体
  8.     _Fs = GetVal(val_FontSize)
  9.     _FD = 1000 / GetVal(val_FXFPS)
  10.     _Spacing = GetVal(val_Spacing)
  11.     GdiFont = gfInitFont(GetVal(val_FontFaceName), _Fs, _Spacing, GetVal(val_SpaceScale), 0, False)

  12. def tcaxPy_Fin():
  13.     gfFinFont(GdiFont)

  14. def tcaxPy_Main(_i, _j, _n, _start, _end, _elapk, _k, _x, _y, _a, _txt):
  15.     ASS_BUF  = []        # 保存ASS特效
  16.     TCAS_BUF = []        # 保存TCAS特效
  17.     ##### 主要特效编写操作 ####
  18.     dx = _x - int((_a + _Spacing) / 2 + 0.5)     # 一个固定操作, 将an5的坐标转换为an7
  19.     dy = _y - int(_Fs / 2 + 0.5)                 # ASS特效默认采用an5坐标, TCAS特效则采用an7坐标
  20.     points = gfGetPoints(GdiFont, _txt)
  21.     pt_num = len(points)                            #把像素字转换成点
  22.     dx = _x - int((_a + _Spacing) / 2 + 0.5)   #同上同于转换
  23.     dy = _y - int(_Fs / 2 + 0.5)
  24.     inix = dx - randint(15, 30)                         #X轴定义一个随机的初始值
  25.     tab_posx = (inix + randint(-40, 40), inix + randint(-130, 130), inix + randint(-130, 130), inix + randint

  26. (-40, 40))                                                      #X轴的随机移动数组?
  27.     tab_posy = (dy + _Fs + randint(-15, 20), _y + randint(-100, 100), _y + randint(-110, 110), dy +

  28. randint(-15, 20))                                              #Y轴的随机移动数组?
  29.     maxi = int(tab_posy[0] - tab_posy[3]) + 90      #获取Y轴的移动坐标?可是中间的那个 - 是做什么的?   

  30. +90是整个Y坐标移动90?  这行代码偶不知道。。这行不解决下面的好像也难明白呢(T.T)
  31.     pos_cur = Bezier3(maxi, tab_posx[0] + randint(-15, 15), tab_posy[0], tab_posx[3] + randint(-15, 15),

  32. tab_posy[3], tab_posx[1] + randint(-20, 20), tab_posy[1], tab_posx[2] + randint(-20, 20), tab_posy[2])  

  33.      #呜咕。。 tab_posx[0]是对应的inix + randint(-40, 40)这个坐标吗。    tab_posy[0]是对应的dy + _Fs +

  34. randint(-15, 20)这个坐标吗。。然后依次类推?  结构就是曲线的:开始点,结束点,控制点1,控制点2  这样


  35.     bucle = max(pt_num, maxi)   #将像素点,和那个偶不明白的代码给max。。然后再给bucle
  36.     for part in range(bucle):    #循环bucle给part?。。这里的循环偶不太明白bucle里的东西如何循环的?。

  37. 。偶只知道时间的循环和次数的循环。。这个没见过。。这次想了解一下
  38.         indice_text = randint(0, pt_num - 1)     #这里是随机取像素点?   为什么要减去1
  39.         indice_pos = randint(0, maxi - 1)           #获取随机的位置?
  40.         x = dx + points[indice_text][0]             #像素点开始的X轴的位置         后面的[0]是什么意思?
  41.         y = dy + points[indice_text][1]             #像素点开始的Y轴的位置
  42.         x_fin = pos_cur[indice_pos][0]              #像素点结束的X轴的位置
  43.         y_fin = pos_cur[indice_pos][1]              #像素点结束的Y轴的位置
  44.         rand_ini = randint(50, 400)                   #随机去一个值  rand_ini 是什么?
  45.         ts = _end - 30 + _j * 2.5                      #字幕结束的时间-30+第j个字乘以2.5     _j * 2.5这定义的是

  46. 什么意思?。。。偶看大大们会用到比如:_A,_J之类的来定义时间是做什么的呀?
  47.         te = ts + 65 + _j * 2.5                         #同上就是不知道_j在这里的作用
  48.         rand_end = 10 * (te - ts)                      #rand_end也不知道。te-ts不就是整个特效存在的时间。。

  49. 难道是像素点的时间?
  50.         EFT = move(x, y, x_fin, y_fin, rand_ini, rand_end) + fad(70, 0) + color1('0337C1') + fsc(125, 125)

  51. + shad(0) + bord(0) + alpha(255 - points[indice_text][2]) + t(alpha(255) + fsc(50, 50))  #points

  52. [indice_text][2]这个偶不明白
  53.         ass_main(ASS_BUF, SubL(ts, te, 0, Pix_Style), EFT, PixPt())
  54.     ##### 将结果返回给tcax进行处理 #####
  55.     return (ASS_BUF, TCAS_BUF)
复制代码
呜咕。。一个一个的问这样实在没效率。。所以偶试着自己翻译代码。。。感觉错误好多。。请M大大帮偶检查一下。。。真心请教
作者: milkyjing    时间: 2013-2-19 19:07:15

爱雪音MiKu 发表于 2013-2-19 15:30
呜咕。。一个一个的问这样实在没效率。。所以偶试着自己翻译代码。。。感觉错误好多。。请M大大帮偶检查一 ...

好像我時間很多一樣 233...

給你一個建議, 按照自己的理解去隨便修改代碼, 生成看效果 --> 重複這步驟. 實踐出真知...


作者: 爱雪音MiKu    时间: 2013-2-19 19:23:03

milkyjing 发表于 2013-2-19 19:07
好像我時間很多一樣 233...

給你一個建議, 按照自己的理解去隨便修改代碼, 生成看效果 --> 重複這步驟.  ...

呜咕。。V。。好的。。偶去修改实践了。。谢谢M大大的建议
作者: 爱雪音MiKu    时间: 2013-2-20 17:38:13

呜咕。。M大大问以个问题。。。maxi = int(tab_posy[0] - tab_posy[3]) + 90   这句代码偶改了感觉没什么变化。。但是偶想不让像素按照曲线扩散,所以就去掉了曲线的那个代码但是   indice_pos = randint(0, maxi + 1)   这行错误总是显示  可能是偶不明白maxi的意思偶所以就不知道该怎么去改了(T.T)
作者: milkyjing    时间: 2013-2-20 19:12:04

爱雪音MiKu 发表于 2013-2-20 17:38
呜咕。。M大大问以个问题。。。maxi = int(tab_posy[0] - tab_posy[3]) + 90   这句代码偶改了感觉没什么变 ...

要學會自己看懂出錯提示... 出錯誤是難免的...
別人能提供的幫助總是有限的...

嘛, 你可以把錯誤截圖貼一下...
作者: 爱雪音MiKu    时间: 2013-2-20 19:18:45

milkyjing 发表于 2013-2-20 19:12
要學會自己看懂出錯提示... 出錯誤是難免的...
別人能提供的幫助總是有限的...

ZKA06JY(5H68EJ6}CS{RMJ0.jpg
呜咕。。偶也想可以看懂错误提示。。但是这种错误偶没遇到过啦。。所以不知道原因。。。

嘎哦。。偶感觉是取值范围的问题?

图片附件: ZKA06JY(5H68EJ6}CS{RMJ0.jpg (2013-2-20 19:16:30, 386.24 KB) / 下载次数 1427
http://tcax.org/forum.php?mod=attachment&aid=MTIzMnw4MjZhNWM4Y3wxNzE0NjE0MzQ3fDB8MA%3D%3D


作者: milkyjing    时间: 2013-2-20 19:33:48

爱雪音MiKu 发表于 2013-2-20 19:18
呜咕。。偶也想可以看懂错误提示。。但是这种错误偶没遇到过啦。。所以不知道原因。。。

嘎哦。。偶感 ...


學會讀懂出錯提示: 第38行代碼錯誤 (有時候需要聯繫上下文), 錯誤信息是 tuple index out of range (一般錯誤提示都是很簡單的英文, 實在不行Google翻譯一下), 意思是說 元素索引越界. 這裡的 "元組" 指的是 points, 索引indice_pos和0都是 (因為是二維數組). 這些內容都是基本的, 必須要掌握. 索引越界意思是 下標超過了最大個數.

有了以上信息之後, 你需要開始排查錯誤原因. 為什麼會出現這個錯誤? 那麼, 你首先要知道 points 元組包含了多少個元素? 這就要回朔到points被賦值的地方, points = gfGetPoints(...). 這裡, 你必須要了解的是元組, 數組的概念 (這個也很基本).

http://www.tcax.org/forum.php?mod=viewthread&tid=22

這個帖子提到的一些內容你是否都已經掌握了呢? 如果回答是肯定的, 我可以繼續幫你分析下去.

嘛, 學習要踏實一點, 一步一個腳印.



作者: 爱雪音MiKu    时间: 2013-2-20 19:46:40

milkyjing 发表于 2013-2-20 19:33
學會讀懂出錯提示: 第38行代碼錯誤 (有時候需要聯繫上下文), 錯誤信息是 tuple index out of range (一般 ...

呜咕。。可以
作者: 爱雪音MiKu    时间: 2013-2-21 18:44:34

milkyjing 发表于 2013-2-20 19:33
學會讀懂出錯提示: 第38行代碼錯誤 (有時候需要聯繫上下文), 錯誤信息是 tuple index out of range (一般 ...

呜咕。。今天下午无聊发呆。。想了一个下午。。决定自己还是重新再一次的系统式的学习一下PY语言。。这一次决定学好会了。。再回来。。。感觉偶自己以现在的方式学的东西是不会多的。。想重新再学一下
作者: milkyjing    时间: 2013-2-21 20:15:57

爱雪音MiKu 发表于 2013-2-21 18:44
呜咕。。今天下午无聊发呆。。想了一个下午。。决定自己还是重新再一次的系统式的学习一下PY语言。。这一 ...

这个想法好。不过学习过程也可以有交流。。。

关键还是合理提问。问合理的问题。
作者: 爱雪音MiKu    时间: 2013-2-21 20:26:48

milkyjing 发表于 2013-2-21 20:15
这个想法好。不过学习过程也可以有交流。。。

关键还是合理提问。问合理的问题。 ...

呜咕。。V。。偶会尽全力自己学习理解的。。遇到实在无法明白的问题。。再来请教大大们的帮助吧。。。这次一定要学好。。
作者: lilight    时间: 2013-5-12 17:36:59

  1.     for part in range(bucle):
  2.         indice_text = randint(0, pt_num - 1)
  3.         indice_pos = randint(0, maxi - 1)
  4.         x = dx + points[indice_text][0]
  5.         y = dy + points[indice_text][1]
  6.         x_fin = pos_cur[indice_pos][0]
  7.         y_fin = pos_cur[indice_pos][1]
  8.         rand_ini = randint(50, 400)
  9.         ts = _end - 30 + _j * 2.5
  10.         te = ts + 65 + _j * 2.5
  11.         rand_end = 10 * (te - ts)
  12.         EFT = move(x, y, x_fin, y_fin, rand_ini, rand_end) + fad(70, 0) + color1('0337C1') + fsc(125, 125) + shad(0) + bord(0) + alpha(255 - points[indice_text][2]) + t(alpha(255) + fsc(50, 50))
复制代码
奶大,关于这一段,问两个问题:

1. 从最后的move代码看,这个是将 “字上的像素” 从原始位置 “移动到” 曲线上 的位置,而不是“沿着”曲线,对吧?


2. 循环中所取的点的下标,是随机取的,因为randint会取到重复的值,可以保证所有点都被取到?
    遇到重复的下标的时候,怎么执行的?

  希望奶大有空的时候看下~
多谢奶大
作者: milkyjing    时间: 2013-5-12 18:39:02

lilight 发表于 2013-5-12 17:36
奶大,关于这一段,问两个问题:

1. 从最后的move代码看,这个是将 “字上的像素” 从原始位置 “移动到” ...

Re1. 是的.

关于让像素点沿着曲线运动, 这个也可以继续做, 对每个像素点, 生成一个曲线路径即可. 但要让效果好, 还是不太容易控制的.

Re2. 会有点重复的, 也不保证能取完.

算法可以进一步改进. 但要以能产生更好的效果为目标.

重复了也没什么影响, 你可以实验一下, 把indice_text改成一个常数, 看看会是什么效果. 然后改成 randint(0, 2), 等等...


作者: stacer    时间: 2014-12-17 20:59:05

为什么我套用了这段代码然后AVS播放什么也不显示?
作者: Det.Rush    时间: 2015-12-23 12:23:55

圆角在Aeg里面显示成直的了,似乎和像素有关?来求解
作者: inalo    时间: 2016-1-19 11:58:54

字幕特效果真有机会做全动画特效了




欢迎光临 TCAX 字幕特效制作工具官方论坛 | ASS | TCAS | Python | Aegisub | Lua (http://tcax.org/) Powered by Discuz! X2