Can I add custom XMP fields, including an array with -csv?

Started by colink, May 20, 2018, 08:20:54 AM

Previous topic - Next topic

colink

If I can add custom / user defined fields and data via CSV I do not know how to define the field names.
The bulb has 3 different watts (power consumption), thus 3 different part numbers  (so I have an array)
(in example below all data is written to one image)

Any suggestions on how to construct the CSV would be appreciated.

Here is my desired field names and example data:
XMP:XMP-xmp:base   XMP:XMP-xmp:diameter   XMP:XMP-xmp:watts   XMP:XMP-xmp:part-number
E5                           5mm                                   6                           e5-6
                                                              10                           e5-10
                                                              15                           e5-15

Thanks ColinK




For context here is an image of the bulb being described
https://www.easy-lightbulbs.com/images/lamps/300x300/les688.jpg

Phil Harvey

#1
Hi Colin,

To write these tags you need to create user-defined XMP tags.

You should use a custom XMP namespace instead of a standard one like "xmp".  See the "xxx" namespace in the sample config file for an example of creating custom XMP tags in your own namespace.  Just rename "xxx" to something unique for you.

I would create a structure for the watts/partnumber and use a config file like this (my.config):

%Image::ExifTool::UserDefined = (
    # new XMP namespaces (eg. xxx) must be added to the Main XMP table:
    'Image::ExifTool::XMP::Main' => {
        xxx => { # <-- must be the same as the NAMESPACE prefix
            SubDirectory => {
                TagTable => 'Image::ExifTool::UserDefined::xxx',
                # (see the definition of this table below)
            },
        },
        # add more user-defined XMP namespaces here...
    },
);

# This is a basic example of the definition for a new XMP namespace.
# This table is referenced through a SubDirectory tag definition
# in the %Image::ExifTool::UserDefined definition above.
# The namespace prefix for these tags is 'xxx', which corresponds to
# an ExifTool family 1 group name of 'XMP-xxx'.
%Image::ExifTool::UserDefined::xxx = (
    GROUPS        => { 0 => 'XMP', 1 => 'XMP-xxx', 2 => 'Image' },
    NAMESPACE     => { 'xxx' => 'http://ns.myname.com/xxx/1.0/' },
    WRITABLE      => 'string', # (default to string-type tags)
    Base => { },
    Diameter => { },
    SKU => {
        # the "Struct" entry defines the structure fields
        Struct => {
            # optional structure name (used for warning messages only)
            STRUCT_NAME => 'SKU',
            # structure field definitions (very similar to tag definitions)
            Watts => { Writable => 'integer' },
            PartNumber => { },
        },
        List => 'Bag', # structures may also be elements of a list
    },
);

1;  #end


Then to generate the tags of your example from the command line:

exiftool -config my.config -base=E5 -diameter=5mm -sku="[{watts=6,partnumber=E5-6},{watts=10,partnumber=E5-10},{watts=15,partnumber=E5-15}]" test.xmp

which creates an XMP file like this:

<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 10.70'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

<rdf:Description rdf:about=''
  xmlns:xxx='http://ns.myname.com/xxx/1.0/'>
  <xxx:Base>E5</xxx:Base>
  <xxx:Diameter>5mm</xxx:Diameter>
  <xxx:SKU>
   <rdf:Bag>
    <rdf:li rdf:parseType='Resource'>
     <xxx:PartNumber>E5-6</xxx:PartNumber>
     <xxx:Watts>6</xxx:Watts>
    </rdf:li>
    <rdf:li rdf:parseType='Resource'>
     <xxx:PartNumber>E5-10</xxx:PartNumber>
     <xxx:Watts>10</xxx:Watts>
    </rdf:li>
    <rdf:li rdf:parseType='Resource'>
     <xxx:PartNumber>E5-15</xxx:PartNumber>
     <xxx:Watts>15</xxx:Watts>
    </rdf:li>
   </rdf:Bag>
  </xxx:SKU>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end='w'?>


And this is how to see what the CSV looks like:

% exiftool -config my.config -G1 -csv -xmp-xxx:all test.xmp
SourceFile,XMP-xxx:Base,XMP-xxx:Diameter,XMP-xxx:SKUPartNumber,XMP-xxx:SKUWatts
test.xmp,E5,5mm,"E5-6, E5-10, E5-15","6, 10, 15"


- 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 ($).

colink

Hi Phil

Thanks for your detailed reply. I know this is all very straightforward for experts, but not for me. I know I am missing at least one important (maybe obvious) point here.

