Name

JpegRDF — Manipulate RDF in JPEG images

Synopsis

This page documents JpegRDF version 1.1.

In general terms, the arguments to JpegRDF consist of a set of options, a set of commands, and a set of JPEG files. Some combinations of options and commands are mutually exclusive. Most options and commands have both a short form and a long form; only the long form is shown in the synopis, but both forms are shown in the summaries.

To get a brief summary of the command line options:

com.nwalsh.jpegrdf.JpegRDF -h

To query the RDF in a JPEG file:

com.nwalsh.jpegrdf.JpegRDF [-c rdffile...] [-v...] [-a] [-s] [-e encoding]
[-ns prefix uri...]
{[-qr qname uri] | [-ql qname literal] | [-q qname]...}
[--] {filename.jpg...}

To update the RDF in a JPEG file:

com.nwalsh.jpegrdf.JpegRDF [-c rdffile...] [-v...] [-s] [-e encoding] [-rdf rdffile] [ -exif | -update ]
[-ns prefix uri...]
{[-ar qname uri] | [-al qname literal] | [-dr qname uri] | [-dl qname literal] | [-d qname]...}
[--] {filename.jpg...}

Options

-a, -and

Indicates that multiple queries should be “anded” together. By default, a file matches multiple queries if it satisfies any of them. With this option, a file matches multiple queries only if it satisfies all of them.

-c rdffile, -config rdffile

Loads a configuration file. The configuration files are in RDF. If multiple configuration files are loaded, they are combined.

-encoding encoding, -e encoding

Loads rdffiles with the specified encoding. This applies to files loaded by the -rdf and -config options.

RDF in the JPEG files is always stored in ISO-8859-1. This is compatible with Rdfpic.

-exif

Converts EXIF data in the JPEG file to RDF. This option has no effect if the RDF already contains properties from the “exif:” namespace. This is mutually exclusive with the -update option.

-h, -help

Displays a brief summary of the command.

-rdf rdffile

Places the RDF in rdffile in each of the JPEG files specified.

-s, -show

Show the RDF from the JPEG files. When querying, the default behavior is to display the list of files that satisfy the query.

-update

