JavaでJPGをWebPに変換する方法

Java

WebP(ウェッピー)はウェブ上で高品質な画像を効率的に表示するための画像フォーマットです。WebPは圧縮率が高く、ファイルサイズが小さくなるため、ウェブサイトの読み込み速度を向上させるのに役立ちます。この記事では、Javaを使用してJPEG(JPG)形式の画像をWebP形式に変換する方法について紹介します。

JPGをWebPに変換

JavaでJPG画像をWebP画像に変換するためにOpenCVのJavaのラッパーであるJavaCVを使用しました。

pom.xmlの依存関係に「javacv-platform」を指定します。

<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv-platform</artifactId>
    <version>1.5.6</version>
</dependency>

JPGをWebPに変換するコードは下記になります。
同名のクラスが複数あるので、コンパイルエラーになる場合は importが正しいかよく確認してください。

package com.example;

import java.io.IOException;

import org.bytedeco.opencv.global.opencv_highgui;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Size;

public class JPGtoWebPConverter {

	public static void main(String[] args) throws IOException {

		// JPG画像を読み込み
		Mat srcImage = opencv_imgcodecs.imread("5672x3014.jpg");

		// リサイズ処理
		Mat dstImage = new Mat();
		opencv_imgproc.resize(srcImage, dstImage, new Size(1280, 680));

		// WebP形式で保存
		opencv_imgcodecs.imwrite("1280x680.webp", dstImage);

		// WebP画像を表示して確認
		opencv_highgui.imshow("", opencv_imgcodecs.imread("1280x680.webp"));
		opencv_highgui.waitKey(0);
	}
}

まず、opencv_imgcodecs.imread(“5672×3014.jpg”)は、指定されたJPG画像をOpenCVのMatオブジェクトとして読み込みます。

MatはOpenCVで画像データを表現するためのクラスです。

opencv_imgproc.resize(srcImage, dstImage, new Size(1280, 680))は、元の画像(srcImage)を指定したサイズ(1280×680)にリサイズして、結果をdstImageに格納します。

opencv_imgcodecs.imwrite("1280x680.webp", dstImage)は、リサイズされた画像(dstImage)をWebP形式で保存します。ファイル名の拡張子を「.webp」にしているため、WebP形式で保存されます。

プロジェクトの構成は下記のようになっています。

実行すると下記のようにWebP形式の画像(1280×680.webp)が作成されました。

JavaCVの依存関係の修正

「javacv-platform」では依存関係が大きすぎるため、特定の依存関係に修正します。

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv</artifactId>
    <version>1.5.6</version>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>openblas</artifactId>
    <version>0.3.17-1.5.6</version>
    <classifier>windows-x86_64</classifier>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>opencv</artifactId>
    <version>4.5.3-1.5.6</version>
    <classifier>windows-x86_64</classifier>
</dependency>

javacvを基本の依存関係として指定し、openblasとopencvを追加の依存関係として指定します。指定するバージョンは Maven Repository で確認できます。

https://mvnrepository.com/artifact/org.bytedeco/javacv/1.5.6

classifierで実行環境の「windows-x86_64」を指定していましたが、最終的にはprofileでビルド環境によって指定するようにしました。pom.xmlの全体が下記になります。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>sample-javacv</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sample-javacv</name>

    <properties>
        <java.version>17</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <javacv.version>1.5.6</javacv.version>
    </properties>

    <dependencies>
<!-- 
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>${javacv.version}</version>
        </dependency>
-->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>${javacv.version}</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>openblas</artifactId>
            <version>0.3.17-${javacv.version}</version>
            <classifier>${classifier}</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>opencv</artifactId>
            <version>4.5.3-${javacv.version}</version>
            <classifier>${classifier}</classifier>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.11.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <profiles>
        <profile>
            <id>linux-arm64</id>
            <activation>
                <os>
                    <family>unix</family>
                    <arch>aarch64</arch>
                </os>
            </activation>
            <properties>
                <classifier>linux-arm64</classifier>
            </properties>
        </profile>
        <profile>
            <id>linux-x86_64</id>
            <activation>
                <os>
                    <family>unix</family>
                    <arch>amd64</arch>
                </os>
            </activation>
            <properties>
                <classifier>linux-x86_64</classifier>
            </properties>
        </profile>
        <profile>
            <id>windows-x86_64</id>
            <activation>
                <os>
                    <family>windows</family>
                    <arch>amd64</arch>
                </os>
            </activation>
            <properties>
                <classifier>windows-x86_64</classifier>
            </properties>
        </profile>
    </profiles>
</project>

以降はいろいろ踏んだ問題の記録です。

UnsatisfiedLinkError: no jniopenblas_nolapack

依存関係にopenblasがないと下記のエラーになりました。

Exception in thread "main" java.lang.UnsatisfiedLinkError: no jniopenblas_nolapack in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)
	at java.lang.Runtime.loadLibrary0(Runtime.java:871)
	at java.lang.System.loadLibrary(System.java:1124)
	at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:1738)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1345)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1157)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1133)
	at org.bytedeco.openblas.global.openblas_nolapack.<clinit>(openblas_nolapack.java:12)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1212)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1157)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1133)
	at org.bytedeco.opencv.global.opencv_imgcodecs.<clinit>(opencv_imgcodecs.java:18)
	at com.example.SampleJavaCV.main(SampleJavaCV.java:13)
