Seite 1 von 2

Procedure wird nicht abgearbeitet

Verfasst: 28.06.2023 12:14
von PB_Rainer
Hallo,
ich hoffe irgendwer aus der PureBasic-Gemeinde kann mir helfen und findet meinen Fehler.

Kurze Beschreibung was das Programm machen soll:
Nach meinen Reisen mache ich meine Urlaubsfilme, in denen immer chronolgisch die Reise gezeigt wird.
Da ich die Bilder und Videos mit mehreren Kameras mache, (Fotocamera, mein Pixel-Handy, IPhone meiner Frau) haben leider alle Bilder verschiedene Dateinamen-Strukturen. Mal ist das Aufnahmedatum im Filename mal nicht. Aber alle haben Exif-Daten! Das Sortieren unter Win10 nach Aufnahmedatum ist nicht wirklich zu gebrauchen. leider!

Um die Bilder im Projektfolder für das Urlaubsvideo in der chronologischen Reihenfolge zu haben möchte ich aller Bilder wie folgt in einen "Date-Renamed"-Folder unter dem Original-Folder kopieren:
  • Falls unter dem Original-Folder noch kein Date-Renamed-Folder besteht, wird er erstellt >>> funktioniert!
  • Dann wird der Selectbalken auf den ersten Eintrag in der Folder Liste gesetzt >>> Funktioniert leider nicht wie gewünscht.
  • Danach wird der Folder Datei für Datei in einer While-Wend-Schleife abgearbeitet und wenn der Eintrag ein Bild ist wird es gezeigt, die Exif-Daten ausgelesen >>> wobei die Anzeige funktioniert, das Auslesen vielleicht, aber das füllen der Listbox mit den Exifdaten funktioniert nicht!
  • Der Folder wird komplett durchgearbeitet >> Funktioniert, denn jedes Bild wird im Preview-Bereich gezeigt.
  • Aber die Exif-Daten, wenn sie denn richtig gelesen werden (kann ich nicht nachvollziehen!) >>> werden nicht gezeigt!
  • Die Schleife soll eigentlich über den Button "Bilder umbenennen abbrechen" abgebrochen werden >>> funktioniert auch nicht.
Vllt. kann mal jemand über den Source-Code schauen. Ich kapiere nicht, warum die Prozedur richtig abgearbeitet, aber die Exif-Daten doch nicht angezeigt werden.

Klicke ich einen Dateinamen in der Explorerliste an, funktioniert die Anzeige der Exif-Daten einwandfrei. Gleiche Prozedur wird in der While-Wend-Schleife aufgerufen und funktioniert nicht!

IM Source-Code nach "MISTAKE" suchen dann ist man in der Prozedure die nicht so funktioniert wie sie soll!

Für Eure Hilfe bedanke ich mich schon mal im voraus.
Rainer

Hier mein Code, der auf einem Code aus dem englische Forum basiert.

Code: Alles auswählen

;/=====================================================================================================================
;| File     : ExifDataTestApp.pb 
;| Purpose  : Show the DateTime Information stored in the Exif data field of Jpeg Files. 
;|            Read information is available only. 
;| 
;|            Specification has so much more information to share... 
;| 
;| Version  : 0.02 
;| 
;| State    : Experimental, tested on only a few jpg images 
;| 
;| OS       : Tested on Windows x64 with ASM Backend only 
;| 
;| License  : MIT 
;| 
;| Copyright (c) 2022 by A.H. (Axolotl) 
;| 
;| ChangeLog : 
;|  0.01  .. first attempt (published on forum) 
;|           Link: 
;| 
;|  0.02  .. added new TAG ImageDescription  
;|           adapted main window with improved Preview for long values 
;| 
;| 
;\=====================================================================================================================

EnableExplicit 
; DebugLevel 9  ; show all debug messages 

Global Rename_Path.s, Only_filename.s, Rename_Abort.i = 0, file.s, index.i, Original_Path.s

; ---== MainWindow ==--------------------------------------------------------------------------------------------------

#ProgramName$          = "ExifDataTestApp" 
#ProgramVersion$       = "0.02" ; internally used + #PB_Editor_BuildCount + "." + #PB_Editor_CompileCount 

#MainCaption$          = "Image Exif Data and more...  V" + #ProgramVersion$ + " ~ EXPERIMENTAL "


Enumeration EWindow 1  ; -----------------------------------------------------------------------------
  #WINDOW_Main 
EndEnumeration 

Enumeration EGadget 1  ; -----------------------------------------------------------------------------
  #GADGET_ExpImageFiles 
  #GADGET_LstImageInfo 
  #GADGET_CnvPreView 
  #GADGET_EdtPreView    ; show selected items (especially very long values) 
  #Frame3D_0
  #Frame3D_1
  #Frame3D_2
  #GADGET_Source_path
  #GADGET_Source_path_show
  #GADGET_Target_path
  #GADGET_Target_path_show
  #GADGET_Button_exit
  #GADGET_Button_rename
  #GADGET_Original_file
  #GADGET_Original_file_show
  #GADGET_Renamed_file
  #GADGET_Renamed_file_show
  #GADGET_Button_rename_abort
  #GADGET_ExplorerTree
EndEnumeration 

Enumeration EImage 1 ; -----------------------------------------------------------------------------
  #IMAGE_PreView 
EndEnumeration 

; -----------------------------------------------------------------------------
;  The example app shows the image, too. 
; -----------------------------------------------------------------------------

UseJPEGImageDecoder() 
UsePNGImageEncoder()
UseJPEG2000ImageDecoder()

; ---== Exif Imaage Data ==--------------------------------------------------------------------------------------------

DeclareModule ExifData  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

  ; ---------------------------------------------------------------------------
  ; Constants 
  ; 
  Enumeration EExifTAG ; Number of the TAG (Exif, TIFF, etc.)  
    #ExifTAG_ImageWidth                = $0100 ; recommended not to use, better use jpeg  
    #ExifTAG_ImageHeight               = $0101 ; recommended not to use, better use jpeg   
    #ExifTAG_BitsPerSample             = $0102 ; 
    #ExifTAG_Compression               = $0103 ; thumbnail stuff .. 
; 
    #ExifTAG_Orientation               = $0112 ; 
    #ExifTAG_XResolution               = $011A ; 
    #ExifTAG_YResolution               = $011B ; 
    #ExifTAG_ResolutionUnit            = $0128 ; 
; ; 
    ; new 
    #ExifTAG_ImageDescription          = $010E ; char string giving the title of the image (no two-char codes) 
; ; 
    #ExifTAG_Make                      = $010F ; "Make", #Exif_Type_ASCII, -1, 0) 
    #ExifTAG_Model                     = $0110 ; "Model", #Exif_Type_ASCII, -1, 0) 
    #ExifTAG_Software                  = $0131 ; "Software", #Exif_Type_ASCII, -1, 0) 
    #ExifTAG_DateTime                  = $0132 ; "DateTime", #Exif_Type_ASCII, 20, 0) 
    #ExifTAG_Artist                    = $013B ; name of the camera owner, photographer or image creator 
    #ExifTAG_Copyright                 = $8298 ; indicate both the photographer and editor copyrights 
; 
    #ExifTAG_ExifVersion               = $9000 ; 36864 (9000.H) | UNDEFINED |   4   | "0232"  ; no NULL termination 
    #ExifTAG_ExifFlashpixVersion       = $A000 ; 40960 (A000.H) | UNDEFINED |   4   | "0100"  ; Flashpix Format Version 1.0 
