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
Titletag of the Dublin Core namespace. -
the IPTC
Object Namefield -
the EXIF
Image DescriptionField
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-metadatajava -jar ./image-metadata-commons-imaging/target/image-metadata-commons-imaging-1.0.0-SNAPSHOT.jarOpen 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 -DnativeCompileThis shorthand system property will activate the Maven profiles:
-
native
-
nativeCompile
So you can also use:
./mvnw clean package -Pnative,nativeCompileThe 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-imagingOn Windows (With the latest version of GraalVM), things got super-easy, just compile and run:
image-metadata-commons-imaging/target/image-metadata-commons-imaging.exeOnce 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-devSee 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-SNAPSHOTWhen adding functionality, it may be necessary to run the native-image-agent. First build the jar with the
native Maven profile:
./mvnw clean package -Pnativejava -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.jarImage Metadata is licensed under the Apache License (ASL), Version 2.0.