Author Topic: Grid-a-Pic (a peck o' pickled peppers...)  (Read 3133 times)

0 Members and 1 Guest are viewing this topic.

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Grid-a-Pic (a peck o' pickled peppers...)
« on: December 06, 2020, 04:34:06 pm »
I haven't done much contributing here lately, as I've been obsessing over my bucket list project, and I'm about the slowest coder on the planet. So I thought I'd share this errant bit of knavery, which I came up with while taking a break from the "bucket..." project.

It's made possible, thanks to Steve's Save Image library, so I included that in the zip.

In keeping with my leanings towards RPG gamemaster utilities, it loads a picture, overlays a hex or square grid which can be shifted and resized. Adjust a grid to a map legend, or grid a picture for tracing, or whatever else one can dream up to do with it.

Mouse or hotkey interface.
Arrow keys pan around the image or drag with mouse in large display.
Change grid size with "+"/"-" or use size buttons
Offset the grid by half in four directions with "ADWZ" or rocker.
Change from hex to box grid with "HB" or buttons. Click or press active again to turn it off.
Save it once it's acceptable.

It kind of works OK, for a quickie.

Code: QB64: [Select]
  1. '$INCLUDE:'SaveImage.BI'
  2.  
  3. 'Grid-a-Pic
  4.  
  5. TYPE object
  6.     x AS INTEGER
  7.     y AS INTEGER
  8.  
  9. 'GLOBAL VARIABLES
  10. DIM SHARED camera AS object
  11. DIM dWidth AS INTEGER
  12. DIM dHeight AS INTEGER
  13. DIM mWidth AS INTEGER
  14. DIM mHeight AS INTEGER
  15. DIM SHARED main&
  16. DIM SHARED grid&
  17. DIM SHARED arw&
  18.  
  19. CONST keyUP = 18432
  20. CONST keyDOWN = 20480
  21. CONST keyLEFT = 19200
  22. CONST keyRIGHT = 19712
  23. CONST PLUS = 43
  24. CONST MINUS = 45
  25. CONST ESC = 27
  26. CONST keyB = 98
  27. CONST keyH = 104
  28. CONST keyO = 111
  29. CONST keyQ = 113
  30. CONST keyA = 97
  31. CONST keyS = 115
  32. CONST keyD = 100
  33. CONST keyW = 119
  34. CONST keyZ = 122
  35.  
  36. 'INITIAL PARAMETERS
  37. dWidth = _DESKTOPWIDTH '                                        Display size
  38. dHeight = _DESKTOPHEIGHT - 80 '                                 leave room for task bar
  39. wWidth = dWidth - 401 '                                         Window size
  40. wHeight = dHeight
  41. mp = _NEWIMAGE(wWidth, wHeight, 32)
  42. mWidth = _WIDTH(mp) '                                           Map/pic size
  43. mHeight = _HEIGHT(mp)
  44. gsiz = 35: hOff = 0: vOff = 0
  45. abyt = 127: rbyt = 127: gbyt = 127: bbyt = 127
  46. main& = _NEWIMAGE(dWidth, dHeight, 32)
  47. grid& = _NEWIMAGE(mWidth, mHeight, 32)
  48. arw& = _NEWIMAGE(30, 30, 32)
  49. Make_Arrow
  50. SCREEN main&
  51. _TITLE "GridPic (esc to quit, arrows to pan, +/- to resize grid, 'h' for hex grid, 'b' for box grid)"
  52.  
  53.     IF _KEYDOWN(keyB) THEN
  54.         IF _READBIT(gtog, 1) THEN
  55.             IF _READBIT(gtog, 0) THEN
  56.                 gtog = _RESETBIT(gtog, 0)
  57.             ELSE
  58.                 gtog = _TOGGLEBIT(gtog, 1)
  59.             END IF
  60.         ELSE
  61.             gtog = _RESETBIT(gtog, 0): gtog = _TOGGLEBIT(gtog, 1)
  62.         END IF
  63.         _DELAY .2
  64.     END IF
  65.     IF _KEYDOWN(keyH) THEN
  66.         IF _READBIT(gtog, 1) THEN
  67.             IF NOT _READBIT(gtog, 0) THEN
  68.                 gtog = _SETBIT(gtog, 0)
  69.             ELSE
  70.                 gtog = _TOGGLEBIT(gtog, 1)
  71.             END IF
  72.         ELSE
  73.             gtog = _SETBIT(gtog, 0): gtog = _TOGGLEBIT(gtog, 1): _DELAY .2
  74.         END IF
  75.         _DELAY .2
  76.     END IF
  77.     IF _KEYDOWN(keyS) THEN Save_Gridpic
  78.     IF _KEYDOWN(keyO) THEN Load_Image
  79.     IF _KEYDOWN(PLUS) THEN gsiz = gsiz + 1
  80.     IF _KEYDOWN(MINUS) THEN gsiz = gsiz - 1
  81.     IF _KEYDOWN(keyUP) THEN camera.y = camera.y - 10
  82.     IF _KEYDOWN(keyDOWN) THEN camera.y = camera.y + 10
  83.     IF _KEYDOWN(keyLEFT) THEN camera.x = camera.x - 10
  84.     IF _KEYDOWN(keyRIGHT) THEN camera.x = camera.x + 10
  85.     IF _KEYDOWN(ESC) THEN SYSTEM
  86.     IF _KEYDOWN(keyQ) THEN SYSTEM
  87.     IF _KEYDOWN(keyA) AND hOff > -gsiz / 2 THEN hOff = hOff - 1
  88.     IF _KEYDOWN(keyD) AND hOff < gsiz / 2 THEN hOff = hOff + 1
  89.     IF _KEYDOWN(keyW) AND vOff > -gsiz / 2 THEN vOff = vOff - 1
  90.     IF _KEYDOWN(keyZ) AND vOff < gsiz / 2 THEN vOff = vOff + 1
  91.  
  92.     IF gsiz < 2 THEN gsiz = 2
  93.     IF camera.x < 0 THEN camera.x = 0
  94.     IF camera.y < 0 THEN camera.y = 0
  95.     IF camera.x > _WIDTH(mp) - wWidth THEN camera.x = _WIDTH(mp) - wWidth
  96.     IF camera.y > _HEIGHT(mp) - wHeight THEN camera.y = _HEIGHT(mp) - wHeight
  97.  
  98.     WEND
  99.         Mouse_Ops _MOUSEX, _MOUSEY
  100.     END IF
  101.  
  102.     _DEST grid&
  103.     CLS
  104.     IF _READBIT(gtog, 1) THEN
  105.         IF _READBIT(gtog, 0) THEN
  106.             Hex_Grid gsiz, hOff, vOff
  107.         ELSE
  108.             Box_Grid gsiz, hOff, vOff
  109.         END IF
  110.     END IF
  111.     _CLEARCOLOR _RGB32(0, 0, 0)
  112.     _DEST main&
  113.     'place finished image in screen window
  114.     CLS
  115.     _PUTIMAGE (400, 0), mp, main&, (camera.x, camera.y)-(camera.x + wWidth, camera.y + wHeight) 'map
  116.     _PUTIMAGE (400, 0), grid&, main&, (camera.x, camera.y)-(camera.x + wWidth, camera.y + wHeight) 'grid overlay
  117.     mF = 400 / _WIDTH(mp)
  118.     _PUTIMAGE (0, _HEIGHT(main&) - 1 - mF * _HEIGHT(mp))-(399, _HEIGHT(main&) - 1), mp 'mini map
  119.     'draw red box on mini map with limits of window display
  120.     LINE (camera.x * mF, _HEIGHT(main&) - 1 - (mF * _HEIGHT(mp)) + camera.y * mF)-_
  121.         ((camera.x + wWidth) * mF, _HEIGHT(main&) - 1 - (mF * _HEIGHT(mp)) + camera.y * mF + wHeight * mF), &HFFFF0000, B
  122.     LINE (camera.x * mF + 1, _HEIGHT(main&) - (mF * _HEIGHT(mp)) + camera.y * mF)-_
  123.         ((camera.x + wWidth) * mF - 1, _HEIGHT(main&) - 2 - (mF * _HEIGHT(mp)) + camera.y * mF + wHeight * mF), &HFFFF0000, B
  124.  
  125.     Para_Disp
  126.     _LIMIT 30
  127.     _DISPLAY
  128. '                                                               END: MAIN MODULE / BEGIN SUBROUTINES
  129.  
  130.  
  131. SUB Box_Grid (siz AS INTEGER, h AS INTEGER, v AS INTEGER)
  132.  
  133.     DIM s, ho, vo
  134.     COLOR _RGBA32(rbyt, gbyt, bbyt, abyt)
  135.     s = siz
  136.     ho = 0
  137.     DO 'vertical lines
  138.         LINE (ho * s + h, 0)-(ho * s + h, _HEIGHT(grid&) - 1)
  139.         ho = ho + 1
  140.     LOOP UNTIL ho * s > _WIDTH(grid&)
  141.     vo = 0
  142.     DO 'horizontal lines
  143.         LINE (0, vo * s + v)-(_WIDTH(grid&) - 1, vo * s + v)
  144.         vo = vo + 1
  145.     LOOP UNTIL vo * s + v > _HEIGHT(grid&)
  146.  
  147. END SUB 'Box_Grid
  148.  
  149.  
  150. SUB Con_Blok (xpos AS INTEGER, ypos AS INTEGER, xsiz AS INTEGER, ysiz AS INTEGER, label AS STRING, high AS INTEGER, col AS _UNSIGNED LONG)
  151.  
  152.     'Create control block
  153.     DIM CN&, x, p, sx, sy
  154.     CN& = _NEWIMAGE(xsiz, ysiz, 32)
  155.     _DEST CN&
  156.     COLOR , col
  157.     CLS
  158.     x = LEN(label)
  159.     sx = xsiz / 2 - x * 4: sy = ysiz / 2 - 8
  160.     FOR p = 1 TO x '                                            iterate through label characters
  161.         IF p = high THEN '                                      print hotkey highlight color (red) else (black)
  162.             IF col = &HFFFF0000 THEN
  163.                 COLOR &HFFFFFFFF
  164.             ELSE
  165.                 COLOR &HFFFF0000
  166.             END IF
  167.         ELSE
  168.             COLOR &HFF000000
  169.         END IF
  170.         _PRINTSTRING (sx + (p - 1) * 8, sy), MID$(label, p, 1)
  171.     NEXT p
  172.     _PUTIMAGE (xpos, ypos), CN&, main&
  173.     _FREEIMAGE CN&
  174.  
  175. END SUB 'Con_Blok
  176.  
  177.  
  178. SUB DialogBox (heading AS STRING, xsiz AS INTEGER, ysiz AS INTEGER, ypos AS INTEGER, bcol AS _UNSIGNED LONG, tcol AS _UNSIGNED LONG)
  179.  
  180.     'superimpose a screen centered input box for various input routines
  181.     T& = _NEWIMAGE(xsiz, ysiz, 32) '                            define box
  182.     _DEST T&
  183.     COLOR tcol, &HFF000000 '                                    set text color with black background
  184.     CLS
  185.     FOR x = 0 TO 5 '                                            draw bounding box 6 pixels thick
  186.         IF x < 2 THEN
  187.             LINE (0 + x, 0 + x)-(_WIDTH(T&) - 1 - x, _HEIGHT(T&) - 1 - x), &HFF000000, B
  188.         ELSE
  189.             LINE (0 + x, 0 + x)-(_WIDTH(T&) - 1 - x, _HEIGHT(T&) - 1 - x), bcol, B
  190.         END IF
  191.     NEXT x
  192.     l = _WIDTH(T&) / 2 - (LEN(heading) * 8) / 2 '                set heading position
  193.     _PRINTSTRING (l, 31), heading, T& '                         print heading
  194.     _PUTIMAGE (_WIDTH(main&) / 2 - _WIDTH(T&) / 2, ypos), T&, main& 'display box
  195.     _DEST main&
  196.     _FREEIMAGE T&
  197.  
  198. END SUB 'DialogBox
  199.  
  200.  
  201. SUB Hex_Grid (siz AS INTEGER, h AS INTEGER, v AS INTEGER)
  202.  
  203.     DIM s, sb, ho, vo, ro, col, of
  204.     CLS
  205.     s = siz / (2 * SIN(_PI / 3)) '                                  side length
  206.     sb = s / 2
  207.     ho = s + (s * COS(_PI / 3)) '                                   horizontal offset
  208.     vo = 2 * (s * SIN(_PI / 3)) '                                   vertical offset
  209.     COLOR _RGBA32(rbyt, gbyt, bbyt, abyt)
  210.     ro = -1
  211.     DO 'x row loop
  212.         col = -1
  213.         DO 'y column loop
  214.             IF ro MOD 2 = 0 THEN of = vo / 2 ELSE of = 0
  215.             LINE (ro * ho - sb + h, col * vo + of + v)-(ro * ho + s - sb + h, col * vo + of + v) 'hex horizontal
  216.             LINE (ro * ho + s - sb + h, col * vo + of + v)-(ro * ho + s + ho - s - sb + h, col * vo + of - (vo / 2) + v) 'hex up leg
  217.             LINE (ro * ho + s - sb + h, col * vo + of + v)-(ro * ho + s + ho - s - sb + h, col * vo + of + (vo / 2) + v) 'hex down leg
  218.             col = col + 1
  219.         LOOP UNTIL (col - 1) * vo > _HEIGHT(grid&)
  220.         ro = ro + 1
  221.     LOOP UNTIL (ro - 1) * ho > _WIDTH(grid&)
  222.  
  223. END SUB 'Hex_Grid
  224.  
  225.  
  226. SUB Load_Image
  227.  
  228.     DialogBox "Load Image", 600, 400, 50, &HFF00FF00, &HFFFFFFFF
  229.     _PRINTSTRING (_WIDTH(main&) / 2 - 140, 116), "Input path \ filename and extension", 0
  230.     _DISPLAY
  231.     _KEYCLEAR
  232.     LOCATE 148 \ 16, (_WIDTH(main&) / 2 - 120) \ 8
  233.     INPUT ": ", fn$: fn$ = _TRIM$(fn$)
  234.         _FREEIMAGE (mp)
  235.         _FREEIMAGE (grid&)
  236.         mp = _LOADIMAGE(fn$, 32)
  237.         mwidth = _WIDTH(mp)
  238.         mheight = _HEIGHT(mp)
  239.         grid& = _NEWIMAGE(mwidth, mheight, 32)
  240.     ELSE
  241.     END IF
  242.  
  243. END SUB 'Load_Image
  244.  
  245.  
  246. SUB Make_Arrow
  247.  
  248.     _DEST arw&
  249.     CLS
  250.     _CLEARCOLOR &HF000000
  251.     COLOR &HFF00FF00
  252.     LINE (15, 5)-(25, 25)
  253.     LINE (25, 25)-(15, 16)
  254.     LINE (15, 16)-(5, 25)
  255.     LINE (5, 25)-(15, 5)
  256.     _DEST 0
  257.  
  258. END SUB 'Make_Arrow
  259.  
  260.  
  261. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  262.  
  263.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  264.  
  265.  
  266.  
  267. SUB Mouse_Ops (xpos AS INTEGER, ypos AS INTEGER)
  268.  
  269.     SELECT CASE xpos
  270.         CASE IS < 400 '                                         left screen cases
  271.             SELECT CASE ypos
  272.                 CASE IS < 25
  273.                     SELECT CASE xpos
  274.                         CASE 0 TO 39 '                          open
  275.                             Load_Image
  276.                         CASE 50 TO 89 '                         save
  277.                             Save_Gridpic
  278.                         CASE 100 TO 139: SYSTEM
  279.                         CASE 200 TO 239 '                       hex button click
  280.                             IF _READBIT(gtog, 1) THEN '         if grid active
  281.                                 IF NOT _READBIT(gtog, 0) THEN ' and box
  282.                                     gtog = _SETBIT(gtog, 0) '   change to hex
  283.                                 ELSE '                          otherwise
  284.                                     gtog = _RESETBIT(gtog, 1) ' make grid inactive
  285.                                 END IF
  286.                             ELSE '                              otherwise if grid inactive
  287.                                 gtog = _SETBIT(gtog, 1) '       activate it
  288.                                 gtog = _SETBIT(gtog, 0) '       as a hex
  289.                             END IF
  290.                             _DELAY .2
  291.                         CASE 250 TO 289 '                       box button click
  292.                             IF _READBIT(gtog, 1) THEN '         if grid active
  293.                                 IF _READBIT(gtog, 0) THEN '     and hex
  294.                                     gtog = _RESETBIT(gtog, 0) ' change to box
  295.                                 ELSE
  296.                                     gtog = _RESETBIT(gtog, 1) ' make grid inactive
  297.                                 END IF
  298.                             ELSE '                              otherwise
  299.                                 gtog = _SETBIT(gtog, 1) '       activate it
  300.                                 gtog = _RESETBIT(gtog, 0) '     as a box
  301.                             END IF
  302.                             _DELAY .2
  303.                     END SELECT
  304.                 CASE IS > 24 '                                  color, size & offset
  305.                     SELECT CASE xpos
  306.                         CASE 5 TO 200 '                         color block
  307.                             SELECT CASE ypos
  308.                                 CASE 50 TO 60 '                 alpha
  309.                                     abyt = map!(xpos, 5, 200, 1, 255)
  310.                                 CASE 90 TO 100 '                red
  311.                                     rbyt = map!(xpos, 5, 200, 1, 255)
  312.                                 CASE 130 TO 140 '               green
  313.                                     gbyt = map!(xpos, 5, 200, 1, 255)
  314.                                 CASE 170 TO 180 '               blue
  315.                                     bbyt = map!(xpos, 5, 200, 1, 255)
  316.                             END SELECT
  317.                         CASE IS > 200 '                         size & offset cross
  318.                             SELECT CASE ypos
  319.                                 CASE 46 TO 70
  320.                                     SELECT CASE xpos
  321.                                         CASE 225 TO 257
  322.                                             gsiz = gsiz - 1
  323.                                         CASE 343 TO 375
  324.                                             gsiz = gsiz + 1
  325.                                     END SELECT
  326.                                 CASE 90 TO 120
  327.                                     SELECT CASE xpos
  328.                                         CASE 286 TO 314 '       offset up
  329.                                             IF vOff > -gsiz / 2 THEN vOff = vOff - 1
  330.                                     END SELECT
  331.                                 CASE 121 TO 149
  332.                                     SELECT CASE xpos
  333.                                         CASE 255 TO 285 '       offset left
  334.                                             IF hOff > -gsiz / 2 THEN hOff = hOff - 1
  335.                                         CASE 286 TO 314 '       offset to (0, 0)
  336.                                             hOff = 0: vOff = 0
  337.                                         CASE 315 TO 345 '       offset right
  338.                                             IF hOff < gsiz / 2 THEN hOff = hOff + 1
  339.                                     END SELECT
  340.                                 CASE 150 TO 180
  341.                                     SELECT CASE xpos
  342.                                         CASE 286 TO 314 '       offset down
  343.                                             IF vOff < gsiz / 2 THEN vOff = vOff + 1
  344.                                     END SELECT
  345.                             END SELECT
  346.  
  347.                     END SELECT
  348.             END SELECT '                                        end: left screen ypos cases
  349.         CASE ELSE
  350.             _MOUSEMOVE 400 + wWidth / 2, wHeight / 2
  351.             camera.x = camera.x - (xpos - 400 - wWidth / 2)
  352.             camera.y = camera.y - (ypos - wHeight / 2)
  353.     END SELECT
  354.  
  355. END SUB 'Mouse_Ops
  356.  
  357.  
  358. SUB Panel_Blank (xpos AS INTEGER, ypos AS INTEGER, xsiz AS INTEGER, ysiz AS INTEGER, col AS LONG)
  359.  
  360.     'Background blank to mark and mask button use and/or changes
  361.     DIM CN&
  362.     CN& = _NEWIMAGE(xsiz, ysiz, 32) '                           active button overlay
  363.     _DEST CN&
  364.     COLOR , col '                                               set overlay background color
  365.     CLS
  366.     _PUTIMAGE (xpos, ypos), CN&, main& '                        cover button
  367.     _FREEIMAGE CN&
  368.  
  369. END SUB 'Panel_Blank
  370.  
  371.  
  372. SUB Para_Disp
  373.  
  374.     'Display available parameters and controls
  375.     Con_Blok 0, 0, 40, 24, "Open", 1, &HFF00FF00
  376.     Con_Blok 50, 0, 40, 24, "Save", 1, &HFF0000FF
  377.     Con_Blok 100, 0, 40, 24, "Quit", 1, &HFFFF0000
  378.     Con_Blok 200, 0, 40, 24, "Hex", 1, &HFFF0F0F0
  379.     Con_Blok 250, 0, 40, 24, "Box", 1, &HFFF0F0F0
  380.     IF _READBIT(gtog, 1) THEN
  381.         IF _READBIT(gtog, 0) THEN
  382.             Panel_Blank 250, 0, 40, 24, &H9F000000
  383.         ELSE
  384.             Panel_Blank 200, 0, 40, 24, &H9F000000
  385.         END IF
  386.     ELSE
  387.         Panel_Blank 200, 0, 40, 24, &H9F000000
  388.         Panel_Blank 250, 0, 40, 24, &H9F000000
  389.     END IF
  390.  
  391.     _PRINTSTRING (5, 30), "Alpha " + STR$(abyt) '               color bars
  392.     LINE (5, 50)-(200, 60), &HFF7F7F7F, B
  393.     LINE (5, 50)-(map!(abyt, 1, 255, 5, 200), 60), &HFF7F7F7F, BF
  394.     _PRINTSTRING (5, 70), "Red " + STR$(rbyt)
  395.     LINE (5, 90)-(200, 100), &HFF7F0000, B
  396.     LINE (5, 90)-(map!(rbyt, 1, 255, 5, 200), 100), &HFF7F0000, BF
  397.     _PRINTSTRING (5, 110), "Green " + STR$(gbyt)
  398.     LINE (5, 130)-(200, 140), &HFF007F00, B
  399.     LINE (5, 130)-(map!(gbyt, 1, 255, 5, 200), 140), &HFF007F00, BF
  400.     _PRINTSTRING (5, 150), "Blue " + STR$(bbyt)
  401.     LINE (5, 170)-(200, 180), &HFF0000FF, B
  402.     LINE (5, 170)-(map!(bbyt, 1, 255, 5, 200), 180), &HFF0000FF, BF
  403.  
  404.     _PRINTSTRING (284, 30), "Size" '                            size buttons
  405.     Con_Blok 225, 46, 32, 24, "-", 1, &HFF00007F
  406.     Con_Blok 343, 46, 32, 24, "+", 1, &HFF00007F
  407.     _PRINTSTRING (284, 48), STR$(gsiz)
  408.  
  409.     LINE (285, 90)-(315, 180), &HFFFFFFFF, B '                  offset cross
  410.     LINE (255, 120)-(345, 150), &HFFFFFFFF, B
  411.     CIRCLE (300, 135), 8, &HFFFF0000
  412.     LINE (290, 135)-(310, 135), &HFFFF0000
  413.     LINE (300, 125)-(300, 145), &HFFFF0000
  414.     RotoZoom3 285 + _WIDTH(arw&) / 2, 90 + _HEIGHT(arw&) / 2, arw&, 1, 1, 0
  415.     RotoZoom3 255 + _WIDTH(arw&) / 2, 120 + _HEIGHT(arw&) / 2, arw&, 1, 1, _PI * 3 / 2
  416.     RotoZoom3 315 + _WIDTH(arw&) / 2, 120 + _HEIGHT(arw&) / 2, arw&, 1, 1, _PI / 2
  417.     RotoZoom3 285 + _WIDTH(arw&) / 2, 150 + _HEIGHT(arw&) / 2, arw&, 1, 1, _PI
  418.  
  419. END SUB 'Para_Disp
  420.  
  421.  
  422. SUB RotoZoom3 (X AS LONG, Y AS LONG, Image AS LONG, xScale AS SINGLE, yScale AS SINGLE, radianRotation AS SINGLE)
  423.  
  424.     ' Thanks be to Galleon and Bplus for this SUB, wish I was this good...
  425.     ' This assumes you have set your drawing location with _DEST or default to screen.
  426.     ' X, Y - is where you want to put the middle of the image
  427.     ' Image - is the handle assigned to the image to be rotated
  428.     ' xScale, yScale - are shrinkage < 1 or magnification > 1 on the given axis, 1 just uses image size.
  429.     ' These are multipliers so .5 will create image .5 size on given axis and 2 for twice image size.
  430.     ' radianRotation is the Angle in Radian units to rotate the image
  431.     ' note: Radian units for rotation because it matches angle units of other Basic Trig functions
  432.     '       and saves a little time converting from degree.
  433.     '       Use the _D2R() function if you prefer to work in degree units for angles.
  434.  
  435.     DIM px(3) AS SINGLE: DIM py(3) AS SINGLE '                  simple arrays for x, y to hold the 4 corners of image
  436.     DIM W&, H&, sinr!, cosr!, i&, x2&, y2& '                    variables for image manipulation
  437.     W& = _WIDTH(Image&): H& = _HEIGHT(Image&)
  438.     px(0) = -W& / 2: py(0) = -H& / 2 '                          left top corner
  439.     px(1) = -W& / 2: py(1) = H& / 2 '                           left bottom corner
  440.     px(2) = W& / 2: py(2) = H& / 2 '                            right bottom
  441.     px(3) = W& / 2: py(3) = -H& / 2 '                           right top
  442.     sinr! = SIN(-radianRotation): cosr! = COS(-radianRotation) 'rotation helpers
  443.     FOR i& = 0 TO 3 '                                           calc new point locations with rotation and zoom
  444.         x2& = xScale * (px(i&) * cosr! + sinr! * py(i&)) + X: y2& = yScale * (py(i&) * cosr! - px(i&) * sinr!) + Y
  445.         px(i&) = x2&: py(i&) = y2&
  446.     NEXT
  447.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, H& - 1)-(W& - 1, H& - 1), Image TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
  448.     _MAPTRIANGLE _SEAMLESS(0, 0)-(W& - 1, 0)-(W& - 1, H& - 1), Image TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
  449.  
  450. END SUB 'RotoZoom3
  451.  
  452.  
  453. SUB Save_Gridpic
  454.  
  455.     DIM si&, fn$, fn1$, r
  456.     DialogBox "Save Image", 600, 400, 50, &HFF0000FF, &HFFFFFFFF
  457.     si& = _COPYIMAGE(mp&, 32)
  458.     _PUTIMAGE , grid&, si&
  459.     _PRINTSTRING (_WIDTH(main&) / 2 - 140, 116), "Input path \ filename and extension", 0
  460.     _DISPLAY
  461.     LOCATE 148 \ 16, (_WIDTH(main&) / 2 - 120) \ 8
  462.     INPUT ": ", fn$: fn$ = _TRIM$(fn$)
  463.     r = SaveImage(fn$, si&, 0, 0, _WIDTH(si&) - 1, _HEIGHT(si&) - 1)
  464.     IF r = 1 THEN
  465.         fn1$ = "grid_" + fn$
  466.         r = SaveImage(fn1$, si&, 0, 0, _WIDTH(si&) - 1, _HEIGHT(si&) - 1)
  467.     END IF
  468.     IF r < 0 THEN
  469.         _PRINTSTRING (_WIDTH(main&) / 2 - 68, 300), "successful export", 0
  470.         _DISPLAY
  471.         SLEEP 2
  472.     END IF
  473.     _FREEIMAGE si&
  474.  
  475. END SUB 'Save_Gridpic
  476.  
  477. '$INCLUDE:'SaveImage.BM'
  478.