Module to easy use Exiftool in your application

Share your advanced PureBasic knowledge/code with the community.
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Dec 25, 2004 2:37 pm

Module to easy use Exiftool in your application

Post by thyphoon »

I am developing an application to replace Google's Picasa.
For that I made a small module to control the fantastic tool that is ExifTool.
ExidTool is a Tool to manipulate metadata from images

ExifTool loads once only... and i send commands to StdIn
You can Download Exiftool: https://www.sno.phy.queensu.ca/~phil/exiftool/
Edit :
-2019-02-02 Version 4.6

Code: Select all

; ******************************************************************** 
; Program:           ETUE (Easy To use Exiftool)
; Version:           4.6
; Description:       use the verry good Perl Package Exiftool
; Author:            Thyphoon
; Date:              January, 2019
; License:           Free, unrestricted, credit 
;                    appreciated but not required.
; Note:              Please share improvement !
;
; Exiftool info:     ExifTool is a platform-independent Perl library plus a command-line application for reading, writing and editing meta information in a wide variety of files
; Exiftool Web:      https://www.sno.phy.queensu.ca/~phil/exiftool/
; Exiftool author:   Phil Harvey 
; ********************************************************************

EnableExplicit

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Windows 
    #SP = "\"
  CompilerCase #PB_OS_Linux
    #SP = "/"
  CompilerCase #PB_OS_MacOS
    #SP = "/"
CompilerEndSelect

CompilerIf #PB_Compiler_Thread=#False
  CompilerError("You must enable Compiler threadsafe")
  End
CompilerEndIf