; 
    #ExifTAG_DateTimeOriginal          = $9003 ; 36867 (9003.H) | ASCII |   20  | None 
    #ExifTAG_DateTimeDigitized         = $9004 ; 36868 (9004.H) | ASCII |   20  | None 
    #ExifTAG_OffsetTime                = $9010 ; 36880 (9010.H) | ASCII |    7  | None       ; including NULL 
    #ExifTAG_OffsetTimeOriginal        = $9011 ; 36881 (9011.H) | ASCII |    7  | None       ; including NULL 
    #ExifTAG_OffsetTimeDigitized       = $9012 ; 36882 (9012.H) | ASCII |    7  | None       ; including NULL 
; 
    #ExifTAG_SubsecTime                = $9290 ; Fractions of seconds for DateTime 
    #ExifTAG_SubsecTimeOriginal        = $9291 ; Fractions of seconds for DateTimeOriginal 
    #ExifTAG_SubsecTimeDigitized       = $9292 ; Fractions of seconds for DateTimeDigitized 
; 
    #ExifTAG_ColorSpace                = $A001 ; Color space information tag 
    #ExifTAG_PixelXDimension           = $A002 ; Valid Image Width  | PixelXDimension | 40962 ~ A002.H ~ SHORT or LONG ~ 1 
    #ExifTAG_PixelYDimension           = $A003 ; Valid Image Height | PixelYDimension | 40963 ~ A003.H ~ SHORT or LONG ~ 1 
  EndEnumeration ; EExifTAG 

  ; ---------------------------------------------------------------------------

  Declare.i ReadExifDataFromFile(FileName$)  ; 
  Declare FreeExifData()  ; 

  Declare ShowResultsOnGadget(Gadget) 

  Declare.i GetExifTagAsInteger(ExifTag, DefaultValue = -1) 
  Declare.s GetExifTagAsString(ExifTag, DefaultValue$ = "") 

EndDeclareModule 

Module ExifData  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

  EnableExplicit 

  ; ---------------------------------------------------------------------------
  ; Constants 
  ; 
  Enumeration EExifTAG ; Number of the TAG (Exif, TIFF, etc.)  
    #ExifTAG_Unsupported               = $0000 ; internal define .. 
    #ExifTAG_ExifIFD                   = $8769 ;                |  LONG     |   1   | 
  EndEnumeration ; EExifTAG 
  ; 
  ; HINT: This constant is representing the number of defined äExifTAG_Xxxx in Enumeration EExifTAG 
  ;       If you add new constants to the enumeration (local or global) you must increase the #ExifTagTableSize as well 
  ; 
  #ExifTagTableSize  = 29                      :Debug "HINT: #ExifTagTableSize: " + #ExifTagTableSize 

  ; ---------------------------------------------------------------------------

  Enumeration EJpegMarkers 
    #JM_Start  = $FF  
    ; ... 

    #JM_SOI    = $D8   ; 
    ; ... 

    #JM_APP1   = $E1   ; EXIF and XMP (XMP not supported yet) 
    ; ... 
    #JM_APP13  = $ED   ; IPTC (not supported yet) 
    #JM_APP14  = $EE   ; (not supported yet) 
    #JM_APP15  = $EF   ; (not supported yet) 
    ; ... 
    #JM_JPG0   = $F0   ; JPG0 == 0xF0 to JPG13 == 0xFD 
    #JM_COM    = $FE   
  EndEnumeration ; EJpegMarkers 

  Enumeration EExifByteOrderMark 
    #ExifByteOderMark_Intel    = $4949         ; Little-endian | 0x4D - 0x49 == 0x04 | II 
    #ExifByteOderMark_Motorola = $4D4D         ; Big-endian    |                     | MM 
  EndEnumeration ; EExifByteOrder 

  Enumeration EExifByteOrder 
    #ExifByteOrder_Motorola 
    #ExifByteOrder_Intel 
  EndEnumeration ; EExifByteOrder 

  ; ---------------------------------------------------------------------------

  #TIFF_TAG_Mark               = $002A         ; constant in correct byte order 
  #TIFF_FirstIFDOffset         = $00000008     ; default offset to the first IDD 

  ; ---------------------------------------------------------------------------
  ; Structure User Defined Types 
  ; 
  Structure TByteArray ; Access to the Image Memory byte by byte 
    Byte.a[0] 
  EndStructure 

  ; ---------------------------------------------------------------------------

  Structure TExifTagEntry  ; TAG structure for ExifTags, etc. 
    Number.i           ; 
    Name$              ; 
   ;Descr$             ; .. Description, <sorry, to much typing or formatting)  
    Private.i          ; .. #False or #True (usage makes sense only inside module) 
  EndStructure 

  ; ---------------------------------------------------------------------------

  Structure TExifTagValue  ; TAG structure for ExifTags, etc. 
    Number.i           ;
    Name$              ;
    Caption$           ; .. display text (different language, maybe in future) 
    Format.i           ; .. data format (type) of TAG 
    Private.i          ; .. IsPrivate = #False or #True ?? 
    ; 
    AddressOffset.i    ; .. address offset of the tag in the memory 
    AddressSize.i      ; .. address size/length of the tag in the memory 
    ; 
    Value.i            ; .. Value, different types are supported ??  
    Value$             ;  \ __ quick solution, needs some improvement 
    Array Vals.i(0)    ;  /
  EndStructure 


  ; ---------------------------------------------------------------------------
  ; Module Global Variables 
  ; 
  Global *ExifData.TByteArray                  ; entire file is stored in this memory 
  Global NewList ResultValues.TExifTagValue()  ; found tags need a place to wait 

  Global Dim ExifTagTable.TExifTagEntry(0)     ; the table of TAGs we can use 


