QB64 Phoenix Edition
Declare an .ico file - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: QB64 Rising (https://qb64phoenix.com/forum/forumdisplay.php?fid=1)
+--- Forum: Code and Stuff (https://qb64phoenix.com/forum/forumdisplay.php?fid=3)
+---- Forum: Help Me! (https://qb64phoenix.com/forum/forumdisplay.php?fid=10)
+---- Thread: Declare an .ico file (/showthread.php?tid=1585)

Pages: 1 2


RE: Declare an .ico file - eoredson - 03-28-2023

@TempodiBasic:


Quote:and so it seems doing QB64pe...
so I miss the meaning of your message.
Please can say me it in other words?

I am not trying to do anything fancy like loading icons or displaying them.

All I want is the icon on the top-left of the titlebar.

Erik. This is my icon..


[Image: SIC64.png]


RE: Declare an .ico file - Petr - 03-29-2023

(03-28-2023, 10:06 PM)eoredson Wrote: Sorry, got the wrong link:
https://qb64phoenix.com/qb64wiki/index.php/ICON
NOTE: Icon files are not supported with _LOADIMAGE and an error will occur.

So again: Use my program LoadIco. Here is another example of how to get an icon (ico file) in the upper left corner of the program window:

ICO File free downloaded from https://icon-icons.com/download/111465/ICO/48/

USE LOADICO FOR SET PROGRAM ICON

Code: (Select All)
'Petr Preclik presents:
'LOADICO function. Use ico files as icons in your programs! Use it as:  handle = LOADICON (ico_file_name$, number of frame in this ICO file)
'                                                   For list all images in ICO file set second parameter to zero (call it in 32 bit screen)
'                                                                  For returning how much frames ICO contains, set second parameter as < 0.

_Title "ICO Loader"
Screen _NewImage(1024, 600, 32)
Cls , _RGB32(25, 0, 12)

file$ = "12099handshake_111465.ico"


Ico = LOADICO(file$, 1)
_Icon Ico






Function LOADICO& (file As String, fram As Integer)
    'file identity header
    PD = _Dest
    Type File_Head
        reserved As Integer '0
        id_Type As Integer '1
        id_Count As Integer 'number of frames in file
    End Type

    Type ICO_Head
        bWidth As _Unsigned _Byte
        bHeight As _Unsigned _Byte
        color_count As _Unsigned _Byte '0 = >256 colors
        bReserved As _Unsigned _Byte '0
        wPlanes As _Unsigned Integer 'number of bit layers
        wBitCount As _Unsigned Integer 'bites per pixel
        dwBytesInRes As Long 'image lenght included palette
        dwImageOffset As Long 'icon begin from file begin (driving record)
    End Type



    Type Ico_Image
        ThisSize As Long '40
        width As Long
        height As Long
        biPlanes As Integer '1
        BitCount As Integer 'bites per pixel, tj 1, 4 , 8, 24
        Compression As Long '0 = BI_RGB, 1 = BI_RLE8, 2 = BI_RLE4
        SizeImage As Long 'image size
        XPelsPerMeter As Long '0
        YPelsPerMeter As Long '0
        nic As Long '0        'nothing :)
        taky_nic As Long '0   'also nothing :)  i have none informations and none sources - for what is this!
    End Type

    Type IcIm 'help array (maybe? - this is wroted long time ago... :-/ )
        W As Integer
        H As Integer
        colors As _Unsigned _Byte
        BPP As _Unsigned _Byte
        L As Long
        Offset As Long
        WP As _Unsigned Integer
    End Type

    Dim FH As File_Head, IH As ICO_Head, II As Ico_Image
    ch = FreeFile

    If _FileExists(file$) Then Open file$ For Binary As #ch Else Print "ICO loader error: file "; file$; " not exist.": Sleep 2: System
    Get #ch, , FH
    If FH.reserved = 0 And FH.id_Type = 1 Then Else Print "unknown format!": System
    frames = FH.id_Count 'frames number (total frames) in file
    If fram < 0 Then LOADICO& = frames: Exit Function '                                                                                                        -1 is for returning number frames in file
    If fram > frames Then Print "This file contains not so much images. File "; file$; " contains "; frames; "frames. Can not using frame"; fram: Sleep 2: Exit Function
    ' PRINT "Frames in file: "; frames
    ReDim Ico(frames) As IcIm
    For al_fr = 1 To frames
        Get #ch, , IH
        Ico(al_fr).W = IH.bWidth
        Ico(al_fr).H = IH.bHeight
        Ico(al_fr).colors = IH.color_count '0 = >256 colors
        Ico(al_fr).BPP = IH.wBitCount 'bites per pixel
        Ico(al_fr).L = IH.dwBytesInRes 'image lenght included palette
        Ico(al_fr).Offset = IH.dwImageOffset + 1 'icon record byte start position from file begin
        If IH.color_count = 0 Then IHcolor_count = 256 Else IHcolor_count = IH.color_count
        Ico(al_fr).WP = IHcolor_count
    Next al_fr
    'vsechny hlavy ke vsem snimkum jsou nacteny. Tato hlava je ridici pro kazdy snimek.
    'all heads for all frames are ready. This is head for every head

    If fram = 0 Then vs = 1: ve = frames Else vs = fram: ve = fram
    For all = vs To ve
        Seek #ch, Ico(all).Offset 'posun na spravnou pozici       skip to correct position

        If Ico(all).BPP = 32 Then ' nejprve otestuju pritomnost PNG pokud je hloubka 32 bit: 'first testing, if PNG is contained in file, when bites per pixel is 32
            current_position = Seek(ch)
            Dim start_test As String * 8
            '            DIM end_test AS STRING * 12
            start$ = Chr$(137) + Chr$(80) + Chr$(78) + Chr$(71) + Chr$(13) + Chr$(10) + Chr$(26) + Chr$(10)
            Get #ch, , start_test$
            If start_test$ = start$ Then
                Ico(all).BPP = 32
                Ico(all).W = 256
                Ico(all).H = 256
                icon& = _CopyImage(extract_png&(ch), 32): GoTo ______skip
            Else
                Seek #ch, current_position
            End If
        End If
        Get #ch, , II '            nactu hlavu obrazku. Tato hlava je navic a nepouziva se, aspon mysim....  ' really i dont know for what is this, just some records

        If Ico(all).BPP > 0 And Ico(all).BPP <= 8 Then depth = 256 Else depth = 32
        If Ico(all).W = 0 Then Ico(all).W = 256
        If Ico(all).H = 0 Then Ico(all).H = 256

        '   PRINT Ico(all).W, Ico(all).H, depth
        icon& = _NewImage(Ico(all).W, Ico(all).H, depth)
        _Dest icon&

        Select Case Ico(all).BPP '   za havou bitmapy nasleduje paleta   After bitmap header is palette
            Case 1
                PalLenght = 1
            Case 4
                PalLenght = 15 'ok pro 4 barvy  OK for 4 colors
            Case 8
                PalLenght = 255
            Case 0, 32
                GoTo _______noPalete
        End Select

        ReDim pal As _Unsigned Long 'vypoctem potvrzeno long   LONG confirmed :)
        For palete = 0 To PalLenght
            Get #ch, , pal
            _PaletteColor palete, pal, icon&
        Next palete
        _______noPalete:

        Select Case Ico(all).BPP 'podle bitove hloubky probehne vykresleni     drawing starts by bit depth

            Case 1 ' testovano na jednom jedinem pripade...      this is tested just on ONE file
                ReDim bwi As String, valuee As _Unsigned _Byte
                For draw1 = 1 To Ico(all).W * Ico(all).H
                    Get #ch, , valuee
                    bwi = bwi + DECtoBIN$(valuee)
                Next

                drawX = 0
                drawY = Ico(all).H
                For DrawXOR = 1 To Ico(all).W * Ico(all).H

                    If (Mid$(bwi$, DrawXOR, 1)) = "1" Then PSet (drawX, drawY)
                    drawX = drawX + 1: If drawX >= Ico(all).W And Ico(all).H Mod 4 = 0 Then drawX = 0: drawY = drawY - 1
                Next

            Case 4 '                                                   pro soubory o jednom snimku naprosto v poradku (neni podpora PNG ale to asi v 16ti barvach nebude potreba)
                '                                                      for files contins one frame is this all right (is not PNG support in 16 colors, i think this is not need)
                Dim R4 As _Unsigned _Byte
                binary$ = ""

                For READ_XOR_DATA = 1 To (Ico(all).W * Ico(all).H) / 2
                    Get #ch, , R4
                    binary$ = binary$ + DECtoBIN$(R4)
                Next READ_XOR_DATA

                Dim colors4(Len(binary$)) As _Byte
                calc_color = 0


                For calc_colors = 1 To Len(binary$) Step 4
                    colors4(calc_color) = BINtoDEC(Mid$(binary$, calc_colors, 4))
                    calc_color = calc_color + 1
                Next calc_colors

                binary$ = ""

                clc = 0

                drawX = -1
                drawY = Ico(all).H - 1
                For DrawXOR = 0 To Ico(all).W * Ico(all).H
                    drawX = drawX + 1: If drawX >= Ico(all).W And Ico(all).H Mod 8 = 0 Then drawX = 0: drawY = drawY - 1
                    If drawX < Ico(all).W Then PSet (drawX, drawY), colors4(clc): clc = clc + 1
                Next



                'Pak je AND maska (sirka * vyska) / 8 a nakonec data obrazku
                'Then is AND mask (widht * height) / 8 and in end are image data
                Erase colors4: binary$ = ""
                AndMaskLen = (Ico(all).H * Ico(all).W) / 8

                For AM = 1 To AndMaskLen
                    Get #ch, , R4
                    binary$ = binary$ + DECtoBIN$(R4)
                Next AM


                clc = 0
                For DrawAND = 0 To Ico(all).W * Ico(all).H
                    drawX = drawX + 1: If drawX >= Ico(all).W And Ico(all).H Mod 8 = 0 Then drawX = 0: drawY = drawY - 1
                    If drawX <= Ico(all).W And Mid$(binary$, clc, 1) = "1" Then
                        _Source icon&
                        cur = Point(drawX, drawY)
                        PSet (drawX, drawY), 255 And cur: clc = clc + 1
                    End If
                Next
                _Source 0

            Case 8
                ReDim colors8(Ico(all).H * Ico(all).W) As _Unsigned _Byte
                For calc_colors = 1 To Ico(all).H * Ico(all).W
                    Get #ch, , colors8(calc_colors)
                Next calc_colors

                binary$ = ""
                AndMaskLen = (Ico(all).H * Ico(all).W) / 8 'predelavano
                ReDim r5 As _Unsigned _Byte
                For AM = 1 To AndMaskLen
                    Get #ch, , r5
                    binary$ = binary$ + DECtoBIN$(r5)
                Next AM

                clc = 0
                For draw_itY = 1 To Ico(all).H
                    For draw_itX = 0 To Ico(all).W - 1
                        clc = clc + 1
                        _Source icon&
                        cur = Point(draw_itX + 1, draw_itY)
                        PSet (draw_itX, Ico(all).H - draw_itY), colors8(clc) ' XOR cur
                Next: Next

                drawY = Ico(all).H - 1
                clc = 0
                For DrawAND = 1 To Ico(all).W * Ico(all).H
                    drawX = drawX + 1: If drawX >= Ico(all).W And Ico(all).H Mod 4 = 0 Then drawX = 0: drawY = drawY - 1
                    clrr = Point(drawX, drawY)
                    clc = clc + 1
                    If Mid$(binary$, clc, 1) = "1" Then PSet (drawX, drawY), 255 And clrr

                Next
                _Source 0


            Case 0, 32 'overeno, v tomto pripade se opravdu ctou 4 byty 'confirmed, in this case are really 4 bytes read
                ReDim cache(1 To Ico(all).W, 1 To Ico(all).H) As _Unsigned Long

                For draw_itY = 1 To Ico(all).H
                    For draw_itX = 1 To Ico(all).W
                        Get #ch, , cache(draw_itX, draw_itY)
                Next: Next

                For draw_itY = 1 To Ico(all).H
                    For draw_itX = 1 To Ico(all).W
                        PSet (draw_itX - 1, Ico(all).H - draw_itY), cache(draw_itX, draw_itY)
                Next: Next
                Erase cache
        End Select

        ______skip:
        _Dest PD
        If fram = 0 Then 'function paramter 0 as fram is for view all images in ico file (my loop muss be in 32 bit graphic mode)
            'vypis pokud bude paramter nula
            If _PixelSize(_Dest) < 4 Then Print "LOADICO parameter is set as 0. This option is for view all frames in ICO and muss be used with 32 bit screen.": Sleep 2: Exit Function
            ______resetview:
            If listed = 0 Then listed = 1: Cls: _PrintString (300, 20), "    Image nr.   Width   Height    BPP    Color count": row = 40
            If _Height - (row + 10) < 256 Then _PrintString (50, row + 100), "Press key for view next...": Sleep: Cls: listed = 0: GoTo ______resetview
            _PutImage (50, row), icon&, 0
            _FreeImage icon&
            row = row + Ico(all).H + 10
            info$ = "  " + Str$(all) + "      " + Str$(Ico(all).W) + "      " + Str$(Ico(all).H) + "    " + Str$(Ico(all).BPP) + "         " + Str$(Ico(all).WP)
            _PrintString (350, row - (Ico(all).H + 10 / 2)), info$
        Else
            If all = fram Then LOADICO& = icon&: _Dest PD: Exit Function Else _FreeImage icon&
        End If
    Next all
End Function



Function DECtoBIN$ (vstup)
    For rj = 7 To 0 Step -1
        If vstup And 2 ^ rj Then DECtoBI$ = DECtoBI$ + "1" Else DECtoBI$ = DECtoBI$ + "0"
    Next rj
    DECtoBIN$ = DECtoBI$
End Function

Function BINtoDEC (b As String)
    For Si = 1 To Len(b)
        e$ = Mid$(b$, Si, 1)
        c = Val(e$) '
        Sj = Len(b) - Si
        BINtoDE = BINtoDE + (c * 2 ^ Sj)
    Next Si
    BINtoDEC = BINtoDE
End Function

Function extract_png& (ch) 'Warning. This function can be very easy used for extraction PNG files from all (also binary) files!
    'BEEP
    start$ = Chr$(137) + Chr$(80) + Chr$(78) + Chr$(71) + Chr$(13) + Chr$(10) + Chr$(26) + Chr$(10) 'PNG start ID string
    eend$ = Chr$(0) + Chr$(0) + Chr$(0) + Chr$(0) + Chr$(73) + Chr$(69) + Chr$(78) + Chr$(68) + Chr$(174) + Chr$(66) + Chr$(96) + Chr$(130) 'PNG end ID string
    Seek #ch, Seek(ch) - 8
    Z = Seek(ch)
    Dim scan As String * 12
    Do
        Get #ch, , scan$
        If scan$ = eend$ Then Exit Do
        Seek #ch, Seek(ch) - 11
    Loop
    K = Seek(ch)
    png$ = Space$(K - Z)
    Seek #ch, Z
    Get #ch, , png$
    swp = FreeFile
    Open "---png_extr_" For Output As #swp
    Close #swp: Open "---png_extr_" For Binary As #swp
    Put #swp, , png$
    Close #swp
    extract_png& = _LoadImage("---png_extr_", 32)
    Kill "---png_extr_"
    png$ = ""
End Function

used free ico file is attached in zip format

Program set icon
[Image: ico-is-there.png]

:


RE: Declare an .ico file - mnrvovrfc - 03-29-2023

Will need a stronger solution away from Windows. I tested on EndeavourOS (based on Arch Linux) but should also check it out on Debian clone.


RE: Declare an .ico file - eoredson - 03-30-2023

@Petr:

Nice code but too complex and beyond the scope of what I am doing.

I am going with the following:

Code: (Select All)
i& = _LoadImage("SIC64.BMP", 32)
If i& < -1 Then
    _Icon i&
    _FreeImage i&
End If
Do
    If Len(InKey$) Then End
Loop



RE: Declare an .ico file - eoredson - 03-30-2023

Alright. I broke down and added y0ur Icon utility mostly to cover my bases:

Code: (Select All)
' set title icon
Sub DisplayIcon
    Icon$ = UCase$(TitleBarIcon$)
    If Right$(Icon$, 4) = ".ICO" Then
        If _FileExists(Icon$) Then
            Icon& = LOADICON&(Icon$, 1)
            If Icon& < -1 Then
                _Icon Icon&
                _FreeImage Icon&
            End If
        End If
    Else
        Icon& = _LoadImage(TitleBarIcon$, 32)
        If Icon& < -1 Then
            _Icon Icon&
            _FreeImage Icon&
        End If
    End If
End Sub



RE: Declare an .ico file - eoredson - 02-26-2024

I found a nice subroutine to return a .bmp file converted from a .ico file:

Code: (Select All)
Function Icon2BMP% (filein As String, fileout As String, index As Integer)
  Dim byte As _Unsigned _Byte, word As Integer, dword As Long
  Dim wide As Long, high As Long, BM As Integer, bpp As Integer
  rf = FreeFile
  If LCase$(Right$(filein, 4)) <> ".ico" Then 'check file extension is ICO only
      Exit Function
  End If
  Open filein For Binary Access Read As rf
  Get rf, , word
  Get rf, , word: icon = word
  Get rf, , word: count = word
  If icon <> 1 Or count = 0 Then Close rf: Exit Function
  If index > 0 And index <= count Then entry = 16 * (index - 1) Else entry = 16 * (count - 1)
  Seek rf, 1 + 6 + entry 'start of indexed Entry header
  Get rf, , byte: wide = byte ' use this unsigned for images over 127
  Get rf, , byte: high = byte ' use this unsigned because it isn't doubled
  Get rf, , word 'number of 4 BPP colors(256 & 32 = 0) & reserved bytes
  Get rf, , dword '2 hot spots both normally 0 in icons, used for cursors
  Get rf, , dword: size = dword 'this could be used, doesn't seem to matter
  Get rf, , dword: offset = dword 'find where the specific index BMP header is
  Seek rf, 1 + offset + 14 'only read the BPP in BMP header
  Get rf, , word: bpp = word
  If bpp = 0 Then Close rf: Exit Function
  If bpp <= 24 Then pixelbytes = bpp / 8 Else pixelbytes = 3
  If bpp > 1 And bpp <= 8 Then palettebytes = 4 * (2 ^ bpp) Else palettebytes = 0
  datasize& = (wide * high * pixelbytes) + palettebytes 'no padder should be necessary
  filesize& = datasize& + 14 + 40 '                      data and palette + header
  bmpoffset& = palettebytes + 54 '                      data offset from start of bitmap
  readbytes& = datasize& + 28 ' (40 - 12) bytes left to read in BMP header and XOR mask only
  BM = CVI("BM") 'this will create "BM" in file like MKI$ would
  wf = FreeFile
  Open fileout For Binary As wf
  Put wf, , BM
  Put wf, , filesize&
  dword = 0
  Put wf, , dword
  Put wf, , bmpoffset& 'byte location of end of palette or BMP header
  dword = 40
  Put wf, , dword '              start of 40 byte BMP header
  Put wf, , wide
  Put wf, , high
  Seek rf, 1 + offset + 12 '    after 12 bytes start copy of BMP header starting at planes
  dat$ = String$(readbytes&, 0) 'create string to hold remaining bytes needed w/o AND mask data
  Get rf, , dat$ '              copy lower header, palette(if used) and XOR mask
  Put wf, , dat$ '              put all of the string data in the bitmap all at once
  Close rf, wf
  Icon2BMP = count '            return the number of icons available in the icon file
End Function



RE: Declare an .ico file - bplus - 02-26-2024

(02-26-2024, 05:02 AM)eoredson Wrote: I found a nice subroutine to return a .bmp file converted from a .ico file:

Code: (Select All)
Function Icon2BMP% (filein As String, fileout As String, index As Integer)
  Dim byte As _Unsigned _Byte, word As Integer, dword As Long
  Dim wide As Long, high As Long, BM As Integer, bpp As Integer
  rf = FreeFile
  If LCase$(Right$(filein, 4)) <> ".ico" Then 'check file extension is ICO only
      Exit Function
  End If
  Open filein For Binary Access Read As rf
  Get rf, , word
  Get rf, , word: icon = word
  Get rf, , word: count = word
  If icon <> 1 Or count = 0 Then Close rf: Exit Function
  If index > 0 And index <= count Then entry = 16 * (index - 1) Else entry = 16 * (count - 1)
  Seek rf, 1 + 6 + entry 'start of indexed Entry header
  Get rf, , byte: wide = byte ' use this unsigned for images over 127
  Get rf, , byte: high = byte ' use this unsigned because it isn't doubled
  Get rf, , word 'number of 4 BPP colors(256 & 32 = 0) & reserved bytes
  Get rf, , dword '2 hot spots both normally 0 in icons, used for cursors
  Get rf, , dword: size = dword 'this could be used, doesn't seem to matter
  Get rf, , dword: offset = dword 'find where the specific index BMP header is
  Seek rf, 1 + offset + 14 'only read the BPP in BMP header
  Get rf, , word: bpp = word
  If bpp = 0 Then Close rf: Exit Function
  If bpp <= 24 Then pixelbytes = bpp / 8 Else pixelbytes = 3
  If bpp > 1 And bpp <= 8 Then palettebytes = 4 * (2 ^ bpp) Else palettebytes = 0
  datasize& = (wide * high * pixelbytes) + palettebytes 'no padder should be necessary
  filesize& = datasize& + 14 + 40 '                      data and palette + header
  bmpoffset& = palettebytes + 54 '                      data offset from start of bitmap
  readbytes& = datasize& + 28 ' (40 - 12) bytes left to read in BMP header and XOR mask only
  BM = CVI("BM") 'this will create "BM" in file like MKI$ would
  wf = FreeFile
  Open fileout For Binary As wf
  Put wf, , BM
  Put wf, , filesize&
  dword = 0
  Put wf, , dword
  Put wf, , bmpoffset& 'byte location of end of palette or BMP header
  dword = 40
  Put wf, , dword '              start of 40 byte BMP header
  Put wf, , wide
  Put wf, , high
  Seek rf, 1 + offset + 12 '    after 12 bytes start copy of BMP header starting at planes
  dat$ = String$(readbytes&, 0) 'create string to hold remaining bytes needed w/o AND mask data
  Get rf, , dat$ '              copy lower header, palette(if used) and XOR mask
  Put wf, , dat$ '              put all of the string data in the bitmap all at once
  Close rf, wf
  Icon2BMP = count '            return the number of icons available in the icon file
End Function

Might be handy! but seems more like a "Utility" routine than a "Help Me" barely related to thread subject that is old anyway. Paint can't do this?