DeclareModule Exiftool
  Declare.b SetExecutableFilePath(FilePath.s)
  Declare.s GetExecutableFilePath()
  Declare Start()
  Declare.b IsRun()
  Declare.b Command(cmd.s)
  Declare.i Execute(Event.i=0,WindowEvent.i=0,*ReturnDataProcedure=0)
  Declare.b Stop()
  
  Declare.s GetResultStdout(ExecuteID.i)
  Declare.s GetResultStdErr(ExecuteID.i)
  Declare.i GetResultRawOut(ExecuteID.i)
  Declare.b WaitExecute(ExecuteID.i,TimeOut.i=#False)
  Declare.b WaitReady(TimeOut.i=5000)
  Declare FreeResult(ExecuteID.i)
  Declare Quit()
EndDeclareModule

Module Exiftool
  
  #Verbose=#True   ;TODO #True or #False  if you want a exiftool Log file
  
  Prototype.i ReturnData(ExecuteID.i) 
  
  Structure Execute
    ReadyToUse.b          ;#True if Stdout and StdErr is ready to use
    StdErr.s
    *RawOut
    Event.i
    EventWindow.i
    ReturnData.ReturnData
  EndStructure
  
  Structure param
    VerboseFileId.i
    VerboseMutex.i
    NumberCount.i
    Map Execute.Execute()
    ExecuteMutex.i
    Thread.i
    ProgFilePath.s
    ProgHandle.i
  EndStructure
  
  Global param.param
  
  param\ExecuteMutex=CreateMutex()
  param\VerboseMutex=CreateMutex()
  
  Procedure StartVerbose()
    If #Verbose=#True
      LockMutex(param\VerboseMutex)
      
      param\VerboseFileId=CreateFile(#PB_Any,"ExifTool.log")
      
      UnlockMutex(param\VerboseMutex)
    EndIf 
  EndProcedure
  
  Procedure Verbose(txt.s)
    If #Verbose=#True
      LockMutex(param\VerboseMutex)
      If IsFile(param\VerboseFileId)
        WriteStringN(param\VerboseFileId,txt)
      EndIf 
      UnlockMutex(param\VerboseMutex)
    EndIf 
  EndProcedure
  
  Procedure StopVerbose()
    If #Verbose=#True
      LockMutex(param\VerboseMutex)
      CloseFile(param\VerboseFileId)
      UnlockMutex(param\VerboseMutex)
    EndIf 
  EndProcedure
  
  Procedure.b SetExecutableFilePath(FilePath.s)
    If FileSize(FilePath)>0
      param\ProgFilePath=FilePath
      ProcedureReturn #True
    Else
      MessageRequester("Exiftools","Exiftool No Found",#PB_MessageRequester_Error)
      ProcedureReturn #False
    EndIf 
  EndProcedure
  
  Procedure.s GetExecutableFilePath()
    ProcedureReturn param\ProgFilePath
  EndProcedure
  
  Procedure.s GetResultStdout(ExecuteID.i)
    Protected Stdout.s
    LockMutex(param\ExecuteMutex)
    If param\Execute(Str(ExecuteID))\RawOut>0
      Stdout=PeekS(param\Execute(Str(ExecuteID))\RawOut,MemorySize(param\Execute(Str(ExecuteID))\RawOut),#PB_UTF8)
    Else
      Stdout=""
      Verbose("NO RAWOUT")
    EndIf 
    UnlockMutex(param\ExecuteMutex)
    ProcedureReturn Stdout
  EndProcedure
  
  Procedure.s GetResultStdErr(ExecuteID.i)
    Protected StdErr.s
    LockMutex(param\ExecuteMutex)
    StdErr=param\Execute(Str(ExecuteID))\StdErr
    UnlockMutex(param\ExecuteMutex)
    ProcedureReturn StdErr
  EndProcedure
  
  Procedure.i GetResultRawOut(ExecuteID.i)
    Protected *Data
    LockMutex(param\ExecuteMutex)
    If param\Execute(Str(ExecuteID))\RawOut>0
      *Data=param\Execute(Str(ExecuteID))\RawOut
    Else
      *Data=0
    EndIf 
    UnlockMutex(param\ExecuteMutex)
    ProcedureReturn *Data
  EndProcedure
  
  Procedure LaunchExifTool(p.l=0)
    Protected Output.s,Stdout.s,StdoutEnd.s,StdErr.s,ExecuteID.s
    Protected result.i
    Protected dataSize.i
    Protected *data
    *buffer = 0
    Protected  ForceEnd.b=#False
    param\ProgHandle=RunProgram(param\ProgFilePath,"-stay_open True -@ -",GetPathPart(param\ProgFilePath),#PB_Program_Open|#PB_Program_Read|#PB_Program_Write|#PB_Program_Error|#PB_Program_Hide)
    If IsProgram(param\ProgHandle)
      ItIsEnd=#False
      While ProgramRunning(param\ProgHandle)
        StdErr.s=ReadProgramError(param\ProgHandle)
        If StdErr<>"":Verbose("/!\ ExifTool ERROR :"+StdErr+"<"):Debug "/!\ ExifTool ERROR :"+StdErr+"<":EndIf
        result.i=AvailableProgramOutput(param\ProgHandle)
        If result>0
            *buffer = AllocateMemory(result)
            ReadProgramData(param\ProgHandle,*buffer,result)
            Stdout=PeekS(*buffer,result,#PB_UTF8)
            ;Test only the End to found the {ready
            StdoutEnd=PeekS(*buffer+result-15,15,#PB_Ascii)
            FindStart.i=FindString(StdoutEnd,"{ready",0)
            If FindStart>0 
              FindStop.i=FindString(StdoutEnd,"}",FindStart+6)
              Debug("FIND {Ready"+Mid(Stdout,FindStart+6,FindStop-(FindStart+6))+"} Start:"+Str(FindStart)+" Stop:"+Str(FindStop))
              ItIsEnd=#True
            Else 
              ItIsEnd=#False
            EndIf 
            
            If *data=0
              *data = AllocateMemory(result)
              dataSize=0
              time.i=ElapsedMilliseconds()
            Else
              time.i=ElapsedMilliseconds()
              dataSize=MemorySize(*data)
            EndIf 
        
          If ItIsEnd=#True
            ; Delete {readyx} from *buffer
            NoreadySize=Len(Right(StdoutEnd,Len(StdoutEnd)-FindStart+1)) ; {ready1} = 10 
            Verbose("NoreadySize="+Str(NoreadySize))
          Else
            NoreadySize=0
          EndIf
          If dataSize+result-NoreadySize>0 ; protect if empty return
            *data = ReAllocateMemory(*data,dataSize+result-NoreadySize)
            Verbose("ReAllocateMemory("+Str(*Data)+","+Str(dataSize)+"+"+Str(result)+"-"+Str(NoreadySize)+")")
            CopyMemory(*buffer,*data+dataSize,MemorySize(*buffer)-NoreadySize)
            Debug "FinalBuffer:"+Str(*Data+dataSize)
          Else 
            ;If return is empty No need more memory 
            FreeMemory(*data):*data=0
          EndIf 
          FreeMemory(*buffer):
          
          ;if it's the end
          If ItIsEnd=#True;FindString(Stdout,"{ready",0);Left(Stdout,6)="{ready"
            ItIsEnd=#False; ready to continue
            ExecuteID=Mid(StdoutEnd,FindStart+6,FindStop-(FindStart+6)) ;at the end chr(13)+chr(10)
            Verbose(">Execute{"+ExecuteID+"}")
            LockMutex(param\ExecuteMutex)
            param\execute(ExecuteID)\StdErr=StdErr
            param\Execute(ExecuteID)\RawOut=*data
            param\Execute(ExecuteID)\ReadyToUse=#True
            ;Send Event to inform the result is available
            If param\execute(ExecuteID)\Event<>0
              PostEvent(param\execute(ExecuteID)\Event,param\execute(ExecuteID)\EventWindow,0,0,Val(ExecuteID))
              Verbose("Post Event:"+Str(param\execute(ExecuteID)\Event)+" from Window:"+Str(param\execute(ExecuteID)\EventWindow))
            EndIf 
            ;If Callback use id
            If  param\execute(ExecuteID)\ReturnData<>0
              param\execute(ExecuteID)\ReturnData(Val(ExecuteID)) ; TODO out this function to Call it afer Unlockmutex
            EndIf 
            *data=0
            UnlockMutex(param\ExecuteMutex)  
          EndIf
        EndIf
        
      Wend
      
      ;0 on success, or 1 if an error occurred, or 2 if all files failed
      Verbose("Code Fin :"+Str(ProgramExitCode(param\ProgHandle)))
      CloseProgram(param\ProgHandle) ; Ferme la connection vers le programme
    Else 
      Debug "No Found"+ param\ProgFilePath
      End 
    EndIf
  EndProcedure
  
  Procedure Start()
    StartVerbose()
    param\Thread=CreateThread(@LaunchExifTool(),0)
  EndProcedure
  
  Procedure.b IsRun()
    ProcedureReturn IsThread(param\Thread)
  EndProcedure
  
  Procedure.b Command(cmd.s)
    Verbose("Command>"+cmd) 
    If IsProgram(param\ProgHandle) And ProgramRunning(param\ProgHandle)
      WriteProgramStringN(param\ProgHandle,Cmd)
      ProcedureReturn #True
    Else 
      ProcedureReturn #False
    EndIf 
  EndProcedure
  
  Procedure.i Execute(Event.i=0,EventWindow.i=0,*ReturnDataProcedure=0)
    Protected ExecuteID.s
    param\NumberCount=param\NumberCount+1
    ExecuteID=Str(param\NumberCount)
    Command("-execute"+ExecuteID)
    LockMutex(param\ExecuteMutex)
    param\execute(ExecuteID)\Event=Event
    param\execute(ExecuteID)\EventWindow=EventWindow
    param\execute(ExecuteID)\ReturnData=*ReturnDataProcedure
    UnlockMutex(param\ExecuteMutex)
    ProcedureReturn param\NumberCount
  EndProcedure
  
  Procedure.b Stop()
    Protected Ex.i
    Command("-stay_open")
    Command("False")
    Ex=Execute()
    WaitExecute(Ex,-1)
  EndProcedure
  
  Procedure.b WaitReady(TimeOut.i=5000)
    Protected StartTime.i=ElapsedMilliseconds()
    Repeat
      
      If TimeOut>0 And ElapsedMilliseconds()>StarTime+TimeOut
        ProcedureReturn #False 
      EndIf 
      Delay(100)
    Until  IsProgram(param\ProgHandle)
    Verbose("ExifTool is Ready")
    ProcedureReturn #True
  EndProcedure
  
  Procedure.b WaitExecute(ExecuteID.i,TimeOut.i=#False)
    Protected StartTime.i=ElapsedMilliseconds()
    Repeat
      LockMutex(param\ExecuteMutex)
      If FindMapElement(param\Execute(),Str(ExecuteID)) And param\Execute()\ReadyToUse=#True
        UnlockMutex(param\ExecuteMutex)
        Verbose("Wait Execute"+Str(ExecuteID)+" and it's finish")
        ProcedureReturn #True
      EndIf 
      UnlockMutex(param\ExecuteMutex)
      If TimeOut>0 And ElapsedMilliseconds()>StarTime+TimeOut
        Verbose("No Finish Execute"+Str(ExecuteID)+" Timeout ! ")
        ProcedureReturn #False 
      EndIf 
      Delay(500)
    Until IsProgram(param\ProgHandle)=0
  EndProcedure
  
  Procedure FreeResult(ExecuteID.i)
    LockMutex(param\ExecuteMutex)
    If param\Execute(Str(ExecuteID))\RawOut>0
      FreeMemory(param\Execute(Str(ExecuteID))\RawOut)
    EndIf 
    DeleteMapElement(param\Execute(),Str(ExecuteID))
    UnlockMutex(param\ExecuteMutex)
  EndProcedure 
  
  Procedure Quit()
    If IsRun()
      Stop()
      Protected time.i=ElapsedMilliseconds()
      Repeat
        Delay(1)
        If ElapsedMilliseconds()>time+5000
          MessageRequester("ExifTool","Can't Stop ExifTool Thread... ",#PB_MessageRequester_Warning|#PB_MessageRequester_Ok)
          Break
        EndIf   
      Until Exiftool::IsRun()=#False 
    EndIf 
  EndProcedure
  
EndModule

;- MAIN TEST

CompilerIf #PB_Compiler_IsMainFile 
  UseJPEGImageDecoder()
  
  Enumeration
    #ModeExtractPreviewImage
    #ModeSimpleLoadImage
  EndEnumeration
  ;In this Demo You can choose the MOde to do a preview image
  #Mode=#ModeExtractPreviewImage ;TODO <- You Canc hange the MODE 
  
  Enumeration
    #Win_Main
    #Gdt_LoadImage
    #Gdt_Image
    #Gdt_MetaList
    #Gdt_Description
    #Gdt_State
    #Gdt_OnOff
    #Gdt_Save
  EndEnumeration
  
  Exiftool::SetExecutableFilePath(GetCurrentDirectory()+"exiftool"+#SP+"exiftool.exe") ; TODO Change the path to found the exiftool.exe
  Exiftool::Start()
  
  Enumeration #PB_Event_FirstCustomValue
    #Cust_Event_Exiftools_Read_Metadatas
    #Cust_Event_Exiftools_Write_Metadatas
  EndEnumeration
  
  Procedure ReturnData(ExecuteID) 
    Protected Stdout.s,StdError.s
    Stdout=Exiftool::GetResultStdout(ExecuteID)
    StdError=Exiftool::GetResultStdErr(ExecuteID)
    If StdError<>""
      MessageRequester("Exiftool",StdError,#PB_MessageRequester_Info)
    EndIf 
    If Stdout<>""
      MessageRequester("Exiftool",Stdout,#PB_MessageRequester_Error)
    EndIf 
  EndProcedure
  
  ;test waitexecute
  Exiftool::WaitReady(-1) ;TODO First wait Exiftool is initialized 
  Exiftool::Command("-ver")
  Define Ei.i=Exiftool::Execute()
  If Exiftool::WaitExecute(Ei,-1)=#True;TODO Wait the Exiftool data return berfore continue -1 = No wait limit. But you can put a TimeOut 
    
    Debug "You Use Exiftool version "+Exiftool::GetResultStdout(Ei)+"You can Thanks Phil Harvey for this great tool"
    If Exiftool::GetResultStdErr(Ei)<>""
      Debug "You Have an Error:"+Exiftool::GetResultStdErr(Ei)
    EndIf 
  Else 
    Debug "Go out before Execute finish"
  EndIf   
  Exiftool::FreeResult(Ei) ;TODO After take data clean used memory
  
  ;Declare.i Execute(Event.i=0,WindowEvent.i=0,*ReturnDataProcedure=0)
  
  If OpenWindow(#Win_Main, 0, 0, 800, 250,"ExifTool test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(#Gdt_LoadImage,0,0,320,25,"Load Image")
    CanvasGadget(#Gdt_Image,0,25,320,200)
    ListIconGadget(#Gdt_MetaList,800-400,0,400,250,"Name",200)
    AddGadgetColumn(#Gdt_MetaList,1,"Value",200)
    
    StringGadget(#Gdt_Description,0,225,320,25,""):GadgetToolTip(#Gdt_Description,"Description")
    TextGadget(#Gdt_State,340,10,50,25,"")
    ButtonGadget(#Gdt_OnOff,340,50,50,25,"ON/OFF")
    ButtonGadget(#Gdt_Save,320,225,50,25,"SAVE")
    Define Event.i
    Repeat
      
      Event=WaitWindowEvent()
      Select Event
        Case #PB_Event_Gadget 
          Select EventGadget()
            Case #Gdt_LoadImage
              Define FilePath.s
              Define.l Width,Height,x,y
              Define.i Image
              Define.f ImgRatio,ContRatio
              FilePath.s=OpenFileRequester("Choose Image", "", "*.jpg|*.pef", 0 )
              If FilePath<>"" And FileSize(FilePath)>0 And (LCase(GetExtensionPart(FilePath))="jpg" Or LCase(GetExtensionPart(FilePath))="pef")
                
                Select #Mode
                  Case #ModeExtractPreviewImage
                    Exiftool::Command("-b")
                    ;Exiftool::Command("-ThumbnailImage")
                    Exiftool::Command("-JpgFromRaw")
                    ;TODO This Toow Line are very Important to Support Path With Special Character Or You Will Have "File Not Found" Error.
                    Exiftool::Command("-charset")                   
                    Exiftool::Command("FILENAME=utf8")
                    Exiftool::Command(FilePath)
                    Ei.i=Exiftool::Execute()
                    If Exiftool::WaitExecute(Ei,-1)=#True
                      
                      If Exiftool::GetResultRawOut(Ei)>0 ;Always check if your are a Memory pointer or 0
                        Debug MemorySize(Exiftool::GetResultRawOut(Ei))
                        Image.i=CatchImage(#PB_Any,Exiftool::GetResultRawOut(Ei))
                      Else
                        MessageRequester("Oups !","No Preview Image on this file May be use a photo and not juste a jpg image",#PB_MessageRequester_Info|#PB_MessageRequester_Ok)
                      EndIf 
                      Exiftool::FreeResult(Ei) ;TODO After take data clean used memory
                    EndIf 
                  Case #ModeSimpleLoadImage
                    Image.i=LoadImage(#PB_Any,FilePath)
                    
                EndSelect
                
                
                If Image>0
                  ImgRatio = ImageWidth(Image) / ImageHeight(Image)
                  ContRatio = GadgetWidth(#Gdt_Image) /GadgetHeight(#Gdt_Image)
                  If ImgRatio<ContRatio
                    Width=ImageWidth(Image)*GadgetHeight(#Gdt_Image)/ImageHeight(Image)
                    height=GadgetHeight(#Gdt_Image)
                    x=(GadgetWidth(#Gdt_Image)-Width)/2
                    y=0
                  Else
                    Width=GadgetWidth(#Gdt_Image)
                    height=ImageHeight(Image)*GadgetWidth(#Gdt_Image)/ImageWidth(Image)
                    x=0
                    y=(GadgetHeight(#Gdt_Image)-height)/2
                  EndIf
                  StartDrawing(CanvasOutput(#Gdt_Image))
                  DrawImage(ImageID(Image),x,y,Width,Height)
                  StopDrawing()
                EndIf 
                Exiftool::Command("-s")                         ; -s[NUM]     (-short)           Short output format
                Exiftool::Command("-args")                      ; -args       (-argFormat)       Format metadata as exiftool arguments
                Exiftool::Command("-a")                         ; -a          (-duplicates)      Allow duplicate tags to be extracted
                Exiftool::Command("-g")                         ; -g[NUM...]  (-groupHeadings)   Organize output by tag group
                Exiftool::Command("-G")                         ; -G[NUM...]  (-groupNames)      Print group name for each tag
                Exiftool::Command("-n")                         ; -n          (--printConv)      No print conversion (output the coordinates as signed decimal degrees)
                                                                ;TODO This Toow Line are very Important to Support Path With Special Character Or You Will Have "File Not Found" Error.
                Exiftool::Command("-charset")                   
                Exiftool::Command("FILENAME=utf8")
                Exiftool::Command(FilePath)
                Exiftool::Execute(#Cust_Event_Exiftools_Read_Metadatas,#Win_main)  ;TODO Exemple to use Event to return data
              EndIf 
            Case #Gdt_OnOff
              
              If Exiftool::IsRun()
                Debug "Debug OFF"
                Exiftool::Stop()
              Else
                Debug "Debug ON"
                Exiftool::Start()
              EndIf 
            Case #Gdt_Save
              Exiftool::Command("-Exif:ImageDescription="+GetGadgetText(#Gdt_Description))
              ;TODO This Toow Line are very Important to Support Path With Special Character Or You Will Have "File Not Found" Error.
              Exiftool::Command("-charset")                   
              Exiftool::Command("FILENAME=utf8")
              Exiftool::Command(FilePath)
              Exiftool::Execute(0,0,@ReturnData()) ;TODO Exemple to Use CallBack to return data
              
          EndSelect
          
        Case #Cust_Event_Exiftools_Read_Metadatas
          Define n.l
          Define ExecuteID.i
          Define Backdata.s
          Define line.s
          Define pos.l
          Define name.s
          Define value.s
          ExecuteID.i=EventData() ;TODO Get ExecuteID who send this Event
          Backdata.s=Exiftool::GetResultStdout(ExecuteID) ;Get the Exiftool Return
          Exiftool::FreeResult(Ei)                        ;TODO After take data clean used memory
          ClearGadgetItems(#Gdt_MetaList)
          Backdata=ReplaceString(Backdata,Chr(13)+Chr(10),Chr(13))
          For n=1 To CountString(Backdata,Chr(13))
            line=StringField(Backdata,n,Chr(13))
            pos=FindString(line,"=")
            name=Trim(Mid(line,1,pos-1))
            value=Trim(Mid(line,pos+1,Len(line)-pos+1))
            If name="-EXIF:ImageDescription"
              SetGadgetText(#Gdt_Description,value)
            EndIf
            AddGadgetItem(#Gdt_MetaList,-1,name+Chr(10)+value)
          Next
      EndSelect 
      ;Just Check if Exiftool is Ready
      If Exiftool::IsRun()
        SetGadgetText(#Gdt_State,"ON")
      Else
        SetGadgetText(#Gdt_State,"OFF")
      EndIf 
      
    Until Event=#PB_Event_CloseWindow
    Exiftool::Stop()
  EndIf
  
CompilerEndIf   

Last edited by thyphoon on Sat Feb 02, 2019 5:26 pm, edited 1 time in total.
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Dec 25, 2004 2:37 pm

Re: Module to easy use Exiftool in your application

Post by thyphoon »

Big Update.
You can get binarie return from Exiftool. I find the solution with "No File Found" if path use special characters.
Exemple is more commented !
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Module to easy use Exiftool in your application

Post by collectordave »

Old thread but landed here when searching for something to help me edit exif data in jpg files.

I have downloaded the ExifTool PKG for the Mac and installed.

When I run Exiftool from the terminal it appears to work, I have tried some of the read examples and they work in terminal.

Every time I run the example I get an 'exiftool not found' message.

What do I need to change to get the example to work?

There is an entry for Exiftool.exe but I cannot find where to direct this to.

collectordave
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Dec 25, 2004 2:37 pm

Re: Module to easy use Exiftool in your application

Post by thyphoon »

Hello,

I use Exiftool only on windows... maybe you must do some change to run with no problem.

but if you have "Exiftool No Found" You must to change path and exiftool name (line 365)

Code: Select all

Exiftool::SetExecutableFilePath(GetCurrentDirectory()+"exiftool"+#SP+"exiftool.exe")
may be macintosh have not .exe :idea:
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Module to easy use Exiftool in your application

Post by collectordave »

Yes there are no .exe on the Mac.

used terminal to list the folder and it reports exiftool as a lib so tried.

Code: Select all

ImportC "/usr/local/bin/exiftool"

EndImport
which compiles ok but where do I go from here?
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Dec 25, 2004 2:37 pm

Re: Module to easy use Exiftool in your application

Post by thyphoon »

try this

Code: Select all

Exiftool::SetExecutableFilePath("/usr/local/bin/exiftool")
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Module to easy use Exiftool in your application

Post by collectordave »

Tried that and it certainly gets me to the main window but as soon as I load a jpg it just locks up.

I think I can issue the commands through running terminal and direct any output to a file.

Would be nice if I could get terminal output straight into my programme not to file but will see.


Thanks
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Module to easy use Exiftool in your application

Post by collectordave »

Ah well getting there but run program will not run the terminal again

I run this in the terminal

exiftool -UserComment /Users/dave/Documents/Testexif/482.jpg > /Users/dave/Documents/TestExif.txt

works perfectly every time.


Tried umpteen ways of using run program and none of them work.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Dec 25, 2004 2:37 pm

Re: Module to easy use Exiftool in your application

Post by thyphoon »

it's ok with old ExifTools version... but with last version (12.30) i Have a problem too. maybe try to found 2019 exiftools version
Post Reply