Author Topic: BMP picture viewer  (Read 9064 times)

0 Members and 1 Guest are viewing this topic.

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: BMP picture viewer
« Reply #45 on: February 07, 2021, 02:49:16 pm »
_vince

RLE compression.  Another update

Steve

you were right about the padding. I should have listened.

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: BMP picture viewer
« Reply #46 on: February 07, 2021, 06:56:01 pm »
Yes, that padding nonsense is a common trap.  The code will work but will distort images with a certain width so it's important to test for.  The article mentions it I believe but I noticed that not all do.

I go and come a lot.  The last week or so, I've been in fairly often, but for the next week or so, I probably won't be.  It's time for me to go get mom and take care of her again for a bit to give my sister a break.  ;)

Nice, good to know! I'm going to make a discord account tonight and join in, see you soon ;-)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: BMP picture viewer
« Reply #47 on: February 09, 2021, 09:43:34 pm »
To make a Sub of the BMP24, take the hunk of code between the 2 =========== bars
start this at bottom of code:

Code: QB64: [Select]
  1. Function LoadBmp24&(Filename$)  'loadBMP24& returns handle to image for display code from main code section.
  2. >>>>>>>>>>>>>>>> Insert Chuck Here
  3.     LoadBMP24& = handle

Code: QB64: [Select]
  1. _TITLE "BMP slide show.   Press ESC to exit"
  2.  
  3.  
  4.     FUNCTION load_dir& (s AS STRING)
  5.     FUNCTION has_next_entry& ()
  6.     SUB close_dir ()
  7.     SUB get_next_entry (s AS STRING, flags AS LONG, file_size AS LONG)
  8.  
  9. DIM flags AS LONG
  10. DIM length AS LONG
  11. DIM F(100) AS STRING
  12. DIM Fcount AS INTEGER
  13. DIM tt AS STRING * 4
  14. DIM t AS STRING * 3
  15. DIM handle AS LONG
  16.  
  17.  
  18. 'To view BMP pictures in the root drive or a particular folder (example)
  19. 'IF load_dir("C:" + CHR$(0)) <> -1 THEN _FULLSCREEN: PRINT: PRINT "Path name does not exist": SLEEP: END
  20. 'IF load_dir("C:\QB64" + CHR$(0)) <> -1 THEN _FULLSCREEN: PRINT: PRINT "Path name does not exist": SLEEP: END
  21.  
  22. 'To view BMP pictures in the directory (folder) from where the EXE is run (current)
  23. IF load_dir("." + CHR$(0)) <> -1 THEN _FULLSCREEN: PRINT: PRINT "Path name does not exist": SLEEP: END
  24.  
  25. 'To view BMP pictures in the parent directory (folder) from where the EXE is run (current)
  26. 'IF load_dir(".." + CHR$(0)) <> -1 THEN _FULLSCREEN: PRINT: PRINT "Path name does not exist": SLEEP: END
  27.  
  28.  
  29.     length = has_next_entry
  30.     IF length = -1 THEN
  31.         PRINT "No more files to process"
  32.         EXIT DO
  33.     END IF
  34.  
  35.     IF length > -1 THEN
  36.         NAM = SPACE$(length)
  37.         get_next_entry NAM, flags, file_size
  38.  
  39.         IF (flags XOR 2) = 0 AND UCASE$(RIGHT$(NAM, 3)) = "BMP" THEN
  40.             PRINT NAM + "                              "
  41.             Fcount = Fcount + 1
  42.             F(Fcount) = NAM
  43.         END IF
  44.  
  45.     END IF
  46.  
  47.  
  48. Fmax = Fcount
  49. close_dir
  50. Fcount = 0
  51.  
  52.     N = 0
  53.  
  54.     Fcount = Fcount + 1
  55. '========================================================= start code chuck
  56.     OPEN F(Fcount) FOR BINARY AS #1   < change F(Fcount) to Sub parameter Filename$
  57.  
  58.     GET #1, 11, OF
  59.     'PRINT "Offset to picture data"; OF
  60.  
  61.     GET #1, 15, L
  62.     'PRINT "Header size "; L
  63.  
  64.     GET #1, , W
  65.     'PRINT "image width "; W
  66.  
  67.     GET #1, , H
  68.     'PRINT "image height "; H
  69.  
  70.     GET #1, , I 'biPlanes. Specifies the number of color planes on the target device.
  71.  
  72.     GET #1, , I 'bits per pixel. Must = 24 for the program to work.
  73.  
  74.     IF I <> 24 THEN
  75.         CLS
  76.         PRINT "width "; W; "    Height "; H; "    Bits per pixel "; I
  77.         PRINT Fcount
  78.         PRINT F(Fcount); " is not a 24 bit per pixel BMP"
  79.         DO
  80.             IF INKEY$ <> "" THEN CLS: EXIT DO
  81.         LOOP
  82.         GOTO LL1
  83.     END IF
  84.  
  85.     DIM a AS _MEM
  86.     handle = _NEWIMAGE(W, ABS(H), 32)
  87.     a = _MEMIMAGE(handle)
  88.  
  89.     pad = 4 - (W * 3) MOD 4
  90.  
  91.     IF pad = 4 THEN pad = 0 'pad = multiple of 4
  92.  
  93.     IF H < 0 THEN
  94.  
  95.         FOR R = 0 TO ABS(H) - 1
  96.  
  97.             FOR C = 1 TO W * 3 STEP 3
  98.                 GET #1, R * (W * 3 + pad) + C + OF, t
  99.                 tt = t + CHR$(255)
  100.                 _MEMPUT a, a.OFFSET + N, tt
  101.                 N = N + 4
  102.             NEXT C
  103.  
  104.         NEXT R
  105.  
  106.     END IF
  107.  
  108.  
  109.     IF H > 0 THEN
  110.  
  111.         FOR R = H - 1 TO 0 STEP -1
  112.  
  113.             FOR C = 1 TO W * 3 STEP 3
  114.                 GET #1, R * (W * 3 + pad) + C + OF, t
  115.                 tt = t + CHR$(255)
  116.                 _MEMPUT a, a.OFFSET + N, tt
  117.                 N = N + 4
  118.             NEXT C
  119.  
  120.         NEXT R
  121.  
  122.     END IF
  123. '===================================================== end of code chunk
  124.  
  125.     SCREEN _NEWIMAGE(W, (ABS(H)), 32)
  126.     _PUTIMAGE (0, 0), handle
  127.     _MEMFREE a
  128.  
  129.  
  130.     t1 = TIMER
  131.     DO
  132.         _LIMIT 100
  133.         t2 = TIMER
  134.         IF t2 - t1 > 2 THEN EXIT DO
  135.         i$ = INKEY$
  136.         IF i$ = CHR$(27) THEN END
  137.     LOOP
  138.     LL1:
  139.  
  140.     CLOSE
  141.  
  142.     IF Fcount = Fmax THEN Fcount = 0
  143.  
  144.  

