QB64 Phoenix Edition
Exercise with picture and text - 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: Programs (https://qb64phoenix.com/forum/forumdisplay.php?fid=7)
+---- Thread: Exercise with picture and text (/showthread.php?tid=2798)

Pages: 1 2


Exercise with picture and text - Kernelpanic - 06-13-2024

At last a small, successful exercise (would a sub-form of exercises make sense?). A standard program with a picture on the side and a gimmick with color and font.

The program calculates the piston speed of an engine. According to Hütten, engines with a piston speed of over 21 meters per second are in danger of flying apart. The book is 40 years old, wether is that still true today? Maybe!

The picture: Two-Stroke Engine

Code: (Select All)

'Kolbengeschwindigkeit berechnen - 13. Juni 2024
'Uebung wie man Text und Bild einfuegt

Screen _NewImage(650, 420, 32)
$Color:32

Option _Explicit

Dim As Double kolbenhub, drehzahl, kolbenges
Dim As Long Bild, myFont
Dim As String Text

Bild = _LoadImage("..\..\Bilder\Zweitackter.gif") 'Siehe Hinweis unten um das Bild zu erhalten
_PutImage (470, 35), Bild 'Platzierung des Bildes. Haengt von der Fenstergroesse ab

Locate 2, 3
Print "Berechnung der Kolbengeschwindigkeit"
Locate 3, 3
Print "===================================="

Locate 5, 3
Input "Kolbenhub in cm                    : ", kolbenhub
Locate 6, 3
Input "Motordrehzahl bei hoechster Leistung: ", drehzahl

'Formel fuer die Kolbengeschwindigkeit - H. Huetten
kolbenges = (((2 * kolbenhub) * drehzahl) / (60 * 100))

If kolbenges <= 21 Then
  Locate 8, 3
  Print Using "Die Kolbengeschwindigkeit betraegt            : ##.##"; kolbenges
Else
  Locate 8, 3
  Beep: Color Red, 0
  Print Using "Die Kolbengeschwindigkeit liegt ueber 21 m/sec: ##.##"; kolbenges
  Locate 9, 3
  Color White, 0
  Print "(Bei Dauerbelastung droht Gefahr fuer den Motor!)"
End If

Text = "Bild von A. Schierwagen, GNU-Lizens - Wikipedia"
myFont = _LoadFont("C:\Windows\Fonts\Dauphinn.ttf", 15, "")
_Font myFont

'Neue Farbe setzen, dunkelgelb
Color _RGB32(255, 165, 0), _RGB32(0, 0, 0)

'Spalte - Zeile (Umgekehrt wie bei Locate)
_PrintString (360, 340), Text

'Farbe und Schrift zuruecksetzen
Color _RGB32(255), _RGB32(0, 0, 0)
_Font 16
_FreeFont myFont

End

[Image: Bild-mit-Text2024-06-13.jpg]

It's an animated gif. Is there a way to get the animation? I couldn't find anything - or didn't understand it.  Rolleyes


RE: Exercise with picture and text - Steffan-68 - 06-13-2024

(06-13-2024, 04:16 PM)Kernelpanik Wrote: Es ist ein animiertes GIF. Gibt es eine Möglichkeit, die Animation abzurufen? Ich habe nichts gefunden - oder es nicht verstanden. 

[Image: Bild-mit-Text2024-06-13.jpg]

Rolleyes
Maybe this can help you, it's not mine but it works 


Code: (Select All)
'#######################################################################################
'# Animated GIF decoder v1.0                                                          #
'# By Zom-B                                                                            #
'#######################################################################################


'$Dynamic

Dim Shared Dbg: Dbg = 0
Dim Shared powerOf2&(11)
For a = 0 To 11: powerOf2&(a) = 2 ^ a: Next a

Type GIFDATA
    file As Integer
    sigver As String * 6
    width As _Unsigned Integer
    height As _Unsigned Integer
    bpp As _Unsigned _Byte
    sortFlag As _Byte ' Unused
    colorRes As _Unsigned _Byte
    colorTableFlag As _Byte
    bgColor As _Unsigned _Byte
    aspect As Single ' Unused
    numColors As _Unsigned Integer
    palette As String * 768
End Type

Type FRAMEDATA
    addr As Long
    left As _Unsigned Integer
    top As _Unsigned Integer
    width As _Unsigned Integer
    height As _Unsigned Integer
    localColorTableFlag As _Byte
    interlacedFlag As _Byte
    sortFlag As _Byte ' Unused
    palBPP As _Unsigned _Byte
    minimumCodeSize As _Unsigned _Byte
    transparentFlag As _Byte 'GIF89a-specific (animation) values
    userInput As _Byte ' Unused
    disposalMethod As _Unsigned _Byte
    delay As Single
    transColor As _Unsigned _Byte
End Type

Screen _NewImage(1300, 900, 32)

' Open gif file. This reads the headers and palette but not the image data.
' The array will be redimentioned to fit the exact number of frames in the file.

Dim gifData As GIFDATA, frameData(0 To 0) As FRAMEDATA

'filename$ = "maygif-11.gif" '<<<<<<<<<<<< Enter a file name here!!!
filename$ = _OpenFileDialog$("Datei Öffnen", "", "*.gif", "Bilddatei", 0)
If Len(filename$) = 0 Then End
openGif filename$, gifData, frameData()

' Loop away.
frame = 0
Do

    For i = 1 To 100
        ' Request a frame. If it has been requested before, it is re-used,
        ' otherwise it is read and decoded from the file.
        _PutImage (80, 80), getGifFrame&(gifData, frameData(), frame)
        _Delay frameData(frame).delay
        frame = (frame + 1) Mod (UBound(frameData) + 1)
    Next i
Loop Until Len(InKey$)

'Close the file and free the allocated frames.
codeGif gifData, frameData()
If InKey$ = Chr$(27) Then System
Run

End

'########################################################################################

Sub openGif (filename$, gifData As GIFDATA, frameData() As FRAMEDATA) Static
    file = FreeFile: gifData.file = file
    Open "B", gifData.file, filename$

    Get file, , gifData.sigver
    Get file, , gifData.width
    Get file, , gifData.height
    Get file, , byte~%%
    gifData.bpp = (byte~%% And 7) + 1
    gifData.sortFlag = (byte~%% And 8) > 0
    gifData.colorRes = (byte~%% \ 16 And 7) + 1
    gifData.colorTableFlag = (byte~%% And 128) > 0
    gifData.numColors = 2 ^ gifData.bpp
    Get file, , gifData.bgColor
    Get file, , byte~%%
    If byte~%% = 0 Then gifData.aspect = 0 Else gifData.aspect = (byte~%% + 15) / 64

    If gifData.sigver <> "GIF87a" And gifData.sigver <> "GIF89a" Then _Dest 0: Print "Invalid version": End
    If Not gifData.colorTableFlag Then _Dest 0: Print "No Color Table": End

    palette$ = Space$(3 * gifData.numColors)
    Get file, , palette$
    gifData.palette = palette$
    If Dbg And 1 Then
        Print "sigver        ="; gifData.sigver
        Print "width          ="; gifData.width
        Print "height        ="; gifData.height
        Print "bpp            ="; gifData.bpp
        Print "sortFlag      ="; gifData.sortFlag
        Print "colorRes      ="; gifData.colorRes
        Print "colorTableFlag ="; gifData.colorTableFlag
        Print "bgColor        ="; gifData.bgColor
        Print "aspect        ="; gifData.aspect
        Print "numColors      ="; gifData.numColors
        For i = 0 To gifData.numColors - 1
            Print Using "pal(###) = "; i;
            Print Hex$(_RGB32(Asc(gifData.palette, i * 3 + 1), Asc(gifData.palette, i * 3 + 2), Asc(gifData.palette, i * 3 + 3)))
        Next
    End If
    Do
        Get file, , byte~%%
        If Dbg And 2 Then Print "Chunk: "; Hex$(byte~%%)
        Select Case byte~%%
            Case &H2C ' Image Descriptor
                If frame > UBound(frameData) Then
                    ReDim _Preserve frameData(0 To frame * 2 - 1) As FRAMEDATA
                End If

                Get file, , frameData(frame).left
                Get file, , frameData(frame).top
                Get file, , frameData(frame).width
                Get file, , frameData(frame).height
                Get file, , byte~%%
                frameData(frame).localColorTableFlag = (byte~%% And 128) > 0
                frameData(frame).interlacedFlag = (byte~%% And 64) > 0
                frameData(frame).sortFlag = (byte~%% And 32) > 0
                frameData(frame).palBPP = (byte~%% And 7) + 1
                frameData(frame).addr = Loc(file) + 1

                If frameData(frame).localColorTableFlag Then
                    Seek file, Loc(file) + 3 * 2 ^ frameData(frame).palBPP + 1
                End If
                Get file, , frameData(frame).minimumCodeSize
                If Dbg And 2 Then
                    Print "addr                ="; Hex$(frameData(frame).addr - 1)
                    Print "left                ="; frameData(frame).left
                    Print "top                ="; frameData(frame).top
                    Print "width              ="; frameData(frame).width
                    Print "height              ="; frameData(frame).height
                    Print "localColorTableFlag ="; frameData(frame).localColorTableFlag
                    Print "interlacedFlag      ="; frameData(frame).interlacedFlag
                    Print "sortFlag            ="; frameData(frame).sortFlag
                    Print "palBPP              ="; frameData(frame).palBPP
                    Print "minimumCodeSize    ="; frameData(frame).minimumCodeSize
                End If
                If localColors Then _Dest 0: Print "Local color table": End
                If frameData(frame).disposalMethod > 2 Then Print "Unsupported disposalMethod: "; frameData(frame).disposalMethod: End
                skipBlocks file

                frame = frame + 1
            Case &H3B ' Trailer
                Exit Do
            Case &H21 ' Extension Introducer
                Get file, , byte~%% ' Extension Label
                If Dbg And 2 Then Print "Extension Introducer: "; Hex$(byte~%%)
                Select Case byte~%%
                    Case &HFF, &HFE ' Application Extension, Comment Extension
                        skipBlocks file
                    Case &HF9
                        If frame > UBound(frameData) Then
                            ReDim _Preserve frameData(0 To frame * 2 - 1) As FRAMEDATA
                        End If

                        Get 1, , byte~%% ' Block Size (always 4)
                        Get 1, , byte~%%
                        frameData(frame).transparentFlag = (byte~%% And 1) > 0
                        frameData(frame).userInput = (byte~%% And 2) > 0
                        frameData(frame).disposalMethod = byte~%% \ 4 And 7
                        Get 1, , delay~%
                        If delay~% = 0 Then frameData(frame).delay = 0.1 Else frameData(frame).delay = delay~% / 100
                        Get 1, , frameData(frame).transColor
                        If Dbg And 2 Then
                            Print "frame          ="; frame
                            Print "transparentFlag ="; frameData(frame).transparentFlag
                            Print "userInput      ="; frameData(frame).userInput
                            Print "disposalMethod  ="; frameData(frame).disposalMethod
                            Print "delay          ="; frameData(frame).delay
                            Print "transColor      ="; frameData(frame).transColor
                        End If
                        skipBlocks file
                    Case Else
                        Print "Unsupported extension Label: "; Hex$(byte~%%): End
                End Select
            Case Else
                Print "Unsupported chunk: "; Hex$(byte~%%): End
        End Select
    Loop

    ReDim _Preserve frameData(0 To frame - 1) As FRAMEDATA
End Sub

Sub skipBlocks (file)
    Do
        Get file, , byte~%% ' Block Size
        If Dbg And 2 Then Print "block size ="; byte~%%
        Seek file, Loc(file) + byte~%% + 1
    Loop While byte~%%
End Sub

Function getGifFrame& (gifData As GIFDATA, frameData() As FRAMEDATA, frame)
    If frameData(frame).addr > 0 Then
        If Dbg And 4 Then
            Print "addr                ="; Hex$(frameData(frame).addr - 1)
            Print "left                ="; frameData(frame).left
            Print "top                ="; frameData(frame).top
            Print "width              ="; frameData(frame).width
            Print "height              ="; frameData(frame).height
            Print "localColorTableFlag ="; frameData(frame).localColorTableFlag
            Print "interlacedFlag      ="; frameData(frame).interlacedFlag
            Print "sortFlag            ="; frameData(frame).sortFlag
            Print "palBPP              ="; frameData(frame).palBPP
            Print "minimumCodeSize    ="; frameData(frame).minimumCodeSize
            Print "transparentFlag    ="; frameData(frame).transparentFlag
            Print "userInput          ="; frameData(frame).userInput
            Print "disposalMethod      ="; frameData(frame).disposalMethod
            Print "delay              ="; frameData(frame).delay
            Print "transColor          ="; frameData(frame).transColor
        End If
        w = frameData(frame).width
        h = frameData(frame).height
        img& = _NewImage(w, h, 256)
        frame& = _NewImage(gifData.width, gifData.height, 256)

        _Dest img&
        decodeFrame gifData, frameData(frame)

        _Dest frame&
        If frameData(frame).localColorTableFlag Then
            _CopyPalette img&
        Else
            For i = 0 To gifData.numColors - 1
                _PaletteColor i, _RGB32(Asc(gifData.palette, i * 3 + 1), Asc(gifData.palette, i * 3 + 2), Asc(gifData.palette, i * 3 + 3))
            Next
        End If

        If frame Then
            Select Case frameData(frame - 1).disposalMethod
                Case 0, 1
                    _PutImage , frameData(frame - 1).addr
                Case 2
                    Cls , gifData.bgColor
                    _ClearColor gifData.bgColor
            End Select
        Else
            Cls , gifData.bgColor
        End If

        If frameData(frame).transparentFlag Then
            _ClearColor frameData(frame).transColor, img&
        End If
        _PutImage (frameData(frame).left, frameData(frame).top), img&
        _FreeImage img&

        frameData(frame).addr = frame&
        _Dest 0
    End If

    getGifFrame& = frameData(frame).addr
End Function


'############################################################################################

Sub decodeFrame (gifdata As GIFDATA, framedata As FRAMEDATA)
    Dim byte As _Unsigned _Byte
    Dim prefix(4095), suffix(4095), colorStack(4095)

    startCodeSize = gifdata.bpp + 1
    clearCode = 2 ^ gifdata.bpp
    endCode = clearCode + 1
    minCode = endCode + 1
    startMaxCode = clearCode * 2 - 1
    nvc = minCode
    codeSize = startCodeSize
    maxCode = startMaxCode

    If framedata.interlacedFlag Then interlacedPass = 0: interlacedStep = 8
    bitPointer = 0
    blockSize = 0
    blockPointer = 0
    x = 0
    y = 0

    file = gifdata.file
    Seek file, framedata.addr

    If framedata.localColorTableFlag Then
        palette$ = Space$(3 * 2 ^ framedata.palBPP)
        Get 1, , palette$

        For i = 0 To gifdata.numColors - 1
            c& = _RGB32(Asc(palette$, i * 3 + 1), Asc(palette$, i * 3 + 2), Asc(palette$, i * 3 + 3))
            _PaletteColor i, c&
        Next
    End If

    Get file, , byte ' minimumCodeSize

    Do
        GoSub GetCode
        stackPointer = 0
        If code = clearCode Then 'Reset & Draw next color direct
            nvc = minCode '          \
            codeSize = startCodeSize ' Preset default codes
            maxCode = startMaxCode '  /

            GoSub GetCode
            currentCode = code

            lastColor = code
            colorStack(stackPointer) = lastColor
            stackPointer = 1
        ElseIf code <> endCode Then 'Draw direct color or colors from suffix
            currentCode = code
            If currentCode = nvc Then 'Take last color too
                currentCode = oldCode
                colorStack(stackPointer) = lastColor
                stackPointer = stackPointer + 1
            End If

            While currentCode >= minCode 'Extract colors from suffix
                colorStack(stackPointer) = suffix(currentCode)
                stackPointer = stackPointer + 1
                currentCode = prefix(currentCode) 'Next color from suffix is described in
            Wend '                                the prefix, else prefix is the last col.

            lastColor = currentCode '              Last color is equal to the
            colorStack(stackPointer) = lastColor ' last known code (direct, or from
            stackPointer = stackPointer + 1 '      Prefix)
            suffix(nvc) = lastColor 'Automatically, update suffix
            prefix(nvc) = oldCode 'Code from the session before (for extracting from suffix)
            nvc = nvc + 1

            If nvc > maxCode And codeSize < 12 Then
                codeSize = codeSize + 1
                maxCode = maxCode * 2 + 1
            End If
        End If

        For i = stackPointer - 1 To 0 Step -1
            PSet (x, y), colorStack(i)
            x = x + 1
            If x = framedata.width Then
                x = 0
                If framedata.interlacedFlag Then
                    y = y + interlacedStep
                    If y >= framedata.height Then
                        Select Case interlacedPass
                            Case 0: interlacedPass = 1: y = 4
                            Case 1: interlacedPass = 2: y = 2
                            Case 2: interlacedPass = 3: y = 1
                        End Select
                        interlacedStep = 2 * y
                    End If
                Else
                    y = y + 1
                End If
            End If
        Next

        oldCode = code
    Loop Until code = endCode

    Get file, , byte
    Exit Sub

    GetCode:
    If bitPointer = 0 Then GoSub ReadByteFromBlock: bitPointer = 8
    WorkCode& = LastChar \ powerOf2&(8 - bitPointer)
    While codeSize > bitPointer
        GoSub ReadByteFromBlock

        WorkCode& = WorkCode& Or LastChar * powerOf2&(bitPointer)
        bitPointer = bitPointer + 8
    Wend
    bitPointer = bitPointer - codeSize
    code = WorkCode& And maxCode
    Return

    ReadByteFromBlock:
    If blockPointer = blockSize Then
        Get file, , byte: blockSize = byte
        a$ = Space$(blockSize): Get file, , a$
        blockPointer = 0
    End If
    blockPointer = blockPointer + 1
    LastChar = Asc(Mid$(a$, blockPointer, 1))
    Return
End Sub


Sub codeGif (gifData As GIFDATA, frameData() As FRAMEDATA)
    For i = 0 To UBound(frameData)
        If frameData(i).addr < 0 Then _FreeImage frameData(i).addr
    Next

    Close gifData.file
End Sub



RE: Exercise with picture and text - bplus - 06-13-2024

+1 hey works for kp's gif, not the ones i have but ok!


RE: Exercise with picture and text - Kernelpanic - 06-13-2024

An inaccuracy. This is easier to understand:

Code: (Select All)

If kolbenges <= 21 Then
  Locate 8, 3
  Print Using "Die Kolbengeschwindigkeit betraegt  : ##.##"; kolbenges;
  Print " m/sec"
Else

Quote:Maybe this can help you, it's not mine but it works 
Thanks! Looks enormous. - I don't really understand the effort involved. Doesn't a GIF image basically run by itself? How do one do it in an image viewer, such as XnView?


RE: Exercise with picture and text - bplus - 06-13-2024

like the engine 2 steps

1
   

2
   


RE: Exercise with picture and text - Kernelpanic - 06-13-2024

@bplus, thanks. But the gif image opens in a separate window, right? And where is the text? Where is the calculation?


RE: Exercise with picture and text - bplus - 06-13-2024

just add your code to the code steffan-68 provided for displaying the gif

Like this:
Code: (Select All)
'$Dynamic
Dim Shared Dbg: Dbg = 0
Dim Shared powerOf2&(11)
For a = 0 To 11: powerOf2&(a) = 2 ^ a: Next a
Type GIFDATA
    file As Integer
    sigver As String * 6
    width As _Unsigned Integer
    height As _Unsigned Integer
    bpp As _Unsigned _Byte
    sortFlag As _Byte ' Unused
    colorRes As _Unsigned _Byte
    colorTableFlag As _Byte
    bgColor As _Unsigned _Byte
    aspect As Single ' Unused
    numColors As _Unsigned Integer
    palette As String * 768
End Type
Type FRAMEDATA
    addr As Long
    left As _Unsigned Integer
    top As _Unsigned Integer
    width As _Unsigned Integer
    height As _Unsigned Integer
    localColorTableFlag As _Byte
    interlacedFlag As _Byte
    sortFlag As _Byte ' Unused
    palBPP As _Unsigned _Byte
    minimumCodeSize As _Unsigned _Byte
    transparentFlag As _Byte 'GIF89a-specific (animation) values
    userInput As _Byte ' Unused
    disposalMethod As _Unsigned _Byte
    delay As Single
    transColor As _Unsigned _Byte
End Type

Dim gifData As GIFDATA, frameData(0 To 0) As FRAMEDATA

openGif "Two-Stroke_engine.gif", gifData, frameData()

'Kolbengeschwindigkeit berechnen - 13. Juni 2024
'Uebung wie man Text und Bild einfuegt

Screen _NewImage(650, 420, 32)
$Color:32


Dim As Double kolbenhub, drehzahl, kolbenges
Dim As Long Bild, myFont
Dim As String Text

'Bild = _LoadImage("..\..\Bilder\Zweitackter.gif") 'Siehe Hinweis unten um das Bild zu erhalten
'_PutImage (470, 35), Bild 'Platzierung des Bildes. Haengt von der Fenstergroesse ab

Locate 2, 3
Print "Berechnung der Kolbengeschwindigkeit"
Locate 3, 3
Print "===================================="

Locate 5, 3
Input "Kolbenhub in cm                    : ", kolbenhub
Locate 6, 3
Input "Motordrehzahl bei hoechster Leistung: ", drehzahl

'Formel fuer die Kolbengeschwindigkeit - H. Huetten
kolbenges = (((2 * kolbenhub) * drehzahl) / (60 * 100))

If kolbenges <= 21 Then
    Locate 8, 3
    Print Using "Die Kolbengeschwindigkeit betraegt            : ##.##"; kolbenges
Else
    Locate 8, 3
    Beep: Color Red, 0
    Print Using "Die Kolbengeschwindigkeit liegt ueber 21 m/sec: ##.##"; kolbenges
    Locate 9, 3
    Color White, 0
    Print "(Bei Dauerbelastung droht Gefahr fuer den Motor!)"
End If

Text = "Bild von A. Schierwagen, GNU-Lizens - Wikipedia"
'myFont = _LoadFont("C:\Windows\Fonts\Dauphinn.ttf", 15, "")
myFont = _LoadFont("C:\Windows\Fonts\ARIAL.ttf", 15, "")
_Font myFont

'Neue Farbe setzen, dunkelgelb
Color _RGB32(255, 165, 0), _RGB32(0, 0, 0)

'Spalte - Zeile (Umgekehrt wie bei Locate)
_PrintString (360, 340), Text

'Farbe und Schrift zuruecksetzen
Color _RGB32(255), _RGB32(0, 0, 0)
_Font 16
_FreeFont myFont
frame = 0
Do
    For i = 1 To 100
        ' Request a frame. If it has been requested before, it is re-used,
        ' otherwise it is read and decoded from the file.
        _PutImage (470, 35), getGifFrame&(gifData, frameData(), frame)
        _Delay frameData(frame).delay
        frame = (frame + 1) Mod (UBound(frameData) + 1)
    Next i
Loop Until Len(InKey$)

End
'########################################################################################
Sub openGif (filename$, gifData As GIFDATA, frameData() As FRAMEDATA) Static
    file = FreeFile: gifData.file = file
    Open "B", gifData.file, filename$
    Get file, , gifData.sigver
    Get file, , gifData.width
    Get file, , gifData.height
    Get file, , byte~%%
    gifData.bpp = (byte~%% And 7) + 1
    gifData.sortFlag = (byte~%% And 8) > 0
    gifData.colorRes = (byte~%% \ 16 And 7) + 1
    gifData.colorTableFlag = (byte~%% And 128) > 0
    gifData.numColors = 2 ^ gifData.bpp
    Get file, , gifData.bgColor
    Get file, , byte~%%
    If byte~%% = 0 Then gifData.aspect = 0 Else gifData.aspect = (byte~%% + 15) / 64
    If gifData.sigver <> "GIF87a" And gifData.sigver <> "GIF89a" Then _Dest 0: Print "Invalid version": End
    If Not gifData.colorTableFlag Then _Dest 0: Print "No Color Table": End
    palette$ = Space$(3 * gifData.numColors)
    Get file, , palette$
    gifData.palette = palette$
    If Dbg And 1 Then
        Print "sigver    ="; gifData.sigver
        Print "width     ="; gifData.width
        Print "height    ="; gifData.height
        Print "bpp      ="; gifData.bpp
        Print "sortFlag   ="; gifData.sortFlag
        Print "colorRes   ="; gifData.colorRes
        Print "colorTableFlag ="; gifData.colorTableFlag
        Print "bgColor    ="; gifData.bgColor
        Print "aspect    ="; gifData.aspect
        Print "numColors   ="; gifData.numColors
        For i = 0 To gifData.numColors - 1
            Print Using "pal(###) = "; i;
            Print Hex$(_RGB32(Asc(gifData.palette, i * 3 + 1), Asc(gifData.palette, i * 3 + 2), Asc(gifData.palette, i * 3 + 3)))
        Next
    End If
    Do
        Get file, , byte~%%
        If Dbg And 2 Then Print "Chunk: "; Hex$(byte~%%)
        Select Case byte~%%
            Case &H2C ' Image Descriptor
                If frame > UBound(frameData) Then
                    ReDim _Preserve frameData(0 To frame * 2 - 1) As FRAMEDATA
                End If
                Get file, , frameData(frame).left
                Get file, , frameData(frame).top
                Get file, , frameData(frame).width
                Get file, , frameData(frame).height
                Get file, , byte~%%
                frameData(frame).localColorTableFlag = (byte~%% And 128) > 0
                frameData(frame).interlacedFlag = (byte~%% And 64) > 0
                frameData(frame).sortFlag = (byte~%% And 32) > 0
                frameData(frame).palBPP = (byte~%% And 7) + 1
                frameData(frame).addr = Loc(file) + 1
                If frameData(frame).localColorTableFlag Then
                    Seek file, Loc(file) + 3 * 2 ^ frameData(frame).palBPP + 1
                End If
                Get file, , frameData(frame).minimumCodeSize
                If Dbg And 2 Then
                    Print "addr        ="; Hex$(frameData(frame).addr - 1)
                    Print "left        ="; frameData(frame).left
                    Print "top        ="; frameData(frame).top
                    Print "width       ="; frameData(frame).width
                    Print "height       ="; frameData(frame).height
                    Print "localColorTableFlag ="; frameData(frame).localColorTableFlag
                    Print "interlacedFlag   ="; frameData(frame).interlacedFlag
                    Print "sortFlag      ="; frameData(frame).sortFlag
                    Print "palBPP       ="; frameData(frame).palBPP
                    Print "minimumCodeSize  ="; frameData(frame).minimumCodeSize
                End If
                If localColors Then _Dest 0: Print "Local color table": End
                If frameData(frame).disposalMethod > 2 Then Print "Unsupported disposalMethod: "; frameData(frame).disposalMethod: End
                skipBlocks file
                frame = frame + 1
            Case &H3B ' Trailer
                Exit Do
            Case &H21 ' Extension Introducer
                Get file, , byte~%% ' Extension Label
                If Dbg And 2 Then Print "Extension Introducer: "; Hex$(byte~%%)
                Select Case byte~%%
                    Case &HFF, &HFE ' Application Extension, Comment Extension
                        skipBlocks file
                    Case &HF9
                        If frame > UBound(frameData) Then
                            ReDim _Preserve frameData(0 To frame * 2 - 1) As FRAMEDATA
                        End If
                        Get 1, , byte~%% ' Block Size (always 4)
                        Get 1, , byte~%%
                        frameData(frame).transparentFlag = (byte~%% And 1) > 0
                        frameData(frame).userInput = (byte~%% And 2) > 0
                        frameData(frame).disposalMethod = byte~%% \ 4 And 7
                        Get 1, , delay~%
                        If delay~% = 0 Then frameData(frame).delay = 0.1 Else frameData(frame).delay = delay~% / 100
                        Get 1, , frameData(frame).transColor
                        If Dbg And 2 Then
                            Print "frame     ="; frame
                            Print "transparentFlag ="; frameData(frame).transparentFlag
                            Print "userInput   ="; frameData(frame).userInput
                            Print "disposalMethod ="; frameData(frame).disposalMethod
                            Print "delay     ="; frameData(frame).delay
                            Print "transColor   ="; frameData(frame).transColor
                        End If
                        skipBlocks file
                    Case Else
                        Print "Unsupported extension Label: "; Hex$(byte~%%): End
                End Select
            Case Else
                Print "Unsupported chunk: "; Hex$(byte~%%): End
        End Select
    Loop
    ReDim _Preserve frameData(0 To frame - 1) As FRAMEDATA
End Sub
Sub skipBlocks (file)
    Do
        Get file, , byte~%% ' Block Size
        If Dbg And 2 Then Print "block size ="; byte~%%
        Seek file, Loc(file) + byte~%% + 1
    Loop While byte~%%
End Sub
Function getGifFrame& (gifData As GIFDATA, frameData() As FRAMEDATA, frame)
    If frameData(frame).addr > 0 Then
        If Dbg And 4 Then
            Print "addr        ="; Hex$(frameData(frame).addr - 1)
            Print "left        ="; frameData(frame).left
            Print "top        ="; frameData(frame).top
            Print "width       ="; frameData(frame).width
            Print "height       ="; frameData(frame).height
            Print "localColorTableFlag ="; frameData(frame).localColorTableFlag
            Print "interlacedFlag   ="; frameData(frame).interlacedFlag
            Print "sortFlag      ="; frameData(frame).sortFlag
            Print "palBPP       ="; frameData(frame).palBPP
            Print "minimumCodeSize  ="; frameData(frame).minimumCodeSize
            Print "transparentFlag  ="; frameData(frame).transparentFlag
            Print "userInput     ="; frameData(frame).userInput
            Print "disposalMethod   ="; frameData(frame).disposalMethod
            Print "delay       ="; frameData(frame).delay
            Print "transColor     ="; frameData(frame).transColor
        End If
        w = frameData(frame).width
        h = frameData(frame).height
        img& = _NewImage(w, h, 256)
        frame& = _NewImage(gifData.width, gifData.height, 256)
        _Dest img&
        decodeFrame gifData, frameData(frame)
        _Dest frame&
        If frameData(frame).localColorTableFlag Then
            _CopyPalette img&
        Else
            For i = 0 To gifData.numColors - 1
                _PaletteColor i, _RGB32(Asc(gifData.palette, i * 3 + 1), Asc(gifData.palette, i * 3 + 2), Asc(gifData.palette, i * 3 + 3))
            Next
        End If
        If frame Then
            Select Case frameData(frame - 1).disposalMethod
                Case 0, 1
                    _PutImage , frameData(frame - 1).addr
                Case 2
                    Cls , gifData.bgColor
                    _ClearColor gifData.bgColor
            End Select
        Else
            Cls , gifData.bgColor
        End If
        If frameData(frame).transparentFlag Then
            _ClearColor frameData(frame).transColor, img&
        End If
        _PutImage (frameData(frame).left, frameData(frame).top), img&
        _FreeImage img&
        frameData(frame).addr = frame&
        _Dest 0
    End If
    getGifFrame& = frameData(frame).addr
End Function
'############################################################################################
Sub decodeFrame (gifdata As GIFDATA, framedata As FRAMEDATA)
    Dim byte As _Unsigned _Byte
    Dim prefix(4095), suffix(4095), colorStack(4095)
    startCodeSize = gifdata.bpp + 1
    clearCode = 2 ^ gifdata.bpp
    endCode = clearCode + 1
    minCode = endCode + 1
    startMaxCode = clearCode * 2 - 1
    nvc = minCode
    codeSize = startCodeSize
    maxCode = startMaxCode
    If framedata.interlacedFlag Then interlacedPass = 0: interlacedStep = 8
    bitPointer = 0
    blockSize = 0
    blockPointer = 0
    x = 0
    y = 0
    file = gifdata.file
    Seek file, framedata.addr
    If framedata.localColorTableFlag Then
        palette$ = Space$(3 * 2 ^ framedata.palBPP)
        Get 1, , palette$
        For i = 0 To gifdata.numColors - 1
            c& = _RGB32(Asc(palette$, i * 3 + 1), Asc(palette$, i * 3 + 2), Asc(palette$, i * 3 + 3))
            _PaletteColor i, c&
        Next
    End If
    Get file, , byte ' minimumCodeSize
    Do
        GoSub GetCode
        stackPointer = 0
        If code = clearCode Then 'Reset & Draw next color direct
            nvc = minCode '     \
            codeSize = startCodeSize ' Preset default codes
            maxCode = startMaxCode ' /
            GoSub GetCode
            currentCode = code
            lastColor = code
            colorStack(stackPointer) = lastColor
            stackPointer = 1
        ElseIf code <> endCode Then 'Draw direct color or colors from suffix
            currentCode = code
            If currentCode = nvc Then 'Take last color too
                currentCode = oldCode
                colorStack(stackPointer) = lastColor
                stackPointer = stackPointer + 1
            End If
            While currentCode >= minCode 'Extract colors from suffix
                colorStack(stackPointer) = suffix(currentCode)
                stackPointer = stackPointer + 1
                currentCode = prefix(currentCode) 'Next color from suffix is described in
            Wend '                the prefix, else prefix is the last col.
            lastColor = currentCode '       Last color is equal to the
            colorStack(stackPointer) = lastColor ' last known code (direct, or from
            stackPointer = stackPointer + 1 '   Prefix)
            suffix(nvc) = lastColor 'Automatically, update suffix
            prefix(nvc) = oldCode 'Code from the session before (for extracting from suffix)
            nvc = nvc + 1
            If nvc > maxCode And codeSize < 12 Then
                codeSize = codeSize + 1
                maxCode = maxCode * 2 + 1
            End If
        End If
        For i = stackPointer - 1 To 0 Step -1
            PSet (x, y), colorStack(i)
            x = x + 1
            If x = framedata.width Then
                x = 0
                If framedata.interlacedFlag Then
                    y = y + interlacedStep
                    If y >= framedata.height Then
                        Select Case interlacedPass
                            Case 0: interlacedPass = 1: y = 4
                            Case 1: interlacedPass = 2: y = 2
                            Case 2: interlacedPass = 3: y = 1
                        End Select
                        interlacedStep = 2 * y
                    End If
                Else
                    y = y + 1
                End If
            End If
        Next
        oldCode = code
    Loop Until code = endCode
    Get file, , byte
    Exit Sub
    GetCode:
    If bitPointer = 0 Then GoSub ReadByteFromBlock: bitPointer = 8
    WorkCode& = LastChar \ powerOf2&(8 - bitPointer)
    While codeSize > bitPointer
        GoSub ReadByteFromBlock
        WorkCode& = WorkCode& Or LastChar * powerOf2&(bitPointer)
        bitPointer = bitPointer + 8
    Wend
    bitPointer = bitPointer - codeSize
    code = WorkCode& And maxCode
    Return
    ReadByteFromBlock:
    If blockPointer = blockSize Then
        Get file, , byte: blockSize = byte
        a$ = Space$(blockSize): Get file, , a$
        blockPointer = 0
    End If
    blockPointer = blockPointer + 1
    LastChar = Asc(Mid$(a$, blockPointer, 1))
    Return
End Sub
Sub codeGif (gifData As GIFDATA, frameData() As FRAMEDATA)
    For i = 0 To UBound(frameData)
        If frameData(i).addr < 0 Then _FreeImage frameData(i).addr
    Next
    Close gifData.file
End Sub



RE: Exercise with picture and text - Kernelpanic - 06-14-2024

Now it works, Thanks. I had to make a few changes. Great program, but mighty mighty. The programmer seems to be German.

Code: (Select All)
filename$ = _OpenFileDialog$("Datei Öffnen", "", "*.gif", "Bilddatei", 0)



RE: Exercise with picture and text - Steffan-68 - 06-14-2024

(06-14-2024, 08:09 PM)Kernelpanic Wrote: Now it works, Thanks. I had to make a few changes. Great program, but mighty mighty. The programmer seems to be German.

Code: (Select All)
filename$ = _OpenFileDialog$("Datei Öffnen", "", "*.gif", "Bilddatei", 0)

I didn't program it, I just changed something for myself and you're right, I'm German.  Big Grin 

I never learned to program, I just do it for fun when I get some time.

in the 80s I played around with QuickBasic 4.5 and 7.1 and now QB64 and QB64PE  Heart


RE: Exercise with picture and text - Kernelpanic - 06-14-2024

Quote:I didn't program it, I just changed something for myself and you're right, I'm German.
Then there we are already two of them. One more and we can found a party. 

[Image: icon-lol.gif]