Caused by: java.lang.UnsatisfiedLinkError: Could not find jniopenblas_nolapack in class, module, and library paths.
	at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:1705)
	... 11 more

UnsatisfiedLinkError: no jniopencv_core

依存関係にopencvがないと下記のエラーになりました。

Exception in thread "main" java.lang.UnsatisfiedLinkError: no jniopencv_core in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)
	at java.lang.Runtime.loadLibrary0(Runtime.java:871)
	at java.lang.System.loadLibrary(System.java:1124)
	at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:1738)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1345)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1157)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1133)
	at org.bytedeco.opencv.global.opencv_core.<clinit>(opencv_core.java:16)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1212)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1157)
	at org.bytedeco.javacpp.Loader.load(Loader.java:1133)
	at org.bytedeco.opencv.global.opencv_imgcodecs.<clinit>(opencv_imgcodecs.java:18)
	at com.example.SampleJavaCV.main(SampleJavaCV.java:13)
Caused by: java.lang.UnsatisfiedLinkError: Could not find jniopencv_core in class, module, and library paths.
	at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:1705)
	... 11 more

Resource handler returned message: “Source bundle is empty or exceeds maximum allowed size: 524288000.

AWS Elastic Beanstalk にデプロイしたときのエラーです。依存関係が「javacv-platform」だとファイルサイズが1GBほどだったので上限500MBの制限に引っかかってしまいました。

ソースバンドルのファイルサイズの上限は 500 MB です。

https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/applications-versions.html

/lib64/libm.so.6: version `GLIBC_2.27′ not found

JavaCVのバージョン1.5.9を使用したときのエラーです。

実行したAmazon Linux 2 の環境でのGLIBCのバージョンが2.26で、2.27が見つからないとエラーになりました。GLIBCのバージョンを2.26から2.27に上げるよりも、JavaCVのバージョンを1.5.9から1.5.6に下げることで回避しました。

java.lang.UnsatisfiedLinkError: /home/webapp/.javacpp/cache/openblas-0.3.23-1.5.9-linux-arm64.jar/org/bytedeco/openblas/linux-arm64/libjniopenblas_nolapack.so: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by /home/webapp/.javacpp/cache/openblas-0.3.23-1.5.9-linux-arm64.jar/org/bytedeco/openblas/linux-arm64/libopenblas_nolapack.so.0)
at java.base/jdk.internal.loader.NativeLibraries.load(Native Method) ~[na:na]
at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:388) ~[na:na]
at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:232) ~[na:na]
at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:174) ~[na:na]
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2389) ~[na:na]
at java.base/java.lang.Runtime.load0(Runtime.java:755) ~[na:na]
at java.base/java.lang.System.load(System.java:1953) ~[na:na]
at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:1779) ~[javacpp-1.5.9.jar!/:1.5.9]
at org.bytedeco.javacpp.Loader.load(Loader.java:1423) ~[javacpp-1.5.9.jar!/:1.5.9]
at org.bytedeco.javacpp.Loader.load(Loader.java:1234) ~[javacpp-1.5.9.jar!/:1.5.9]
at org.bytedeco.javacpp.Loader.load(Loader.java:1210) ~[javacpp-1.5.9.jar!/:1.5.9]
at org.bytedeco.openblas.global.openblas_nolapack.<clinit>(openblas_nolapack.java:12) ~[openblas-0.3.23-1.5.9.jar!/:0.3.23-1.5.9]
at java.base/java.lang.Class.forName0(Native Method) ~[na:na]
at java.base/java.lang.Class.forName(Class.java:467) ~[na:na]
at org.bytedeco.javacpp.Loader.load(Loader.java:1289) ~[javacpp-1.5.9.jar!/:1.5.9]
at org.bytedeco.javacpp.Loader.load(Loader.java:1234) ~[javacpp-1.5.9.jar!/:1.5.9]
at org.bytedeco.javacpp.Loader.load(Loader.java:1210) ~[javacpp-1.5.9.jar!/:1.5.9]
at org.bytedeco.opencv.global.opencv_imgcodecs.<clinit>(opencv_imgcodecs.java:18) ~[opencv-4.7.0-1.5.9.jar!/:4.7.0-1.5.9]

https://repost.aws/questions/QUrXOioL46RcCnFGyELJWKLw/glibc-2-27-on-amazon-linux-2

GLIBCのバージョンは下記のコマンドで確認できます。

$ ldd --version
ldd (GNU libc) 2.26
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

Compute type BUILD_GENERAL1_MEDIUM is not supported for ARM_CONTAINER

ビルド環境を実行環境と合わせる必要があったため、AWS CodeBuildのDockerイメージを「aws/codebuild/amazonlinux2-aarch64-standard:3.0」に変更したときのエラーです。

ARM_CONTAINER には SMALL か LARGE しかないので、どちらかのコンピューティングタイプを選択したら大丈夫です。

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-env-ref-compute-types.html

サンプル画像

こちらのパブリックドメインのきれいなJPG画像を使わせていただきました。

https://gahag.net/010812-kaaterskill-falls/

コメント

タイトルとURLをコピーしました