La prima volta che ho provato a ruotare e ridimensionare una bitmap, ho fatto la scelta più ovvia: prendere ogni pixel dalla matrice di origine, trasformarlo con una rotazione e una scala e scrivere il valore nella posizione trasformata nella destinazione.Il risultato è simile a questo:
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 holesIl testo trasformato presenta dei buchi
Sembra terribile. Il modo corretto è usare l'inverso della matrice di trasformazione e chiedere "Per ogni pixel nella bitmap di destinazione, quale pixel dovrei usare dalla sorgente?" Ma la risposta cadrà quasi sempre tra quattro pixel. Una risposta ragionevole è utilizzare una media ponderata dei quattro pixel e risposte più complicate potrebbero sembrare un'interpolazione bicubica. Questo codice utilizza una media ponderata:
// 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 interpolationCampionamento dell'immagine sorgente con interpolazione lineare
L'ultima metà del codice non riguarda tanto le trasformazioni di matrici quanto la creazione di un'immagine interessante. Le striature orizzontali vengono create fondendo insieme un numero di copie dell'immagine, ciascuna spostata di un pixel, e mantenendo meno spostamenti più distanti.
Big, tilted, orangeGrande, inclinato, arancione