This option updates the intrinsic EXIF properties in the RDF. For example, if you rotate an image (save and restore the RDF when you do as the rotation probably won't preserve the JPEG comment), the height and width in the RDF will be wrong. Running JpegRDF with the -update option will fix that error. This is mutually exclusive with the -exif option.

By the way, I recommend jpegtran for doing the rotation as it preserves the fidelity of the image.

-v, -verbose

Makes the program more verbose. Specifying this option more than once makes the program progressively more verbose.

Commands

-al qname literal, -add-literal qname literal

Adds the RDF property qname with a literal value of literal to the JPEG file(s).

-ar qname uri, -add-resource qname uri

Adds the RDF property qname with a resource value of uri to the JPEG file(s).

-d qname, -delete qname

Deletes the RDF property qname from the JPEG file(s), regardless of its value. If the property occurs multiple times, all instances are deleted.

If the qname consists of only a prefix (e.g., “exif:”), all properties in that namespace are deleted.

-dl qname literal, -delete-literal qname literal

Deletes the RDF property qname with the literal value of literal from the JPEG file(s).

-dr qname uri, -delete-resource qname uri

Deletes the RDF property qname with the resource value of uri from the JPEG file(s).

-ns prefix uri, -namespace prefix uri

Associates the prefix with the uri for QNames specified on the command line.

-q qname, -query qname

Queries the JPEG file(s) for the RDF property qname. The query is satisfied if the property exists, regardless of its value.

If the qname consists of only a prefix (e.g., “exif:”), the query is satisfied if any property in that namespace exists.

-ql qname literal, -query-literal qname literal

Queries the JPEG file(s) for the RDF property qname. The query is satisfied if the property exists and has the literal value literal.

-qr qname uri, -query-resource qname uri

Queries the JPEG file(s) for the RDF property qname. The query is satisfied if the property exists and has the resource value uri.

--

Separates commands from files. If you have JPEG files whose names begin with “-”, use this option to disable JpegRDFs processing of options and commands.

Description

The JpegRDF command reads and manipulates RDF metadata stored in the comment section of JPEG images. It can extract, query, and augment the data. Manipulating JPEG images with JpegRDF does not modify the actual image data or any other sections of the file.

You can use JpegRDF to associate arbitrary properties with an image. Properties can be either literal values or resources (identified by URI).

A sample image is provided in the extras directory.

For the moment, JpegRDF includes a modified version of the org.w3c.tools.jpeg package. You may have troubles if that package exits elsewhere on your classpath. I'm going to look into getting my changes merged into the W3C library.

EXIF Metadata

Many digital cameras store metadata about the image in a special section of the JPEG file called “EXIF”. This data often includes information about the make and model of camera, exposure details, and camera settings.

In order to make this information accessible for processing with other metadata, JpegRDF can automatically convert it to RDF.

When JpegRDF stores EXIF data, it can store five related properties that are intrinsic to the image. (In other words, they are not strictly EXIF data, but they are equally useful.) Those properties are the actual image dimensions, the compression algorithm used, the number of bits per pixel, and the number of color components (is the picture color or black and white).

String values in the EXIF data can contain values that are not allowed in XML or that might not be valid in the RDF's encoding. To avoid these problems, JpegRDF uses URI-style percent-encoding for characters that are not in the ASCII range.

The namespace “http://nwalsh.com/rdf/exif#” is used for storing EXIF properties.

Loading and Storing Metadata

Metadata in the JPEG file is identifed with rdf:about='' because the data is about the file that contains it (the empty URI means the current document). When this data is shown (with -s), the URI for the image (as it was identified on the command line) is used. So, if you say JpegRDF -s extras/sample.jpg, the RDF will be identify the resource as rdf:about='extras/sample.jpg'. Note, in particular, that a relative pathname will become a relative URI.

When RDF is loaded (with -rdf), JpegRDF has to associate the metadata in the RDF model with each filename. It relies on the following heuristics:

  • If the model contains a resource with a URI equal to the filename, that resource is used. The URI and the filename must match exactly, so it's important to use the same paths (absolute or relative) in the update operation that you used in the query operation.

  • If the model contains exactly one resource and that resource has a URI of '', that resource is used. Note that this means the same RDF will be applied to each image if you specify multiple JPEG files in this case.

  • If the model contains exactly one resource and that resource has a URI which is neither empty nor the same as the JPEG filename, that resource is used, but a warning is generated.

  • If the model contains more than one resource, and no resource matches the filename, no RDF is added to the JPEG.

Installation

Before running JpegRDF, you must have a working Java virtual machine (v1.3.1 or later). You must also install an XML parser, such as the one provided by Sun's JAXP, and HP Lab's Jena toolkit.

Make sure that the XML parser, Jena libraries, and jpegrdf.jar appear on your CLASSPATH.

After you have satisfied the prerequisites, running JpegRDF should be a simple matter of invoking it with Java:

java com.nwalsh.jpegrdf.JpegRDF [options] [commands] [file.jpg...]

Configuration

The namespaces available by default, the names of EXIF properties, and the names of intrinsic properties are read from a configuration file. For convenience (mine, in particular :-), but perhaps also yours) the configuration file is in RDF. A sample is included in the extras directory of the distribution.

You can specify configuration files with the -c option. If multiple configuration files are specified, they are merged. If none are specified, JpegRDF reads configuration information from .jpegrdf.rdf in the home directory of the user running the program.

In the configuration data, JpegRDF looks for its configuration information as properties of the “http://nwalsh.com/rdf/configuration#jpegrdf resource.

The following properties are recognized:

Namespace Properties

Namespace properties are themselves in the “http://nwalsh.com/rdf/jpegrdf/ns#” namespace.

prefix

Every property in this namespace associates a prefix with a namespace URI for use on the command line. For example, the following property associates the “foo” prefix with the URI “http://example.org/properties#foo”:

<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
         xmlns:ns='http://nwalsh.com/rdf/jpegrdf/ns#'>

  <rdf:Description rdf:about="http://nwalsh.com/rdf/configuration#jpegrdf">
    <ns:foo>http://example.org/properties#foo</ns:foo>
  </rdf:Description>
</rdf:RDF>

EXIF Properties

EXIF properties are in the “http://nwalsh.com/rdf/jpegrdf/exif#” namespace.

name

Every property in this namespace associates a name with the tag number of an EXIF entry. Tag numbers can be expressed in decimal, or in hexidecimal if they begin with “0x”.

For example, the following property associates the EXIF tag number “0x132” with the name “datetime”.

This has the practical result of storing the value of the EXIF tag 0x132 in the RDF associated with the image using the property name “datetime” in the namespace used for EXIF properties.

<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
         xmlns:exif='http://nwalsh.com/rdf/jpegrdf/exif#'>

  <rdf:Description rdf:about="http://nwalsh.com/rdf/configuration#jpegrdf">
    <exif:datetime>0x132</exif:datetime>
  </rdf:Description>
</rdf:RDF>

Note that the namespace of EXIF properties in the image and the namespace used to identify their names are not the same.

EXIF Intrinsic Properties

