Main Menu

.NET "wrapper" dll

Started by brain2cpu, September 13, 2013, 08:27:20 AM

Previous topic - Next topic

brain2cpu

Hi all,
I'd like to add my little contribution to this wonderful project, so here comes ExiftoolWrapper, a .NET dll with source code (C#), to bring a step closer exiftool to .NET developers.
The main goal was to use the "-stay_open" flag in the most transparent way. 
The simplest usage example would be:


#using BBCSharp;

using(ExifToolWrapper extw = new ExifToolWrapper())
{
    extw.Start();
    Dictionary<string, string> d = extw.FetchExifFrom(@"d:\Temp\D800-DSC_8059.NEF");
}


The dictionary above will contain all data exfitool can extract. The Start method loads exiftool(-k).exe (must be in your application's startup folder in case of the parameterless constructor), Dispose will stop it. Start needs some time, so this approach is advised when you need to extract exif from multiple files.
Binary and source code are free to use in any way you like (though I'll appreciate an email just to let me know).

After download please replace the empty exiftool(-k).exe files in the archive with the real one, posting the full zip (around 7MB) fails.

PH Edit: See this post for the most recent version of the wrapper.

Phil Harvey

Nice!  I have added a link from the ExifTool home page.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

rajesh

I have to updated exif keywords but not able to update IPTC keywords using C#.
Please let me know to can get Exif keyword's value and add to IPTC keywords?

thanks

iaremrsir

Hello, I've tried using your wrapper with success in reading metadata, but I'd like to be able to write metadata as well, which I'm having a hard time with. I've easily used your FetchExifFrom function. But now I'm trying to write metadata using the SendCommand function and it does nothing when I send strings to it.

Here's what my code block looks like now. Reading works fine, but I just can't write anything. My goal is to edit 3 tags of all DNG files in a directory. Any advice?

using (ExifToolWrapper exiftool = new ExifToolWrapper())
{
  exiftool.Start();
  foreach (string dir in workingDir)
  {
    // Get first DNG to check for ISO 100
    string[] dng = System.IO.Directory.GetFiles(dir, "*.dng");
    if (dng.Length == 0) continue;

    Dictionary<string, string> exif = exiftool.FetchExifFrom(dng[0]);

    // Build EXIF write command
    string command = "\n-Exif:BaselineExposure=2.4 " + dir + "\\*.dng\n-Exif:CalibrationIlluminant1=\"Standard Light A\" " + dir + "\\*.dng\n-Exif:CalibrationIlluminant2=\"D65\" " + dir + "\\*.dng\n";
    if (100 == Convert.ToInt32(exif["Exposure Index"]))
      command += "-Exif:WhiteLevel=3660 " + dir + "\\*.dng\n-stay_open\nFalse\n";

    exiftool.SendCommand(command);
  }
}

Phil Harvey

I have no idea what you are trying to do, and I don't know how the DLL API works, but you are not being consistent in the arguments you are sending exiftool.  Either the API takes arguments from a -argfile intput separated by newlines (likely), or as a command line separated by spaces.  You have done both.  I suspect that the code should look more like this (but I am just guessing):

    string command = dir + "\\*.dng\n-Exif:BaselineExposure=2.4\n-Exif:CalibrationIlluminant1=\"Standard Light A\"\n-Exif:CalibrationIlluminant2=\"D65\"\n";
    if (100 == Convert.ToInt32(exif["Exposure Index"]))
      command += "-Exif:WhiteLevel=3660\n";

    exiftool.SendCommand(command);


Also, I'm not sure why you were doing -stay_open False, and why this was only if the exposure index was 100, but I have removed this.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

iaremrsir

Quote from: Phil Harvey on December 21, 2014, 09:45:21 AM
I have no idea what you are trying to do, and I don't know how the DLL API works, but you are not being consistent in the arguments you are sending exiftool.  Either the API takes arguments from a -argfile intput separated by newlines (likely), or as a command line separated by spaces.  You have done both.  I suspect that the code should look more like this (but I am just guessing):

    string command = dir + "\\*.dng\n-Exif:BaselineExposure=2.4\n-Exif:CalibrationIlluminant1=\"Standard Light A\"\n-Exif:CalibrationIlluminant2=\"D65\"\n";
    if (100 == Convert.ToInt32(exif["Exposure Index"]))
      command += "-Exif:WhiteLevel=3660\n";

    exiftool.SendCommand(command);


Also, I'm not sure why you were doing -stay_open False, and why this was only if the exposure index was 100, but I have removed this.

- Phil

I'm trying to add metadata to a directory of Cinema DNG files, but I haven't been able to write a string to send to the wrapper that actually does anything. So thanks for the suggestion, I'll try it to see how it works.

iaremrsir

Okay so the string you gave me worked for a single command. The string only added -Exif:BaselineExposure, and it ignored the rest of the commands. So I think I'll have to split the command calling into loop of some sort. Anyway that fixed the problem of writing metadata, but now I have a new problem. Writing to the DNG files caused exiftool to automatically create a .dng_original file for each dng. I read the documentation and remember seeing the command line argument -overwrite_original. Would I want to add this to the command I send to stay open or could I just add it to the argument list that starts the exiftool process?

iaremrsir

Okay, so adding -overwrite_original to the arguments list of the wrapper worked. But splitting the string that Phil suggested into singular commands didn't work. I'm going to fiddle around some more and update if I figure something out. Thanks for the help.

brain2cpu

#8
I'd like to post ExiftoolWrapper v2; main changes: direct get/set for orientation, get creation date as DateTime, the SetExifInto method, thread-safe communication with the exiftool process; you can find more in the attached source code.

PH Edit: See this post for the most recent version of the wrapper.

CodeWorks

SetExifInto isn't working.   What am i doing wrong?    The code executes with no errors but the metadata doesn't update.

            using (ExifToolWrapper extw = new ExifToolWrapper())
            {
                // Start ExifTool
                extw.Start();
                // Get Metadata
                Dictionary<string, string> d = extw.FetchExifFrom(Application.StartupPath + "/photos/SAI01.jpg");
                // Remove existing Lens Model
                d.Remove("Lens Model");
                // Add new Lens Model
                d.Add("Lens Model", "lens1234");
                //Write new Metadata
                extw.SetExifInto(Application.StartupPath + "/photos/SAI01.jpg", d, true);
            }

Thanks

Phil Harvey

I'm no expert on this interface, but I would guess that it should use tag names, in which case you should use "LensModel" and not "Lens Model" (ie. remove the space).  If this is the problem, reading ExifTool FAQ 2 may help in determining the appropriate tag names to use.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

brain2cpu

Quote from: CodeWorks on May 22, 2015, 04:46:47 PM
Dictionary<string, string> d = extw.FetchExifFrom(Application.StartupPath + "/photos/SAI01.jpg");
.........
d.Add("Lens Model", "lens1234");
extw.SetExifInto(Application.StartupPath + "/photos/SAI01.jpg", d, true);
You can see existing tags as keys of dictionary d, you should check if you really have "Lens Model". Arbitrary keys and values can not be set as exif tags!
SetExifInto returns true if succeeded, please check returned value.
If you want to modify a single key the
SetExifInto(string path, string key, string val, bool overwriteOriginal = true)
method should be used, the override above will try to overwrite all tags with existing values.

CodeWorks

Thanks Phil and brain2cpu.   Removing the space between "Lens Model" worked.

I put a space in it because all the existing tags as Keys (such as "Lens Model") in dictionary d have a space.   Weird.  Perhaps FetchExifFrom isn't using the exact spelling of the Tag name for the Key name.

Thanks again


SarahC

brain2cpu, could you spare half an hour to help me work through this hanging problem I've got?   :)

I'm using your wonderful wrapper with my cataloging system - but I've got a hanging problem I've not been able to trace.

Would you be able to give me some pointers about what may be happening?

Thank you so much!   :D


https://exiftool.org/forum/index.php/topic,6524.0.html


(I've just noticed you've released a V2 of it - I've not had a chance to try that one.)

brain2cpu

SarahC, I just downloaded your source code and noticed you converted the C# code to vb, did you tried using the dll instead? I'm using it in my mp3Manager without problems.