Then move all DIM 's Variable in main that got moved to Function into Function at top

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: BMP picture viewer
« Reply #48 on: February 09, 2021, 10:11:19 pm »
 
Code: QB64: [Select]
  1.  
  2.   'code  . . . . .
  3.  
  4. 'input filename
  5. 'returns W image width (if W = 0 then error)
  6. 'returns H image height (negative or positive value)
  7. 'returns HANDLE
  8. SUB loadBMP24 (FILENAME AS STRING, W AS LONG, H AS LONG, HANDLE AS LONG)
  9.     DIM OF AS _UNSIGNED LONG
  10.     DIM tt AS STRING * 4
  11.     DIM t AS STRING * 3
  12.     DIM pad AS INTEGER
  13.  
  14.     N = 0
  15.  
  16.     OPEN FILENAME FOR BINARY AS #1
  17.  
  18.     GET #1, 11, OF 'Offset to picture data
  19.  
  20.     GET #1, 15, L 'Header size
  21.  
  22.     GET #1, , W 'image width
  23.  
  24.     GET #1, , H 'image height
  25.  
  26.     GET #1, , I 'biPlanes. Specifies the number of color planes on the target device.
  27.  
  28.     GET #1, , I 'bits per pixel. Must = 24 for the program to work.
  29.  
  30.     IF I <> 24 THEN W = 0: GOTO LL1
  31.  
  32.     HANDLE = _NEWIMAGE(W, ABS(H), 32)
  33.     a = _MEMIMAGE(HANDLE)
  34.  
  35.     pad = 4 - (W * 3) MOD 4
  36.  
  37.     IF pad = 4 THEN pad = 0 'pad = multiple of 4
  38.  
  39.     IF H < 0 THEN
  40.  
  41.         FOR R = 0 TO ABS(H) - 1
  42.  
  43.             FOR C = 1 TO W * 3 STEP 3
  44.                 GET #1, R * (W * 3 + pad) + C + OF, t
  45.                 tt = t + CHR$(255)
  46.                 _MEMPUT a, a.OFFSET + N, tt
  47.                 N = N + 4
  48.             NEXT C
  49.  
  50.         NEXT R
  51.  
  52.     END IF
  53.  
  54.  
  55.     IF H > 0 THEN
  56.  
  57.         FOR R = H - 1 TO 0 STEP -1
  58.  
  59.             FOR C = 1 TO W * 3 STEP 3
  60.                 GET #1, R * (W * 3 + pad) + C + OF, t
  61.                 tt = t + CHR$(255)
  62.                 _MEMPUT a, a.OFFSET + N, tt
  63.                 N = N + 4
  64.             NEXT C
  65.  
  66.         NEXT R
  67.  
  68.     END IF
  69.     LL1:
  70.     CLOSE
« Last Edit: February 09, 2021, 10:12:34 pm by NOVARSEG »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: BMP picture viewer
« Reply #49 on: February 09, 2021, 10:48:23 pm »
OK and now use the rest of the code for the main section to test calling up the Function or Sub.

