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

 找回密码
 新人加入
查看: 2859|回复: 6

[已解决] 请问在TCAS中怎么旋转PIX? [复制链接]

Rank: 4

发表于 2012-8-13 21:08:39 |显示全部楼层
沿z轴的旋转貌似可以先转成image再rotate, 如果是沿x轴和y轴呢

Administrator

TCAX Dev.

Rank: 7Rank: 7Rank: 7

发表于 2012-8-13 21:21:06 |显示全部楼层
貌似我没见到直接的方法, 但如果有一定编码能力的话, 可以按照如下思路去编写:
  1. def ca_frz(x, y, a):
  2.     x2 = x * cos(a) + y * sin(a)
  3.     y2 = x * sin(a) + y * cos(a)
  4.     return x2, y2

  5. def ca_fry(x, y, a):
  6.     x2 = x * cos(a)
  7.     y2 = y
  8.     return x2, y2

  9. def ca_frx(x, y, a):
  10.     x2 = x
  11.     y2 = y * cos(a)
  12.     return x2, y2
复制代码
这个是我为cairo模块写的旋转代码, 利用这个原理, 以及双线性插值
  1. int x = floor(u);
  2.    int y = floor(v);
  3.    double u_ratio = u - x;
  4.    double v_ratio = v - y;
  5.    double u_opposite = 1 - u_ratio;
  6.    double v_opposite = 1 - v_ratio;
  7.    double result = (tex[x][y]   * u_opposite  + tex[x+1][y]   * u_ratio) * v_opposite +
  8.                    (tex[x][y+1] * u_opposite  + tex[x+1][y+1] * u_ratio) * v_ratio;
复制代码
(目标PIX中的一点由源PIX中最近的4点决定)

关于PIX的操作, 可以看最新版的TCAX中的tcaxPy.py, 里面有一些相关的函数可供参考.

p.s. 我没时间来编码这东西了, 所以靠自己努力吧, Fight~


Administrator

TCAX Dev.

Rank: 7Rank: 7Rank: 7

发表于 2012-8-18 18:03:53 |显示全部楼层
抽空写了个简单的, 基于最近点的绕X轴旋转代码. 未测试
  1. # PIX rotate around x-axis, nearest point approach,
  2. # the position of PIX is maintained by fixing the middle of the original PIX still
  3. # point (x, y) maps to a new point (u, v) by the formula u = x, v = y * cos(ag)
  4. # so destination resolution of PIX is dst_width = src_width, dst_height = src_height * cos(ag)
  5. def PixRotateX_nearest(PIX, ag):
  6.     src_width = PIX[1][0]
  7.     src_height = PIX[1][1]
  8.     dst_width = src_width
  9.     dst_height = int(src_height * cos(ag) + 0.5)
  10.     PIX_pos = (PIX[0][0], PIX[0][1] + (src_height - dst_height) / 2)
  11.     PIX_res = (dst_width, dst_height)
  12.     size = dst_height * dst_width * 4
  13.     PIX_rgba = [0 for c in range(size)]
  14.     for h in range(dst_height):
  15.         for w in range(dst_width):
  16.             dst_idx = 4 * (h * dst_width + w)
  17.             src_idx = 4 * (int(h * cos(ag) + 0.5) * src_width + w)
  18.             PIX_rgba[dst_idx] = PIX[2][src_idx]
  19.             PIX_rgba[dst_idx + 1] = PIX[2][src_idx + 1]
  20.             PIX_rgba[dst_idx + 2] = PIX[2][src_idx + 2]
  21.             PIX_rgba[dst_idx + 3] = PIX[2][src_idx + 3]
  22.     return (PIX_pos, PIX_res, tuple(PIX_rgba))
复制代码

Administrator

TCAX Dev.

Rank: 7Rank: 7Rank: 7

