・2018/09/15
Raspberry Piの C言語で JPEG画像ライブラリ libjpegや libjpeg_turboを使ってみるサンプル
(ラズパイの libjpegや libjpeg_turboで C言語で JPEG画像ファイルを読む方法)
Tags: [Raspberry Pi], [電子工作]
● Raspberry Piで JPEG画像ライブラリ libjpegを C言語でいじってみるテスト
OpenCVの最適化の時に OpenCVで使用する JPEG画像ライブラリ libjpegや libjpeg_turbo等で訳が分からなくなって混乱したので素の libjpegを C言語でいじってみる事にしました。
※ JPEG画像ライブラリを変更した時のベンチマークの為に毎回 OpenCVをビルドするのに飽きたのが理由
・2018/09/01
Raspberry Pi 3用に NEONと VFPV3を有効化して最適化版の OpenCVをビルドする方法
ラズパイ3用に NEONと VFPV3を有効化した最適化版の OpenCVをビルドする方法
● オープンソースの JPEG画像ライブラリ libjpeg
● Independent JPEG Group
Independent JPEG Group
http://www.ijg.org/files/
JPEG Reference
● libjpeg
libjpeg
LuaDist/libjpeg
● libjpeg-turbo
libjpeg-turbo
libjpeg-turbo/libjpeg-turbo
● Raspberry Piの JPEG画像ライブラリを調べる
●検証に使用した Raspbian OS
Raspbian OS Debian Stretch
Version:June 2018
Release date:2018-06-27
pi@raspberrypi:~/libjpeg-turbo-1.5.3/build $ uname -a
Linux raspberrypi 4.14.50-v7+ #1122 SMP Tue Jun 19 12:26:26 BST 2018 armv7l GNU/Linux
●素の状態の Raspbian OSには JPEGライブラリは有りません
findコマンドでファイル検索をします。
~ $ find /usr -name "libjpeg*.so"
/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/jre/lib/arm/libjpeg.so
pi@raspberrypi:~ $ find /usr -name "libturbojpeg*.so"
pi@raspberrypi:~ $ find /usr -name "jpeglib.h"
※ 上記の /usr/lib/jvm内のライブラリは Javaのプログラムが使用する JPEGライブラリなので C言語からは使えません。
● Raspbian OS標準の JPEGライブラリのインストール
標準のインストールコマンド apt-get installで libjpeg-devパッケージをインストールします。
libjpeg-devだけの指定ですが、libjpeg62-turbo-devも自動的にインストールされます。
sudo apt-get -y install libjpeg-dev
# Setting up libjpeg62-turbo-dev:armhf (1:1.5.1-2) ...
# Setting up libjpeg-dev (1:1.5.1-2) ...
#
find /usr -name "libjpeg*.so"
find /usr -name "libturbojpeg*.so"
find /usr -name "jpeglib.h"
pi@raspberrypi:~ $ find /usr -name "libjpeg*.so"
/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/jre/lib/arm/libjpeg.so
/usr/lib/arm-linux-gnueabihf/libjpeg.so
pi@raspberrypi:~ $ find /usr -name "libturbojpeg*.so"
pi@raspberrypi:~ $ find /usr -name "jpeglib.h"
/usr/include/jpeglib.h
g++ test_jpeglib.cpp -ljpeg
# pi@raspberrypi:~ $ ls -l a.out
# -rwxr-xr-x 1 pi pi 9172 Sep 15 13:19 a.out
./a.out
# 9.682569892
./a.out
# 9.690281819
大体 9.68秒程度の実行速度になりました。
● -staticでライブラリを実行ファイル内に組み入れます。
g++ test_jpeglib.cpp -ljpeg -static
# pi@raspberrypi:~ $ ls -l a.out
# -rwxr-xr-x 1 pi pi 722444 Sep 15 13:20 a.out
pi@raspberrypi:~ $ ./a.out
9.835744528
pi@raspberrypi:~ $ ./a.out
9.812825986
大体 9.82秒程度の実行速度になりました。
● -static無しのダイナミックリンク形式の場合、remove libjpeg62-turboで JPEGライブラリを削除すると実行時に「JPEGライブラリが無い」でエラーになります。
g++ test_jpeglib.cpp -ljpeg
sudo apt-get -y remove libjpeg62-turbo
ls -l a.out
# -rwxr-xr-x 1 pi pi 9172 Sep 15 13:26 a.out
./a.out
# ./a.out: error while loading shared libraries: libjpeg.so.62: cannot open shared object file: No such file or directory
# 「JPEGライブラリが無い」でエラー
● -staticでコンパイルした版は JPEGライブラリを削除していても大丈夫
作成したアプリを不特定多数に配布する場合は -staticでコンパイルする方がトラブルが少ない。
但し、-staticでコンパイルするとライブラリファイルの内容も実行ファイルに含まれるので実行ファイルのサイズが大きくなります。(ある意味当たり前の事ですが)
g++ test_jpeglib.cpp -ljpeg -static
# pi@raspberrypi:~ $ ls -l a.out
# -rwxr-xr-x 1 pi pi 722444 Sep 15 13:20 a.out
sudo apt-get -y remove libjpeg62-turbo
./a.out
# 9.835744528
# 実行できる
# あらかじめ下記のコマンドで JPEG画像ファイルをダウンロードしておきます。
cd
wget https://github.com/opencv/opencv/raw/master/samples/data/lena.jpg
● libjpeg-turbo 1.5.3の JPEGライブラリのインストール
# libjpeg-turbo 1.5.3
# @dcommander dcommander released this Dec 14, 2017
cd
wget -O libjpeg-turbo_153.zip https://github.com/libjpeg-turbo/libjpeg-turbo/archive/1.5.3.zip
unzip libjpeg-turbo_153.zip
cd
cd libjpeg-turbo-1.5.3
sudo apt-get -y install nasm
sudo apt-get -y install dh-autoreconf
autoreconf -fiv
mkdir build
cd build
../configure --prefix=/usr/libjpeg-turbo --mandir=/usr/share/man --with-jpeg8 --enable-static --docdir=/usr/share/doc/libjpeg-turbo-1.5.3
# 不要
# CC= gcc -fPIC
# nano Makefile
# Build libjpeg-turbo
make -j4
# make test
# Install libjpeg-turbo
sudo make install
pi@raspberrypi:~/libjpeg-turbo-1.5.3/build $ find /usr -name "libjpeg*.so"
/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/jre/lib/arm/libjpeg.so
/usr/lib/arm-linux-gnueabihf/libjpeg.so
/usr/libjpeg-turbo/lib/libjpeg.so
pi@raspberrypi:~/libjpeg-turbo-1.5.3/build $ find /usr -name "libturbojpeg*.so"
/usr/libjpeg-turbo/lib/libturbojpeg.so
pi@raspberrypi:~/libjpeg-turbo-1.5.3/build $ find /usr -name "jpeglib.h"
/usr/include/jpeglib.h
/usr/libjpeg-turbo/include/jpeglib.h
●そのままの状態だと -static無しのダイナミックリンク形式の場合の実行時に「JPEGライブラリが無い」でエラーになります。
g++ test_jpeglib.cpp -ljpeg -I/usr/libjpeg-turbo/include -L/usr/libjpeg-turbo/lib
./a.out
# ./a.out: error while loading shared libraries: libjpeg.so.62: cannot open shared object file: No such file or directory
●解決方法 その1 -staticで staticリンク形式でコンパイルする
実行ファイルにライブラリファイルの内容を含める
g++ test_jpeglib.cpp -ljpeg -I/usr/libjpeg-turbo/include -L/usr/libjpeg-turbo/lib -static
# pi@raspberrypi:~ $ ls -l a.out
# -rwxr-xr-x 1 pi pi 732672 Sep 15 12:21 a.out
pi@raspberrypi:~ $ ./a.out
9.375252913
pi@raspberrypi:~ $ ./a.out
9.304052184
●解決方法 その2 ldconfigコマンドでライブラリの検索パスを追加する
/etc/ld.so.conf.d/
ディレクトリ内にライブラリのパスを記述した .confファイルを作成して、ldconfigコマンドでライブラリのパス情報を更新します。
# 事前にライブラリパスの情報を確認する
ls -l /etc/ld.so.conf.d/
cat /etc/ld.so.conf.d/*.conf
# */
# ライブラリパスを記述した .confファイルを作成する
echo "/usr/libjpeg-turbo/lib" > libjpeg-turbo-1.5.3.conf
sudo cp libjpeg-turbo-1.5.3.conf /etc/ld.so.conf.d/
# ldconfigコマンドでライブラリの検索パスの情報を更新する
sudo ldconfig
# -static無しでコンパイルした実行ファイルでも実行できる様になった
g++ test_jpeglib.cpp -ljpeg -I/usr/libjpeg-turbo/include -L/usr/libjpeg-turbo/lib
./a.out
pi@raspberrypi:~ $ ./a.out
9.701963069
pi@raspberrypi:~ $ ./a.out
9.695254736
大体 9.7秒程度の実行速度になりました。
g++ test_jpeglib.cpp -ljpeg -I/usr/libjpeg-turbo/include -L/usr/libjpeg-turbo/lib
# pi@raspberrypi:~ $ ls -l a.out
# -rwxr-xr-x 1 pi pi 9172 Sep 15 12:25 a.out
# pi@raspberrypi:~ $ ls -l /usr/libjpeg-turbo/lib/libjpeg.so.8.1.2
# -rwxr-xr-x 1 root root 288628 Sep 15 12:17 /usr/libjpeg-turbo/lib/libjpeg.so.8.1.2
# pi@raspberrypi:~ $ ls -l /usr/libjpeg-turbo/lib/libturbojpeg.so.0.1.0
# -rwxr-xr-x 1 root root 333212 Sep 15 12:17 /usr/libjpeg-turbo/lib/libturbojpeg.so.0.1.0
● libjpeg-turbo 2.0.0の JPEGライブラリのインストール
# libjpeg-turbo 2.0.0
# @dcommander dcommander released this Jul 27, 2018
cd
wget -O libjpeg-turbo_200.zip https://github.com/libjpeg-turbo/libjpeg-turbo/archive/2.0.0.zip
unzip libjpeg-turbo_200.zip
cd
cd libjpeg-turbo-2.0.0
mkdir build
cd build
cmake ..
# Build libjpeg-turbo
make -j4
# 3分でビルド完了
# make test
# Install libjpeg-turbo
sudo make install
pi@raspberrypi:~/libjpeg-turbo-2.0.0/build $ find /usr -name "libjpeg*.so"
/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/jre/lib/arm/libjpeg.so
/usr/lib/arm-linux-gnueabihf/libjpeg.so
/usr/libjpeg-turbo/lib/libjpeg.so
pi@raspberrypi:~/libjpeg-turbo-2.0.0/build $ find /opt -name "libjpeg*.so"
/opt/libjpeg-turbo/lib32/libjpeg.so
pi@raspberrypi:~/libjpeg-turbo-2.0.0/build $ find /opt -name "libturbojpeg*.so"
/opt/libjpeg-turbo/lib32/libturbojpeg.so
pi@raspberrypi:~/libjpeg-turbo-2.0.0/build $ find /opt -name "jpeglib.h"
/opt/libjpeg-turbo/include/jpeglib.h
●そのままの状態だと -static無しのダイナミックリンク形式の場合の実行時に「JPEGライブラリが無い」でエラーになります。
g++ test_jpeglib.cpp -I/opt/libjpeg-turbo/include -L/opt/libjpeg-turbo/lib32 -ljpeg
./a.out
# ./a.out: error while loading shared libraries: libjpeg.so.62: cannot open shared object file: No such file or directory
●解決方法 その1 -staticで staticリンク形式でコンパイルする
g++ test_jpeglib.cpp -I/opt/libjpeg-turbo/include -L/opt/libjpeg-turbo/lib32 -ljpeg -static
# pi@raspberrypi:~ $ ls -l a.out
# -rwxr-xr-x 1 pi pi 730604 Sep 15 12:56 a.out
pi@raspberrypi:~ $ ./a.out
9.408597705
pi@raspberrypi:~ $ ./a.out
9.335505934
●解決方法 その2 ldconfigコマンドでライブラリの検索パスを追加する
# 事前にライブラリパスの情報を確認する
ls -l /etc/ld.so.conf.d/
cat /etc/ld.so.conf.d/*.conf
# */
# ライブラリパスを記述した .confファイルを作成する
echo "/opt/libjpeg-turbo/lib32" > libjpeg-turbo-2.0.0.conf
sudo cp libjpeg-turbo-2.0.0.conf /etc/ld.so.conf.d/
# ldconfigコマンドでライブラリの検索パスの情報を更新する
sudo ldconfig
# -static無しでコンパイルした実行ファイルでも実行できる様になった
g++ test_jpeglib.cpp -I/opt/libjpeg-turbo/include -L/opt/libjpeg-turbo/lib32 -ljpeg
# pi@raspberrypi:~ $ ls -l a.out
# -rwxr-xr-x 1 pi pi 9172 Sep 15 12:54 a.out
# pi@raspberrypi:~ $ ls -l /opt/libjpeg-turbo/lib32/libjpeg.so.62.3.0
# -rw-r--r-- 1 root root 286776 Sep 15 12:39 /opt/libjpeg-turbo/lib32/libjpeg.so.62.3.0
# pi@raspberrypi:~ $ ls -l /opt/libjpeg-turbo/lib32/libturbojpeg.so.0.2.0
# -rw-r--r-- 1 root root 363440 Sep 15 12:39 /opt/libjpeg-turbo/lib32/libturbojpeg.so.0.2.0
pi@raspberrypi:~ $ ./a.out
9.639376559
pi@raspberrypi:~ $ ./a.out
9.644926507
● Raspberry Piで JPEG画像ライブラリ libjpegを C++言語で読み込むサンプル
cd
nano test_jpeglib.cpp
test_jpeglib.cpp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <jpeglib.h>
// JPEGファイルを伸張
int read_jpeg_file(const char *filename)
{
// JPEGで使用する構造体
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
// スキャンラインの配列
JSAMPARRAY buffer;
FILE *infile;
// JPEGファイルを開いて読み込み
if ((infile = fopen(filename, "rb")) == NULL)
{
fprintf(stderr, "can't open %s\n", filename);
return 0;
}
// JPEG処理のエラー設定
cinfo.err = jpeg_std_error(&jerr);
// JPEGファイルの展開開始
jpeg_create_decompress(&cinfo);
// JPEGファイルの設定
jpeg_stdio_src(&cinfo, infile);
// JPEGファイルのヘッダ情報の読み込み指定
jpeg_read_header(&cinfo, TRUE);
// JPEGファイルの読み込み開始
jpeg_start_decompress(&cinfo);
// printf("width = %d, height = %d, ch = %d\n",
// cinfo.output_width, cinfo.output_height, cInfo.output_components);
// JPEGファイルの読み込みデータのメモリを確保(W*H*RGB Color bytes)
// スキャンラインの配列
buffer = (JSAMPARRAY)malloc(sizeof(JSAMPROW) * cinfo.output_height);
for (int i = 0; i < cinfo.output_height; ++i)
{
buffer[i] = (JSAMPROW)calloc(sizeof(JSAMPLE),
cinfo.output_width * cinfo.output_components);
}
// JPEGファイルを読み込んでライン毎に展開するループ
while (cinfo.output_scanline < cinfo.output_height)
{
// JPEGファイルを読み込んでライン毎に展開する
jpeg_read_scanlines(&cinfo, buffer + cinfo.output_scanline,
cinfo.output_height - cinfo.output_scanline);
}
// JPEGファイルの読み込み終了
jpeg_finish_decompress(&cinfo);
// JPEGファイルの展開完了
jpeg_destroy_decompress(&cinfo);
// JPEGファイルを閉じる
fclose(infile);
return 1;
}
int main(int argc, char *argv[])
{
// clock_getres, clock_gettime, clock_settime - クロックと時間の関数
// https://linuxjm.osdn.jp/html/LDP_man-pages/man2/clock_getres.2.html
struct timespec startTime, endTime;
// 開始時間
clock_gettime(CLOCK_REALTIME, &startTime);
// 1000回ループ
// ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
// 固定文字列を char *に代入すると怒られるので const char *fnにする
const char *fn = "lena.jpg";
for (int i=0; i < 1000; ++i)
{
read_jpeg_file(fn);
}
// 終了時間
clock_gettime(CLOCK_REALTIME, &endTime);
// Calculate diff of two struct timespec
// Elapsed Time
// http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
// 開始時間と終了時間を引き算して実行時間を計算する
// 整数秒と小数秒(ns単位)が分かれているので上手に差分を計算する
time_t tv_sec = endTime.tv_sec - startTime.tv_sec;
long tv_nsec = endTime.tv_nsec - startTime.tv_nsec;
if (tv_nsec < 0L) {
tv_sec -= 1;
tv_nsec += 1000000000L; // ns単位なので 1000*1000*1000
}
printf("%10ld.%09ld\n", tv_sec, tv_nsec);
return 1;
}
Tags: [Raspberry Pi], [電子工作]
●関連するコンテンツ(この記事を読んだ人は、次の記事も読んでいます)
FWinSdCardImager SDカード イメージ書き込みアプリ、ラズパイの Raspbian OS、Jetson Nanoの Ubuntuの書き込みに便利
ラズパイや Jetson Nano等のワンボードマイコン等への OSイメージの書き込みが簡単にできる
FWinPiFinder ラズベリーパイ IPアドレス発見アプリ。ARPコマンドでラズパイの IPアドレスを探索発見する
Raspberry Piや NVIDIA Jetson Nano等の IPアドレスを MACアドレスの OUI部分を使用して発見する
Raspberry Pi 3系のトラブルであるある第一位の電源トラブル、低電圧警報に関する情報のまとめ
ラズパイ3B系での低電圧警報に関する情報まとめ、コマンドラインやログファイルから低電圧を検知する方法
Raspberry Piで CPUの脆弱性 Spectreと Meltdownの脆弱性をチェックする方法
ラズパイで 2018年初頭に大騒ぎになったスペクターとメルトダウンの CPUの脆弱性をチェックする方法
Raspberry Pi Zero Wを海外通販の Pimoroni等での購入方法、購入できる通販ショップ一覧まとめ
ラズパイゼロW ワイヤレスモデルを海外通販でサクッと簡単に個人輸入で入手。技適通過でも国内販売は常に品切れ
Raspberry Pi 3で安定して使える相性の無い最適な microSDカードの種類のまとめ
ラズパイ3で安定して使える microSDカードを購入する Teamと SanDiskは絶対に買わない
Raspberry Pi 3 Model Bに専用カメラモジュール RaspiCamを接続する方法
ラズパイに専用カメラモジュールを接続して Raspbianで写真の静止画撮影や動画を録画する方法
Raspberry Pi 3の Linuxコンソール上で使用する各種コマンドまとめ
ラズパイの Raspbian OSのコマンドラインで使用する便利コマンド、負荷試験や CPUシリアル番号の確認方法等も
Raspberry Pi 3公式フォーラムの FAQの内容の日本語訳
ラズパイ公式フォーラムの「The Raspberry Pi 3 Model B Q&A thread」の日本語訳
Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法
ラズパイ3の GPIO端子の I2C機能を有効にして各種センサーを繋げる方法まとめ
大人気の CPUボード、Raspberry Pi 3 Model Bで作ってみよう
Raspberry Piの開発環境の構築やタッチパネル付き液晶ディスプレイや各種センサーの使い方まとめ
Raspberry Pi関連はこちらへまとめました
下記以外にも多数のラズパイ関係の記事が有ります。
(I2C制御、GPIO制御、1-Wire制御、シリアル通信、日本語音声合成、日本語音声認識、中国語音声合成、MeCab 形態素解析エンジン、赤外線リモコン制御、秋月 I2C液晶モジュール、KeDei 3.5インチ液晶、HDMI 5インチ液晶、NFCカードリーダ、コマンドライン操作方法等)
Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板
Espressif ESP8266 ESP-12-E NodeMCU V1 ESP12 CP2102
BangGood通販はドローン以外にも面白い商品がまだまだ有った(電子工作編)
レーザー彫刻機、カラー液晶の DIYオシロ、Arduinoや Raspberry Pi用の小型カラー液晶
[HOME]
|
[BACK]
リンクフリー(連絡不要、ただしトップページ以外は Web構成の変更で移動する場合があります)
Copyright (c)
2018 FREE WING,Y.Sakamoto
Powered by 猫屋敷工房 & HTML Generator
http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_ijg_jpeg_libjpeg_turbo/