I don't see the need to pass anything but the handle for the image to display in the main.

Do you have to change something when displaying for h < 0? Couldn't the adjustment be made before the sub or function passes the handle to main for display.

Remember to _FeeImage handles to avoid memory leaks.

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: BMP picture viewer
« Reply #50 on: February 09, 2021, 11:05:11 pm »
@bplus

Quote
I don't see the need to pass anything but the handle for the image to display in the main.
   
In the main this code displays
SCREEN _NEWIMAGE(W, (ABS(H)), 32)
    _PUTIMAGE (0, 0), HANDLE
    _MEMFREE a

which requires W and H.  The SUB returns W, H and handle.  Notice the ABS(H) because the Sub will return either -H or H depending on the BMP

Also if there is an error (not a 24BMP) the sub will return W = 0

Maybe only a HANDLE is needed but at least there is the optional W and H returned

That is one of the problems with SUBs - what data do we think does not have to be returned
***
Quote
Do you have to change something when displaying for h < 0? Couldn't the adjustment be made before the sub or function passes the handle (height?) to main for display.

Inside the sub there could be an H = ABS(H) but what if your code in the main wanted to know if the BMP had -H or +h height?

****
Quote
Remember to _FreeImage handles to avoid memory leaks.

how  is _FreeImage used?
« Last Edit: February 09, 2021, 11:28:35 pm by NOVARSEG »

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: BMP picture viewer
« Reply #51 on: February 09, 2021, 11:43:45 pm »
OK here is another version of the BMP viewer that shows how the SUB works

Code: QB64: [Select]
  1. _TITLE "BMP slide show.   Press ESC to exit"
  2.  
  3.  
  4.  
  5.     FUNCTION load_dir& (s AS STRING)
  6.     FUNCTION has_next_entry& ()
  7.     SUB close_dir ()
  8.     SUB get_next_entry (s AS STRING, flags AS LONG, file_size AS LONG)
  9.  
  10. DIM flags AS LONG
  11. DIM length AS LONG
  12. DIM F(100) AS STRING
  13. DIM Fcount AS INTEGER
  14. DIM tt AS STRING * 4
  15. DIM t AS STRING * 3
  16. DIM HANDLE AS LONG
  17.  
  18. 'To view BMP pictures in the root drive or a particular folder (example)
  19. 'IF load_dir("C:" + CHR$(0)) <> -1 THEN _FULLSCREEN: PRINT: PRINT "Path name does not exist": SLEEP: END
  20. 'IF load_dir("C:\QB64" + CHR$(0)) <> -1 THEN _FULLSCREEN: PRINT: PRINT "Path name does not exist": SLEEP: END
  21.  
  22. 'To view BMP pictures in the directory (folder) from where the EXE is run (current)
  23. IF load_dir("." + CHR$(0)) <> -1 THEN _FULLSCREEN: PRINT: PRINT "Path name does not exist": SLEEP: END
  24.  
  25. 'To view BMP pictures in the parent directory (folder) from where the EXE is run (current)
  26. 'IF load_dir(".." + CHR$(0)) <> -1 THEN _FULLSCREEN: PRINT: PRINT "Path name does not exist": SLEEP: END
  27.  
  28.  
  29.     length = has_next_entry
  30.     IF length = -1 THEN
  31.         PRINT "No more files to process"
  32.         EXIT DO
  33.     END IF
  34.  
  35.     IF length > -1 THEN
  36.         NAM = SPACE$(length)
  37.         get_next_entry NAM, flags, file_size
  38.  
  39.         IF (flags XOR 2) = 0 AND UCASE$(RIGHT$(NAM, 3)) = "BMP" THEN
  40.             PRINT NAM + "                              "
  41.             Fcount = Fcount + 1
  42.             F(Fcount) = NAM
  43.         END IF
  44.  
  45.     END IF
  46.  
  47.  
  48. Fmax = Fcount
  49. close_dir
  50. Fcount = 0
  51.     Fcount = Fcount + 1
  52.  
  53.     loadBMP24 F(Fcount), W, H, HANDLE
  54.     IF W = 0 THEN
  55.         CLS
  56.         PRINT F(Fcount); " Is not a 24 bit per pixel BMP"
  57.         PRINT W; H
  58.         GOTO LL1
  59.     END IF
  60.  
  61.  
  62.  
  63.     SCREEN _NEWIMAGE(W, (ABS(H)), 32)
  64.     _PUTIMAGE (0, 0), HANDLE
  65.     _MEMFREE a
  66.  
  67.     LL1:
  68.     t1 = TIMER
  69.     DO
  70.         _LIMIT 100
  71.         t2 = TIMER
  72.         IF t2 - t1 > 1 THEN EXIT DO
  73.         i$ = INKEY$
  74.         IF i$ = CHR$(27) THEN END
  75.     LOOP
  76.  
  77.  
  78.     IF Fcount = Fmax THEN Fcount = 0
  79.  
  80.  
  81.  
  82.  
  83. 'SUB loadBMP24
  84. 'input filename
  85. 'returns W image width (if = 0 then error)
  86. 'returns H image height (negative or positive value)
  87. 'returns HANDLE
  88.  
  89. SUB loadBMP24 (FILENAME AS STRING, W AS LONG, H AS LONG, HANDLE AS LONG)
  90.  
  91.     DIM OF AS _UNSIGNED LONG
  92.     DIM tt AS STRING * 4
  93.     DIM t AS STRING * 3
  94.     DIM pad AS INTEGER
  95.  
  96.     N = 0
  97.  
  98.     OPEN FILENAME FOR BINARY AS #1
  99.  
  100.     GET #1, 11, OF 'Offset to picture data
  101.  
  102.     GET #1, 15, L 'Header size
  103.  
  104.     GET #1, , W 'image width
  105.  
  106.     GET #1, , H 'image height
  107.  
  108.     GET #1, , I 'biPlanes. Specifies the number of color planes on the target device.
  109.  
  110.     GET #1, , I 'bits per pixel. Must = 24 for the program to work.
  111.  
  112.     IF I <> 24 THEN W = 0: GOTO LL1
  113.  
  114.     HANDLE = _NEWIMAGE(W, ABS(H), 32)
  115.     a = _MEMIMAGE(HANDLE)
  116.  
  117.     pad = 4 - (W * 3) MOD 4
  118.  
  119.     IF pad = 4 THEN pad = 0 'pad = multiple of 4
  120.  
  121.     IF H < 0 THEN
  122.  
  123.         FOR R = 0 TO ABS(H) - 1
  124.  
  125.             FOR C = 1 TO W * 3 STEP 3
  126.                 GET #1, R * (W * 3 + pad) + C + OF, t
  127.                 tt = t + CHR$(255)
  128.                 _MEMPUT a, a.OFFSET + N, tt
  129.                 N = N + 4
  130.             NEXT C
  131.  
  132.         NEXT R
  133.  
  134.     END IF
  135.  
  136.  
  137.     IF H > 0 THEN
  138.  
  139.         FOR R = H - 1 TO 0 STEP -1
  140.  
  141.             FOR C = 1 TO W * 3 STEP 3
  142.                 GET #1, R * (W * 3 + pad) + C + OF, t
  143.                 tt = t + CHR$(255)
  144.                 _MEMPUT a, a.OFFSET + N, tt
  145.                 N = N + 4
  146.             NEXT C
  147.  
  148.         NEXT R
  149.  
  150.     END IF
  151.     LL1:
  152.     CLOSE

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: BMP picture viewer
« Reply #52 on: February 10, 2021, 12:20:33 am »
Works great! All the images loaded and displayed fine! Really easy to load the sub and use it for displaying images.

