- UID
- 2
- 积分
- 8682
- 帖子
- 2905
- 主题
- 199
- 论坛币
- 11739
- 威望
- 16
- EP值
- 2349
- MP值
- 15
- 阅读权限
- 200
- 注册时间
- 2011-8-3
- 在线时间
- 2597 小时
- 最后登录
- 2024-8-28
|
5. 如何编写TCAS特效
5.1 什么是PIX
从上面的例子中, 我们看出TCAS特效离不开一种结构, PIX. 下面就来详解一下PIX.
从宏观角度来看, PIX就是一张存放在内存中的图片, 至于图片的内容, 既可以是字符, 也可以是纹理, 或者就是单纯一张普通图片. PIX是编写TCAS特效要操作的主要对象. 作个类比, 在ASS中, 我们可以对文字或者绘图代码通过特效代码施加各种特殊效果, 如"{\blur2}好", 可以给"好"这个对象增加模糊效果. 在TCAS中, 我们可以使用各种PIX操作函数来操作PIX, 如PixBlur(PIX, 2), 可以返回一个新的PIX, 如果原来的PIX是一个写有"好"字的图片, 则返回的PIX效果就相当于"{\blur2}好"
从微观角度来看, PIX就是一个Python的复合Tuple(元组)对象, 其具体结构如下:
((x, y), (width, height), (r, g, b, a, r, g, b, a, ....))
PIX[0], 即(x, y), 保存的是这个PIX的相对位置信息
PIX[1], 即(width, height), 保存的是这个PIX的宽高
PIX[2], 即(r, g, b, a, r, g, b, a, ....), 保存的是实际像素信息, 存放方式是r, g, b, a(红, 绿, 蓝, 不透明度)四个一组, 按照行存储. 像素是一个重要概念, 如果对此还不太了解, 可以参考 http://zh.wikipedia.org/zh/像素
PIX的内部细节可参考如下代码:- # 像素字特效固定代码框架 开始
- PIX = TextPix(_Font, _txt) # 获取当前文字的PIX结构
- initPosX = _x - int(_a / 2 + 0.5) + PIX[0][0] # 第一个像素的X轴坐标
- initPosY = _y - int(_Fs / 2 + 0.5) + PIX[0][1] # 第一个像素的Y轴坐标
- for h in range(PIX[1][1]): # 开始纵向扫描
- posY = initPosY + h # 当前像素Y轴坐标
- for w in range(PIX[1][0]): # 开始横向扫描
- posX = initPosX + w # 当前像素X轴坐标
- idx = 4 * (h * PIX[1][0] + w) # 脚标
- pixR = PIX[2][idx + 0] # 当前像素的红色分量
- pixG = PIX[2][idx + 1] # 当前像素的绿色分量
- pixB = PIX[2][idx + 2] # 当前像素的蓝色分量
- pixA = PIX[2][idx + 3] # 当前像素的透明度
- if pixA != 0: # 如果当前像素不为透明则进行如下操作
- # 增加你的效果, 注意Style使用Pix_Style
- ass_main(ASS_BUF, SubL(_start, _end, 0, Pix_Style), pos(posX, posY) + color1(FmtRGB(pixR, pixG, pixB)) + alpha1(255 - pixA), PixPt())
- # 像素字特效固定代码框架 结束
复制代码 补充: 关于PIX[2]的结构, 以及idx的计算.
(图片改为 忘却の小伊 的了)
图片是由一个一个像素点构成的, 我们可以把它当做是放置于直角坐标系中的一个矩形. 如果我们固定矩形的左下角顶点为坐标原点, 则图片上的每一个像素点都对应一个整数坐标(x, y), 其中0<=x<width, 0<=y<height. 如图, 红色标示的像素点, 其坐标为(1, 2), 但我们用的是一维数组来存储这个二维图片, 并且是按照行来存储的, 也即, PIX[2]中的第0~(width-1)号元素存的是图片的第一行像素, width~(2*width - 1)号元素存的是第二行像素, 依次类推. 所以在PIX[2]中, 图片的红色点坐标可以转换为2 * 5 + 1. 之所以计算idx需要乘上4, 是因为对于一个像素点, 我们需要4个元素来分别存储它的红, 绿, 蓝, 不透明度分量.
通常我们不需要关心PIX的细节, 因为PIX的操作函数是把PIX当做一个整体来操作的, 返回的结果仍然是一个PIX.
5.2 如何得到PIX
由基本函数构造原始PIX
TextPix()函数, 可以由字符来构造PIX, 如 PIX = TextPix(Font, "你好"), 则PIX是一张包含"你好"二字的图片
ImagePix()函数, 可以读入一张png格式的图片, 如 PIX = ImagePix(abspath('test.png')), 则PIX是一张包含test.png内容的图片
BlankPix()函数, 可以构造一张纯色的图片, 如 PIX = BlankPix(width, height, MakeRGBA(255, 0, 0, 128)), 则PIX是一张红色的半透明图片
util.cairo模块的surface.get_pix()函数可以由cairo的surface对象构造PIX
util.magick模块的pmgToPix()函数可以由magick的image对象构造PIX
由PIX操作函数转换已有PIX而得
如PixBlur()等函数, 该类型函数可接受一个或多个PIX对象, 以及一些额外参数, 进行适当的变换后返回一个新的PIX对象.
自己手动构造
即, 不使用内部函数, 直接用Python脚本编写代码构造出一个满足条件的PIX对象. 需要对PIX的内部细节有较为详细的了解, 并熟悉Python的tuple及list等操作, 在此基础上, 就可以自由构造PIX对象了.
5.3 TCAS特效相关函数参考
tcaxLib.pyd模块文档
编译版 (更适合查看)
原始文档
pixStone.pyd模板文档
未整理, 仅作参考
util.cairo模块文档
Pycairo Documentation
util.magick模板文档
Magick++ Documentation
5.4 实例教程
完整工程下载:
tcas_example.rar
(7.12 MB, 下载次数: 4634)
编写一个TCAS特效, 可以归结为创建PIX, 变换PIX, 将PIX写入文件, 这三个主要步骤, 额外的, 我们一般需要先利用InitFont()函数创建至少一个字体.
教程实例代码如下:- ##################################################################
- ## 声明: 本脚本为TCAS特效使用教程所编写, 请广泛传播 ##
- ## 教程: http://www.tcax.org/forum.php?mod=viewthread&tid=220 ##
- ## 讨论: http://www.tcax.org/forum.php?mod=viewthread&tid=226 ##
- ## 版本: 1.0 ##
- ## 作者: milkyjing ##
- ## 日期: 2012-01-26 ##
- ##################################################################
- ##### 基本函数库, 必须包含 #####
- from tcaxPy import *
- ##### 拓展函数库, 本特效需要包含 #####
- from pixLibs.ImageStone import *
- ##### 初始化函数, 用于设定一些全局变量 #####
- def tcaxPy_Init():
- ##### 声明全局变量 #####
- global _FD # Frame Duration, 即一帧的长度, 单位是毫秒, 对于FPS=23.976的特效来说, _FD约为42毫秒
- global _Fs # Font Size, 即字体大小
- global _Spacing # 字体间距
- global Font # 主要字体
- global FontOut # 字体边框
- global PIX_tex1 # 纹理1, 因为本特效只用到两个静态纹理, 故直接在tcaxPy_Init()函数中定义以提高脚本执行效率
- global PIX_tex2 # 纹理2
- ##### 获取预定义的值 #####
- _FD = 1000 / GetVal(val_FXFPS)
- _Fs = GetVal(val_FontSize)
- _Spacing = GetVal(val_Spacing)
- fontFileName = GetVal(val_FontFileName) # 字体文件名
- faceID = GetVal(val_FaceID) # 字体face序号
- ##### 设置自定义变量的值 #####
- Font = InitFont(fontFileName, faceID, _Fs, _Spacing, GetVal(val_SpaceScale), MakeRGB(0, 0, 0), 1, False) # 通过InitFont()函数初始化一个字体
- FontOut = InitFont(fontFileName, faceID, _Fs, _Spacing, GetVal(val_SpaceScale), MakeRGB(0, 0, 0), 5, True) # 后三个参数分别为颜色, 边框厚度, 是否只保留边框
- PIX_tex1 = ImagePix(abspath('tex1.png'), _Fs, 0) # 通过ImagePix()函数载入一张图片作为纹理, abspath()函数用于展开相对路径为绝对路径
- PIX_tex2 = ImagePix(abspath('tex2.png')) # 后两个参数为目标宽高, 其中之一为0, 表示其值按照保持目标的宽高比不变, 自动进行计算
- ##### 结束函数, 用于一些收尾工作 #####
- def tcaxPy_Fin():
- ##### 清理一些全局变量 #####
- FinFont(Font) # 通过InitFont()函数创建的字体必须通过FinFont()函数进行销毁
- FinFont(FontOut)
- ##### 脚本主函数, 会对每个文字执行一次 #####
- # _i 第_i句, 即当前操作的文字所在的句子序号
- # _j 第_i句中的第_j个文字, 即当前操作文字在该行中的序号
- # _n 第_i句中有_n个文字, 即当前句子所包含的文字数
- # _start 句子的开始时间, 单位为10毫秒
- # _end 句子的结束时间, 单位为10毫秒
- # _elapk 到第_j个字经过的时间, _start + _elapk 到 _start + _elapk + _k 即为当前文字的存在时间, 单位为10毫秒
- # _k 第_j个文字的卡拉OK时间, 单位为10毫秒
- # _x 第_j个文字的水平坐标
- # _y 第_j个文字的垂直坐标
- # _a 第_j个文字的水平跨距, 可以看作文字的宽度, 同样_Fs也可近似看成文字的高度
- # _txt 第_j个文字的内容
- def tcaxPy_Main(_i, _j, _n, _start, _end, _elapk, _k, _x, _y, _a, _txt):
- ASS_BUF = [] # 保存ASS特效
- TCAS_BUF = [] # 保存TCAS特效
- ##### 主要特效编写操作 #####
- # 基本坐标的计算
- dx = _x - int((_a + _Spacing) / 2 + 0.5) # 一个固定操作, 将an5的坐标转换为an7
- dy = _y - int(_Fs / 2 + 0.5) # ASS特效默认采用an5坐标, TCAS特效则采用an7坐标
- if _i == 12: # 因为时间上有重叠, 所以需要把这一句的坐标往下移一点, 使两句歌词不至于重叠显示
- dy += _Fs + 8
- # 基本时间的计算
- ts_0 = 10 * _start - _FD * 10 # 提前显示歌词, 提前量为10帧长度, "10 * _start"只是一个单位转换, ASS特效使用了两种时间单位, 10毫秒及1毫秒, TCAS特效则统一使用1毫秒为单位
- ts = 10 * _start
- te = 10 * _end
- te_0 = te + _FD * 5 # 延后量为5帧长度
- tm = 10 * (_start + _elapk) # 当前文字特效开始的时间
- # 构造原始PIX结构对象
- PIX_t = TextPix(Font, _txt) # 通过TextPix()函数从文字构造PIX结构对象
- PIX_t = PixTexture(PIX_t, PIX_tex1) # 为PIX_t增加纹理
- PIX_out = TextPix(FontOut, _txt) # 获取边框
- PIX_out = PixBlur(PIX_out, 6) # 增加模糊
- PIX_out = PixTexture(PIX_out, PIX_tex2) # 增加纹理
- PIX_out = PixColorMul(PIX_out, 1, 1, 1, 0.8) # 减少不透明度, 即增加透明度
- PIX_0 = CombinePixs(PIX_out, PIX_t) # 混合文字主体和边框 (边框作底)
- # 入场效果, 移动(用到了简单的平面几何知识) + 模糊逐渐变清晰
- center = _n / 2 - 0.5 # 根据该公式5个字符的中心索引为2, 6个字符的中心索引为2.5, 因为索引是从0开始计算的
- x = dx + 50 * (_j - center) / center
- y = dy + 10
- for i in range(10):
- x = x + (dx - x) * (i + 1) / 5 # 逐帧修改坐标
- y = y + (dy - y) * (i + 1) / 5
- PIX = PixBlur(PIX_0, 40 - i * 4) # 逐渐减少模糊度
- tcas_main(TCAS_BUF, PIX, ts_0 + _FD * i, ts_0 + _FD * (i + 1), x, y, 0) # 通过tcas_main()函数向TCAS_BUF缓冲带增加一个PIX对象, 最后一个参数表示Layer, 含义与ASS特效中的Layer相同
- # 存在效果, 无特殊效果
- PIX = PIX_0
- tcas_main(TCAS_BUF, PIX, ts, te, dx, dy, 0)
- # 表现效果, 闪烁特效
- for dur in range(0, 10 * _k, int(2 * _FD)):
- PIX = pstSoftGlow(PIX_0, 10, 180, 180) # 柔光效果, 该函数定义在pixStone.pyd模块中
- tcas_main(TCAS_BUF, PIX, tm + dur, tm + dur + _FD, dx, dy, 0) # 隔一帧显示一次
- # 出场效果, 清晰变模糊 + 淡出
- for i in range(5):
- PIX = PixBlur(PIX_0, (i + 1) * 4) # 逐渐增加模糊度
- PIX = PixColorMul(PIX, 1, 1, 1, 0.5 + 0.5 * (5 - i - 1) / 5) # 逐渐减少不透明度, 即逐渐变得透明
- tcas_main(TCAS_BUF, PIX, te_0 - _FD * (5 - i), te_0 - _FD * (5 - i - 1), dx, dy, 0)
- ##### 将结果返回给TCAX进行处理 #####
- return (ASS_BUF, TCAS_BUF)
复制代码 该代码中使用的函数的具体描述, 可以参考本教程的5.3节
|
|