发表于 2012-8-19 18:08:11 |显示全部楼层
经测试, 上帖第17行代码 h * cos(ag) 应改为 h / cos(ag), 顺带写了绕Y轴的最近点算法版本.
注: 不管是绕X轴旋转抑或是绕Y轴旋转, 都未考虑进"透视感"(即, 近端变大, 远端变小). 有待升级
  1. from math import cos

  2. # PIX rotate around x-axis, nearest point approach,
  3. # the position of PIX is maintained by fixing the middle of the original PIX still
  4. # point (x, y) maps to a new point (u, v) by the formula u = x, v = y * cos(ag)
  5. # so destination resolution of PIX is dst_width = src_width, dst_height = src_height * cos(ag)
  6. def PixRotateX_nearest(PIX, ag):
  7.     src_width = PIX[1][0]
  8.     src_height = PIX[1][1]
  9.     dst_width = src_width
  10.     dst_height = int(src_height * cos(ag) + 0.5)
  11.     PIX_pos = (PIX[0][0], PIX[0][1] + (src_height - dst_height) / 2)
  12.     PIX_res = (dst_width, dst_height)
  13.     size = dst_height * dst_width * 4
  14.     PIX_rgba = [0 for c in range(size)]
  15.     for h in range(dst_height):
  16.         for w in range(dst_width):
  17.             dst_idx = 4 * (h * dst_width + w)
  18.             src_idx = 4 * (int(h / cos(ag) + 0.5) * src_width + w)
  19.             PIX_rgba[dst_idx] = PIX[2][src_idx]
  20.             PIX_rgba[dst_idx + 1] = PIX[2][src_idx + 1]
  21.             PIX_rgba[dst_idx + 2] = PIX[2][src_idx + 2]
  22.             PIX_rgba[dst_idx + 3] = PIX[2][src_idx + 3]
  23.     return (PIX_pos, PIX_res, tuple(PIX_rgba))

  24. # PIX rotate around y-axis, nearest point approach,
  25. # the position of PIX is maintained by fixing the middle of the original PIX still
  26. # point (x, y) maps to a new point (u, v) by the formula u = x * cos(ag), v = y
  27. # so destination resolution of PIX is dst_width = src_width * cos(ag), dst_height = src_height
  28. def PixRotateY_nearest(PIX, ag):
  29.     src_width = PIX[1][0]
  30.     src_height = PIX[1][1]
  31.     dst_width = int(src_width * cos(ag) + 0.5)
  32.     dst_height = src_height
  33.     PIX_pos = (PIX[0][0] + (src_width - dst_width) / 2, PIX[0][1])
  34.     PIX_res = (dst_width, dst_height)
  35.     size = dst_height * dst_width * 4
  36.     PIX_rgba = [0 for c in range(size)]
  37.     for h in range(dst_height):
  38.         for w in range(dst_width):
  39.             dst_idx = 4 * (h * dst_width + w)
  40.             src_idx = 4 * (h * src_width + int(w / cos(ag) + 0.5))
  41.             PIX_rgba[dst_idx] = PIX[2][src_idx]
  42.             PIX_rgba[dst_idx + 1] = PIX[2][src_idx + 1]
  43.             PIX_rgba[dst_idx + 2] = PIX[2][src_idx + 2]
  44.             PIX_rgba[dst_idx + 3] = PIX[2][src_idx + 3]
  45.     return (PIX_pos, PIX_res, tuple(PIX_rgba))
复制代码

Administrator

TCAX Dev.

Rank: 7Rank: 7Rank: 7

发表于 2012-8-19 18:20:15 |显示全部楼层
VSFilter中, 关于frx, fry, frz的代码是(同时输入3个角度以及一个坐标原点, 一同进行变换, 未指定的角度, 默认为0)
  1. void CWord::Transform(CPoint org)
  2. {
  3.         double scalex = m_style.fontScaleX/100;
  4.         double scaley = m_style.fontScaleY/100;

  5.         double caz = cos((3.1415/180)*m_style.fontAngleZ);
  6.         double saz = sin((3.1415/180)*m_style.fontAngleZ);
  7.         double cax = cos((3.1415/180)*m_style.fontAngleX);
  8.         double sax = sin((3.1415/180)*m_style.fontAngleX);
  9.         double cay = cos((3.1415/180)*m_style.fontAngleY);
  10.         double say = sin((3.1415/180)*m_style.fontAngleY);

  11.         for(int i = 0; i < mPathPoints; i++)
  12.         {
  13.                 double x, y, z, xx, yy, zz;

  14.                 x = scalex * (mpPathPoints[i].x + m_style.fontShiftX * mpPathPoints[i].y) - org.x;
  15.                 y = scaley * (mpPathPoints[i].y + m_style.fontShiftY * mpPathPoints[i].x) - org.y;
  16.                 z = 0;

  17.                 xx = x*caz + y*saz;
  18.                 yy = -(x*saz - y*caz);
  19.                 zz = z;

  20.                 x = xx;
  21.                 y = yy*cax + zz*sax;
  22.                 z = yy*sax - zz*cax;

  23.                 xx = x*cay + z*say;
  24.                 yy = y;
  25.                 zz = x*say - z*cay;

  26.                 zz = max(zz, -19000);

  27.                 x = (xx * 20000) / (zz + 20000);
  28.                 y = (yy * 20000) / (zz + 20000);

  29.                 mpPathPoints[i].x = (LONG)(x + org.x + 0.5);
  30.                 mpPathPoints[i].y = (LONG)(y + org.y + 0.5);
  31.         }
  32. }
复制代码

Rank: 5Rank: 5

发表于 2012-8-20 08:28:42 |显示全部楼层
别折磨好少年了,牛奶大,直接搞内置函数得了@@

Rank: 4

发表于 2012-8-29 20:52:54 |显示全部楼层
受益良多!感谢牛奶大
您需要登录后才可以回帖 登录 | 新人加入

GitHub|TCAX 主页

GMT+8, 2024-3-19 19:01

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部
RealH