; ---== Simple Helpers ==----------------------------------------------------------------------------------------------

  Macro DQ 
    " 
  EndMacro 

  Macro ByteToHex(_Value_) 
    "0x" + RSet(Hex(_Value_, #PB_Byte), 2, "0") + ", (" + Str(_Value_) + ")" 
  EndMacro 

  Macro WordToHex(_Value_) 
    "0x" + RSet(Hex(_Value_, #PB_Word), 4, "0") + ", (" + Str(_Value_) + ")" 
  EndMacro 

  Macro LongToHex(_Value_) 
    "0x" + RSet(Hex(_Value_, #PB_Long), 8, "0") + ", (" + Str(_Value_) + ")" 
  EndMacro 

  Macro IntToHex(_Value_) 
    "0x" + RSet(Hex(_Value_, #PB_Quad), 16, "0") + ", (" + Str(_Value_) + ")" 
  EndMacro 

; ---== Fetch BYTE, WORD, LONG, ASCII from *Memory ==------------------------------------------------------------------

  ; Little Endian (LE) == 8, 0; Big Endian (BE) == 0, 8 
  Global Dim ByteOrderWord(1, 1)  ; (ByteOrderLE, Offset) 
    ByteOrderWord(0, 0) = 8 : ByteOrderWord(0, 1) = 0   ; <-- BE 
    ByteOrderWord(1, 0) = 0 : ByteOrderWord(1, 1) = 8   ; <-- LE 

  ; Little Endian (LE) == 24, 16, 8, 0; Big Endian (BE) == 0, 8, 16, 24 
  Global Dim ByteOrderLong(1, 3)  ; (ByteOrderLE, Offset) 
    ByteOrderLong(0, 0) = 24 : ByteOrderLong(0, 1) = 16 : ByteOrderLong(0, 2) =  8 : ByteOrderLong(0, 3) =  0 ; <-- BE 
    ByteOrderLong(1, 0) =  0 : ByteOrderLong(1, 1) =  8 : ByteOrderLong(1, 2) = 16 : ByteOrderLong(1, 3) = 24 ; <-- LE 

  ; ---------------------------------------------------------------------------
  Procedure.i FetchByte(Offset)  ; return $00 
    ProcedureReturn *ExifData\Byte[Offset] 
  EndProcedure 
  ; ---------------------------------------------------------------------------
  Procedure.i FetchWord(Offset, ByteOrderLE=0)  ; returns $00 00 
    ProcedureReturn *ExifData\Byte[Offset + 0] << ByteOrderWord(ByteOrderLE, 0) + 
                    *ExifData\Byte[Offset + 1] << ByteOrderWord(ByteOrderLE, 1) 
  EndProcedure 
  ; ---------------------------------------------------------------------------
  Procedure.i FetchLong(Offset, ByteOrderLE=0)  ; returns $00 00 00 00 
    ProcedureReturn *ExifData\Byte[Offset + 0] << ByteOrderLong(ByteOrderLE, 0) + 
                    *ExifData\Byte[Offset + 1] << ByteOrderLong(ByteOrderLE, 1) + 
                    *ExifData\Byte[Offset + 2] << ByteOrderLong(ByteOrderLE, 2) + 
                    *ExifData\Byte[Offset + 3] << ByteOrderLong(ByteOrderLE, 3) 
  EndProcedure 
  ; ---------------------------------------------------------------------------
  Procedure.s FetchAscii(Offset, Length)  ; returns value$[Length] 
    ProcedureReturn PeekS(*ExifData + Offset, Length, #PB_Ascii)  
  EndProcedure 
  ; ---------------------------------------------------------------------------
  Procedure.s GetByteOrderName(ByteOrder) 
    Select ByteOrder 
      Case #ExifByteOrder_Motorola : ProcedureReturn "Motorola" 
      Case #ExifByteOrder_Intel    : ProcedureReturn "Intel" 
    EndSelect 
    ProcedureReturn "" 
  EndProcedure 
  ; ---------------------------------------------------------------------------
  Procedure LogOut(Message$)  ; @ Todo: further improvements 

    Debug "LOG -> " + Message$ 

  EndProcedure 
  ; ---------------------------------------------------------------------------
  ; temp marco for use in the next procedure only 
  Macro _setTagEntry(_ConstantName_, _Private_) ; _Private_ == #False or #True 
    ExifTagTable(Index)\Number  = _ConstantName_ 
    ExifTagTable(Index)\Name$   = Mid(DQ#_ConstantName_#DQ, 11) ; cut off #ExifTAG_ constant prefix 
    ExifTagTable(Index)\Private = _Private_ 
    Index + 1 
  EndMacro 
  ; 
  Procedure InitializeExifTagTable()  ; fill the table with supported TAGs 
    Protected Index = 0 

    Dim ExifTagTable(#ExifTagTableSize)   ; constant avoid redim at the end 

    ; internal used constants 
    _setTagEntry(#ExifTAG_Unsupported        , #False)  ; internal stuff ?? 

    _setTagEntry(#ExifTAG_ImageWidth         , #False)  
    _setTagEntry(#ExifTAG_ImageHeight        , #False)  
    _setTagEntry(#ExifTAG_BitsPerSample      , #False)  
    _setTagEntry(#ExifTAG_Compression        , #False)  

    _setTagEntry(#ExifTAG_Orientation        , #False) 
    _setTagEntry(#ExifTAG_XResolution        , #False) 
    _setTagEntry(#ExifTAG_YResolution        , #False) 
    _setTagEntry(#ExifTAG_ResolutionUnit     , #False) 

    _setTagEntry(#ExifTAG_ImageDescription   , #False)  ; new 

    _setTagEntry(#ExifTAG_Make               , #False) 
    _setTagEntry(#ExifTAG_Model              , #False) 
    _setTagEntry(#ExifTAG_Software           , #False) 
    _setTagEntry(#ExifTAG_DateTime           , #False) 

    _setTagEntry(#ExifTAG_Artist             , #False) 
    _setTagEntry(#ExifTAG_Copyright          , #False) 

    _setTagEntry(#ExifTAG_ExifIFD            , #True)   ; offset to IFD (Image File Directory) 
    _setTagEntry(#ExifTAG_ExifVersion        , #False) 

    _setTagEntry(#ExifTAG_ExifFlashpixVersion, #False) 

    _setTagEntry(#ExifTAG_DateTimeOriginal   , #False) 
    _setTagEntry(#ExifTAG_DateTimeDigitized  , #False) 
    _setTagEntry(#ExifTAG_OffsetTime         , #False) 
    _setTagEntry(#ExifTAG_OffsetTimeOriginal , #False) 
    _setTagEntry(#ExifTAG_OffsetTimeDigitized, #False) 

    _setTagEntry(#ExifTAG_SubsecTime         , #False) 
    _setTagEntry(#ExifTAG_SubsecTimeOriginal , #False) 
    _setTagEntry(#ExifTAG_SubsecTimeDigitized, #False) 
    _setTagEntry(#ExifTAG_ColorSpace         , #False) 
    _setTagEntry(#ExifTAG_PixelXDimension    , #False) 
    _setTagEntry(#ExifTAG_PixelYDimension    , #False) 

    If Index - 1 <> #ExifTagTableSize 
      Debug "INTERNAL INFO: ARRAY SIZE is redimmed to " + Str(Index-1) + "  constant = " + #ExifTagTableSize 

      ; optimize the memory usage 
      ReDim ExifTagTable(Index-1)  ; the number of Tags we can use 
    EndIf 

    ; for binary search the numbers must be sorted 
    SortStructuredArray(ExifTagTable(), 0, OffsetOf(TExifTagEntry\Number), TypeOf(TExifTagEntry\Number)) 
    
    ; Debug #LF$+"Show ExifTagTable  " 
    ; For Index = 0 To #ExifTagTableSize 
    ;   Debug "  " + index + ".  " + ExifTagTable(Index)\Name$ + ", 0x" + Hex(ExifTagTable(Index)\Number) + ", " + ExifTagTable(Index)\Private 
    ; Next Index 
    ; Debug "" 
  EndProcedure 
  ; 
  UndefineMacro _setTagEntry 
  ; 
  InitializeExifTagTable()  ; call it directly to fill the arrays  
; ---------------------------------------------------------------------------
  Procedure.i GetExifTagIndex(Number)  ; returns index or -1 
    ; >> Iterative Binary Search -- faster than Linear or Sequential search on sorted arrays 
    Protected retIdx, firstIdx, lastIdx, midIdx                               ;:Debug #LF$+#PB_Compiler_Procedure+"(0x"+Hex(Number)+")", 9 

    retIdx   = -1                                      ; default return value == -1 
    firstIdx =  0                                      ; start search with entire array 
    lastIdx  = ArraySize(ExifTagTable())               ;   -"- 

    While lastIdx - firstIdx > 1 
      midIdx = (lastIdx + firstIdx) / 2                                       ;:Debug "  iterate: " + firstIdx + ", " + lastIdx + ", " + midIdx, 9 
      If ExifTagTable(midIdx)\Number < Number 
        firstIdx = midIdx + 1 
      Else 
        lastIdx = midIdx 
      EndIf 
    Wend 
    If ExifTagTable(firstIdx)\Number = Number 
      retIdx = firstIdx 
    ElseIf ExifTagTable(lastIdx)\Number = Number 
      retIdx = lastIdx 
    EndIf                                                                     ;:Debug "Found 0x" + Hex(Number) + " at Index " + retIdx, 9 
    ProcedureReturn retIdx  ; return -1 (not found) or index (0..ArraySize()) 
  EndProcedure 
; ---------------------------------------------------------------------------
  Procedure.i ParseTagValue(entryOffset, tiffStart, byteOrderLE)  
    Protected fmt, numValues, valueOffset, offset, n, numerator, denominator  :Debug #LF$+#PB_Compiler_Procedure+"()", 9 
    Protected ret_val, tmp$, v.f 

    fmt         = FetchWord(entryOffset + 2, byteOrderLE)              ;.. acc. to spec.  
    numValues   = FetchLong(entryOffset + 4, byteOrderLE)              ;.. 
    valueOffset = FetchLong(entryOffset + 8, byteOrderLE) + tiffStart  ;.. 

    ResultValues()\Format = fmt  ; 

    Select fmt  
      Case 1, 7  ;// 1 -> byte, 8-bit unsigned int .. 7 -> undefined, 8-bit byte, value depending on field 
        If numValues = 1 
          ResultValues()\Value = FetchByte(entryOffset + 8) 
        Else  
          If numValues > 4 : offset = valueOffset : Else : offset = entryOffset + 8 : EndIf 
          ResultValues()\Value$ = FetchAscii(offset, numValues)  ; numValues == 4 
        EndIf 
        ; keep the position (address) of the value to overwrite with new data ???? 
        ResultValues()\AddressOffset = offset 
        ResultValues()\AddressSize = numValues 
        ret_val = #True 

      Case 2   ;// 2 -> ascii, 8-bit byte 
        If numValues > 4 : offset = valueOffset : Else : offset = entryOffset + 8 : EndIf 
        ResultValues()\Value$ = FetchAscii(offset, numValues - 1) 

        ; keep the position (address) of the value to overwrite with new data ???? 
        ResultValues()\AddressOffset = offset 
        ResultValues()\AddressSize = numValues - 1  ; different (because no trailing ZERO) 
        ret_val = #True 

      Case 3   ;// 3  -> short, 16 bit int 
        If numValues = 1  
          ResultValues()\Value = FetchWord(entryOffset + 8, byteOrderLE) 
        Else 
          If numValues > 2 : offset = valueOffset : Else : offset = entryOffset + 8 : EndIf 
          ReDim ResultValues()\Vals(numValues) 
          For n = 0 To numValues - 1  
            ResultValues()\Vals(n) = FetchWord(offset + 2 * n, byteOrderLE) 
          Next n 
        EndIf 
        ; keep the position (address) of the value to overwrite with new data ???? 
        ResultValues()\AddressOffset = offset 
        ResultValues()\AddressSize = numValues - 1 
        ret_val = #True 

      Case 4    ;// 4 -> long, 32 bit int 
        If numValues = 1 
          ResultValues()\Value = FetchLong(entryOffset + 8, byteOrderLE) 
        Else  
          ReDim ResultValues()\Vals(numValues) 
          For n = 0 To numValues - 1  
            ResultValues()\Vals(n) = FetchLong(offset + 4 * n, byteOrderLE) 
          Next n 
        EndIf 
        ; keep the position (address) of the value to overwrite with new data ???? 
        ResultValues()\AddressOffset = offset 
        ResultValues()\AddressSize = numValues - 1 
        ret_val = #True 

      Case 5        ;// 5 -> rational = two long values, first is numerator, second is denominator
        If numValues = 1 
          numerator = FetchLong(valueOffset, byteOrderLE) 
          denominator = FetchLong(valueOffset + 4, byteOrderLE) 
          v = numerator / denominator 
          ResultValues()\Value$ = StrF(v) 
        Else  
          For n = 0 To numValues - 1 
            numerator = FetchLong(valueOffset + 8*n, byteOrderLE) 
            denominator = FetchLong(valueOffset + 4 + 8*n, byteOrderLE) 
            v = numerator / denominator 
            ResultValues()\Value$ + StrF(v) + ";"  ; ?? 
          Next n 
        EndIf 
       ;ResultValues()\Private = #True ; don't share, not verified by now 
        ret_val = #False  ; not supported yet. 

      Case 9  ;// 9 ; slong, 32 bit signed int 
        If numValues = 1 
          ResultValues()\Value = FetchLong(entryOffset + 8, byteOrderLE) & $FFFF ; ?? 
        Else 
          ReDim ResultValues()\Vals(numValues) 
          For n = 0 To numValues - 1 
            ResultValues()\Vals(n) = FetchLong(offset + 4 * n, byteOrderLE) & $FFFF ; ?? 
          Next n 
        EndIf 
        ; keep the position (address) of the value to overwrite with new data ???? 
        ResultValues()\AddressOffset = offset 
        ResultValues()\AddressSize = numValues - 1 
        ret_val = #True 

      Case 10   ;// 10 -> signed rational, two slongs, first is numerator, second is denominator 
        If numValues = 1 
          ResultValues()\Value = FetchLong(valueOffset, byteOrderLE) / FetchLong(valueOffset+4, byteOrderLE)  ;?? 
        Else 
          ReDim ResultValues()\Vals(numValues) 
          For n = 0 To numValues - 1 
            ResultValues()\Vals(n) = FetchLong(valueOffset + 8*n, byteOrderLE) / FetchLong(valueOffset+4 + 8*n, byteOrderLE)  ;?? 
          Next n 
        EndIf 
       ;ResultValues()\Private = #True ; don't share, not verified by now 
        ret_val = #False  ; not supported yet. 

    EndSelect 
    ProcedureReturn ret_val 
  EndProcedure 
; ---------------------------------------------------------------------------------------------------------------------
  Procedure.i ParseTags(tiffStart, dirStart, byteOrderLE)  ; 
    Protected entries, entryOffset, tag, ii, idx, name$                             :Debug #LF$+#PB_Compiler_Procedure+"()", 9 
    Protected ret_val 

    entries = FetchWord(dirStart, byteOrderLE)                                 :Debug "  entries = " + entries, 9 
    For ii = 0 To entries - 1 
      entryOffset = dirStart + ii * 12 + 2   ;.. calulation  acc. to specification -- jump over unsupported tags  

      tag = FetchWord(entryOffset, byteOrderLE)   
      idx = GetExifTagIndex(tag)  ; look for TAG in the ExifTagTable() 
      If idx = -1 
; ##_TAG_## 
;       ; Log all available but not supported Tags 
;       LogOut("TAG: " + WordToHex(tag) + " not supported!") 
        Continue ; with the next tag 
      EndIf 

      ; work on supported TAGs 
      AddElement(ResultValues()) 
      ResultValues()\Number = tag                        ; copy TAG Number ... 
      ResultValues()\Name$  = ExifTagTable(idx)\Name$    ; ... and name$ 
      ResultValues()\Private = ExifTagTable(idx)\Private ; ... and private flag  

    ;;LogOut("TAG: " + WordToHex(tag) + "  " + ExifTagTable(idx)\Name$ + " supported!") 

      ret_val | ParseTagValue(entryOffset, tiffStart, byteOrderLE)  ; one valid tag is enough :) 
    Next ii 
    ProcedureReturn ret_val 
  EndProcedure 
; -----------------------------------------------------------------------------
  Procedure.i ParseEXIFData(Start) 
    Protected byteOrderLE, tags, tag, exifData, gpsData, tiffOffset            :Debug #LF$+#PB_Compiler_Procedure+"()", 9 
    Protected firstIFD_offset, ExifIFD_offset 
    Protected ret_val, rc 

    If FetchAscii(Start, 4) <> "Exif" 
      LogOut("Not valid EXIF data! " + FetchAscii(Start, 4)) 
      ProcedureReturn #False  
    EndIf 

    tiffOffset = Start + 6  ; kept for further investigation 

    ; test for TIFF validity and byte order 
    If FetchWord(tiffOffset) = #ExifByteOderMark_Intel         ; 0x4949 == Intel Byte Order 
      byteOrderLE = #True  ; ..                                            \-> little endian 
    ElseIf FetchWord(tiffOffset) = #ExifByteOderMark_Motorola  ; 0x4D4D == Motorola Byte Order 
      byteOrderLE = #False  ; ..                                           \-> big endian 
    Else  
      LogOut("Not valid TIFF data! (no 0x4949 or 0x4D4D)") 
      ProcedureReturn #False  ;.. failure because of unknown byteorder! 
    EndIf 

    If FetchWord(tiffOffset + 2, byteOrderLE) <> #TIFF_TAG_Mark  ; 0x002A  == TIFF_TAG_Mark 
      LogOut("Not valid TIFF data! (no 0x002A)") 
      ProcedureReturn #False  
    EndIf 

    firstIFD_offset = FetchLong(tiffOffset + 4, byteOrderLE) 
    If firstIFD_offset < #TIFF_FirstIFDOffset                   ; == 0x00000008 (Default offset) 
      LogOut("Not valid TIFF data! (First offset less than 8)  " + FetchLong(tiffOffset + 4, byteOrderLE)) 
      ProcedureReturn #False ; failure 
    EndIf 

    ret_val = ParseTags(tiffOffset, tiffOffset + firstIFD_offset, byteOrderLE)    ;; ### TiffTags --> ARRAY or MAP ???? 
    If ret_val 
      If ResultValues()\Number = #ExifTAG_ExifIFD ; <--> 0x8769 == ExifIFD pointer 
        ExifIFD_offset = ResultValues()\Value 
; Debug "HINT:    ExifIFD-Offset = " + ExifIFD_offset + "  // parse tags " 
        rc = ParseTags(tiffOffset, tiffOffset + ExifIFD_offset, byteOrderLE)  ; 
        ; .. needs some further investigation .. 
      EndIf 
    EndIf 
    ProcedureReturn ret_val 
  EndProcedure 
; ---== Read, Write, Free ImageFile and *Memory ==---------------------------------------------------------------------
  Procedure.i ReadExifDataFromFile(FileName$)  ; 
    Protected FILE, memsize, bytes                                :Debug #LF$+#PB_Compiler_Procedure+"("+FileName$+")", 9 
    Protected offset, marker 

    FreeExifData() 
    ClearList(ResultValues())  

    FILE = ReadFile(#PB_Any, FileName$) ; read with no flags 
    If FILE 
      memsize = Lof(FILE) ; Lof .. Length of (opened) file 
      *ExifData = AllocateMemory(memsize)    ; returns the address, or zero if the memory cannot be allocated 
      If *ExifData 
        bytes = ReadData(FILE, *ExifData, memsize)  ; read all data into memory block 
        LogOut("Read file with length of " + Str(bytes) + " bytes. ") 
      EndIf 
      CloseFile(FILE) 
    Else 
      *ExifData = 0 ; 
      LogOut("ERROR: Couldn't open the file '" + FileName$ + "'") 
      ProcedureReturn #False ; not a valid image (jpeg) file 
    EndIf 

    ; analyze file from the beginning 
    If FetchByte(0) <> #JM_Start Or FetchByte(1) <> #JM_SOI  ;.. == FFD8 
      LogOut("Not a valid JPEG") 
      ProcedureReturn #False ; not a valid jpeg 
    EndIf 

    offset = 2  ; jump over the first two bytes :) 
    While offset < memsize  ; scan the file memory byte by byte for find the marker 0xFFE1 
      If FetchByte(offset) <> #JM_Start 
        LogOut("Not a valid marker at offset " + offset + ", found: " + FetchByte(offset)) 
        ProcedureReturn #False  ; not a valid marker, something is wrong 
      EndIf 

      marker = FetchByte(offset + 1) 

      ; we could implement handling for other markers here, but we're only looking for 0xFFE1 for EXIF data  

      If marker = #JM_APP1  ; == 225 = $E1 
        LogOut("Found 0xFFE1 marker") 
        ProcedureReturn ParseEXIFData(offset + 4) 
      Else 
        offset + 2 + FetchWord(offset + 2) 
      EndIf 
    Wend 
    ProcedureReturn #False  ; return failure, could not found a valid marker 
  EndProcedure 
; ---------------------------------------------------------------------------
  Procedure FreeExifData()  ; 
    If *ExifData <> 0                                                          :Debug #LF$+#PB_Compiler_Procedure+"() // in use, clear it first.", 9 
      FreeMemory(*ExifData)  ; in use, free memory first 
      *ExifData = 0 
    EndIf 
  EndProcedure 
; ---------------------------------------------------------------------------
  Procedure ShowResultsOnGadget(Gadget)  ; Gadget is a #ListIcon and has two (2) columns 
    Protected txt$, ii 

    If IsGadget(Gadget) And GadgetType(Gadget) = #PB_GadgetType_ListIcon And GetGadgetAttribute(Gadget, #PB_ListIcon_ColumnCount) = 2 
;     Debug #LF$+"ResultValues(): " 
      ForEach ResultValues() 
;       Debug "  " + ResultValues()\Name$ + "  " + ResultValues()\Value + " | '" + ResultValues()\Value$ + "' | ... " 
        If ResultValues()\Private = #True  ; <-->  for internal use only :) 
          Continue  
        EndIf 
;       Debug "  " + ResultValues()\Name$ + "  " + ResultValues()\Value + " | '" + ResultValues()\Value$ + "' | ... " 

        If ResultValues()\Value$ <> "" 
          txt$ = ResultValues()\Value$
        ElseIf ResultValues()\Value <> 0 
          txt$ = Str(ResultValues()\Value) 
        Else 
          For ii = 0 To ArraySize(ResultValues()\Vals()) - 1 
            txt$ + Str(ResultValues()\Vals(ii)) + ";" 
          Next ii 
        EndIf 

        AddGadgetItem(Gadget, -1, ResultValues()\Name$ + #LF$ + txt$)  
      Next 
    Else ; not the correct gadget 
      Debug "INTERNAL: Gadget " + Gadget + " is not the correct gadget type. " 
    EndIf 
  EndProcedure 
  ; ---------------------------------------------------------------------------
  Procedure.i GetExifTagAsInteger(ExifTag, DefaultValue = -1) 
    ForEach ResultValues() 
      If ResultValues()\Number = ExifTag 
        ProcedureReturn ResultValues()\Value 
      EndIf 
    Next 
    ProcedureReturn DefaultValue 
  EndProcedure 
; ---------------------------------------------------------------------------
  Procedure.s GetExifTagAsString(ExifTag, DefaultValue$ = "") 
    ForEach ResultValues() 
      If ResultValues()\Number = ExifTag 
        ProcedureReturn ResultValues()\Value$ 
      EndIf 
    Next 
    ProcedureReturn DefaultValue$ 
  EndProcedure 
  ; ---------------------------------------------------------------------------
; Procedure GetExifTagValue(ExifTag) 
; EndProcedure 
  ; ---------------------------------------------------------------------------
EndModule ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; ---== MainWindow ==--------------------------------------------------------------------------------------------------
Procedure ShowImagePreview(FileName$)  ; update all UI gadgets 
  Protected IMAGE 
  Protected ix, iy, iw, ih, gw, gh, txt$  

  gw = GadgetWidth(#GADGET_CnvPreView)   ; <-- get the size of the image gadget 
  gh = GadgetHeight(#GADGET_CnvPreView) 

  If FileSize(FileName$) > 0  ; FileName$ = "" returns -1 as well 
    IMAGE = LoadImage(#PB_Any, FileName$)  ; <-- load image 
  EndIf 

  If IMAGE 
    iw = ImageWidth(IMAGE) 
    ih = ImageHeight(IMAGE) 
    txt$ = "Image Size = " + Str(iw) + " x " + Str(ih) 

    ; calc factor to reduce to the available gadget size 
    ix = 1 : While iw/ix > gw : ix + 1 : Wend 
    iy = 1 : While ih/iy > gh : iy + 1 : Wend 
    If ix < iy : ix = iy : EndIf  ; the bigger the better :) 

    iw / ix : ih / ix  ; shrink the size 

    ; center in hori and verti orientation 
    ix = (gw - iw) / 2  : If ix < 0 : ix = 0 : EndIf 
    iy = (gh - ih) / 2  : If iy < 0 : iy = 0 : EndIf 
  Else  ; <-- default ?? 
    txt$ = "Image: Nothing selected or found!" 
  EndIf 

  If StartDrawing(CanvasOutput(#GADGET_CnvPreView)) 
    Box(0, 0, gw, gh, #White) 
    If IMAGE  ; <-- valid image 
      DrawImage(ImageID(IMAGE), ix, iy, iw, ih) 
    EndIf 
    DrawingMode(#PB_2DDrawing_Transparent) 
    DrawText(4, 4, txt$, #Blue) 
    StopDrawing() 
  EndIf 

  If IMAGE 
    FreeImage(IMAGE) 
  EndIf 
EndProcedure 
;­-----------------------------------------------------------------------------
Procedure UpdateImage(FileName$)
  If FileName$ And ExifData::ReadExifDataFromFile(FileName$) 
    ExifData::ShowResultsOnGadget(#GADGET_LstImageInfo) 
    ExifData::FreeExifData() 
  Else  ; do some info 
    AddGadgetItem(#GADGET_LstImageInfo, -1, "No Exif-Info!")  
  EndIf 
  ShowImagePreview(FileName$)  
EndProcedure 
; -----------------------------------------------------------------------------
Procedure ResizeGadgetsWindow_0()
  Protected FormWindowWidth, FormWindowHeight
  FormWindowWidth = WindowWidth(#WINDOW_Main)
  FormWindowHeight = WindowHeight(#WINDOW_Main)
  ResizeGadget(#GADGET_ExpImageFiles, 20, 20, 240, FormWindowHeight - 180)
  ResizeGadget(#GADGET_LstImageInfo, 270, 20, 320, FormWindowHeight - 180)
  ResizeGadget(#GADGET_CnvPreView, 600, 20, FormWindowWidth - 620, FormWindowHeight - 250)
  ResizeGadget(#GADGET_EdtPreView, 600, FormWindowHeight - 220, FormWindowWidth - 620, 60)
  ResizeGadget(#GADGET_Source_path, 20, FormWindowHeight - 130, 70, 25)
  ResizeGadget(#GADGET_Source_path_show, 100, FormWindowHeight - 130, FormWindowWidth - 570, 25)
  ResizeGadget(#GADGET_Target_path, 20, FormWindowHeight - 100, 70, 25)
  ResizeGadget(#GADGET_Target_path_show, 100, FormWindowHeight - 100, FormWindowWidth - 570, 25)
  ResizeGadget(#Frame3D_0, 10, 0, FormWindowWidth - 20, FormWindowHeight - 150)
  ResizeGadget(#Frame3D_1, 10, FormWindowHeight - 150, FormWindowWidth - 20, 80)
  ResizeGadget(#Frame3D_2, 10, FormWindowHeight - 70, FormWindowWidth - 20, 60)
  ResizeGadget(#GADGET_Original_file, FormWindowWidth - 460, FormWindowHeight - 130, 120, 25)
  ResizeGadget(#GADGET_Original_file_show, FormWindowWidth - 330, FormWindowHeight - 130, 310, 25)
  ResizeGadget(#GADGET_Renamed_file, FormWindowWidth - 460, FormWindowHeight - 100, 120, 25)
  ResizeGadget(#GADGET_Renamed_file_show, FormWindowWidth - 330, FormWindowHeight - 100, 310, 25)
  ResizeGadget(#GADGET_Button_exit, 20, FormWindowHeight - 50, 180, 25)
  ResizeGadget(#GADGET_Button_rename, FormWindowWidth - 200, FormWindowHeight - 50, 180, 25)
  ResizeGadget(#GADGET_Button_rename_abort, FormWindowWidth - 400, FormWindowHeight - 50, 180, 25)
EndProcedure
; -----------------------------------------------------------------------------
Procedure OpenMainWindow(WndW, WndH)  ; 
  If OpenWindow(#WINDOW_Main, 0, 0, 1120, 750,  "", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
    StickyWindow(#WINDOW_Main, 1)  ; always on top, my sreen is a mess :) 
    
    FrameGadget(#Frame3D_0, 10, 0, 1100, 600, "")
  	FrameGadget(#Frame3D_1, 10, 600, 1100, 80, "")
  	FrameGadget(#Frame3D_2, 10, 680, 1100, 60, "")
  	
    ExplorerListGadget(#GADGET_ExpImageFiles, 20, 20, 240, 570, "C:\Users\Rainer\Pictures\*.jpg", #PB_Explorer_AlwaysShowSelection | #PB_Explorer_FullRowSelect) 
    RemoveGadgetColumn(#GADGET_ExpImageFiles, 1) ; we don't need the other columns 
    RemoveGadgetColumn(#GADGET_ExpImageFiles, 1) ; -"- 
    RemoveGadgetColumn(#GADGET_ExpImageFiles, 1) ; -"- 
    SetGadgetItemAttribute(#GADGET_ExpImageFiles, 0, #PB_Explorer_ColumnWidth, 216, 0)
    SetGadgetItemState(#GADGET_ExpImageFiles, 0, #PB_Explorer_Selected | #PB_Explorer_AlwaysShowSelection | #PB_Explorer_FullRowSelect )

    ListIconGadget(#GADGET_LstImageInfo, 270, 20, 320, 570, "Name", 120, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_GridLines) 
    AddGadgetColumn(#GADGET_LstImageInfo, 1, "Value", 200-24)  

    CanvasGadget(#GADGET_CnvPreView, 600, 20, 500, 500, #PB_Canvas_Border) 

    EditorGadget(#GADGET_EdtPreView , 600, 530, 500, 60, #PB_Editor_WordWrap|#PB_Editor_ReadOnly) 
    SetGadgetText(#GADGET_EdtPreView, "No Selected Value!") 
    
   	TextGadget(#GADGET_Source_path, 20, 620, 70, 25, "Quell-Pfad:", #PB_Text_Right)
    TextGadget(#GADGET_Source_path_show, 100, 620, 550, 25, "", #PB_Text_Border)
    
  	TextGadget(#GADGET_Target_path, 20, 650, 70, 25, "Ziel-Pfad:", #PB_Text_Right)
  	TextGadget(#GADGET_Target_path_show, 100, 650, 550, 25, "", #PB_Text_Border)
  	
  	TextGadget(#GADGET_Original_file, 660, 620, 120, 25, "Original-Dateiname:", #PB_Text_Right)
  	TextGadget(#GADGET_Original_file_show, 790, 620, 310, 25, "", #PB_Text_Border)
  	
  	TextGadget(#GADGET_Renamed_file, 660, 650, 120, 25, "Renamed-Dateiname:", #PB_Text_Right)
  	TextGadget(#GADGET_Renamed_file_show, 790, 650, 310, 25, "", #PB_Text_Border)

  	ButtonGadget(#GADGET_Button_exit, 20, 700, 180, 25, "Programm beenden")
  	ButtonGadget(#GADGET_Button_rename, 920, 700, 180, 25, "Bilder umbennen starten")
  	
  	ButtonGadget(#GADGET_Button_rename_abort, 720, 700, 180, 25, "Bilder umbennen abbrechen")
  	DisableGadget(#GADGET_Button_rename_abort, #True)
    ProcedureReturn 1  ; success 
  EndIf 
  ProcedureReturn 0  ; failure 
EndProcedure
; ---------------------------------------------------------------------------
; MISTAKE !!!!

;	In this Procedure I want to work down the exlorerlist-entries 1 by 1 from top to bottom.
;	If it is a jpg-file I want to show the picture and want to show the exif-Data in the listbox. 
; In the next step I want to read the DateTimeDigitized or the DateTimeOriginal-date to
;	copy the picture into the created folder "Date-Renamed" under a new name like this: "Digitized_date-Filename.ext"

; But it does not work the wanted!
; The list will be worked down 1 by 1 >> OK
;	The picture will be shown in the Canvas >> OK
; The selected filename should be highlighted >> will not be done!!
;	The Exif-date should be shown in the listbox >> will not be done!!
;	The Rename-abort-button will not be recognized >> no abort action in the While-wend loop happens, the loop will not be ended!

Procedure Rename_Pictures()
	Protected File_Loop.i = 0, Rename_FileName.s, Exif_Date.s, File_Extension.s, Items_in_Folder.i = 0, List_File.s
	
	SetGadgetItemState(#GADGET_ExpImageFiles, 0, #PB_Explorer_Selected )
	Items_in_Folder = CountGadgetItems(#GADGET_ExpImageFiles)
	ClearGadgetItems(#GADGET_LstImageInfo)
	While Items_in_Folder > File_Loop
		Select WaitWindowEvent()
    	Case #PB_Event_Gadget	
    		Select EventGadget()
    			Case #GADGET_Button_rename_abort
          	Select EventType()  
            	Case #PB_EventType_LeftClick 
            		Break
            EndSelect
        EndSelect    
    EndSelect
		SetGadgetItemState(#GADGET_ExpImageFiles, File_Loop, #PB_Explorer_Selected )
		List_File = GetGadgetText(#GADGET_ExpImageFiles) + GetGadgetItemText(#GADGET_ExpImageFiles, File_Loop, 0)
		If Not FileSize(List_File) = -2		;Nur Dateinamen werden bearbeitet, keine Verzeichnisse	
     	Only_Filename = GetFilePart(List_File)
    	File_Extension = UCase(GetExtensionPart(Only_filename))
    	If (File_Extension = "JPG") Or (File_Extension = "PNG") Or (File_Extension = "BMP")
				ClearGadgetItems(#GADGET_LstImageInfo)
    		UpdateImage(List_File)
    		Exif_Date = "Exif_Date-"  ;Get Exif_Date
    		Rename_FileName = Exif_Date + Only_filename
     		SetGadgetText(#GADGET_Original_file_show, Only_Filename)
    		SetGadgetText(#GADGET_Renamed_file_show, Rename_FileName)
    		Delay(1000)
    	EndIf
    EndIf
    File_Loop + 1             
  Wend
  DisableGadget(#GADGET_Button_rename_abort, #True)
  DisableGadget(#GADGET_Button_exit, #False)
  DisableGadget(#GADGET_Button_rename, #False)
EndProcedure
; ---== main program ==------------------------------------------------------------------------------------------------
Procedure main() 
  Protected WndW = 1120, WndH = 750   
	InitKeyboard()
  ExamineDesktops() 
  If DesktopWidth(0) < WndW Or DesktopHeight(0) < WndH 
    MessageRequester("Display Information", "Your current resolution is to small for this application!") 
    WndW = 800 : WndH = 600 
  EndIf 

  If OpenMainWindow(WndW, WndH) 
    If FileSize("C:\Temp\camera") = -2 ; existing directory ... some test pictures exists on my computer 
      SetGadgetText(#GADGET_ExpImageFiles, "C:\Temp\camera\*.jpg") 
    EndIf 

    Repeat  ; <--- main loop --- 
      Select WaitWindowEvent() 
        Case #PB_Event_CloseWindow 
        	Break   ; say good bye 
        Case #PB_Event_SizeWindow
      		ResizeGadgetsWindow_0()
        Case #PB_Event_Gadget 
        	Select EventGadget() 	
            Case #GADGET_ExpImageFiles  ; Explorer with Images 
              Select EventType()               		
                Case #PB_EventType_Change 
                  ClearGadgetItems(#GADGET_LstImageInfo) 
                  index = GetGadgetState(#GADGET_ExpImageFiles) 
                  SetGadgetText(#GADGET_Source_path_show, GetGadgetText(#GADGET_ExpImageFiles)) 
                  If index > -1 
                  	file = GetGadgetText(#GADGET_ExpImageFiles) + GetGadgetItemText(#GADGET_ExpImageFiles, index, 0)
                  	If Not FileSize(file) = -2		;Nur Dateinamen werden gezeigt, keine Verzeichnisse
                  		Only_Filename = GetFilePart(file)
                  		SetGadgetText(#GADGET_Original_file_show, Only_Filename)
                  	Else
                  		SetGadgetText(#GADGET_Original_file_show, "")	
                  	EndIf
                  Else  ; update image section anyway 
                  	file = "" 
                  EndIf 
                  UpdateImage(file) 
                  SetGadgetText(#GADGET_EdtPreView, "No Selected Value!") 
              EndSelect 
            Case #GADGET_LstImageInfo  ; Info of selected Image 
              Select EventType()  
                Case #PB_EventType_Change 
                  index = GetGadgetState(#GADGET_LstImageInfo) 
                  If index > -1 
                    SetGadgetText(#GADGET_EdtPreView, GetGadgetItemText(#GADGET_LstImageInfo, index, 1)) 
                  Else 
                    SetGadgetText(#GADGET_EdtPreView, "No Selected Value!") 
                  EndIf 
              EndSelect            
            Case #GADGET_Button_rename
            	Select EventType()  
            		Case #PB_EventType_LeftClick
            			DisableGadget(#GADGET_Button_rename_abort, #False)
            			DisableGadget(#GADGET_Button_exit, #True)
            			DisableGadget(#GADGET_Button_rename, #True)
            			Rename_Path = GetGadgetText(#GADGET_ExpImageFiles) + "\Date_Renamed" ; Rename_Path_Namen erstellen
            			If FileSize(Rename_Path) = -1  ;Prüfen ob der RenamePfad schon existiert
            				If CreateDirectory(Rename_Path) ; Pfad wird erstellt          					
            					MessageRequester("Information", "Rename-Pfad zum Quell-Verzeichnis wurde erstellt", #PB_MessageRequester_Ok | #PB_MessageRequester_Info)   
            					SetGadgetText(#GADGET_Target_path_show, Rename_Path)
											Rename_Pictures()
            				EndIf
            			ElseIf FileSize(Rename_Path) = -2
            				MessageRequester("Information", "Rename-Pfad zum Quell-Verzeichnis ist bereits vorhanden", #PB_MessageRequester_Ok | #PB_MessageRequester_Info)
            				SetGadgetText(#GADGET_Target_path_show, Rename_Path)
										Rename_Pictures()
									EndIf
            	EndSelect
            Case #GADGET_Button_exit
            	Select EventType()  
            		Case #PB_EventType_LeftClick 
            			Break   ; say good bye 
            	EndSelect	
            Case #GADGET_Button_rename_abort
            	Select EventType()  
            		Case #PB_EventType_LeftClick 
            			Rename_Abort = 1 
            	EndSelect		
          EndSelect ; EventGadget() 
      EndSelect ; WaitWindowEvent() 
    ForEver ; <-- main loop end 
  EndIf ; OpenMainWindow() 
  ProcedureReturn 0 
EndProcedure 
; ---------------------------------------------------------------------------
End main() 
;----== Bottom of File ==----------------------------------------------------------------------------------------------

Re: Procedure wird nicht abgearbeitet

Verfasst: 28.06.2023 12:59
von NicTheQuick
Ich schätze das Problem ist, dass du keine korrekt Ereignisschleife hast.
Eigentlich sollte man ja im ganzen Programm nur eine Ereignisschleife haben. Aber dafür müsste man so einiges umbauen bei dir und mit Threads und PostEvent arbeiten.
Deshalb hier noch eine Schnellschusslösung. Ändere diesen Code...

Code: Alles auswählen

		Select WaitWindowEvent()
			Case #PB_Event_Gadget	
				Select EventGadget()
					Case #GADGET_Button_rename_abort
						Select EventType()  
							Case #PB_EventType_LeftClick 
								Break
						EndSelect
				EndSelect    
		EndSelect
...ab in diesen...

Code: Alles auswählen

		Repeat
			Select WindowEvent()
				Case #PB_Event_Gadget	
					Select EventGadget()
						Case #GADGET_Button_rename_abort
							Select EventType()  
								Case #PB_EventType_LeftClick 
									Break
							EndSelect
					EndSelect    
				Case 0
					Break
			EndSelect
		ForEver
Damit sollten immer alle Events abgearbeitet werden können, die da sind. In deinem Fall wird maximal ein Event abgearbeitet pro Schleifendurchlauf, obwohl wegen deiner ganzen SetGadget...()-Befehle viel mehr pro Durchlauf anfallen.

Das ist keine sonderlich hübsche Lösung, könnte aber funktionieren.

Und vielleicht sollte ich dazu sagen, dass ich meine Lösung nicht getestet habe, sondern das alles nur eine Vermutung ist.

Re: Procedure wird nicht abgearbeitet

Verfasst: 28.06.2023 15:06
von PB_Rainer
Hi,
damit ist das Programm dann in einer Dauerloop, bringt also nichts.
Trotzdem Danke

Re: Procedure wird nicht abgearbeitet

Verfasst: 28.06.2023 16:59
von NicTheQuick
Nein, ist es nicht. Wenn kein Event kommt, dann wird aus der Schleife herausgesprungen. Hast du es denn ausprobiert?

Re: Procedure wird nicht abgearbeitet

Verfasst: 28.06.2023 17:22
von PB_Rainer
Hi,
ja natürlich, dann hängt es irgendwo anders, war genauso ein Verhalten wie mit der Original-Abfrage-Schleife.

Auf das Abbrechen könnte ich ja verzichten, aber, daß die Prozedur zwar ein Bild nach dem anderen anzeigt, aber die Exif-Data nicht in die Listbox bringt ist das große Problem welches ich lösen muß, mit Eurer Hilfe.

Problem ist ja schon, daß der Button nicht highlighted wird beim drüberfahren, der scheint nicht zu reagieren.

Trotzdem danke
Rainer

Re: Procedure wird nicht abgearbeitet

Verfasst: 28.06.2023 17:26
von NicTheQuick
Mein Problem ist, dass ich dein Programm nicht testen kann, da es nicht ordentlich auf Linux funktioniert. Den einzigen Knopf, den ich drücken kann, ist "Bilder umbenennen starten". Und dann erstellt er mir im Home-Verzeichnis einen Ordner mit dem Namen "\Date_Renamed". Ich verstehe noch nicht wie ich den Quell-Pfad einstellen kann. Abgesehen davon kommt dein Programm wahrscheinlich nicht mit dem Pfadtrenner "/" zurecht, sondern nur mit "\" wie es unter Windows üblich ist.

Von daher kann ich gerade leider nicht viel mehr helfen.

Re: Procedure wird nicht abgearbeitet

Verfasst: 28.06.2023 17:43
von PB_Rainer
Hi,
also unter windows, wechsele ich in das Win-Verzeichnis pictures unter dem alle meine Bilder gespeichert sind. Ein Folder pro Jahr, darin die Folder pro Reise oder anderem Thema. Zuerst wähle ich im Explorer den Folder der Reise aus, die ich als Video erstellen will, unter diesem Folder wird dann der Date-Renamed-Folder erzeugt. Dort hinein sollen dann die Bilder mit dem ExifDateTime am Anfang Kopiert werden, damit man sie nach Exif sortieren kann.
Gruß Rainer

Re: Procedure wird nicht abgearbeitet

Verfasst: 28.06.2023 18:03
von NicTheQuick
Okay, mein ExplorerGadget ist komplett leer und weiß. Und ich weiß schon woran es lag. Es lag daran, dass du da als initiales Verzeichnis

Code: Alles auswählen

"C:\Users\Rainer\Pictures\*.jpg"
stehen hattest. Das habe ich mal durch

Code: Alles auswählen

GetHomeDirectory() + "*.jpg"
ersetzt.

Dann wurde mir auch was angezeigt. Ich habe dann in einen Bilder-Ordner navigiert und auf "Bilder umbenennen starten" geklickt. Es wurde durch alle Bilder iteriert, und es wurde für jedes die EXIF-Daten und die Vorschau angezeigt. Anschließend waren im Ziel-Ordner allerdings keine Bilder.
Das kam dann im Debug-Fenster:
HINT: #ExifTagTableSize: 29
LOG -> Read file with length of 0 bytes.
LOG -> Not a valid JPEG
LOG -> Read file with length of 0 bytes.
LOG -> Not a valid JPEG
LOG -> Read file with length of 0 bytes.
LOG -> Not a valid JPEG
LOG -> Read file with length of 0 bytes.
LOG -> Not a valid JPEG
LOG -> Read file with length of 0 bytes.
LOG -> Not a valid JPEG
LOG -> Read file with length of 1950943 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 1950943 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2181610 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2492350 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2055479 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2333130 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2829055 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2959248 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2451851 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2238088 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2031524 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2076109 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2540218 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2068636 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2600169 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2619759 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2143649 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 1694550 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2328461 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 1866108 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2955962 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 4218908 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2345306 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2173140 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 3133243 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 1766786 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 3102606 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 1694695 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2830881 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 2998990 bytes.
LOG -> Found 0xFFE1 marker
LOG -> Read file with length of 1943911 bytes.
LOG -> Found 0xFFE1 marker
Ist das soweit das selbe wie es bei dir passiert?

Re: Procedure wird nicht abgearbeitet

Verfasst: 28.06.2023 19:03
von PB_Rainer
Ja, soweit passiert das bei mir auch, und meine Debug-Ausgabe sieht auch so aus. Allerdings werden die Exif_Daten nicht im mittleren Bereich bei jedem Bild gezeigt. Nur ganz zum Schluß, nach abarbeiten von ca. 90% der Files kommen ein paar Exifdaten. Das entspricht auch ungefähr dem was im englischen Forum beschrieben wurde.
Ich denke da muß ich tatsächlich auf Thread umlernen und programmieren. Mich wundert allerdings daß bei die die Exifdaten bei jedem Bild gezeigt werden.
Kann sein, daß im Source der Kopierbefehl noch auskommentiert ist!
Gruß
Rainer

Re: Procedure wird nicht abgearbeitet

Verfasst: 28.06.2023 19:13
von NicTheQuick
Naja, der Unterschied zu Linux bezüglich GUI kann da schon was ausmachen. Ich hatte allerdings auch meinen Code reingepackt mit der extra-Schleife, damit alle Events abgearbeitet werden. Und ich habe das Delay(1000) entfernt, damit es schneller geht. Das Delay ist halt auch sehr unpraktisch, weil das Abarbeiten der Events verhindert. Wieso hast du das überhaupt da?