Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .project
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,15 @@
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures>
<filteredResources>
<filter>
<id>1769460831746</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
95 changes: 69 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,91 @@
# ImageOptimization - Library for losslessly optimizing images #

Copyright (c) 2016, Salesforce.com. All rights reserved.
Copyright (c) 2026, Salesforce.com. All rights reserved.

Created by <span itemscope="" itemtype="http://schema.org/Person">
<a itemprop="url" rel="author" href="https://github.com/eperret"><span itemprop="name">Eric Perret</span></a>
</span>
Created by [Eric Perret](https://www.ericperret.org)

## Summary ##

ImageOptimization is a JAVA batch program / service used to optimize images by reducing the size (less bytes) of images without changing the quality of the images. This process is called [lossless compression](http://en.wikipedia.org/wiki/Image_compression#Lossy_and_lossless_compression).
ImageOptimization is a JAVA batch program / service used to optimize images by reducing the size (less bytes) of images without changing the quality of the images. This process is called [lossless compression](https://en.wikipedia.org/wiki/Image_compression#Lossy_and_lossless_image_compression).

Apart from optimizing an image, it also supports a few other things

* Converting image types, GIFs to PNGs, if it will make the image smaller.
* Create a Chrome (browser) specific version, [WebP](https://developers.google.com/speed/webp/?csw=1)
* Automated validation of images.

## Installation ##
## Getting Started ##

## 🚀 Quick Install & Setup ##

We provide a helper script to automate the installation of the Java application and all required binary dependencies (including `pngout`, `optipng`, `jpegtran`, etc.).

### Installation ###

Run the management script located in the `script/` directory. This script detects your OS (Linux/Mac), installs system tools via `apt` or `brew`, builds the project, and configures the `image-optimizer` command.

```bash
# 1. Give execution permission to the script
chmod +x script/install.sh

# 2. Run the installer
./script/install.sh
```

This will install the application for the current user so it can be called from anywhere using the following command.

```bash
image-optimizer path/to/image.png path/to/folder/of/images/
```

### Uninstallation ###

To remove the application and all installed files, run:

```bash
./script/install.sh uninstall
```

This will remove:

* The `image-optimizer` wrapper script from `~/.local/bin/`
* The entire installation directory at `~/.local/share/ImageOptimization/`

Note: This does not remove system packages (like Maven, ImageMagick, etc.) that were installed via package managers (apt/brew). Those must be removed manually if desired.

## Full Install & Setup ##

### Prerequisites ###

* Some version of **Git**
* If you are on the Mac, you should already have the command line version of git installed.
* For other OSs or for the GUI version, they can be downloaded [here](http://git-scm.com/downloads).
* For other OSs or for the GUI version, [download Git from git-scm.com](https://git-scm.com/install/).
* **JDK 8**
* [download it from Oracle](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
* **[Apache Maven](http://maven.apache.org/download.cgi) 3.3** or later
* [Download JDK 17 from Oracle](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) or later
* **[Apache Maven](https://maven.apache.org/download.cgi) 3.3** or later

A few binaries needed by the code have to be installed on the OS.

_Note: This only works on Linux and has only been tested on Ubuntu. There are a number of non-java binaries that are required for this project and I have only tried compiling them for for Linux, specifically Ubuntu._
_Note: This only works on Linux (only been tested on Ubuntu) and Mac. There are a number of non-java binaries that are required for this project and I have only tried compiling them for for Linux, specifically Ubuntu, and Mac._

* [ImageMagick](https://www.imagemagick.org/script/binary-releases.php) needs to be installed on the system (used for converting images because JAVA cannot handle certain file types).
* The following binaries need to be compiled into the root of the project in the `<PROJECT_DIRECTORY>/lib/binary/linux` directory.
* advpng ([source](https://github.com/amadvance/advancecomp/), [homepage](http://advancemame.sourceforge.net/doc-advpng.html))
* gifsicle ([source](https://www.lcdf.org/gifsicle/gifsicle-1.88.tar.gz), [homepage](https://www.lcdf.org/gifsicle/))
* jfifremove ([source](https://lyncd.com/files/imgopt/jfifremove.c))
* jpegtran ([source](http://www.ijg.org/files/jpegsrc.v9b.tar.gz), [homepage](http://jpegclub.org/jpegtran/))
* optipng ([source](http://prdownloads.sourceforge.net/optipng/optipng-0.7.5.tar.gz?download), [homepage](http://optipng.sourceforge.net/))
* pngout ([source](http://www.jonof.id.au/kenutils), [homepage](http://advsys.net/ken/utils.htm))
* advpng ([source](https://github.com/amadvance/advancecomp/), [homepage](https://www.advancemame.it/doc-advpng.html))
* gifsicle ([source](https://github.com/kohler/gifsicle), [homepage](https://www.lcdf.org/gifsicle/))
* jfifremove ([source](https://github.com/x2q/imgopt/blob/master/jfifremove.c))
* jpegtran ([source](https://www.ijg.org/files/), [homepage](https://jpegclub.org/jpegtran/))
* optipng ([source](https://prdownloads.sourceforge.net/optipng/optipng-7.9.1.tar.gz?download), [homepage](https://optipng.sourceforge.net/))
* pngout ([source](https://www.jonof.id.au/kenutils.html), [homepage](https://www.jonof.id.au/kenutils.html))
* cwebp ([source](https://storage.googleapis.com/downloads.webmproject.org/releases/webp/index.html), [homepage](https://developers.google.com/speed/webp/docs/cwebp))
* gif2webp ([source](https://storage.googleapis.com/downloads.webmproject.org/releases/webp/index.html), [homepage](https://developers.google.com/speed/webp/docs/gif2webp))
* pngquant ([source](https://github.com/pornel/pngquant), [homepage](https://pngquant.org/))

* pngquant ([source](https://github.com/kornelski/pngquant), [homepage](https://pngquant.org/))

### Additional Maven set up ###

Maven uses the JDK pointed to be the `JAVA_HOME` environment variable. Verify that Maven is using JDK 8, for example:
Maven uses the JDK pointed to be the `JAVA_HOME` environment variable. Verify that Maven is using JDK 17+, for example:
Maven 3.3.3+ is recommended.

```
```bash
$ mvn --version

Apache Maven 3.3.3 (r01de14724cdef164cd33c7c8c2fe155faf9602da; 2013-02-19 05:51:28-0800)
Expand All @@ -64,19 +102,24 @@ There are 2 ways that the library can be used:

Calling the main method from the commandline with a list of files or folders.

java -jar ImageOptimization-1.2.jar -DbinariesDirectory=<PATH_TO_BINARIES_DIRECTORY> path/to/image.png path/to/folder/of/images/
```bash
java -jar ImageOptimization-1.2.jar -DbinariesDirectory=<PATH_TO_BINARIES_DIRECTORY> path/to/image.png path/to/folder/of/images/
```

The `<PATH_TO_BINARIES_DIRECTORY>` is the path where the binaries exist that are used to optimize the images. By default the code will look for the binaries in the `./lib/binary/linux/` directory

You can also call this code programmatically from existing JAVA code by using the API, `com.salesforce.perfeng.uiperf.imageoptimization.service.ImageOptimizationService.optimizeAllImages(FileTypeConversion, boolean, Collection<File>)`.

Example:

final IImageOptimizationService<Void> service = new ImageOptimizationService.createInstance(<PATH_TO_BINARIES_DIRECTORY>);
final List<OptimizationResult<Void>> list = service.optimizeAllImages(FileTypeConversion.NONE, false, new File("path/to/image.jpg"), File("path/to/image2.jpg"));
System.out.println(list);
```java
final IImageOptimizationService<Void> service = new ImageOptimizationService.createInstance(<PATH_TO_BINARIES_DIRECTORY>);
final List<OptimizationResult<Void>> list = service.optimizeAllImages(FileTypeConversion.NONE, false, new File("path/to/image.jpg"), File("path/to/image2.jpg"));
System.out.println(list);
```

The main API is `ImageOptimizationService.optimizeAllImages`.

* The 1st argument indicates if / how the image should be converted. There are currently 3 types of conversion. `FileTypeConversion.NONE`: None of the images will be converted to a different files type; `FileTypeConversion.ALL`: There are no restrictions around which images will be converted to different images types as long as it results in a smaller file size (less bytes) and optimization is lossless; `FileTypeConversion.IE6SAFE`: The same as `ALL` except that it will not convert the image if it is a GIF with Alpha transparency. PNG files with transparency, when loaded in IE6, show the transparent parts as gray.
* The 2nd argument indicates if browser specific versions of the file should be generated in addition to the optimized version of the image.
* The 3rd argument is the collection of image files to optimize.
Expand All @@ -85,11 +128,11 @@ The function returns a list of `OptimizationResult` objects.

### How is the Optimization Actually Accomplished? ###

The heavy lifing is done by 6 different binary applications: [advpng](http://advancemame.sourceforge.net/doc-advpng.html), [gifsicle](http://www.lcdf.org/gifsicle/), [jfifremove](https://lyncd.com/files/imgopt/jfifremove.c), [jpegtran](http://jpegclub.org/jpegtran/), [optipng](http://optipng.sourceforge.net/), [pngout](http://advsys.net/ken/utils.htm), [pngquant](https://pngquant.org/).
The heavy lifing is done by 6 different binary applications: [advpng](https://www.advancemame.it/doc-advpng.html), [gifsicle](https://www.lcdf.org/gifsicle/), [jfifremove](https://lyncd.com/files/imgopt/jfifremove.c), [jpegtran](https://jpegclub.org/jpegtran/), [optipng](https://optipng.sourceforge.net/), [pngout](https://www.jonof.id.au/kenutils.html), [pngquant](https://pngquant.org/).

The JAVA code calls out to these binaries and using the appropriate ones for the image format. The code does this twice. For some reason passing in an already optimized image will result in a few bytes reduction the second time it is optimized.

For converting the images we use 3 binaries: [ImageMagick](http://www.imagemagick.org/), [cwebp](https://developers.google.com/speed/webp/docs/cwebp), [gif2webp](https://developers.google.com/speed/webp/docs/gif2webp).
For converting the images we use 3 binaries: [ImageMagick](https://imagemagick.org/), [cwebp](https://developers.google.com/speed/webp/docs/cwebp), [gif2webp](https://developers.google.com/speed/webp/docs/gif2webp).

### Automated Validation ###

Expand Down
36 changes: 36 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ Note: It only runs on Linux and requires additional binaries</description>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.salesforce.perfeng.uiperf.imageoptimization.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
Expand All @@ -120,6 +132,30 @@ Note: It only runs on Linux and requires additional binaries</description>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.salesforce.perfeng.uiperf.imageoptimization.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Expand Down
Loading
Loading