I made some significant changes to the code. To make it easier to use there is now a command set of 5 commands you can use (see the code for complete documentation):
SetupMagnify - set magnifier screen settings
Magnify - identify the image or screen to magnify
GetMagImage - get the magnified image at the supplied coordinates
MagX - the x coordinate of the magnifier screen in relation to the coordinates given in GetMagImage
MagY - the y coordinate of the magnifier screen in relation to the coordinates given in GetMagImage
Each subroutine and function has detailed instructions on use.
You can now magnify an image or the screen. The image to magnify once again must at least match the screen dimensions, however this does not apply when magnifying the screen itself.
The command set will make using this code much easier to implement.
---------------------
END OF UPDATE
--------------------
I wrote an image magnification routine that magnifies an image, not the screen. I know there are other very well written magnification routines on the forum. However, I needed one that settings could be changed that affect the behavior of the magnifier screen. I also needed a routine that would maintain the aspect ratio of an image as seen on the screen.
The image to magnify must at least match the screen dimensions (ie stretching a small image onto a large screen will give undesirable results). You can use the 2080x2080 image I provided in the ZIP file below to test the code.
This is what I came up with. It could easily be adapted to a simple library if needed.
Code: (Select All)
'+---------------------------------------------------------------------+
'| Image or Screen Magnifier |
'| |
'| By Terry Ritchie 04/17/24 |
'| |
'| The image and screen must be at least the same dimensions when |
'| magnifying an image. This does not apply to magnifying the screen. |
'| |
'| Images that have been stretched to a screen with a different aspect |
'| ratio than the image is ok. The magnified image will retain the new |
'| aspect ratio. |
'| |
'| This routine has the ability to magnify the screen or an image. |
'| (See the subroutine SetupMagnify below for details) |
'| |
'| The following command set has been added (04/17/24): |
'| |
'| SetupMagnify - set magnifier screen settings |
'| Magnify - Identify the image or screen to magnify |
'| GetMagImage - get the magnified image at given coordinates |
'| MagX - the x coordinate location of the magnifier screen |
'| MagY - the y coordinate location of the magnifier screen |
'| |
'| 1. SetupMagnify must be run first to initialize magnifier screen. |
'| 2. Magnify must be run second to identify the image or screen. |
'| |
'| See each subroutine and function section below to get detailed |
'| instructions of each command. |
'+---------------------------------------------------------------------+
OPTION _EXPLICIT ' declare those variables!
'+------------------------------------------------------------------+
'| Magnification will work regardless of screen aspect ratio chosen |
'+------------------------------------------------------------------+
TYPE MAGSCREEN ' MAGNIFIER SCREEN PROPERTIES
Image AS LONG ' image to magnify ' (set)
MagImage AS LONG ' magnified image holder (calculate)
Width AS INTEGER ' magnifier screen width (not including border) (set)
Height AS INTEGER ' magnifier screen height (not including border) (set)
MagWidth AS INTEGER ' magnifier screen width (including border) (calculate)
MagHeight AS INTEGER ' magnifier screen height (including border) (calculate)
Border AS INTEGER ' size of border around magnifier screen in pixels (set)
Magnify AS SINGLE ' magnification level (1=100%, 1.5=150%, 2=200%, etc..) (set)
MagX AS INTEGER ' upper left x coordinate of magnifier screen (set)
MagY AS INTEGER ' upper left y coordinate of magnifier screen (set)
MinX AS INTEGER ' minimum x coordinate of magnifier screen (set)
MaxX AS INTEGER ' maximum x coordinate of magnifier screen (set)
MinY AS INTEGER ' minimum y coordinate of magnifier screen (set)
MaxY AS INTEGER ' maximum y coordinate of magnifier screen (set)
ScreenX AS INTEGER ' x center point coordinate on screen (calculate)
ScreenY AS INTEGER ' y center point coordinate on screen (calculate)
ImageX AS INTEGER ' upper left x coordinate on image to be magnified (calculate)
ImageY AS INTEGER ' upper left y coordinate on image to be magnified (calculate)
RatioX AS SINGLE ' ratio of image width to screen width (calculate)
RatioY AS SINGLE ' ratio of image height to screen height (calculate)
LengthX AS INTEGER ' width of area on image to magnify (calculate)
LengthY AS INTEGER ' height of area on image to magnify (calculate)
END TYPE
DIM MagScreen AS MAGSCREEN ' define the magnifier screen properties
DIM Image AS LONG ' the image to magnify
DIM MagnifiedImage AS LONG ' the magnified image
SCREEN _NEWIMAGE(SCREENWIDTH, SCREENHEIGHT, 32) ' enter a graphics screen
Image = _LOADIMAGE("qb64pe.png", 32) ' load 2080x2080 image to magnify
'+--------------------------------+
'| Set up the on-screen magnifier |
'+--------------------------------+
SetupMagnify 200, 200, 10, 2, 0, 0, 0, 0 ' set up magnifier screen properties (must be done first)
Magnify Image ' magnify the image (one or the other) (must be done second)
'Magnify 0 ' magnify the screen (one or the other) (must be done second)
'+--------------------+
'| Begin main program |
'+--------------------+
DO ' begin main program loop
_LIMIT 30 ' 30 frames per second
_PUTIMAGE , Image, 0 ' clear the screen with image to magnify
WHILE _MOUSEINPUT: WEND ' get latest mouse update
MagnifiedImage = GetMagImage(_MOUSEX, _MOUSEY) ' get the magnified image at current mouse pointer
_PUTIMAGE (MagX, MagY), MagnifiedImage ' display magnified image on screen
_DISPLAY ' update screen with changes
LOOP UNTIL _KEYDOWN(27) ' leave when ESC key pressed
_FREEIMAGE Image ' remove image to magnify from RAM
_FREEIMAGE MagnifiedImage ' remove magnified image from RAM
SYSTEM ' return to the operating system
'+------------------+
'| End main program |
'+------------------+
' ______________________________________________________________________________________________________________________________
'/ \
FUNCTION MagX% ' MagX% |
' __________________________________________________________________________________________________________________________|_____
'/ \
'| Returns the current x coordinate location of the magnification screen in relation to the coordinate center point supplied |
'| to GetMagImage. |
'|________________________________________________________________________________________________________________________________|
' |
SHARED MagScreen AS MAGSCREEN ' need access to magnify properties |
' |
MagX% = MagScreen.MagX ' return the current x coordinate of the magnification screen |
' |
END FUNCTION ' |
'\____________________________________________________________________________________________________________________________________/
' ______________________________________________________________________________________________________________________________
'/ \
FUNCTION MagY% ' MagY% |
' __________________________________________________________________________________________________________________________|_____
'/ \
'| Returns the current y coordinate location of the magnification screen in relation to the coordinate center point supplied |
'| to GetMagImage. |
'|________________________________________________________________________________________________________________________________|
' |
SHARED MagScreen AS MAGSCREEN ' need access to the magnify properties |
' |
MagY% = MagScreen.MagY ' |
' |
END FUNCTION ' |
'\____________________________________________________________________________________________________________________________________/
' ______________________________________________________________________________________________________________________________
'/ \
FUNCTION GetMagImage& (x AS INTEGER, y AS INTEGER) ' GetMagImage& |
' __________________________________________________________________________________________________________________________|_____
'/ \
'| Returns the magnified image identified by the x,y center point coordinates specified. |
'| |
'| MagnifiedImage& = GetMagImage&(x%, y%) ' return the magnified image handle |
'| |
'| x - x center coordinate on screen |
'| y - y center coordinate on screen |
'|________________________________________________________________________________________________________________________________|
' |
SHARED MagScreen AS MAGSCREEN ' need access to the magnify properties |
' |
IF MagScreen.Image = -1 THEN ' has the screen or image been identified? |
SCREEN 0, 0, 0, 0 ' no, enter a text mode only screen |
PRINT ' display error message to programmer |
PRINT " -------------------------------------------------------------------" ' |
PRINT " You must use Magnify to identify the image or screen to magnify." ' |
PRINT " -------------------------------------------------------------------" ' |
END ' end program |
END IF ' |
'+-----------------------------------------------------------+ |
'| Get upper left x,y location of image area to be magnified | |
'+-----------------------------------------------------------+ |
MagScreen.ScreenX = x ' current x coordinate of mouse pointer |
MagScreen.ScreenY = y ' current y coordinate of mouse pointer |
MagScreen.ImageX = MagScreen.ScreenX * MagScreen.RatioX - MagScreen.LengthX * .5 ' left x coordinate on image to be magnified |
MagScreen.ImageY = MagScreen.ScreenY * MagScreen.RatioY - MagScreen.LengthY * .5 ' upper y coordinate on image to be magnified |
IF MagScreen.ImageX < 0 THEN ' x above minimum limit? |
MagScreen.ImageX = 0 ' no, set x coordinate to minimum allowed |
ELSEIF MagScreen.ImageX + MagScreen.LengthX > _WIDTH(MagScreen.Image) - 1 THEN ' x below maximum amount? |
MagScreen.ImageX = _WIDTH(MagScreen.Image) - 1 - MagScreen.LengthX ' no, set x coordinate to maximum allowed |
END IF ' |
IF MagScreen.ImageY < 0 THEN ' y above minimum limit? |
MagScreen.ImageY = 0 ' no, set y coordinate to minimum allowed |
ELSEIF MagScreen.ImageY + MagScreen.LengthY > _HEIGHT(MagScreen.Image) - 1 THEN ' y below maximum limit? |
MagScreen.ImageY = _HEIGHT(MagScreen.Image) - 1 - MagScreen.LengthY ' no, set y coordinate to maximum allowed |
END IF ' |
'+-----------------------------------------------------+ |
'| Get upper left x,y location of magnification screen | |
'+-----------------------------------------------------+ |
MagScreen.MagX = MagScreen.ScreenX - MagScreen.Width * .5 - MagScreen.Border ' left x coordinate of magnifier screen |
MagScreen.MagY = MagScreen.ScreenY - MagScreen.Height * .5 - MagScreen.Border ' upper y coordinate of magnifier screen |
IF MagScreen.MagX < MagScreen.MinX THEN ' x above minimum limit? |
MagScreen.MagX = MagScreen.MinX ' no, set x coordinate to minimum allowed |
ELSEIF MagScreen.MagX + MagScreen.Width + MagScreen.Border * 2 > MagScreen.MaxX THEN ' x below maximum limit? |
MagScreen.MagX = MagScreen.MaxX + 1 - MagScreen.Width - MagScreen.Border * 2 ' no, set x coordinate to maximum allowed |
END IF ' |
IF MagScreen.MagY < MagScreen.MinY THEN ' y above minimum limit? |
MagScreen.MagY = MagScreen.MinY ' no, set y coordinate to minimum allowed |
ELSEIF MagScreen.MagY + MagScreen.Height + MagScreen.Border * 2 > MagScreen.MaxY THEN ' y below maximum limit? |
MagScreen.MagY = MagScreen.MaxY + 1 - MagScreen.Height - MagScreen.Border * 2 ' no, set y coordinate to maximum allowed |
END IF ' |
'+---------------------------------------------------+ |
'| Get magnified area of image and display on screen | |
'+---------------------------------------------------+ |
_PUTIMAGE (MagScreen.Border, MagScreen.Border)-_
(MagScreen.MagWidth - MagScreen.Border, MagScreen.MagHeight - MagScreen.Border),_
MagScreen.Image, MagScreen.MagImage,_
(MagScreen.ImageX, MagScreen.ImageY)-_
(MagScreen.ImageX + MagScreen.LengthX, MagScreen.ImageY + MagScreen.LengthY) ' get mag area and place in mag screen |
_PUTIMAGE (MagScreen.MagX, MagScreen.MagY), MagScreen.MagImage ' display the magnified screen |
GetMagImage& = MagScreen.MagImage ' return magnified image |
' |
END FUNCTION ' |
'\____________________________________________________________________________________________________________________________________/
' ______________________________________________________________________________________________________________________________
'/ \
SUB Magnify (i AS LONG) ' Magnify |
' __________________________________________________________________________________________________________________________|_____
'/ \
'| Identifies the image or screen to magnify. |
'| |
'| Magnify MyImage& ' use MyImage& as the image to magnify |
'| Magnify 0 ' use the screen as image to magnify |
'| |
'| i - the image or screen to magnify |
'|________________________________________________________________________________________________________________________________|
' |
SHARED MagScreen AS MAGSCREEN ' need access to magnify properties |
DIM bpp AS INTEGER ' number of bytes per pixel |
' |
IF MagScreen.Width > 0 THEN ' has magnifier screen been set up? |
bpp = _PIXELSIZE(i) ' yes, get number of bytes per pixel |
IF (i = 0) OR (i < -1) THEN ' is this a valid image or screen? |
IF bpp > 0 THEN ' yes, is it a text mode only image? |
IF bpp = 1 THEN bpp = 256 ELSE bpp = 32 ' no, set mode of magnified image holder |
MagScreen.Image = i ' set image to magnify |
MagScreen.MagImage = _NEWIMAGE(MagScreen.Width + MagScreen.Border * 2, MagScreen.Height + MagScreen.Border * 2, bpp) '|
MagScreen.MagWidth = _WIDTH(MagScreen.MagImage) ' width of magnifier screen (inc border) |
MagScreen.MagHeight = _HEIGHT(MagScreen.MagImage) ' height of magnifier screen (inc border) |
MagScreen.RatioX = _WIDTH(i) / _WIDTH(0) ' ratio of screen width to image width |
MagScreen.RatioY = _HEIGHT(i) / _HEIGHT(0) ' ratio of screen height to image height |
MagScreen.LengthX = MagScreen.Width * MagScreen.RatioX / MagScreen.Magnify - 1 ' width of area on image to magnify |
MagScreen.LengthY = MagScreen.Height * MagScreen.RatioY / MagScreen.Magnify - 1 ' height of area on image to magnify |
CLS , _RGB32(0, 0, 0), MagScreen.MagImage ' remove transparency |
ELSE ' yes, text mode only |
SCREEN 0, 0, 0, 0 ' enter a text mode only screen |
PRINT " ----------------------------------------------------------" ' display error message to programmer |
PRINT " The image or screen to magnify must be a color graphics." ' |
PRINT " ----------------------------------------------------------" ' |
END ' end program |
END IF ' |
ELSE ' no, not a valid image or screen |
SCREEN 0, 0, 0, 0 ' enter a text mode only screen |
PRINT ' display error message to programmer |
PRINT " ---------------------------------------------------" ' |
PRINT " The image chosen to magnify is not a valid image." ' |
PRINT " ---------------------------------------------------" ' |
END ' end program |
END IF ' |
ELSE ' no, magnifier has not been set up |
SCREEN 0, 0, 0, 0 ' enter a text mode only screen |
PRINT ' display error message to programmer |
PRINT " ---------------------------------------------------------------------" ' |
PRINT " You must first use SetupMagnify to set initial magnifier settings." ' |
PRINT " ---------------------------------------------------------------------" ' |
END ' end program |
END IF ' |
' |
END SUB ' |
'\____________________________________________________________________________________________________________________________________/
' ______________________________________________________________________________________________________________________________
'/ \
SUB SetupMagnify (w AS INTEGER, h AS INTEGER, b AS INTEGER, m AS SINGLE, x1 AS INTEGER, y1 AS INTEGER, x2 AS INTEGER, y2 AS INTEGER)
' __________________________________________________________________________________________________________________________|_____
'/ \
'| Sets up the on-screen magnifier properties. |
'| |
'| SetupMagnify 150, 150, 5, 3, 100, 100, _WIDTH(0) - 101, _HEIGHT(0) - 101 ' custom values |
'| |
'| SetupMagnify 0, 0, 0, 0, 0, 0, 0, 0 ' use built-in defaults (see below) |
'| |
'| w - width of magnifier screen (not including border) (must be 0 to _WIDTH(0) - 1 ) |
'| h - height of magnifier screen (not including border) (must be 0 to _HEIGHT(0) - 1 ) |
'| b - width of border in pixels surrounding the magnifier screen (must be 0 or greater ) |
'| m - the amount of magnification (1=100%, 1.5=150%, 2=200%, etc..) (must be 1 or greater ) |
'| x1,y1 - upper left corner of boxed area magnifier screen is allowed to move within (0,0 to _WIDTH(0) - 1, _HEIGHT(0) - 1) |
'| x2,y2 - lower right corner of boxed area magnifier screen is allowed to move within (0,0 to _WIDTH(0) - 1, _HEIGHT(0) - 1) |
'| |
'| If a value of 0 is supplied for w the default value of 200 will be used |
'| If a value of 0 is supplied for h the default value of 200 will be used |
'| If a value less than 0 is supplied for b the default value of 0 will be used |
'| If a value less than 1 is supplied for m the default value of 2 (200%) will be used |
'| If x1 equals x2 then the magnifier screen will default to moving across the entire horizontal width of the screen |
'| if y1 equals y2 then the magnifier screen will default to moving across the entire vertical height of the screen |
'|________________________________________________________________________________________________________________________________|
' |
SHARED MagScreen AS MAGSCREEN ' need access to magnify properties |
' |
IF _PIXELSIZE(0) > 0 THEN ' in a graphics screen? |
IF w <= 0 THEN MagScreen.Width = 200 ELSE MagScreen.Width = w ' yes, use default value if 0 supplied for magnifier width |
IF h <= 0 THEN MagScreen.Height = 200 ELSE MagScreen.Height = h ' use default value if 0 supplied for magnifier height |
IF b < 0 THEN MagScreen.Border = 0 ELSE MagScreen.Border = b ' use default value if less than 0 supplied for border |
IF m < 1 THEN MagScreen.Magnify = 2 ELSE MagScreen.Magnify = m ' use default value if less than 1 supp for magnification |
IF x1 < 0 THEN MagScreen.MinX = 0 ' minimum x can't be less than 0 |
IF x1 > _WIDTH(0) - 1 THEN MagScreen.MinX = _WIDTH(0) - 1 ' minimum x can't be greater than screen x coordinates |
IF x2 < 0 THEN MagScreen.MaxX = 0 ' maximum x can't be less than 0 |
IF x2 > _WIDTH(0) - 1 THEN MagScreen.MaxX = _WIDTH(0) - 1 ' maximum x can't be greater than screen x coordinates |
IF y1 < 0 THEN MagScreen.MinY = 0 ' minimum y can't be less than 0 |
IF y1 > _HEIGHT(0) - 1 THEN MagScreen.MinY = _HEIGHT(0) - 1 ' minimum y can't be greater than screen y coordinates |
IF y2 < 0 THEN MagScreen.MaxY = 0 ' maximum y can't be less than 0 |
IF y2 > _HEIGHT(0) - 1 THEN MagScreen.MaxY = _HEIGHT(0) - 1 ' maximum y can't be greater than screen y coordinates |
IF x1 = x2 THEN ' do minimum and maximum x values equal each other? |
MagScreen.MinX = 0 ' yes, use default value for minimum x |
MagScreen.MaxX = _WIDTH(0) - 1 ' use default value for maximum x |
ELSE ' no |
MagScreen.MinX = x1 ' set minimum x value |
MagScreen.MaxX = x2 ' set maximum x value |
END IF ' |
IF y1 = y2 THEN ' do minimum and maximum y values equal each other? |
MagScreen.MinY = 0 ' yes, use default value for minimum y |
MagScreen.MaxY = _HEIGHT(0) - 1 ' use default value for maximum y |
ELSE ' no |
MagScreen.MinY = y1 ' set minimum y value |
MagScreen.MaxY = y2 ' set maximum y value |
END IF ' |
MagScreen.Image = -1 ' no image chosen yet |
ELSE ' no, not in graphics screen |
SCREEN 0, 0, 0, 0 ' enter a text mode only screen |
PRINT ' display error message to programmer |
PRINT " ------------------------------------------------------------------------------" ' |
PRINT " You need to be in a color graphics screen before setting magnifier settings." ' |
PRINT " ------------------------------------------------------------------------------" ' |
END ' end program |
END IF ' |
' |
END SUB ' |
'\____________________________________________________________________________________________________________________________________/
It does a great job of counting cards. I took it to Vegas yesterday. We were up $500 but after the levels of learning had sufficiently increased, the robot became self aware and blew it all on the cocktail girl. Oh well, back to the drawing board.
This is a function I think is useful, and I hope I won't find out that one of QB/QB64pe's more than 20,000 keywords, functions and compiler directives, does the same thing. (Yes, I know it's just under 500, but sometimes it feels like it's a lot more.)
I've created a subroutine called PrintW to take a string, breaking it at the last space or hyphen, printing up to that point, then repeating with what is left of the string. In short, it provides a print with wraparound.
I have tested it with an appropriate passage, the three paragraph Gettysburg Address.
Code: (Select All)
L$ = "Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal."
PrintW L$
Print
PrintW "Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this."
Print
PrintW "But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow, this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us, that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion, that we here highly resolve that these dead shall not have died in vain, that this nation, under God, shall have a new birth of freedom, and that government of the people, by the people, for the people, shall not perish from the earth."
Print
Print "- Abraham Lincoln"
End
Sub PrintW (Msg$)
Dim Temp$, Split$, breakspace%, breakdash%
Temp$ = Msg$
While Len(Temp$) > 79
'' Print Len(Temp$)
Split$ = Left$(Temp$, 79)
breakspace% = _InStrRev(Split$, " ")
breakdash% = _InStrRev(Split$, "-")
'' Print Split$
'' Print breakspace%; breakdash%
'' Input X$
If breakspace% > breakdash% Then
Split$ = Left$(Split$, breakspace%)
Temp$ = Mid$(Temp$, breakspace% + 1, Len(Temp$))
Else
Split$ = Left$(Split$, breakdash%)
Temp$ = Mid$(Temp$, breakdash% + 1, Len(Temp$))
End If
'' Print "*"; Len(Temp$)
Print Split$
Wend
Print Temp$
End Sub
While working with legacy screens I noticed something odd. Circles are not circles. They need to be forced to an aspect ratio of 1 to become true circles.
I realize these screens were stretched onto CRT monitors with 4:3 aspect ratios. Is that why the default circle is squashed?
Code: (Select All)
SCREEN 2
CIRCLE (100, 99), 50 ' not a circle
CIRCLE (300, 99), 50, , , , .418 ' this seems to be the default aspect ratio
CIRCLE (500, 99), 50, , , , 1 ' forced to an aspect ratio of 1:1, now a circle
The PCOPY statement has been added to lesson 5 along with an example game highlighting its use. The tutorial asset file has also been updated to include this code.
UPDATE 04/13/24
--------------------
The _PIXELSIZE and _NEWIMAGE statements have been added to lesson 5. _NEWIMAGE was always included but now broken out to it's own section.
Legacy screens are now covered in the SCREEN section in lesson 5.
Screen pages and page flipping are now covered in lesson 5.
The tutorial asset file has once again been updated to include the new sample source code.
------------------------------
The DRAW, POINT, and PSET statements have been added to Lesson 5 of the tutorial.
The tutorial asset file has also been updated to incorporate the associated example programs that go along with the additions.
This is a big update, the DRAW command has a huge subset of commands to explain.
PSET was always included in Lesson 5 but just as a paragraph from another command. I broke it out to its own section.