REM. Apple deform 2


     
*ESC OFF


     *FLOAT 64



     ON ERROR PROCerror( REPORT$, TRUE )



     REM. Reserve 2MB of RAM for this program
     
M% = 2
     HIMEM = LOMEM + M%*&100000
     HIMEM = (HIMEM + 3) AND -4


     REM. Prevent the user from resizing the window
     REM. (although it can still be minimized)
     
PROCfixWindowSize


     SYS "SetWindowText", @hwnd%, "Apple deform 2"


     REM. Set our program window's dimensions (640 x 480)
     
WinW% = 640
     WinH% = 512
     VDU 23, 22, WinW%; WinH%; 8, 16, 16, 0 : OFF


     
REM. Install and initialise GFXLIB and required external modules
     
INSTALL @lib$ + "GFXLIB2"
     PROCInitGFXLIB

     INSTALL @lib$ + "GFXLIB_modules\BPlotScaleNC"
     PROCInitModule

     INSTALL @lib$ + "GFXLIB_modules\PlotRotateScale2"
     PROCInitModule


     REM. Load in the 400x400 apple bitmap (JPEG image)
     REM. The image will automatically be converted to the format (32bpp ARGB) required by GFXLIB
     
bm% = FNLoadImg( @dir$ + "apple_400x400.JPG", 0 )


     REM. Set up a bitmap buffer of sufficient size to contain a 32bpp 640x512 bitmap
     
bm2% = FNmalloc( 4*640*512 )


     REM. bmW% and bmH% must be the bitmap's actual width and height
     
bmW% = 400
     bmH% = 400


     REM. Get base address of dispVars struct into D% (for slightly more access speed)
     
D% = dispVars{}


     REM. Disable the automatic window refresh
     
*REFRESH OFF


     REPEAT

       SYS
GFXLIB_Clr%, dispVars{}, FNrgb( 255, 255, 255 )

       newBmH% = bmH% + 100*SIN(TIME/18)

       bmX% = (WinW% - bmW%) DIV 2
       bmY% = (WinH% - newBmH%) DIV 2

       REM. dx is the time-varying X displacement of the middle point of the quadratic curve
       
dx = 1.5*(newBmH% - bmH%)

       REM. Set up our three quadratic curve coordinates
       REM. (x1,y1),  (x2,y2),  (x3,y3)

       
x1 = bmX%
       y1 = bmY%

       x2 = x1 + dx
       y2 = y1 + newBmH%DIV2

       x3 = x1
       y3 = y1 + newBmH%


       REM. Our quadratic curve is of the form X = aY^2 + bY + c
       REM. We need to compute the unknown coefficients a, b and c
       
PROCgetQuadraticCoeffs( y1, x1, y2, x2, y3, x3, a, b, c )


       REM. Some pre-calculations (to improve loop efficiency)
       REM. Sorry if this appears rather cryptic
       
hScale% = newBmH% / bmH%
       bmW4% = 4 * bmW%
       x2`% = 2*bmX% + bmW%
       dy% = y3 - bmY%
       s = bmH% / dy%


       REM. Now draw the scaled rows of pixels from the bitmap
       
SYS GFXLIB_SaveDispVars%, dispVars{}
       SYS GFXLIB_SetDispVars2%, dispVars{}, bm2%, 640, 512
       SYS GFXLIB_Clr%, dispVars{}, 0
       REM. Draw the individual scaled rows of pixels from the bitmap
       
FOR Y% = y1 TO y3-1

         REM. Calculate the base address of a row of pixels
         
pRow% = bm% + bmW4% * INT(s*(Y%-bmY%))

         REM. Calculate the X-coordinate of the row
         
X = a*Y%^2 + b*Y% + c

         REM. Calculate the width of the row
         
rowWidth% = x2`% - 2*X

         REM. Draw the row of pixels
         
SYS GFXLIB_BPlotScaleNC%, D%, pRow%, bmW%, 1, rowWidth%, hScale%+1, X, Y%

       NEXT
       SYS
GFXLIB_RestoreDispVars%, dispVars{}


       REM. Display the rotated and scaled stretched/squashed apple bitmap
       
SYS GFXLIB_PlotRotateScale2%, dispVars{}, bm2%, 640, 512, WinW%DIV2, WinH%DIV2, \
       
\ &100000*360*SIN(TIME/400), &100000*ABS(3*SIN(TIME/1500)*COS(TIME/2019))


       REM. Update the program window
       
PROCdisplay

     UNTIL FALSE
     END


     
DEF PROCgetQuadraticCoeffs( x1, y1, x2, y2, x3, y3, RETURN a, RETURN b, RETURN c )
     PROCsolve2x2( x1^2-x2^2, x1-x2, y1-y2, \
     
\ x1^2-x3^2, x1-x3, y1-y3, \
     
\ a, b )
     c = y1 - (a*x1^2 + b*x1)
     ENDPROC


     
DEF PROCsolve2x2(A, B, C, D, E, F, RETURN x, RETURN y)
     LOCAL d
     d = (A*E - B*D)^-1
     x = d * (E*C - B*F)
     y = d * (A*F - D*C)
     ENDPROC


     
DEF PROCfixWindowSize
     LOCAL GWL_STYLE, WS_THICKFRAME, WS_MAXIMIZEBOX, ws%
     GWL_STYLE = -16
     WS_THICKFRAME = &40000
     WS_MAXIMIZEBOX = &10000
     SYS "GetWindowLong", @hwnd%, GWL_STYLE TO ws%
     SYS "SetWindowLong", @hwnd%, GWL_STYLE, ws% AND NOT (WS_THICKFRAME+WS_MAXIMIZEBOX)
     ENDPROC


     
DEF PROCerror( msg$, L% )
     OSCLI "REFRESH ON" : ON
     COLOUR
1, &FF, &FF, &FF
     COLOUR 1
     PRINT TAB(1,1)msg$;
     IF L% THEN
       PRINT
" at line "; ERL;
     ENDIF
     VDU
7
     REPEAT UNTIL INKEY(1)=0
     ENDPROC