utiliser simplement et efficacement Exiftool

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
Thyphoon
Messages : 2697
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

utiliser simplement et efficacement Exiftool

Message par Thyphoon »

Je suis en train de développer une application pour remplacer feu Picasa de Google.
Pour cela j'ai fait un petit module pour piloter le fantastique outil qu'est ExifTool.
Vu que Ar-s me l'a demandé.

Voici le code
ExifTool se charge une seul fois... et on lui envoie les commandes via le StdIn
pour télécharger Exiftool : https://www.sno.phy.queensu.ca/~phil/exiftool/

2019-02-02 Version 4.6

Code : Tout sélectionner

; ******************************************************************** 
; 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   
Dernière modification par Thyphoon le sam. 02/févr./2019 17:20, modifié 3 fois.
Avatar de l’utilisateur
Ar-S
Messages : 9477
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: utiliser simplement et efficacement Exiftool

Message par Ar-S »

Merci c'est intéressant. Je n'ai cependant que besoin de l'Orientation. Du coup ça fait un peu lourd. J'utilise un proce de Marc56 qui va bien mais je viens de me rendre compte que j'ai toujours une image d'iphone 5s qui n'affiche pas un ID classique d'orientation... Au final ça vient donc de la photo.
L'ID est de 6 sur exiftool et 157 via la proce que j'utilise. Et comme je n'ai pas d'autre photos de ce type, je ne sais pas si c'est le cas sur toutes les photos d'Iphone 5s, d'iphone 6,7 etc ou si c'est vraiment cette photo le soucis.
En tout cas je prends tout de même ton code qui marche très bien et te remercie de ta promptitude. :wink:
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Thyphoon
Messages : 2697
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: utiliser simplement et efficacement Exiftool

Message par Thyphoon »

Ar-S a écrit :Merci c'est intéressant. Je n'ai cependant que besoin de l'Orientation. Du coup ça fait un peu lourd. J'utilise un proce de Marc56 qui va bien mais je viens de me rendre compte que j'ai toujours une image d'iphone 5s qui n'affiche pas un ID classique d'orientation... Au final ça vient donc de la photo.
L'ID est de 6 sur exiftool et 156 via la proce que j'utilise. Et comme je n'ai pas d'autre photos de ce type, je ne sais pas si c'est le cas sur toutes les photos d'Iphone 5s, d'iphone 6,7 etc ou si c'est vraiment cette photo le soucis.
En tout cas je prends tout de même ton code qui marche très bien et te remercie de ta promptitude. :wink:
De rien ! Effectivement ça fait un peu lourd juste pour cette info.
Mais j'avais un code qui permettait de trouver l'orientation de la photo... je ne sais pas si c'est le même que celle de Marc56... si je retrouve je te l'envoie On sait jamais.
sinon regarde là... si ça peut t'inspirer https://code.i-harness.com/fr/q/5ef0e5
boby
Messages : 261
Inscription : jeu. 07/juin/2007 22:54

Re: utiliser simplement et efficacement Exiftool

Message par boby »

Effectivement ça fait un peu lourd juste pour cette info.
Bof.. C'est un module, donc une page qu'on peut laissé fermé. S'pas pour les quelques Ko que ça va rajouté à l’exécutable que ça crains. Les Modules c'est la vie !

Merci pour le partage Thyphoon.
Marc56
Messages : 2147
Inscription : sam. 08/févr./2014 15:19

Re: utiliser simplement et efficacement Exiftool

Message par Marc56 »

boby a écrit :
Effectivement ça fait un peu lourd juste pour cette info.
Bof.. C'est un module, donc une page qu'on peut laissé fermé. S'pas pour les quelques Ko que ça va rajouté à l’exécutable que ça crains.
Euh? Il faut au moins les 8 Mo d'ExifTool, puisque c'est celui-ci qui fait le travail (par RunProgram())

De plus, ExifTool n'est pas un 'véritable' EXE, puisque c'est un script Perl.
Pour ceux qui ne savent pas: Perl, tout comme Python ne produit pas de binaire, les EXE sont des encapsulation d'un runtime + toutes les libs. Au lancement il se décompacte en mémoire et se lance (comme un zip EXE).

Pour les curieux: Ce type d'EXE s'ouvre avec 7zip (clic droit>7zip>ouvrir avec). Pour ExifTool, il est composé de 845 fichiers et 145 dossiers.
Ça n'enlève rien à la qualité, mais est-ce satisfaisant intellectuellement pour des codeurs :roll:

PS. Je dis ça comme ça, mais Perl est mon gagne pain et je l'adore :mrgreen:

@Ar-s j'ai téléchargé pour tester des photos issues d'iPhone 5s et c'est vrai, les exifs ne sont pas visibles à l'endroit standard, par contre ils sont présents si on regarde le début du fichier avec un éditeur hexa.

:wink:
Avatar de l’utilisateur
Thyphoon
Messages : 2697
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: utiliser simplement et efficacement Exiftool

Message par Thyphoon »

