第一次尝试旋转和缩放位图时,我做了一个显而易见的选择:从源矩阵中取出每个像素,通过旋转和缩放对其进行变换,然后将值写入目标中变换后的位置。结果如下所示:
bitmap = J( bmy = 200, bmx = 300, RGB Color( 1, 1, 1 ) );//white
scale = 3;
tranmat = (1 || 0 || 80) |/ (0 || 1 || 10) |/ (0 || 0 || 1); // 2D translation matrix
scalmat = (scale || 0 || 0) |/ (0 || scale || 0) |/ (0 || 0 || 1); // 2D scale matrix
angle = 33 * Pi() / 180;
sangle = Sin( angle );
cangle = Cos( angle );
rotamat = (cangle || -sangle || 0) |/ (sangle || cangle || 0) |/ (0 || 0 || 1); // 2D rotation matrix
forward = (tranmat * scalmat * rotamat)`; // transpose here
// make a sample image
testimage = Text Box( "matrix", <<SETWRAP></SETWRAP>
Transformed text has holesTransformed text has holesTransformed text has holesTransformed text has holes转换后的文本有漏洞
看起来很糟糕。 正确的方法是使用变换矩阵的逆矩阵并询问“对于目标位图中的每个像素,我应该使用源中的哪个像素?” 但答案几乎总是落在四个像素之间。 一个合理的答案是使用四个像素的加权平均值,更复杂的答案可能看起来像双三次插值。 此代码使用加权平均值:
// this bitmap is used to build the image. drawtext will write
// each string into this bitmap.
bitmap = J( bmy = 300, bmx = 580, RGB Color( 1, 1, 1 ) );//white
// drawtext is a slow routine that draws a text string into a buffer,
// then samples that buffer to create a rotated, scaled copy in the
// bitmap buffer.
drawtext = Function(
{x = 0, y = 0, txt = "hello", degAngle = 0, xjust = 0, yjust = 1, fontsize = 99, scale = .5, textcolor = RGB Color( 0, 0, 0 )}, // parms
{// locals, initialized. Creates a transform matrix and its inverse
t = Text Box( txt, <<SETWRAP></SETWRAP>
Sampling the source image with linear interpolationSampling the source image with linear interpolationSampling the source image with linear interpolationSampling the source image with linear interpolation使用线性插值对源图像进行采样
代码的后半部分与其说是关于矩阵变换,不如说是制作一幅有趣的图画。 水平条纹是通过将多个图像副本混合在一起创建的,每个副本移动一个像素,并保留较少的更远的移动。
Big, tilted, orangeBig, tilted, orangeBig, tilted, orangeBig, tilted, orange大,倾斜,橙色