I have created the my.config file by replacing xxx with cknamespace (My test namespace)

Ran the command exiftool -config my.config -base=E5 -diameter=5mm -sku="[{watts=6,partnumber=E5-6},{watts=10,partnumber=E5-10},{watts=15,partnumber=E5-15}]" test.xmp

which creates test.xmp similar to your example but with cknamespacw

From here I am confused:
You say
"And this is how to see what the CSV looks like:"

% exiftool -config my.config -G1 -csv -xmp-xxx:all test.xmp
SourceFile,XMP-xxx:Base,XMP-xxx:Diameter,XMP-xxx:SKUPartNumber,XMP-xxx:SKUWatts
test.xmp,E5,5mm,"E5-6, E5-10, E5-15","6, 10, 15"


The top row looks like the command I run at the command line - am I correct?
The middle row looks like the csv field names
The bottom row contains the data for the CSV

But
1. If the last two rows are the CSV, what do I name this CSV and how do I refer to it when I run the command form the top row?
2. nowhere in any file is there a reference to any .jpg file so how do I write to a single .jpg file?
and
How would I write to multiple jpg files as I would do when I use a csv file and multiple image file locations under SourceFile with a command like
exiftool -csv=c:\users\colin\exif-img\online-search\mwg-csv-test.csv  c:\users\colin\exif-img\online-search -use mwg



Phil Harvey

Quote from: colink on May 21, 2018, 12:10:13 PM
The top row looks like the command I run at the command line - am I correct?

Yes.

QuoteThe middle row looks like the csv field names
The bottom row contains the data for the CSV

Together these are the CSV file.  The first row of the CSV file are the tag names.

Quote1. If the last two rows are the CSV, what do I name this CSV and how do I refer to it when I run the command form the top row?

Just try running the command in the top row.  ExifTool will generate the CSV for you.  You can then generate a CSV file in the same format but with different values to import into other files.

Quote2. nowhere in any file is there a reference to any .jpg file so how do I write to a single .jpg file?

The first column of the CSV are the file names, and you must specify the files to process when importing the csv, like this:

exiftool -csv=my.csv test.jpg

QuoteHow would I write to multiple jpg files as I would do when I use a csv file and multiple image file locations under SourceFile with a command like
exiftool -csv=c:\users\colin\exif-img\online-search\mwg-csv-test.csv  c:\users\colin\exif-img\online-search -use mwg

Exactly.  You just need to start from a CSV file with one row for each file in c:\users\colin\exif-img\online-search.

- 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 ($).

colink

Hi Phill

Another error - no surprise, I am sure I ahve missed something or doing something wrong.

All instances of xxx changed to cknamespace

All of the following in the same folder:
exiftool
test.xmp
my.config

Command = % exiftool -config my.config -G1 -csv -xmp-cknamespace:all test.xmp

Error = % is not recognised as an internal or external command.

Any help would be appreciated.

ColinK


Phil Harvey

Hi Colin,

The "%" is the command prompt on my system.  The command is:

exiftool -config my.config -G1 -csv -xmp-cknamespace:all test.xmp

- 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 ($).

colink

Hi Phil

Sorry to hassle you again. That did something - no error. See cmd screenshot

Only thing I changed was xmp filename to test-custom.xmp

You say "ExifTool will generate the CSV for you. "

I expected to find a new csv file in the same folder as the other related files - I do not see one.

Any suggestions or what have I missed?

ColinK


Phil Harvey

The CSV file goes to the console.  Use a command like this to send it to a file (out.csv) in the current directory:

exiftool -config my.config -G1 -csv -xmp-cknamespace:all test.xmp > out.csv

- 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 ($).

colink

Hi Phil

You were too quick for me, I came back to add the screenshot that I forgot to add and you had answered.

=====
I am still missing something:
Here is the CV created from the xmp file (I edited to include full path for source) and renamed out.csv to bulb-write.csv
SourceFile,XMP-cknamespace:Base,XMP-cknamespace:Diameter,XMP-cknamespace:SKUPartNumber,XMP-cknamespace:SKUWatts
c:/users/colin/exif-img/online-search/bulb-write.jpg,E5,5mm,"E5-6, E5-10, E5-15","6, 10, 15"

My command: exiftool -csv=bulb-write.csv bulb-write.jpg

Result:
C:\Users\Colin\exif-img\online-search>exiftool -csv=bulb-write.csv bulb-write.jpg
    0 image files updated
    1 image files unchanged