effectivement ExifTool est un peu lourd... mais il n'y a pas mieux pour lire et écrire des métadonnées. :P
Marc56
Messages : 2147
Inscription : sam. 08/févr./2014 15:19

Re: utiliser simplement et efficacement Exiftool

Message par Marc56 »

Si tu veux un truc plus léger, il y a Irfanview qui peut être utilisé en ligne de commandes.
Aide F1 ou fichier "i_options.txt"

Pour avoir un fichier texte avec toutes les exifs et autres

Code : Tout sélectionner

"\Program Files\IrfanView\i_view64.exe" image.jpg /info=info.txt /fullinfo
:idea: Ensuite, tu peux remplacer (ReplaceString) les '-' par des '=' et tu as un fichier INI directement utilisable avec les fonctions PB
(Juste la ligne - EXIF - à supprimer ou a remplacer par une section exemple [Exif])
Il n'y a pas de ligne en double donc possibilité aussi d'en faire une Map

Je pense qu'XnView (NConvert) doit aussi avoir des options similaires, mais je le connais moins.
De même ImageMagick qui je crois peut s'utiliser en tant que DLL (mais utiliser une DLL, j'en suis pas encore là, je ne pratique PB que depuis 2008, je suis très lent :mrgreen: )

:wink:

Ooops, j'ai fais dévier ton sujet :oops: :oops: :oops: (un modo, help: nettoyage svp)
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: utiliser simplement et efficacement Exiftool

Message par Kwai chang caine »

Ca peut être utile, merci du partage 8)
Marc56 a écrit :Pour ceux qui ne savent pas: Perl, tout comme Python ne produit pas de binaire, les EXE sont des encapsulation d'un runtime + toutes les libs
Je le savais pour PYTHON mais pas pour PERL merci des infos
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: utiliser simplement et efficacement Exiftool

Message par Ollivier »

Ça faisait longtemps Thyphoon...

Ça va c'est sympa de te revoir !
Avatar de l’utilisateur
Thyphoon
Messages : 2697
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: utiliser simplement et efficacement Exiftool

Message par Thyphoon »

Marc56 a écrit :Si tu veux un truc plus léger, il y a Irfanview
Merci Marc56 , mais j'ai déjà testé ... et le fait de fonctionner en ligne de commande on se trouve avec des problèmes d'encodage de caractère.... et il y a plein de format non supporté.
Mais ton info n'est pas du tout hors sujet. :wink:
Ollivier a écrit :Ça faisait longtemps Thyphoon...

Ça va c'est sympa de te revoir !
Merci :D
C'est sympa de voir qu'on m'a pas oublié 8)
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: utiliser simplement et efficacement Exiftool

Message par Kwai chang caine »

Chez PB....on oublie personne :wink:
Tous ceux qui partent nous manquent :|
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
Thyphoon
Messages : 2697
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: utiliser simplement et efficacement Exiftool

Message par Thyphoon »

Kwai chang caine a écrit :Chez PB....on oublie personne :wink:
Tous ceux qui partent nous manquent :|
Effectivement :wink:
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: utiliser simplement et efficacement Exiftool

Message par djes »

Je me demande si Fred n'a pas déjà «donné les clefs» à quelqu'un, puisque le jpeg est utilisé par PB depuis assez longtemps, il doit y avoir moyen via une petite interface d'utiliser la lib de façon plus complète.

Edit : dans la lib jpeg y'a pas grand chose sur les exifs, contrairement à la lib tiff.

Par contre, boddhi avait fait une bibliothèque exif : https://www.purebasic.fr/french/viewtop ... =3&t=10788
Pour moi elle fonctionne très bien.
Avatar de l’utilisateur
Thyphoon
Messages : 2697
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: utiliser simplement et efficacement Exiftool

Message par Thyphoon »

djes a écrit :Je me demande si Fred n'a pas déjà «donné les clefs» à quelqu'un, puisque le jpeg est utilisé par PB depuis assez longtemps, il doit y avoir moyen via une petite interface d'utiliser la lib de façon plus complète.

Edit : dans la lib jpeg y'a pas grand chose sur les exifs, contrairement à la lib tiff.

Par contre, boddhi avait fait une bibliothèque exif : https://www.purebasic.fr/french/viewtop ... =3&t=10788
Pour moi elle fonctionne très bien.
Ooooh ! tiens ! toi d'ici :mrgreen:

Le problème c'est que j'ai besoin de lire et d'écrire EXIF IPTC et XMP. ça fait quelques années que je travail sur un projet d'une application de remplacement de Picasa... mais je désire aller plus loin... J'expliquerai tout ça plus en detail quand j'aurais quelques choses de prêt a vous montrer
Avatar de l’utilisateur
Thyphoon
Messages : 2697
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: utiliser simplement et efficacement Exiftool

Message par Thyphoon »

Nouvelle version avec quelques améliorations et surtout l'ajout de la commande WaitExecute(ExecuteID.i,TimeOut.i=5000)
qui permet d'attendre que Exiftool soit prêt a donner le résultat
Répondre