Announcement

Collapse
No announcement yet.

How to make a BMP image in memory? Any pointers?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    More info... Looks like the image the device needs is a RAW BGR... Any thoughts on that?

    Comment


    • #22
      Or you could use the software that came with the device... Drag and drop makes it so easy. I'm just saying...

      Comment


      • #23
        Hi Jim!

        Your are right! However I am trying to write something that doesn't need the factory software - more of an industrial control / security thing. The factory is enormous and spralling. I think I can do it in a single .EXE around 100K in size. I have it mostly working just having trouble with the images.

        What I know so far is that the "image" is 80*80 - 6400 bytes, some people have said 72*72 bytes.

        You send it to the Stream Deck in 20 packets each 1024 bytes long. The first 16 bytes in each packet is the HID header. So I am a bit spun around on what I need to send for the image data. It starts with BM so I figured it was a normal bitmap. It may be!

        Comment


        • #24
          How do you need it, as a string, an array of longs, or an array of bytes?

          String:
          GRAPHIC GET BITS TO A$

          Long:
          Code:
          GRAPHIC ATTACH BMP, 0
          DIM BRGAry(0 TO High  - 1,  0 TO Wide - 1)
          FOR I = 0  TO High - 1
            FOR J = 0 TO Wide - 1
               GRAPHIC GET PIXEL(J, I) TO Color&
               Color& = BGR(Color&)
               BGTAry(I, J) = Color&
            NEXT J
          NEXT I
          Bytes:
          Code:
          GRAPHIC GET BITS TO A$
          LngPtr = STRPTR(A$) + 8
          BytPtr = VARPTR(Color&)
          DIM BYTAry(0 TO High * Wide * 3
          K = 0
          FOR I = 0 TO High - 1
            FOR J = 0 TO Wide - 1
              Color$ = @LngPtr
              BYTAry(K) = @BytPtr[2]
              K = K + 1
              BYTAry(K) = @BytPtr[1]
             K = K + 1
              BYTAry(K) = @BytPtr[0]
             K = K + 1
             INCR LngPtr
           NEXT J
          NEXT I

          Walt Decker

          Comment


          • #25
            I guess a string would be easy since I have to add an HID header to each send packet.The header is 16 bytes and changes a little with each packet.

            Comment


            • #26
              Originally posted by David Clarke View Post
              This is the device I am working on - https://www.elgato.com/en/gaming/stream-deck-mini

              This looks like it could be very handy in the studio for A/V production.
              I am legally blind. Please forgive any typos. I do try and catch as many as I can.

              Comment


              • #27
                See photos... The correct one is the image installed by the factory application. The rotated and mirrored image is installed by my application.
                Exact same file!



                Click image for larger version

Name:	IMG_1949.JPG
Views:	79
Size:	374.6 KB
ID:	781287Click image for larger version

Name:	IMG_1948.JPG
Views:	58
Size:	434.5 KB
ID:	781288

                Comment


                • #28
                  Exact same file!
                  Can you attach the file?

                  The raw data is recorded in a bitmap file "Upside down" ie the data immediately following the header is the bottom line of the picture. It is written left to right though, so that doesn't explain the 90 degree rotation.

                  Have you put the raw data into an array? Maybe row, column order in memory is at play..
                  Rgds, Dave

                  Comment


                  • #29
                    Hi Dave
                    I attached the file. Click image for larger version

Name:	Bitmap.bmp
Views:	83
Size:	18.9 KB
ID:	781294

                    Comment


                    • #30
                      Here is the way I am doing it.


                      Code:
                      OPEN "bitmap.bmp" FOR BINARY AS #1
                           GET$ #1, LOF(1), IMAGE_STRING
                          CLOSE #1
                      
                      
                      
                         FOR I = 0 TO 18
                         WRITE_BUFFER = ""
                      
                         HID_PACKET_HEADER_16 = CHR$(02, 01) + CHR$(I) + CHR$(00, 00) +  CHR$(KEY_NUMBER) + CHR$(00, 00, 00, 00, 00, 00, 00, 00, 00, 00)
                      
                         TEXT_TO_SCREEN STR$(LEN(IMAGE_STRING))
                         WRITE_BUFFER = HID_PACKET_HEADER_16 + LEFT$(IMAGE_STRING, 1008)
                         IMAGE_STRING = CLIP$(LEFT,IMAGE_STRING,1008)
                      
                      
                         SEND_PACKET_TO_DEVICE WRITE_BUFFER
                      
                         SLEEP 1
                         TEXT_TO_SCREEN "loop = " + STR$(i)
                         NEXT
                      
                         ' The final row... 
                         HID_PACKET_HEADER_16 = CHR$(02, 01) + CHR$(19) + CHR$(00, 01) +  CHR$(KEY_NUMBER) + CHR$(00, 00, 00, 00, 00, 00, 00, 00, 00, 00)
                         TEXT_TO_SCREEN STR$(LEN(IMAGE_STRING))
                         WRITE_BUFFER = HID_PACKET_HEADER_16 + LEFT$(IMAGE_STRING + NUL$(1024), 1008)
                      
                      
                         SEND_PACKET_TO_DEVICE WRITE_BUFFER  

                      Comment


                      • #31
                        Originally posted by David Clarke View Post
                        See photos... The correct one is the image installed by the factory application. The rotated and mirrored image is installed by my application.
                        Exact same file!



                        Click image for larger version

Name:	IMG_1949.JPG
Views:	79
Size:	374.6 KB
ID:	781287Click image for larger version

Name:	IMG_1948.JPG
Views:	58
Size:	434.5 KB
ID:	781288
                        Can you manually rotate and invert the bitmaps before sending them so they work properly then?
                        The world is strange and wonderful.*
                        I reserve the right to be horrifically wrong.
                        Please maintain a safe following distance.
                        *wonderful sold separately.

                        Comment


                        • #32
                          Hi Kurt,
                          At the moment I don't know how to do that. I was just reading about that.

                          Comment


                          • #33
                            From a friend of mine - "Bmp images have 0,0 in bottom left, instead of top left like any other file format and canvases."

                            There must be something I am missing here. BMP files I make with MS paint or Photoshop are not 0,0 in the bottom left... AND a BMP I make with PB Graphic calls are not in 0,0 the bottom left.

                            From Wikipedia - - The pixel array is a block of 32-bit DWORDs, that describes the image pixel by pixel. Usually pixels are stored "bottom-up", starting in the lower left corner, going from left to right, and then row by row from the bottom to the top of the image.[4] Unless BITMAPCOREHEADER is used, uncompressed Windows bitmaps also can be stored from the top to bottom, when the Image Height value is negative.

                            What is that telling me? That my images have used BITMAPCOREHEADER?

                            Comment


                            • #34
                              The bitmap that you have attached above uses a 124byte BITMAPV5HEADER. (NOT BITMAPCOREHEADER which is 64 bytes).

                              You could possibly load the bitmap pixel info into an array and then use MAT commands to rotate and invert it before sending it?

                              Alternatively, if the manufacturers software allows you to rotate or flip an imported image there may be an instruction in the HID_PACKET_HEADER_16 that you have missed?

                              Click image for larger version  Name:	WindowsBmpHeaders.png Views:	0 Size:	24.3 KB ID:	781336
                              Rgds, Dave

                              Comment


                              • #35
                                From a friend of mine - "Bmp images have 0,0 in bottom left, instead of top left like any other file format and canvases."

                                There must be something I am missing here. BMP files I make with MS paint or Photoshop are not 0,0 in the bottom left... AND a BMP I make with PB Graphic calls are not in 0,0 the bottom left.

                                Comment


                                • #36
                                  Dave, Again you are showing me something I didn't know! I will digest what you have told me and get back to you! Thanks Again!

                                  What are MAT commands? A PB thing or API thing or something else?

                                  Comment


                                  • #37
                                    MAT for PowerBASIC matrix functions. Among other things, useful for operating quickly on arrays - array copy, removing row/col of 2D array. Help has more.

                                    Comment


                                    • #38
                                      Hi David,
                                      Yes, in PowerBASIC we work with 0,0 as the upper left. But that's not the same as where the BMP file format says to store the data. When PowerBASIC reads in a BMP file, it then conveniently allows you to reference 0,0 as the upper left, hiding from you the details of where the pixel data is stored in the actual file.

                                      Comment


                                      • #39
                                        Originally posted by David Clarke View Post
                                        Hi Kurt,
                                        At the moment I don't know how to do that. I was just reading about that.
                                        I think I posted a BMP transformations set to sample code a while back.
                                        I guess it only keeps twenty pages and things roll off onto the floor after a while.
                                        Code:
                                        #COMPILE EXE
                                        #DIM ALL
                                        ENUM hndls SINGULAR     'create named numerical equates for buttons and rotate functions
                                            IDB_open = 1000
                                            IDB_save
                                            IDB_right
                                            IDB_left
                                            IDB_180
                                            IDB_mirror
                                            IDB_invert
                                            IDG_grph
                                        END ENUM
                                        
                                        FUNCTION PBMAIN() AS LONG
                                            LOCAL hDlg AS DWORD     'create dialog and controls
                                            DIALOG NEW PIXELS, 0, "Bitmap Rotation", , , 900,750, %WS_SYSMENU, 0 TO hDlg
                                            CONTROL ADD BUTTON, hDlg, %IDB_open, "&Open Image", 10,5,100,22, %WS_TABSTOP
                                            CONTROL ADD BUTTON, hDlg, %IDB_left, "Rotate &Left", 120,5,100,22, %WS_TABSTOP
                                            CONTROL ADD BUTTON, hDlg, %IDB_right, "Rotate &Right", 230,5,100,22, %WS_TABSTOP
                                            CONTROL ADD BUTTON, hDlg, %IDB_180, "Rotate &One-eighty", 340,5,100,22, %WS_TABSTOP
                                            CONTROL ADD BUTTON, hDlg, %IDB_mirror, "&Mirror Image", 450,5,100,22, %WS_TABSTOP
                                            CONTROL ADD BUTTON, hDlg, %IDB_invert, "&Invert Image", 560,5,100,22, %WS_TABSTOP
                                            CONTROL ADD BUTTON, hDlg, %IDB_save, "&Save Image", 670,5,100,22, %WS_TABSTOP
                                            CONTROL ADD GRAPHIC, hDlg, %IDG_grph,"", 0, 35, 900, 715
                                            DIALOG SHOW MODAL hDlg CALL DlgProc
                                        END FUNCTION
                                        
                                        CALLBACK FUNCTION DlgProc() AS LONG
                                            STATIC hBmp_load, hBmp_save AS DWORD
                                            SELECT CASE CB.MSG
                                                CASE %WM_COMMAND
                                                    SELECT CASE CB.CTL
                                                        CASE %IDCANCEL: DIALOG END CB.HNDL
                                                        CASE %IDB_open
                                                            IF hBmp_load > 0 THEN GRAPHIC ATTACH hBmp_load, 0: GRAPHIC BITMAP END: GRAPHIC DETACH
                                                            hBmp_load = Loadbmp(CB.HNDL)
                                                            GRAPHIC ATTACH CB.HNDL, %IDG_grph
                                                            GRAPHIC CLEAR
                                                            IF hBmp_load <> 0 THEN
                                                                GRAPHIC COPY hBmp_load, 0
                                                            END IF
                                                        CASE %IDB_save
                                                            GRAPHIC ATTACH hBmp_load, 0
                                                            ? "Save operation " + IIF$(SaveBmp(CB.HNDL), "successful.", "failed.")
                                                        CASE %IDB_180, %IDB_right, %IDB_left, %IDB_mirror, %IDB_invert
                                                            IF hBmp_load > 0 THEN hBmp_load = Bmp_rot(hBmp_load, CB.CTL)
                                                            IF hBmp_load > 0 THEN
                                                                GRAPHIC ATTACH CB.HNDL, %IDG_grph, REDRAW
                                                                GRAPHIC CLEAR
                                                                GRAPHIC COPY hBmp_load, 0
                                                                GRAPHIC REDRAW
                                                            END IF
                                                    END SELECT
                                            END SELECT
                                        END FUNCTION
                                        
                                        FUNCTION Loadbmp(hDlg AS DWORD) AS DWORD
                                            LOCAL filter, bmpname AS STRING, hBmp AS DWORD
                                            filter = "BITMAP" + CHR$(0) + "*.bmp" + CHR$(0)
                                            DISPLAY OPENFILE hDlg, 10, 30, "Open Bitmap", "", filter, "", "", %OFN_FILEMUSTEXIST TO bmpname
                                            IF bmpname <> "" THEN
                                                TRY
                                                    GRAPHIC BITMAP LOAD bmpname, 0, 0 TO hBmp
                                                CATCH
                                                    ? "File Open Operation Failed."
                                                    EXIT FUNCTION
                                                END TRY
                                            END IF
                                            FUNCTION = hBmp
                                        END FUNCTION
                                        
                                        FUNCTION Savebmp(hDlg AS DWORD) AS DWORD
                                            LOCAL filter, bmpname AS STRING
                                            filter = "BITMAP" + CHR$(0) + "*.bmp" + CHR$(0)
                                            DISPLAY SAVEFILE hDlg, 10, 30, "Save Bitmap", "", filter, "", "", %OFN_CREATEPROMPT TO bmpname
                                            IF bmpname <> "" THEN
                                                IF INSTR(UCASE$(bmpname), ".BMP") < 1 THEN bmpname += ".bmp"
                                                TRY
                                                    GRAPHIC SAVE bmpname: FUNCTION = -1
                                                CATCH
                                                    EXIT FUNCTION
                                                END TRY
                                            END IF
                                        END FUNCTION
                                        
                                        'Rotation function, compacted and without comments. Expanded and commented version is below
                                        'FUNCTION Bmp_rot(hbmp AS DWORD, action AS LONG) AS DWORD
                                        '    LOCAL rot_bmp AS DWORD, x, y, a(), b(), dx, dy AS LONG, str_src, str_dst AS STRING
                                        '    GRAPHIC ATTACH hbmp, 0: GRAPHIC GET BITS TO str_src: GRAPHIC GET CANVAS TO dx, dy
                                        '    REDIM a(dx - 1, dy - 1) AT STRPTR(str_src) + 8
                                        '    SELECT CASE action
                                        '        CASE %IDB_left, %IDB_right: GRAPHIC BITMAP NEW dy, dx TO rot_bmp
                                        '        CASE %IDB_180, %IDB_invert, %IDB_mirror: GRAPHIC BITMAP NEW dx, dy TO rot_bmp
                                        '        CASE ELSE: EXIT FUNCTION
                                        '    END SELECT: GRAPHIC ATTACH rot_bmp, 0: GRAPHIC GET BITS TO str_dst
                                        '    SELECT CASE action
                                        '        CASE %IDB_left: REDIM b(dy - 1, dx - 1) AT STRPTR(str_dst) + 8
                                        '            FOR x = 0 TO (dx - 1):  FOR y = 0 TO (dy - 1): b(y, dx - x - 1) = a(x, y): NEXT: NEXT
                                        '        CASE %IDB_right: REDIM b(dy - 1, dx - 1) AT STRPTR(str_dst) + 8
                                        '            FOR x = 0 TO (dx - 1): FOR y = 0 TO (dy - 1): b(dy - y - 1, x) = a(x, y): NEXT: NEXT
                                        '        CASE %IDB_180: REDIM b(dx - 1, dy - 1) AT STRPTR(str_dst) + 8
                                        '            FOR x = 0 TO (dx - 1): FOR y = 0 TO (dy - 1): b(dx - x - 1, dy - y - 1) = a(x, y): NEXT: NEXT
                                        '        CASE %IDB_invert: REDIM b(dx - 1, dy - 1) AT STRPTR(str_dst) + 8
                                        '            FOR x = 0 TO (dx - 1): FOR y = 0 TO (dy - 1): b(x, dy - y - 1) = a(x, y): NEXT: NEXT
                                        '        CASE %IDB_mirror: REDIM b(dx - 1, dy - 1) AT STRPTR(str_dst) + 8
                                        '            FOR x = 0 TO (dx - 1): FOR y = 0 TO (dy - 1): b(dx - x - 1, y) = a(x, y): NEXT: NEXT
                                        '    END SELECT: GRAPHIC SET BITS str_dst: FUNCTION = rot_bmp: GRAPHIC ATTACH hbmp, 0: GRAPHIC BITMAP END
                                        'END FUNCTION
                                        
                                        FUNCTION Bmp_rot(hbmp AS DWORD, action AS LONG) AS DWORD    'receive original bitmap handle and what to do
                                            LOCAL rot_bmp AS DWORD                                  'used for new bitmap handle
                                            LOCAL x, y, a(), b(), dx, dy AS LONG                    'used for iteration, size and graphic string pixel arrays
                                            LOCAL str_src, str_dst AS STRING                        'used for bitmap pixel strings
                                            GRAPHIC ATTACH hbmp, 0                              'attach source bitmap
                                            GRAPHIC GET BITS TO str_src                         'create bit string
                                            GRAPHIC GET CANVAS TO dx, dy                        'get bitmap size : if dialog units are used, convert
                                            REDIM a(dx - 1, dy - 1) AT STRPTR(str_src) + 8      'create long integer array in string space
                                            SELECT CASE action                                  'Bitmap dimensions are one-based : Arrays are zero-based
                                                CASE %IDB_left, %IDB_right
                                                    GRAPHIC BITMAP NEW dy, dx TO rot_bmp        'new bitmap swaps x and y size parameters for left or right rotate
                                                CASE %IDB_180, %IDB_invert, %IDB_mirror
                                                    GRAPHIC BITMAP NEW dx, dy TO rot_bmp        'new bitmap has same x and y parameters for 180, mirror or invert
                                                CASE ELSE
                                                    EXIT FUNCTION                               'no action taken
                                            END SELECT
                                            GRAPHIC ATTACH rot_bmp, 0                           'attach destination bitmap
                                            GRAPHIC GET BITS TO str_dst                         'creat bit string
                                            SELECT CASE action
                                                CASE %IDB_left
                                                    REDIM b(dy - 1, dx - 1) AT STRPTR(str_dst) + 8  'create long integer array in string space, swapped x, y
                                                    FOR x = 0 TO (dx - 1)                           'iterate through all pixels in array
                                                        FOR y = 0 TO (dy - 1)
                                                            b(y, dx - x - 1) = a(x, y)              'read lines and write to columns, top-left = left-bottom
                                                        NEXT
                                                    NEXT
                                                CASE %IDB_right                                     'same as rotate left, but top-left = right-top
                                                    REDIM b(dy - 1, dx - 1) AT STRPTR(str_dst) + 8
                                                    FOR x = 0 TO (dx - 1)
                                                        FOR y = 0 TO (dy - 1)
                                                            b(dy - y - 1, x) = a(x, y)
                                                        NEXT
                                                    NEXT
                                                CASE %IDB_180
                                                    REDIM b(dx - 1, dy - 1) AT STRPTR(str_dst) + 8  'create long integer array in string space
                                                    FOR x = 0 TO (dx - 1)
                                                        FOR y = 0 TO (dy - 1)
                                                            b(dx - x - 1, dy - y - 1) = a(x, y)     'read right side up, write upside down and backwards
                                                        NEXT                                        'top-left = bottom-right
                                                    NEXT
                                                CASE %IDB_invert
                                                    REDIM b(dx - 1, dy - 1) AT STRPTR(str_dst) + 8  'create long integer array in string space
                                                    FOR x = 0 TO (dx - 1)
                                                        FOR y = 0 TO (dy - 1)
                                                            b(x, dy - y - 1) = a(x, y)              'read top to bottom, write bottom to top.
                                                        NEXT                                        'top-left = bottom-left and top-right = bottom-right
                                                    NEXT
                                                CASE %IDB_mirror
                                                    REDIM b(dx - 1, dy - 1) AT STRPTR(str_dst) + 8  'create long integer array in string space
                                                    FOR x = 0 TO (dx - 1)
                                                        FOR y = 0 TO (dy - 1)
                                                            b(dx - x - 1, y) = a(x, y)              'read right to left, write left to right.
                                                        NEXT                                        'top-left = top-right and bottom-left = bottom-right
                                                    NEXT
                                            END SELECT
                                            GRAPHIC SET BITS str_dst        'write string data from graphic array back to bitmap
                                            FUNCTION = rot_bmp              'function equals handle of new, altered bitmap
                                            GRAPHIC ATTACH hbmp, 0          'attach original bitmap
                                            GRAPHIC BITMAP END              'delete original bitmap from memory
                                        END FUNCTION
                                        Last edited by Kurt Kuzba; 16 May 2019, 05:30 AM. Reason: Added code for bitmap manipulation
                                        The world is strange and wonderful.*
                                        I reserve the right to be horrifically wrong.
                                        Please maintain a safe following distance.
                                        *wonderful sold separately.

                                        Comment


                                        • #40
                                          David, I guess you solved you're USB problems. What was tripping you up?

                                          Comment

                                          Working...
                                          X