Als ich zum ersten Mal versuchte, eine Bitmap zu drehen und zu skalieren, traf ich die offensichtliche Wahl: Nimm jedes Pixel aus der Quellmatrix, transformiere es mit einer Drehung und Skalierung und schreibe den Wert an die transformierte Position im Ziel.Das Ergebnis sieht so aus:
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 holesTransformierter Text hat Löcher
Sieht schrecklich aus. Der richtige Weg besteht darin, die Umkehrung der Transformationsmatrix zu verwenden und zu fragen: "Welches Pixel sollte ich für jedes Pixel in der Ziel-Bitmap aus der Quelle verwenden?" Aber die Antwort wird fast immer zwischen vier Pixel fallen. Eine vernünftige Antwort ist die Verwendung eines gewichteten Durchschnitts der vier Pixel, und kompliziertere Antworten könnten wie eine bikubische Interpolation aussehen. Dieser Code verwendet einen gewichteten Durchschnitt:
// 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 interpolationAbtasten des Quellbildes mit linearer Interpolation
In der letzten Hälfte des Codes geht es weniger um Matrixtransformationen als um ein interessantes Bild. Die horizontalen Streifen werden erzeugt, indem eine Anzahl von Kopien des Bildes zusammengemischt werden, wobei jede um ein Pixel verschoben wird, und weniger der weiter entfernten Verschiebungen beibehalten werden.
Big, tilted, orangeBig, tilted, orangeBig, tilted, orangeBig, tilted, orangeGroß, schräg, orange