EXIF intrinsic properties are in the “http://nwalsh.com/rdf/jpegrdf/exif/intrinsic#” namespace.

height

Identifies the name of the property that will be used to store the intrinsic height of the image in the RDF. This property will be in the EXIF namespace. For example, the following example would cause the intrinsic hieght to be stored in the property “vsize”:

<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
         xmlns:exifi='http://nwalsh.com/rdf/jpegrdf/exif/intrinsic#'>

  <rdf:Description rdf:about="http://nwalsh.com/rdf/configuration#jpegrdf">
    <exifi:height>vsize</exifi:height>
  </rdf:Description>
</rdf:RDF>
width

Identifies the name of the property that will be used to store the intrinsic width of the image in the RDF.

compression

Identifies the name of the property that will be used to store the compression method of the image in the RDF.

bitsPP

Identifies the name of the property that will be used to store the number of bits per pixel of the image in the RDF.

numCC

Identifies the name of the property that will be used to store the number of color components of the image in the RDF.

EXIF Decoders

EXIF decoders are Java classes that implement the org.w3c.tools.jpeg.TagDecoder interface. They can be used to decode EXIF fields that are identified as “undefined” in the actual EXIF data. For example, the MakerNote field often contains additional information encoded in a proprietary way. If you write a class that can decode the MakerNote field data encoded by your camera, you can tell JpegRDF to use it.

EXIF decoders are identified with the “http://nwalsh.com/rdf/jpegrdf/exif/decoder#” namespace.

decoder

Identifies the class that will be used to decode the named field. For example, the following example identifies com.nwalsh.jpegrdf.Nikon950Decoder as the class to use to decode the MakerNote field:

<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
         xmlns:exif='http://nwalsh.com/rdf/jpegrdf/exif#'
         xmlns:exifi='http://nwalsh.com/rdf/jpegrdf/exif/intrinsic#'>

  <rdf:Description rdf:about="http://nwalsh.com/rdf/configuration#jpegrdf">
    <exif:MakerNote>0x927c</exif:MakerNote>
    <exifd:MakerNote>com.nwalsh.jpegrdf.Nikon950Decoder</exifd:MakerNote>
  </rdf:Description>
</rdf:RDF>

Examples

Add the dc:subject property with the literal value “landscape” to all the JPEG files in the current directory:

JpegRDF -al dc:subject landscape *.jpg

Add the dc:coverage property with the resource value “http://example.org/countries#england” to stonehenge.jpg:

JpegRDF -ar dc:coverage 'http://example.org/countries/#england' stonehenge.jpg

Delete the dc:rights properties with the literal value “Norman Walsh” from all the JPEG files in the current directory:

JpegRDF -dl dc:rights 'Norman Walsh' *.jpg

Delete all the dc:rights properties, regardless of their value:

JpegRDF -d dc:rights *.jpg

Delete all the properties in the “http://example.org/dummy#” namespace, regardless of their value:

JpegRDF -ns foo "http://example.org/dummy#" -d foo: *.jpg

Report the images that contain either a dc:subject of “pasture” or a dc:subject of “seascape”:

JpegRDF -ql dc:subject pasture -ql dc:subject seascape *.jpg

Report the images that contain both a dc:subject of “pastureand a dc:creator of “http://nwalsh.com/rdf/people#norman-walsh”:

JpegRDF -a -ql dc:subject pasture -qr dc:creator "http://nwalsh.com/rdf/people#norman-walsh" *.jpg

Extract the EXIF information from the images in the current directory and store it in the JPEG files as RDF:

JpegRDF -exif *.jpg

Extract the RDF information from all the files in the current directory and store it in an RDF/XML document:

JpegRDF -s *.jpg > images.rdf

Store the RDF information from images.rdf into the files in the current directory:

JpegRDF -rdf images.rdf *.jpg

Author

Norman Walsh () maintains JpegRDF.

Copyright

Copyright © 2003 Norman Walsh. Portions copyright © 1994-2001 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. For full details, see COPYRIGHT in the distribution.

Credits

This program was inspired by the Rdfpic application. I hacked the W3C JPEG library to support decoding JPEG EXIF data. I relied on the source code for jhead to figure out how EXIF data is encoded. I couldn't (well, I wouldn't, anyway) have written it without the Jena repository.

jena

HP Labs, Jena Semantic WebToolkit.

jhead

Matthias Wandel, Jhead.

Rdfpic

Yves Lafon and Bert Bos, Rdfpic.

Bugs

Instead of percent-encoding non-ASCII characters in EXIF strings, I should probably only escape those characters that are not valid in the ISO-8859-1 encoding.