Skip to content

Commit ee875c1

Browse files
committed
Sample for e-paper display with IT8951 controller
1 parent 4abd0e0 commit ee875c1

File tree

5 files changed

+566
-0
lines changed

5 files changed

+566
-0
lines changed

examples/epaper_display/README.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# E-Paper Display
2+
3+
This sample shows how to communicate with an IT8951 controller for e-paper displays, e.g. [Waveshare E-Ink display HAT for Raspberry Pi](https://www.waveshare.com/9.7inch-e-paper-hat.htm)
4+
5+
## Prerequisites
6+
7+
- Java 20
8+
- Apache Maven
9+
- 64-bit operating system (macOS, Linux, Windows)
10+
- IT8951 controller
11+
12+
On Windows, the display controller's driver must be replaced with the *WinUSB* driver
13+
using [Zadig](https://zadig.akeo.ie/).
14+
15+
On macOS, root privileges are required to successfully run the sample. (The standard driver will
16+
be temporarily detached.)
17+
18+
## How to run
19+
20+
### Install Java 20
21+
22+
Check that *Java 20* is installed:
23+
24+
```shell
25+
$ java -version
26+
```
27+
28+
If not, download and install it, e.g. from [Azul](https://www.azul.com/downloads/?package=jdk).
29+
30+
### Install Maven
31+
32+
Check that *Maven* is installed:
33+
34+
```shell
35+
$ mvn -version
36+
```
37+
38+
If it is not present, install it, typically using package manager like *Homebrew* on macOS, *Chocolately* on Windows and *apt* on Linux.
39+
40+
### Run the sample
41+
42+
```shell
43+
$ cd JavaDoesUSB/examples/epaper_display
44+
$ mvn compile exec:exec
45+
[INFO] Scanning for projects...
46+
[INFO]
47+
[INFO] -------------< net.codecrete.usb.examples:epaper-display >--------------
48+
[INFO] Building epaper-display 0.5.1
49+
[INFO] from pom.xml
50+
[INFO] --------------------------------[ jar ]---------------------------------
51+
[INFO]
52+
[INFO] --- resources:3.3.1:resources (default-resources) @ epaper-display ---
53+
[INFO] skip non existing resourceDirectory /Users/me/Documents/JavaDoesUSB/examples/epaper_display/src/main/resources
54+
[INFO]
55+
[INFO] --- compiler:3.11.0:compile (default-compile) @ epaper-display ---
56+
[INFO] Changes detected - recompiling the module! :source
57+
[INFO] Compiling 2 source files with javac [debug release 20] to target/classes
58+
[INFO]
59+
[INFO] --- exec:3.1.0:exec (default-cli) @ epaper-display ---
60+
Display size: 1200 x 825
61+
[INFO] ------------------------------------------------------------------------
62+
[INFO] BUILD SUCCESS
63+
[INFO] ------------------------------------------------------------------------
64+
[INFO] Total time: 1.502 s
65+
[INFO] Finished at: 2023-07-02T14:08:50+02:00
66+
[INFO] ------------------------------------------------------------------------
67+
```
68+
69+
### Run the sample on macOS
70+
71+
In order to run the sample with root privileges, the best approach is to build it first without
72+
root privileges and then run it as root without Maven:
73+
74+
```shell
75+
$ cd JavaDoesUSB/examples/epaper_display
76+
$ mvn compile
77+
[INFO] Scanning for projects...
78+
...
79+
[INFO] ------------------------------------------------------------------------
80+
$ sudo -i
81+
Password:
82+
$ cd /Users/me/Documents/JavaDoesUSB/examples/epaper_display
83+
$ export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-20.jdk/Contents/Home
84+
$ JAVA_HOME/bin/java --enable-preview --enable-native-access=ALL-UNNAMED -cp target/classes:/Users/me/.m2/repository/net/codecrete/usb/java-does-usb/0.5.1/java-does-usb-0.5.1.jar net.codecrete.usb.examples.EPaperDisplay
85+
Display size: 1200 x 825
86+
```

examples/epaper_display/pom.xml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>net.codecrete.usb.examples</groupId>
8+
<artifactId>epaper-display</artifactId>
9+
<version>0.5.1</version>
10+
11+
<name>epaper-display</name>
12+
<url>https://github.com/manuelbl/JavaDoesUSB/examples/epaper_display</url>
13+
14+
<properties>
15+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
16+
<maven.compiler.source>20</maven.compiler.source>
17+
<maven.compiler.target>20</maven.compiler.target>
18+
</properties>
19+
20+
<dependencies>
21+
<dependency>
22+
<groupId>net.codecrete.usb</groupId>
23+
<artifactId>java-does-usb</artifactId>
24+
<version>0.5.1</version>
25+
</dependency>
26+
</dependencies>
27+
28+
<build>
29+
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
30+
<plugins>
31+
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
32+
<plugin>
33+
<artifactId>maven-clean-plugin</artifactId>
34+
<version>3.3.1</version>
35+
</plugin>
36+
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
37+
<plugin>
38+
<artifactId>maven-resources-plugin</artifactId>
39+
<version>3.3.1</version>
40+
</plugin>
41+
<plugin>
42+
<artifactId>maven-compiler-plugin</artifactId>
43+
<version>3.11.0</version>
44+
<configuration>
45+
<release>20</release>
46+
<compilerArgs>
47+
<arg>--enable-preview</arg>
48+
</compilerArgs>
49+
<source>20</source>
50+
<target>20</target>
51+
</configuration>
52+
</plugin>
53+
<plugin>
54+
<artifactId>maven-surefire-plugin</artifactId>
55+
<version>2.22.1</version>
56+
<configuration>
57+
<argLine>--enable-preview --enable-native-access=ALL-UNNAMED</argLine>
58+
</configuration>
59+
</plugin>
60+
<plugin>
61+
<artifactId>maven-jar-plugin</artifactId>
62+
<version>3.1.2</version>
63+
</plugin>
64+
<plugin>
65+
<artifactId>maven-install-plugin</artifactId>
66+
<version>3.1.1</version>
67+
</plugin>
68+
<plugin>
69+
<artifactId>maven-deploy-plugin</artifactId>
70+
<version>3.1.1</version>
71+
</plugin>
72+
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
73+
<plugin>
74+
<artifactId>maven-site-plugin</artifactId>
75+
<version>3.12.1</version>
76+
</plugin>
77+
<plugin>
78+
<artifactId>maven-project-info-reports-plugin</artifactId>
79+
<version>3.4.5</version>
80+
</plugin>
81+
<plugin>
82+
<groupId>org.codehaus.mojo</groupId>
83+
<artifactId>exec-maven-plugin</artifactId>
84+
<version>3.1.0</version>
85+
<configuration>
86+
<executable>java</executable>
87+
<arguments>
88+
<argument>--enable-preview</argument>
89+
<argument>--enable-native-access=ALL-UNNAMED</argument>
90+
<argument>-classpath</argument>
91+
<classpath />
92+
<argument>net.codecrete.usb.examples.EPaperDisplay</argument>
93+
</arguments>
94+
</configuration>
95+
</plugin>
96+
</plugins>
97+
</pluginManagement>
98+
</build>
99+
</project>
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//
2+
// Java Does USB
3+
// Copyright (c) 2023 Manuel Bleichenbacher
4+
// Licensed under MIT License
5+
// https://opensource.org/licenses/MIT
6+
//
7+
8+
package net.codecrete.usb.examples;
9+
10+
import javax.imageio.ImageIO;
11+
import java.awt.*;
12+
import java.awt.image.BufferedImage;
13+
import java.io.File;
14+
import java.io.IOException;
15+
16+
/**
17+
* Example program for displaying an image and text on an e-paper display
18+
* controlled by an IT8951 controller.
19+
*/
20+
public class EPaperDisplay {
21+
22+
public static void main(String[] args) throws IOException {
23+
// load image of tiger
24+
var tigerImage = ImageIO.read(new File("tiger.jpg"));
25+
26+
// connect to display controller
27+
var display = new IT8951Driver();
28+
display.open();
29+
30+
var width = display.info().width();
31+
var height = display.info().height();
32+
System.out.printf("Display size: %d x %d%n", width, height);
33+
34+
// resize image to fit display (converting it to grayscale)
35+
var image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
36+
image = resizedImage(tigerImage, width, height);
37+
38+
// add text to image
39+
Graphics2D g = (Graphics2D) image.getGraphics();
40+
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
41+
g.setFont(new Font("Arial", Font.BOLD, 40));
42+
g.drawString("Java Does USB", 20, height - 40);
43+
g.dispose();
44+
45+
// display image
46+
display.displayImage(image, 0, 0);
47+
48+
display.close();
49+
}
50+
51+
/**
52+
* Returns a copy of the image, resized to the specified width and height.
53+
* <p>
54+
* To prevent distortion, the image is cropped to fit the target width and height.
55+
* </p>
56+
* <p>
57+
* The new image will be in 8-bit grayscale.
58+
* </p>
59+
* @param image image to resize
60+
* @param width width, in pixels
61+
* @param height height, in pixels
62+
* @return resized image
63+
*/
64+
static BufferedImage resizedImage(BufferedImage image, int width, int height) {
65+
66+
var resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
67+
var g = (Graphics2D) resizedImage.createGraphics();
68+
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
69+
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
70+
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
71+
72+
int srcWidth = image.getWidth();
73+
int srcHeight = image.getHeight();
74+
var targetAspectRatio = (double) width / height;
75+
var srcAspectRatio = (double) srcWidth / srcHeight;
76+
77+
if (targetAspectRatio > srcAspectRatio) {
78+
// target image is wider than source image - fit width and cut top and bottom
79+
var modifiedHeight = width / srcAspectRatio;
80+
var cutY = (int) Math.round((modifiedHeight - height) / 2);
81+
g.drawImage(image, 0, -cutY, width, height + cutY, 0, 0, srcWidth, srcHeight, null);
82+
} else {
83+
// target image is narrower than source image - fit height and cut left and right
84+
var modifiedWidth = height * srcAspectRatio;
85+
var cutX = (int) Math.round((modifiedWidth - width) / 2);
86+
g.drawImage(image, -cutX, 0, width + cutX, height, 0, 0, srcWidth, srcHeight, null);
87+
}
88+
89+
g.dispose();
90+
return resizedImage;
91+
}
92+
}

0 commit comments

Comments
 (0)