To double check that I had correct file locations and file names etc. I created the following file that ads MWG:creator as last item:
SourceFile,XMP-cknamespace:Base,XMP-cknamespace:Diameter,XMP-cknamespace:SKUPartNumber,XMP-cknamespace:SKUWatts,MWG:Creator
c:/users/colin/exif-img/online-search/bulb-write-mwg.jpg,E5,5mm,"E5-6, E5-10, E5-15","6, 10, 15",Creator CK

My command: exiftool -csv=bulb-write-mwg.csv bulb-write-mwg.jpg -use mwg

Result:
C:\Users\Colin\exif-img\online-search>exiftool -csv=bulb-write-mwg.csv bulb-write-mwg.jpg -use mwg
    1 image files updated

When I check the file the MWG:creator tags have been update but not the XMP-cknamespace: tags

====
My main confusion here is if the out.csv (renamed bulb-write.csv) "should" write the new tags, why do we need to go through the steps to create an .XMP file first - we could just have created the new csv file with the new namespaces manually added.

So I am assuming the write command needs some reference to the xmp file.

As usual, your advice would be appreciated.

ColinK


Phil Harvey

Quote from: colink on May 24, 2018, 09:29:24 AM
My command: exiftool -csv=bulb-write.csv bulb-write.jpg

You need to load the user-defined and MWG tags if you want to be able to write those tags:

exiftool -config my.config -use mwg -csv=bulb-write.csv bulb-write.jpg

- 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 ($).

colink

Great Phil

Very satisfying to get this working. One small issue which I do not need fixed for this test procedure, but you might want to comment.

XMP-cknamespace:SKUWatts did not write
I noted the code you gave me had watts marked as integer, I removed Integer to make Watts same as PartNumber and it writes OK (but I realise for some data Integer would be good to use)

# Watts => { Writable => 'integer' },  - does not write
Watts => { },                                    - writes OK
PartNumber => { },

======
I would appreciate if you (or someone) could suggest if there is a better way to write the data to show the relationship between Base, Diameter, Watts and PartNumber. I know how I would do it on a relational database.

This is the current result (read from Jeffrey's tool)
Base                           E5
Diameter                   5mm
Sku Part Number   E5-6, E5-10, E5-15
Sku Watts                   6, 10, 15

I am not sure it is clear from this that we are dealing with 3 different bulbs or the relationship between eg 6 & E5-6

In the real world there are bulbs with multiple base sizes, Watts and Part Numbers

Base   Diameter   Watts   PartNumber
E5   5mm           6            E5-6
              10            E5-10
              15            E5-15
E10   10mm   10            E10-10
              15            E10-15
              20            E10-20

Is there a better way to write this data - either with new custom fields or in a format using standard fields (or both), perhaps something like hierarchical keywords?
eg something like:
XMP-mwg-kw:HierarchicalKeywords1
Base: E5; Diameter: 5mm; Watts:6; PartNumber:E5-6,Base: E5; Diameter: 5mm; Watts:10; PartNumber:E5-10
XMP-mwg-kw:HierarchicalKeywords2
Base: E10; Diameter: 10mm; Watts:6; PartNumber:E10-10

Thanks ColinK


Phil Harvey

Quote from: colink on May 25, 2018, 06:44:02 AM
I noted the code you gave me had watts marked as integer, I removed Integer to make Watts same as PartNumber and it writes OK (but I realise for some data Integer would be good to use)

# Watts => { Writable => 'integer' },  - does not write
Watts => { },                                    - writes OK

Ah, right.  Sorry.  I should have added -sep ", " to the command when importing the CSV so that the lists got split back into individual items.  Without this, the string "6, 10, 15" (which isn't an integer) is written instead of separate items "6", "10" and "15".

QuoteI would appreciate if you (or someone) could suggest if there is a better way to write the data to show the relationship between Base, Diameter, Watts and PartNumber.

I can't think of a better way to write this.  Structured information is somewhat tricky, but is best handled as a structure (the way I wrote it in my first example).  To read back as a structure, you do this:

% exiftool test.xmp -xmp:all -struct
XMP Toolkit                     : Image::ExifTool 10.99
Base                            : E5
Diameter                        : 5mm
Sku                             : [{PartNumber=E5-6,Watts=6},{PartNumber=E5-10,Watts=10},{PartNumber=E5-15,Watts=15}]


- 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 ($).

colink

Thanks Phil

That works exactly as your suggestion. I should have thought about -sep as I had read about using it to prevent individual data elements writing as strings

I may well come back top this when I try to implement a more complex version of this, but thanks again for your great help in learning how to create add structured data with custom xmp tags.

ColinK