初めてビットマップの回転とスケーリングを試みたとき、当然の選択をしました。ソース マトリックスから各ピクセルを取得し、回転とスケーリングで変換し、値を変換先の変換された場所に書き込みます。結果は次のようになります。
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 holes変換されたテキストに穴があります
ひどいですね。 正しい方法は、変換行列の逆を使用して、「宛先ビットマップの各ピクセルについて、ソースからどのピクセルを使用する必要があるか?」と尋ねることです。 しかし、答えはほとんどの場合、4 ピクセルの間に収まります。 合理的な答えは、4 つのピクセルの加重平均を使用することです。より複雑な答えは、双 3 次補間のように見える場合があります。 このコードは加重平均を使用します。
// 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 interpolation線形補間によるソース画像のサンプリング
コードの後半は、興味深い図を作成するための行列変換に関するものではありません。 水平方向のストリーキングは、画像の多数のコピーを一緒にブレンドすることによって作成され、それぞれが 1 ピクセルずつシフトされ、より離れたシフトは少なく維持されます。
Big, tilted, orange大きい、傾いた、オレンジ