This repository contains examples for processing image metadata using Java. Currently, the following module is available:
-
image-metadata-commons-imaging
This Spring Boot 3 application will allow you to upload images (JPG, PNG, GIF) and the application will extract the metadata from those files using Apache Commons Imaging. This includes:
-
EXIF (Exchangeable image file format)
-
IPTC (International Press Telecommunications Council)
-
XMP (eXtensible Metadata Platform)
-
Generic file metadata
To learn more about the alphabet soup, see my blog post: Read & Write Image Metadata with Java — Part 1 This demo application also provides the following additional features:
-
Remove all image metadata
-
Populate image metadata such as image title and reference id
-
Ability to resize images
-
Slightly sharpen resized images using a Gaussian Unsharp Mask
-
Add a font label to resized images
-
Ability to load images using ImageIO or AWT Toolkit (To study performance differences)
-
Ability to download the stored image
Note
|
Image metadata is manipulated during file upload. Any other manipulation such as resizing is done during image retrieval. This is purely a demo app and not meant to be production ready. |
The main input field (and only mandatory input field) is the file upload option. You can select any image of the following type to extract metadata from:
-
JPG
-
PNG
-
GIF
The title input field, will populate
-
the XMP
Title
tag of the Dublin Core namespace. -
the IPTC
Object Name
field -
the EXIF
Image Description
Field
In case you also selected the Remove Metadata
checkbox, we will also populate the XPTitle
EXIF tag.
Populates the IPTC field OriginalTransmissionReference
as well as the XMP tag TransmissionReference
. These two fields
are commonly used as a job identifier. So if you need to tie your images to e.g. a database record, this might be a useful
field to know about. For more information, please also see the following links for more information:
The following tags are the Windows-specific exif tags:
-
XPTitle (Populated by EXIF tag ImageDescription)
-
XPComment
-
XPAuthor (Populated by EXIF tag Artist)
-
XPKeywords
-
XPSubject
-
Rating
-
RatingPercent
If the checkbox is selected AND the Caption/Title input field is populated, we will populate the xptitle
tag.
Please also see the EXIF tag documentation at https://exiftool.org/TagNames/EXIF.html.
-
Git to clone the repository
For the native compilation support, you will need a GraalVM based implementation of Java. As this application uses AWT classes, Bellsoft’s Liberica Native Image Kit (NIK) is currently (as of Oct 24, 2023) the best implementation. The following version was used for testing:
Note
|
Oracle GraalVM does not work on MacOS, yet. You will encounter a If you try, you will see an exception like the following: 2023-02-12T09:38:34.721-10:00 ERROR 65901 --- [nio-8080-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed: java.lang.UnsatisfiedLinkError: no awt in java.library.path] with root cause
java.lang.UnsatisfiedLinkError: no awt in java.library.path
... |
Tip
|
Use SDKMAN! to install GraalVM. |
Check out the project using Git:
git clone https://github.com/ghillert/image-metadata.git
cd image-metadata
java -jar ./image-metadata-commons-imaging/target/image-metadata-commons-imaging-1.0.0-SNAPSHOT.jar
Open your browser and go to http://localhost:8080/
Native compilation has been a bit of a moving target when using AWT classes. Luckily, the situation is continuously improving. For instance, until recently the story on Windows was a bit more involved, requiring to compile the project using the x64 Native Tools Command Prompt for VS 2022 (See the following blog post for more information.)
Luckily as of GraalVM for JDK 17.0.8 the situation on Windows is much improved - See the following blog post for details.
IMPORTANT
When using AWT and ImageIO classes etc. the native GraalVM Native Image metadata seems to be specific to the relevant platform.
Therefore, you may need to rename the respective folder under
image-metadata-commons-imaging/src/main/resource/META-INF
to native-image
. I provide the following folders:
-
native-image-linux
-
native-image-mac
-
native-image-windows
Alternatively, you can run the native-image-agent as described under Development below.
Creating a local image should be as easy as:
./mvnw clean package -DnativeCompile
This shorthand system property will activate the Maven profiles:
-
native
-
nativeCompile
So you can also use:
./mvnw clean package -Pnative,nativeCompile
The result (if successful) will be an executable binary at: image-metadata-commons-imaging/target/image-metadata-commons-imaging
Tip
|
You can use Ultimate Packer for eXecutables (UPX) to further compress the binary. E.g.
upx -9 image-metadata-commons-imaging/target/image-metadata-commons-imaging
|
Note
|
UPX is currently broken on MacOS 13. See the relevant GitHub issue ticket for details. |
As the application uses some AWT classes for image processing, the native version for macOS will not run using Oracle GraalVM. There is an open GitHub issue at the GraalVM project.
However, compilation will succeed and the application will run when using Liberica Native Image Kit (NIK).
./image-metadata-commons-imaging/target/image-metadata-commons-imaging
On Windows (With the latest version of GraalVM), things got super-easy, just compile and run:
image-metadata-commons-imaging/target/image-metadata-commons-imaging.exe
Once compiled you need to provide the java.home
to the executable. This is needed to load the font sub-system. However,
the contents of java.home
just needs one file fontconfig.properties
with the contents:
version=1
sequence.allfonts=default
Note
|
This was previously for the Windows executable as well but seems to work now without. So maybe this may not be needed eventually. For more information see: |
For simplicity, the project provides a fontconfig.properties
file. Therefore, once the binary is created, launch the
application using:
./image-metadata-commons-imaging/target/image-metadata-commons-imaging \
-Djava.home=iage-metadata-commons-imaging/src/lib/
Note
|
You may also need to install apt install gcc zlib1g-dev build-essential libfreetype6-dev See also: graalvm/mandrel#189 |
image-metadata-commons-imaging uses fonts, which on Linux requires fontconfig
to be installed. That’s why I use
paketobuildpacks/builder:full
and not the default paketobuildpacks/builder:tiny
.
Important
|
Please make sure your Docker daemon is running. |
./mvnw -Pnative spring-boot:build-image -pl :image-metadata-commons-imaging
docker run --rm -p 8080:8080 docker.io/library/image-metadata-commons-imaging:1.0.0-SNAPSHOT
When adding functionality, it may be necessary to run the native-image-agent. First build the jar with the
native
Maven profile:
./mvnw clean package -Pnative
java -Dspring.aot.enabled=true \
-agentlib:native-image-agent=config-output-dir=image-metadata-commons-imaging/src/main/resources/META-INF/native-image \
-jar image-metadata-commons-imaging/target/image-metadata-commons-imaging-1.0.0-SNAPSHOT.jar
Image Metadata is licensed under the Apache License (ASL), Version 2.0.