Navigate your hard disk for BMP24's to display:
Code: QB64: [Select]
  1. _Title "Pipecom Browser 2 for BMP24 File Display" 'b+ testing one array system with pipecom
  2. ' Thanks to Spriggsy, Zak, for convincing me pipecom is better!
  3. ' Using Steve's fixed BMP24 loader
  4. ' Also thanks to Dav for 1 window for file and folder selection idea
  5. ' Also thanks to NOVARSEG who got me going on this for a better filename$ retriever
  6. ' 2021-02-10 update with LoadBMP24 Sub
  7.  
  8. Declare Library "pipecom"
  9.     Function pipecom$ (cmd As String)
  10.  
  11. Screen _NewImage(1280, 740, 32)
  12. _Delay .25
  13. _ScreenMove 65, 0 ' your screen might need different
  14.  
  15. ReDim myFile$
  16. ReDim As Long col, row, charW, charH, W, H, image
  17. Color , &HFF000033
  18. Do 'test our new function
  19.     ScnState 0
  20.     col = 16: row = 3: charW = 128: charH = 40
  21.     myFile$ = GetFileName$(row, col, charW, charH)
  22.     ScnState -1 ' <<<<<<<<<<<<<<<<<<<<<<<<<<< this is supposed to restore back color
  23.     'image& = loadBMP24&(myFile$)
  24.  
  25.     loadBMP24 myFile$, W, H, image
  26.     Color , &HFF000033
  27.     Cls
  28.     If image <> 0 Then
  29.         _Title myFile$ + " press any to get another BMP24 file image, esc to quit"
  30.         _PutImage ((_Width - _Width(image&)) / 2, (_Height - _Height(image&)) / 2)-Step(_Width(image&), _Height(image&)), image&, 0
  31.         Sleep
  32.         _FreeImage image&
  33.     End If
  34.  
  35. 'NOVARSEG's fixed loadBLP24 Sub 2021-02-10 AAAAM https://www.qb64.org/forum/index.php?topic=3602.msg129753#msg129753
  36. Sub loadBMP24 (FILENAME As String, W As Long, H As Long, HANDLE As Long)
  37.  
  38.     Dim OF As _Unsigned Long
  39.     Dim tt As String * 4
  40.     Dim t As String * 3
  41.     Dim pad As Integer
  42.     Dim a As _MEM 'not defined
  43.  
  44.     N = 0
  45.  
  46.     Open FILENAME For Binary As #1
  47.     Get #1, 11, OF 'Offset to picture dat
  48.     Get #1, 15, L 'Header size
  49.     Get #1, , W 'image width
  50.     Get #1, , H 'image height
  51.     Get #1, , I 'biPlanes. Specifies the number of color planes on the target device.
  52.     Get #1, , I 'bits per pixel. Must = 24 for the program to work.
  53.     If I <> 24 Then W = 0: GoTo LL1
  54.     HANDLE = _NewImage(W, Abs(H), 32)
  55.     a = _MemImage(HANDLE)
  56.     pad = 4 - (W * 3) Mod 4
  57.     If pad = 4 Then pad = 0 'pad = multiple of 4
  58.     If H < 0 Then
  59.         For R = 0 To Abs(H) - 1
  60.             For C = 1 To W * 3 Step 3
  61.                 Get #1, R * (W * 3 + pad) + C + OF, t
  62.                 tt = t + Chr$(255)
  63.                 _MemPut a, a.OFFSET + N, tt
  64.                 N = N + 4
  65.             Next C
  66.         Next R
  67.     End If
  68.     If H > 0 Then
  69.         For R = H - 1 To 0 Step -1
  70.             For C = 1 To W * 3 Step 3
  71.                 Get #1, R * (W * 3 + pad) + C + OF, t
  72.                 tt = t + Chr$(255)
  73.                 _MemPut a, a.OFFSET + N, tt
  74.                 N = N + 4
  75.             Next C
  76.         Next R
  77.     End If
  78.     LL1:
  79.     Close
  80.  
  81. Function loadBMP24& (Filename$) ' Steve's revised version without the extra handle and memory leak
  82.     Dim As _Unsigned Long of, l, w, r, c
  83.     Dim a As _MEM
  84.     Dim As Long handle, h ' <<< edit as per NOVARSEG
  85.     Dim tt As String * 4
  86.     Dim t As String * 3
  87.     Dim padding$
  88.  
  89.     If Right$(UCase$(Filename$), 4) <> ".BMP" Then Exit Function
  90.     Print Filename$
  91.     Open Filename$ For Binary As #1
  92.     Get #1, 11, of
  93.     Get #1, 15, l
  94.     Get #1, , w
  95.     Get #1, , h
  96.     Get #1, , i
  97.     Get #1, , i 'get I twice ???
  98.     If i <> 24 Then Exit Function
  99.     handle = _NewImage(w, h, 32)
  100.     a = _MemImage(handle)
  101.     If ((w * 3) Mod 4) <> 0 Then padding$ = Space$((4 - ((w * 3) Mod 4))) '’need padding pixels
  102.     Seek #1, of + 1 'go to the offset where the data starts
  103.     For r = h - 1 To 0 Step -1 'from the bottom to top
  104.         For c = 0 To w - 1 'left to right
  105.             Get #1, , t 'get the data sequentially
  106.             tt = t + Chr$(255)
  107.             _MemPut a, a.OFFSET + (w * r + c) * 4, tt
  108.         Next c
  109.         Get #1, , padding$ 'Get the padding at the end of the line
  110.     Next r
  111.     Close
  112.     loadBMP24& = handle
  113.     _MemFree a
  114.  
  115. Function GetFileName$ (LocateR, LocateC, CharWide, CharHigh) ' < careful Locate Row, Col NOT x, y
  116.     'This Funtion needs:
  117.     ' pipecom.h in same folder as QB64.exe
  118.     ' This in main code section near top:
  119.     ' Declare Library "pipecom"
  120.     '    Function pipecom$ (cmd As String)
  121.     ' End Declare
  122.     ' sub  Split source$, delimiter$, arr$()
  123.     ' function GetArrayItem$(x, y, w, h, arr$())
  124.  
  125.     ReDim As String d, s, dr
  126.     ReDim As _Unsigned Long fc, bc
  127.     fc = _DefaultColor: bc = _BackgroundColor ' save colors
  128.     Getfolder:
  129.     Color fc, bc: Cls
  130.     d = pipecom("dir /n /o:gend") '/n files on right (40) /o = order g for group dirs first, e extension, name, date
  131.     d = Left$(d, Len(d) - 1) ' always ends with delimiter
  132.     ReDim dir(1 To 1) As String
  133.     Split d, Chr$(10), dir()
  134.     s = GetArrayItem$(LocateR, LocateC, CharWide, CharHigh, dir())
  135.     If InStr(s, "<DIR>") Then 'isolate name
  136.         dr = _Trim$(Mid$(s, InStr(s, "<DIR>") + 6))
  137.         ChDir dr
  138.         GoTo Getfolder
  139.     ElseIf InStr(s, "AM") Or InStr(s, "PM") Then
  140.         GetFileName$ = _Trim$(Mid$(s, 40))
  141.         Color fc, bc: Cls
  142.     ElseIf s = "" Then 'cancel, escape, bad line
  143.         Color fc, bc: Cls ' will return empty string
  144.     End If
  145.  
  146. Sub Split (SplitMeString As String, delim As String, loadMeArray() As String)
  147.     Dim curpos As Long, arrpos As Long, LD As Long, dpos As Long 'fix use the Lbound the array already has
  148.     curpos = 1: arrpos = LBound(loadMeArray): LD = Len(delim)
  149.     dpos = InStr(curpos, SplitMeString, delim)
  150.     Do Until dpos = 0
  151.         loadMeArray(arrpos) = Mid$(SplitMeString, curpos, dpos - curpos)
  152.         arrpos = arrpos + 1
  153.         If arrpos > UBound(loadMeArray) Then ReDim _Preserve loadMeArray(LBound(loadMeArray) To UBound(loadMeArray) + 1000) As String
  154.         curpos = dpos + LD
  155.         dpos = InStr(curpos, SplitMeString, delim)
  156.     Loop
  157.     loadMeArray(arrpos) = Mid$(SplitMeString, curpos)
  158.     ReDim _Preserve loadMeArray(LBound(loadMeArray) To arrpos) As String 'get the ubound correct
  159.  
  160.  
  161. ' Help: all this I hope is intuitive so Help window is provided
  162. ' "Mouse, mouse wheel, and arrow keys should work as expected for item selection."
  163. ' "Press spacebar to select a highlighted item or just click it."
  164. ' "Use number(s) + enter to select an array item by it's index number,"
  165. ' "backspace will remove last number pressed, delete will clear a number started.
  166. ' "Numbers started are shown in bottom right PgDn bar."
  167. ' "Enter will also select the highlighted item, if no number has been started."
  168. ' "Home starts you at lowest array index, End highlights then highest index."
  169. ' "Use PgUp and PgDn keys to flip through pages of array items."
  170. '
  171. ' Escape to Cancel Return "" else Return the selected string from the array
  172. Function GetArrayItem$ (LocateRoww, LocateColumn, BoxWidth, BoxHeight, Arr() As String)
  173.     'Notes: locateRow, locateColumn for top right corner of selection box on screen in characters for LOCATE.
  174.     'boxWidth and boxHeight are in character units, again for locate and print at correct places.
  175.     'All displaying is restricted to inside the box, which has PgUP and PgDn as top and bottom lines in the display.
  176.  
  177.     ReDim As Long maxWidth, maxHeight, page, hlite, mx, my, locateRow, lastMX, lastMY, row, mb
  178.     ReDim As Long lba, uba, choice, kh, index
  179.     Dim clrStr As String, b As String
  180.  
  181.     'ScnState 0 ' use out side this function before and after
  182.     locateRow = LocateRoww + 1 'fix a miscalc in coding
  183.     maxWidth = BoxWidth '       number of characters in box
  184.     maxHeight = BoxHeight - 2 ' number of lines displayed of array at one time = 1 page
  185.     lba = LBound(arr)
  186.     uba = UBound(arr)
  187.     page = 0
  188.     hlite = 0 '                 line in display ready for selection by spacebar or if no number is started, enter
  189.     clrStr$ = Space$(maxWidth) 'clearing a display line
  190.  
  191.     GoSub update '              show the beginning of the array items for selection
  192.     choice = -1719
  193.     Do 'until get a selection or demand exit
  194.  
  195.         'handle the key stuff
  196.         kh& = _KeyHit
  197.         If kh& Then
  198.             If kh& > 0 And kh& < 255 Then
  199.                 If InStr("0123456789", Chr$(kh&)) > 0 Then
  200.                     b$ = b$ + Chr$(kh&): GoSub update
  201.                 ElseIf kh& = 13 Then 'enter pressed check if number is being entered?
  202.                     If Len(b$) Then
  203.                         If Val(b$) >= lba And Val(b$) <= uba Then 'we have number started
  204.                             choice = Val(b$): Exit Do
  205.                         Else 'clear b$ to show some response to enter
  206.                             b$ = "": GoSub update 'clear the value that doesn't work
  207.                         End If
  208.                     Else
  209.                         choice = hlite + page * maxHeight + lba 'must mean to select the highlighted item
  210.                     End If
  211.                 ElseIf kh& = 27 Then
  212.                     Exit Do 'escape clause offered to Cancel selection process
  213.                 ElseIf kh& = 32 Then
  214.                     choice = hlite + page * maxHeight + lba 'best way to choose highlighted selection
  215.                 ElseIf kh& = 8 Then 'backspace to edit number
  216.                     If Len(b$) Then b$ = Left$(b$, Len(b$) - 1): GoSub update
  217.                 End If
  218.             Else
  219.                 Select Case kh& 'choosing sections of array to display and highlighted item
  220.                     Case 21248 ' delete so clear b$
  221.                         b$ = "": GoSub update
  222.                     Case 20736 ' pg dn
  223.                         If (page + 1) * maxHeight + lba <= uba Then page = page + 1: GoSub update
  224.                     Case 18688 ' pg up
  225.                         If (page - 1) * maxHeight + lba >= lba Then page = page - 1: GoSub update
  226.                     Case 18432 ' up
  227.                         If hlite - 1 < 0 Then
  228.                             If page > 0 Then
  229.                                 page = page - 1: hlite = maxHeight - 1: GoSub update
  230.                             End If
  231.                         Else
  232.                             hlite = hlite - 1: GoSub update
  233.                         End If
  234.                     Case 20480 'down
  235.                         If (hlite + 1) + page * maxHeight + lba <= uba Then 'ok to move up
  236.                             If hlite + 1 > maxHeight - 1 Then
  237.                                 page = page + 1: hlite = 0: GoSub update
  238.                             Else
  239.                                 hlite = hlite + 1: GoSub update
  240.                             End If
  241.                         End If
  242.                     Case 18176 'home
  243.                         page = 0: hlite = 0: GoSub update
  244.                     Case 20224 ' end
  245.                         page = Int((uba - lba) / maxHeight): hlite = maxHeight - 1: GoSub update
  246.                 End Select
  247.             End If
  248.         End If
  249.  
  250.         'handle the mouse stuff
  251.         While _MouseInput
  252.             If _MouseWheel = -1 Then 'up?
  253.                 If hlite - 1 < 0 Then
  254.                     If page > 0 Then
  255.                         page = page - 1: hlite = maxHeight - 1: GoSub update
  256.                     End If
  257.                 Else
  258.                     hlite = hlite - 1: GoSub update
  259.                 End If
  260.             ElseIf _MouseWheel = 1 Then 'down?
  261.                 If (hlite + 1) + page * maxHeight + lba <= uba Then 'ok to move up
  262.                     If hlite + 1 > maxHeight - 1 Then
  263.                         page = page + 1: hlite = 0: GoSub update
  264.                     Else
  265.                         hlite = hlite + 1: GoSub update
  266.                     End If
  267.                 End If
  268.             End If
  269.         Wend
  270.         mx = Int((_MouseX - LocateColumn * 8) / 8) + 2: my = Int((_MouseY - locateRow * 16) / 16) + 2
  271.         If _MouseButton(1) Then 'click contols or select array item
  272.             'clear mouse clicks
  273.             mb = _MouseButton(1)
  274.             If mb Then 'clear it
  275.                 While mb 'OK!
  276.                     If _MouseInput Then mb = _MouseButton(1)
  277.                     _Limit 100
  278.                 Wend
  279.             End If
  280.  
  281.             If mx >= 1 And mx <= maxWidth And my >= 1 And my <= maxHeight Then
  282.                 choice = my + page * maxHeight + lba - 1 'select item clicked
  283.             ElseIf mx >= 1 And mx <= maxWidth And my = 0 Then 'page up or exit
  284.                 If my = 0 And (mx <= maxWidth And mx >= maxWidth - 2) Then 'exit sign
  285.                     Exit Do 'escape plan for mouse click top right corner of display box
  286.                 Else 'PgUp bar clicked
  287.                     If (page - 1) * maxHeight + lba >= lba Then page = page - 1: GoSub update
  288.                 End If
  289.             ElseIf mx >= 1 And mx <= maxWidth And my = maxHeight + 1 Then 'page down bar clicked
  290.                 If (page + 1) * maxHeight + lba <= uba Then page = page + 1: GoSub update
  291.             End If
  292.         Else '   mouse over highlighting, only if mouse has moved!
  293.             If mx >= 1 And mx <= maxWidth And my >= 1 And my <= maxHeight Then
  294.                 If mx <> lastMX Or my <> lastMY Then
  295.                     If my - 1 <> hlite And (my - 1 + page * maxHeight + lba <= uba) Then
  296.                         hlite = my - 1
  297.                         lastMX = mx: lastMY = my
  298.                         GoSub update
  299.                     End If
  300.                 End If
  301.             End If
  302.         End If
  303.         _Limit 200
  304.     Loop Until choice >= lba And choice <= uba
  305.     If choice <> -1719 Then GetArrayItem$ = Arr(choice) 'set function and restore screen
  306.     'ScnState -1 'restore
  307.  
  308.     'display of array sections and controls on screen  ====================================================
  309.     update:
  310.  
  311.     'fix hlite if it has dropped below last array item
  312.     While hlite + page * maxHeight + lba > uba
  313.         hlite = hlite - 1
  314.     Wend
  315.  
  316.     'main display of array items at page * maxHeight (lines high)
  317.     For row = 0 To maxHeight - 1
  318.         If hlite = row Then Color _RGB(200, 200, 255), _RGB32(0, 0, 88) Else Color _RGB32(0, 0, 88), _RGB(200, 200, 255)
  319.         Locate locateRow + row, LocateColumn: Print clrStr$;
  320.         index = row + page * maxHeight + lba
  321.         If index >= lba And index <= uba Then
  322.             Locate locateRow + row, LocateColumn
  323.             Print Left$(LTrim$(Str$(index)) + ") " + Arr(index), maxWidth);
  324.         End If
  325.     Next
  326.  
  327.     'make page up and down bars to click, print PgUp / PgDn if available
  328.     Color _RGB32(200, 200, 255), _RGB32(0, 100, 50)
  329.     Locate locateRow - 1, LocateColumn: Print Space$(maxWidth);
  330.     If page <> 0 Then Locate locateRow - 1, LocateColumn: Print Left$(" Pg Up" + Space$(maxWidth), maxWidth);
  331.     Locate locateRow + maxHeight, LocateColumn: Print Space$(maxWidth);
  332.     If page <> Int(uba / maxHeight) Then
  333.         Locate locateRow + maxHeight, LocateColumn: Print Left$(" Pg Dn" + Space$(maxWidth), maxWidth);
  334.     End If
  335.     'make exit sign for mouse click
  336.     Color _RGB32(255, 255, 255), _RGB32(200, 100, 0)
  337.     Locate locateRow - 1, LocateColumn + maxWidth - 3
  338.     Print " X ";
  339.  
  340.     'if a number selection has been started show it's build = b$
  341.     If Len(b$) Then
  342.         Color _RGB(255, 255, 0), _RGB32(0, 0, 0)
  343.         Locate locateRow + maxHeight, LocateColumn + maxWidth - Len(b$) - 1
  344.         Print b$;
  345.     End If
  346.     _Display
  347.     _Limit 100
  348.     Return
  349.  
  350. Sub ScnState (restoreTF As Long) 'Thanks Steve McNeill  should we get a snap shot of screen?
  351.     Static As _Unsigned Long defaultColor, backGroundColor
  352.     Static As Long font, dest, source, row, col, autodisplay, mb, snap
  353.     If restoreTF Then
  354.         _Font font
  355.         Color defaultColor, backGroundColor
  356.         _Dest dest
  357.         _Source source
  358.  
  359.         _KeyClear
  360.         While _MouseInput: Wend 'clear mouse clicks
  361.         mb = _MouseButton(1)
  362.         If mb Then 'need this if line ?
  363.             Do
  364.                 While _MouseInput: Wend
  365.                 mb = _MouseButton(1)
  366.                 _Limit 100
  367.             Loop Until mb = 0
  368.         End If
  369.         _PutImage , snap, dest
  370.         _FreeImage snap
  371.         _Display
  372.         If autodisplay Then _AutoDisplay Else _Display
  373.         Locate row, col
  374.     Else
  375.         snap = _NewImage(_Width, _Height, 32)
  376.         _PutImage , 0, snap
  377.         font = _Font: defaultColor = _DefaultColor: backGroundColor = _BackgroundColor
  378.         dest = _Dest: source = _Source
  379.         row = CsrLin: col = Pos(0): autodisplay = _AutoDisplay
  380.         While _MouseInput: Wend 'clear mouse clicks
  381.         mb = _MouseButton(1)
  382.         If mb Then 'need this if line ?
  383.             Do
  384.                 While _MouseInput: Wend
  385.                 mb = _MouseButton(1)
  386.                 _Limit 100
  387.             Loop Until mb = 0
  388.         End If
  389.         _KeyClear
  390.     End If
  391.  
  392.  
  393.  
  394.  

