HOME
  Security
   Software
    Hardware
  
FPGA
  CPU
   Android
    Raspberry Pi
  
nLite
  Xcode
   etc.
    ALL
  
English Translate 中文翻訳
LINK
BACK
 

[NEW] 2018/09/15

Raspberry Piの C言語で JPEG画像ライブラリ libjpegや libjpeg_turboを使ってみるサンプル 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をビルドするのに飽きたのが理由


[NEW] 2018/09/01
Raspberry Pi 3用に NEONと VFPV3を有効化して最適化版の OpenCVをビルドする方法
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], [電子工作]

●関連するコンテンツ(この記事を読んだ人は、次の記事も読んでいます)

Raspberry Pi 3B系のトラブルであるある第一位の電源トラブル、低電圧警報に関する情報のまとめ
Raspberry Pi 3B系のトラブルであるある第一位の電源トラブル、低電圧警報に関する情報のまとめ

  ラズパイ系での低電圧警報に関する情報まとめ、コマンドラインやログファイルから低電圧を検知する方法

Raspberry Piで CPUの脆弱性 Spectreと Meltdownの脆弱性をチェックする方法
Raspberry Piで CPUの脆弱性 Spectreと Meltdownの脆弱性をチェックする方法

  ラズパイで 2018年初頭に大騒ぎになったスペクターとメルトダウンの CPUの脆弱性をチェックする方法

Raspberry Pi Zero Wを海外通販の Pimoroni等での購入方法、購入出来る通販ショップ一覧まとめ
Raspberry Pi Zero Wを海外通販の Pimoroni等での購入方法、購入出来る通販ショップ一覧まとめ

  ラズパイゼロW ワイヤレスモデルを海外通販でサクッと簡単に個人輸入で入手。技適通過でも国内販売は常に品切れ

Raspberry Pi 3で安定して使える相性の無い最適な microSDカードの種類のまとめ
Raspberry Pi 3で安定して使える相性の無い最適な microSDカードの種類のまとめ

  ラズパイ3で安定して使える microSDカードを購入する Teamと SanDiskは絶対に買わない

Raspberry Pi 3 Model Bに専用カメラモジュール RaspiCamを接続する方法
Raspberry Pi 3 Model Bに専用カメラモジュール RaspiCamを接続する方法

  ラズパイに専用カメラモジュールを接続して Raspbianで写真の静止画撮影や動画を録画する方法

Raspberry Pi 3の Linuxコンソール上で使用する各種コマンドまとめ
Raspberry Pi 3の Linuxコンソール上で使用する各種コマンドまとめ

  ラズパイの Raspbian OSのコマンドラインで使用する便利コマンド、負荷試験や CPUシリアル番号の確認方法等も

Raspberry Pi 3公式フォーラムの FAQの内容の日本語訳
Raspberry Pi 3公式フォーラムの FAQの内容の日本語訳

  ラズパイ公式フォーラムの「The Raspberry Pi 3 Model B Q&A thread」の日本語訳

Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法
Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法

  ラズパイ3の GPIO端子の I2C機能を有効にして各種センサーを繋げる方法まとめ

大人気の CPUボード、Raspberry Pi 3 Model Bで作ってみよう
大人気の CPUボード、Raspberry Pi 3 Model Bで作ってみよう

  Raspberry Piの開発環境の構築やタッチパネル付き液晶ディスプレイや各種センサーの使い方まとめ


Raspberry Pi 3、シングルボードコンピュータ ラズパイ3 Raspberry Pi関連はこちらへまとめました
 下記以外にも多数のラズパイ関係の記事が有ります。
 (I2C制御、GPIO制御、1-Wire制御、シリアル通信、日本語音声合成、日本語音声認識、中国語音声合成、MeCab 形態素解析エンジン、赤外線リモコン制御、秋月 I2C液晶モジュール、KeDei 3.5インチ液晶、HDMI 5インチ液晶、NFCカードリーダ、コマンドライン操作方法等)
Raspberry Pi 3に HDMI接続の 800x480 5インチ TFT液晶を接続して使用する方法
Raspbian Jessie 2017-07最終版で LIRCを使って学習リモコン、赤外線リモコンを送受信する方法
Raspberry Pi 3の WiFiを広告ブロック機能付きの無線LANアクセスポイント化 hostapd + dnsmasq編
Raspberry Pi 3の Bluetoothで ブルテザで通信する方法(Bluetooth編)
Raspberry Pi 3で日本語音声を合成して喋らせる方法(OpenJTalk編)
Raspberry Pi 3に USB Micを接続して日本語の音声認識をする方法(Julius編)
Raspberry Pi 3の GPIOに LEDとスイッチを接続して Lチカする方法
Raspberry Pi 3の GPIOに LEDとスイッチを接続してシャットダウンボタンを実装する方法
Raspberry Pi 3で GPIO端子の I2C機能を有効化する方法
Raspberry Pi 3の GPIOに I2C通信方式の気圧計 BMP280を接続する方法
Raspberry Pi 3に I2C通信方式の NFCリーダライタ PN532を接続して NFC FeliCaカードを読む方法
Raspberry Pi 3でネットワーク ライブカメラを構築する方法 Motion編
Raspberry Pi 3でネットワーク ライブカメラを構築する方法 MJPG-streamer編
Raspberry Pi 3 Model Bで動画処理アプリ FFmpegをコンパイルする方法
Raspberry Pi3の X-Window Systemに Windowsのリモートデスクトップから接続する方法
Raspberry Pi3に WebRTCの STUN/TRUNサーバと PeerJSサーバをインストールする方法
【成功版】Raspberry Piで NNPACK対応版の Darknet Neural Network Frameworkをビルドする方法


Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板
Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板

  Espressif ESP8266 ESP-12-E NodeMCU V1 ESP12 CP2102

BangGood通販はドローン以外にも面白い商品がまだまだ有った(電子工作編)
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/