Need this in your QB64.exe Folder
* pipecom.h (Filesize: 0.45 KB, Downloads: 129)
« Last Edit: February 10, 2021, 12:24:32 am by bplus »

Offline NOVARSEG

  • Forum Resident
  • Posts: 509
    • View Profile
Re: BMP picture viewer
« Reply #53 on: February 10, 2021, 12:40:17 am »
That is the first sub I have written in years!
 Do  I need the latest ver of QB64 to see this?   

Glad it worked even on -h too ?

i see you used  _FreeImage image&

Ok prob works better than  _MEMFREE a   
« Last Edit: February 10, 2021, 12:46:25 am by NOVARSEG »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: BMP picture viewer
« Reply #54 on: February 10, 2021, 10:53:54 am »
That is the first sub I have written in years!
 Do  I need the latest ver of QB64 to see this?   

Glad it worked even on -h too ?

i see you used  _FreeImage image&

Ok prob works better than  _MEMFREE a   

For your version QB64, you might have to change the REDIM statements that declare Types in groups like:
ReDim As Long x, y, z

Just make:
Redim x as long, y as long, z as long

Or get the 1.5 dev version ;)


I used _FreeImage because what was stored in Handle was an image.

_MEMFREE a should have been in LoadBMP24 Sub because that is where the variable, a, resides.
I don't know with _Mem stuff if a is automatically cleared like a regular variable as soon as you exit the sub. We know images wont.