MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Qtの応用 - ImageMagickのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Qtの応用 - ImageMagick
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == ImageMagickライブラリは、画像処理を行う場合の強力なツールである。<br> 画像の読み込み、編集、変換、保存等、包括的な画像処理機能を提供している。<br> <br> ImageMagickライブラリは200以上の画像フォーマットをサポートしており、プロフェッショナルな画像処理が可能である。<br> <br> 画像の変換や編集において、ぼかし、シャープ化、回転、リサイズ等の基本的な操作から高度なフィルタ処理まで実行できる。<br> また、画像のメタデータの読み取りや編集も可能である。<br> <br> ImageMagickライブラリのパフォーマンスについて、大量の画像処理を行う場合はメモリ使用量に注意が必要となる。<br> 必要に応じて、画像のキャッシュサイズを調整することができる。<br> <br> <u>スレッド安全性のにおいて、ImageMagickライブラリは基本的にスレッドセーフであるが、初期化処理は必ずメインスレッドで行う必要がある。</u><br> <br> ImageMagickライブラリは高度な画像処理機能を提供する強力なツールとして活用できる。<br> 上記の例は基本的な使用方法の一部であり、さらに多くの機能や最適化オプションが用意されている。<br> <br><br> == ImageMagickのインストール == ==== パッケージ管理システムからインストール ==== # RHEL sudo dnf install ImageMagick-devel libMagick++-devel # SUSE sudo zypper install ImageMagick-devel libMagick++-devel <br> ==== ソースコードからインストール ==== まず、ImageMagickのビルドに必要なライブラリをインストールする。<br> # RHEL # SUSE sudo zypper install make gcc libtool libzip-devel zlib-devel libzstd-devel fontconfig-devel freetype2-devel libxml2-devel \ libdjvulibre-devel libraqm-devel liblcms2-devel pango-devel cairo-devel \ libjpeg8-devel libjxl-devel libjbig-devel openjpeg2-devel libheif-devel liblqr-devel \ libpng16-devel openexr-devel libtiff-devel libraw-devel libraw1394-devel libwebp-devel libwmf-devel <br> [https://imagemagick.org/script/install-source.php ImageMagickの公式Webサイト]または[https://github.com/ImageMagick/ImageMagick Github]にアクセスして、ソースコードをダウンロードする。<br> ダウンロードしたファイルを解凍する。<br> tar ImageMagick.tar.gz または tar xf ImageMagick-<バージョン>.tar.gz cd ImageMagick-<バージョン> <br> ImageMagickをビルドおよびインストールする。<br> mkdir build && cd build ../configure --prefix=<ImageMagickのインストールディレクトリ> \ --with-modules make -j $(nproc) make install <br> ~/.profileファイル等に、ImageMagickへの環境変数<code>PATH</code>等を追記する。<br> vi ~/.profile <br> <syntaxhighlight lang="sh"> # ~/.profileファイル等 export PATH="/<ImageMagickのインストールディレクトリ>/bin:$PATH" export LD_LIBRARY_PATH="<ImageMagickのインストールディレクトリ>/lib:$LD_LIBRARY_PATH" </syntaxhighlight> <br> ImageMagickが正しく動作していることを確認する。<br> magick logo: logo.gif identify logo.gif display logo.gif <br> ImageMagickを動作させるため、以下に示すライブラリをインストールする。<br> # RHEL sudo dnf install libraqm0 # SUSE sudo zypper install libraqm0 <br><br> == 画像の読み込み == <syntaxhighlight lang="c++"> #include <Magick++.h> // ライブラリの初期化 Magick::InitializeMagick(nullptr); // 画像の読み込み Magick::Image image; image.read("input.jpg"); </syntaxhighlight> <br><br> == 画像のサイズ変更 == <syntaxhighlight lang="c++"> #include <Magick++.h> // ライブラリの初期化 Magick::InitializeMagick(nullptr); // 画像のリサイズ image.resize(Magick::Geometry(800, 600)); </syntaxhighlight> <br><br> == 画像の保存 == <syntaxhighlight lang="c++"> #include <Magick++.h> // ライブラリの初期化 Magick::InitializeMagick(nullptr); // 画像の保存 image.write("output.png"); </syntaxhighlight> <br><br> == 画質調整 == JPEG画質の設定やノイズ除去等、画質に関する詳細な制御が可能である。<br> <syntaxhighlight lang="c++"> #include <Magick++.h> // ライブラリの初期化 Magick::InitializeMagick(nullptr); Magick::Image image("input.jpg"); // JPEG品質を85%に設定 image.quality(85); image.write("output.jpg"); </syntaxhighlight> <br><br> == エラーハンドリング == ImageMagickライブラリは、専用の例外処理を使用してエラーを処理する。<br> <br> <syntaxhighlight lang="c++"> #include <Magick++.h> // ライブラリの初期化 Magick::InitializeMagick(nullptr); try { Magick::Image image; image.read("nonexistent.jpg"); } catch (Magick::Exception &error) { qDebug() << "エラー: " << QString::fromStdString(error.what()); } </syntaxhighlight> <br><br> == 基本的な使用例 == 以下の例では、ImageMagickライブラリを使用して、画像処理 (ノイズ除去、コントラスト調整、シャープネス強調、カラーバランス調整) を行っている。<br> <br> * 非同期処理 *: QtConcurrentクラスを使用して画像処理を非同期で実行する。(メインスレッドをブロックせずに実行) *: QFutureWatcherクラスを使用して、処理の完了を監視する。 *: シグナル / スロットによる非同期通信を行う。 *: <br> * ストリーミング処理 *: 画像処理をパイプライン形式で実装する。 *: 進捗状況をリアルタイムで通知する。 *: 段階的な画像処理を行う。(ノイズ除去、コントラスト調整等) *: <br> * その他の機能 *: スマートポインタを使用したメモリ管理 <br> まず、QtプロジェクトでImageMagickを使用するには、QtプロジェクトファイルまたはCMakeLists.txtファイルを使用して、必要なライブラリをリンクする必要がある。<br> また、Pkg-configを使用する場合は、ImageMagickライブラリのパスを確認する。<br> pkg-config --modversion Magick++ pkg-config --cflags --libs Magick++ <br> * Qtプロジェクトファイルを使用する場合 <syntaxhighlight lang="make"> # pkg-configを使用 CONFIG += link_pkgconfig PKGCONFIG += Magick++ ImageMagick # より詳細な設定が必要な場合は、特定のバージョンを指定することもできる # ImageMagick 7を使用する場合 CONFIG += link_pkgconfig PKGCONFIG += Magick++-7.Q16HDRI </syntaxhighlight> * CMakeLists.txtファイルを使用する場合 <syntaxhighlight lang="cmake"> # CMakeLists.txtファイル # Qt 5 または Qt 6コンポーネントを検索 find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Concurrent) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Concurrent) if(NOT Qt${QT_VERSION_MAJOR}_FOUND) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Concurrent) endif() pkg_check_modules(QT_CORE Qt${QT_VERSION_MAJOR}Core REQUIRED IMPORTED_TARGET) pkg_check_modules(QT_CORE Qt${QT_VERSION_MAJOR}Concurrent REQUIRED IMPORTED_TARGET) # ImageMagick++を検索 find_package(ImageMagick REQUIRED COMPONENTS Magick++) if(NOT ImageMagick_FOUND) message(FATAL_ERROR "ImageMagick++が見つかりません") endif() # インクルードディレクトリを設定 target_include_directories(${PROJECT_NAME} PRIVATE # ...略 ${ImageMagick_INCLUDE_DIRS} ) # 各ライブラリをリンク target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Concurrent ${ImageMagick_LIBRARIES} ) </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // ImageProcessor.hファイル #include <QObject> #include <QFile> #include <QFuture> #include <QFutureWatcher> #include <QtConcurrent> #include <memory> #include <stdexcept> #include <Magick++.h> #include <QDebug> class ImageProcessor : public QObject { Q_OBJECT private: std::unique_ptr<QFutureWatcher<void>> m_futureWatcher; // 画像処理の実装 void processImage(const QString& inputPath, const QString& outputPath) { try { // ImageMagickの初期化 Magick::InitializeMagick(nullptr); // 画像の読み込み Magick::Image image; image.read(inputPath.toStdString()); // ストリーミング処理の実行 processImageStream(image); // 画像の保存 image.write(outputPath.toStdString()); emit progressUpdated(100); } catch (const Magick::Exception &e) { throw std::runtime_error(QString("ImageMagick処理エラー: %1").arg(e.what()).toStdString()); } catch (const std::exception &e) { throw std::runtime_error(QString("一般エラー: %1").arg(e.what()).toStdString()); } } // ストリーミング処理の実装 void processImageStream(Magick::Image& image) { try { // 画像処理のパイプライン // 1. ノイズ除去 image.reduceNoise(); emit progressUpdated(25); // 2. コントラスト調整 image.normalize(); emit progressUpdated(50); // 3. シャープネス強調 image.sharpen(0, 1.0); emit progressUpdated(75); // 4. カラーバランス調整 image.modulate(100, 100, 100); emit progressUpdated(90); } catch (Magick::Exception &e) { qDebug() << "エラー: " << QString::fromStdString(e.what()); } catch (const Magick::Exception &e) { throw std::runtime_error(QString("ストリーム処理エラー: %1").arg(e.what()).toStdString()); } } public: explicit ImageProcessor(QObject* parent = nullptr) : QObject(parent), m_futureWatcher(std::make_unique<QFutureWatcher<void>>()) { // 非同期処理完了時のシグナルとスロットを接続 connect(m_futureWatcher.get(), &QFutureWatcher<void>::finished, this, &ImageProcessor::handleProcessingFinished); } ~ImageProcessor() = default; // 画像処理を開始する void processImageAsync(const QString& inputPath, const QString& outputPath) { try { // 入力ファイルの存在確認 if (!QFile::exists(inputPath)) { emit errorOccurred("入力ファイルが存在しない: " + inputPath); return; } // 非同期処理を開始 QFuture<void> future = QtConcurrent::run([this, inputPath, outputPath]() { try { processImage(inputPath, outputPath); } catch (const std::exception& e) { // 非同期処理内でのエラーをメインスレッドに通知 QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, Q_ARG(QString, QString("画像処理エラー: %1").arg(e.what()))); } }); m_futureWatcher->setFuture(future); } catch (const std::exception &e) { emit errorOccurred(QString("非同期処理の開始に失敗: %1").arg(e.what())); } } signals: void progressUpdated(int percentage); // 進捗状況を通知するシグナル void processingCompleted(); // 処理完了を通知するシグナル void errorOccurred(const QString& error); // エラーを通知するシグナル private slots: // 非同期処理完了時のスロット void handleProcessingFinished() { try { // 非同期処理の結果を確認 m_futureWatcher->result(); emit processingCompleted(); } catch (const std::exception& e) { emit errorOccurred(QString("処理完了時のエラー: %1").arg(e.what())); } } }; </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // main.cppファイル #include <QCoreApplication> #include "ImageProcessor.h" int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); ImageProcessor processor; // 進捗処理シグナルの接続 QObject::connect(&processor, &ImageProcessor::progressUpdated, [](int percentage) { qDebug() << "進捗: " << percentage << "%"; }); // 処理完了シグナルの接続 QObject::connect(&processor, &ImageProcessor::processingCompleted, []() { qDebug() << "処理が完了しました"; QCoreApplication::quit(); }); // エラーシグナルの接続 QObject::connect(&processor, &ImageProcessor::errorOccurred, [](const QString& error) { qDebug() << "エラー: " << error; QCoreApplication::quit(); }); // 画像処理の開始 processor.processImageAsync("input.jpg", "output.jpg"); return app.exec(); } </syntaxhighlight> <br><br> == 画像のリサイズと形式変換 == <syntaxhighlight lang="c++"> #include <Magick++.h> #include <stdexcept> #include <filesystem> /** * @brief 画像のリサイズと形式変換を行う * @param inputPath 入力画像のパス * @param outputPath 出力画像のパス * @param width 目標の幅 * @param height 目標の高さ * @param maintainAspectRatio アスペクト比を維持するかどうか */ void resizeAndConvert(const std::string& inputPath, const std::string& outputPath, size_t width, size_t height, bool maintainAspectRatio = true) { try { Magick::Image image(inputPath); image.resize(Magick::Geometry(width, height, 0, 0, maintainAspectRatio)); image.quality(90); // JPEG品質を設定 image.write(outputPath); } catch (const Magick::Exception& e) { throw std::runtime_error("リサイズ処理でエラーが発生: " + std::string(e.what())); } } // 使用例 try { // 画像のリサイズと形式変換 ImageUtils::resizeAndConvert("input.jpg", "output.png", 800, 600 ); } catch (const std::exception &e) { std::cerr << "エラーが発生: " << e.what() << std::endl; return -1; } </syntaxhighlight> <br><br> == フィルタの適用 == <syntaxhighlight lang="c++"> #include <Magick++.h> #include <stdexcept> /** * @brief 画像に各種フィルタを適用する * @param inputPath 入力画像のパス * @param outputPath 出力画像のパス * @param blurRadius ぼかしの半径 * @param sharpenRadius シャープの半径 */ void applyFilters(const std::string& inputPath, const std::string& outputPath, double blurRadius = 0.0, double sharpenRadius = 0.0) { try { Magick::Image image(inputPath); // ノイズ除去 image.reduceNoise(); // ぼかし処理 (指定された場合) if (blurRadius > 0.0) { image.blur(0.0, blurRadius); } // シャープ処理 (指定された場合) if (sharpenRadius > 0.0) { image.sharpen(0.0, sharpenRadius); } // コントラスト調整 image.normalize(); image.write(outputPath); } catch (const Magick::Exception &e) { throw std::runtime_error("フィルタ処理でエラーが発生: " + std::string(e.what())); } } // 使用例 try { applyFilters("input.jpg", "filtered.jpg" 2.0, // ブラー 1.0 // シャープ ); } catch (const std::exception &e) { std::cerr << "エラーが発生: " << e.what() << std::endl; return -1; } </syntaxhighlight> <br><br> == 透かしの追加 == <syntaxhighlight lang="c++"> #include <Magick++.h> #include <stdexcept> /** * @brief 画像に透かしを追加する * @param inputPath 入力画像のパス * @param watermarkPath 透かし画像のパス * @param outputPath 出力画像のパス * @param opacity 透かしの不透明度(0.0-1.0) */ void addWatermark(const std::string& inputPath, const std::string& watermarkPath, const std::string& outputPath, double opacity = 0.5) { try { Magick::Image baseImage(inputPath); Magick::Image watermark(watermarkPath); // 透かしのサイズを調整 (元画像の1/4サイズにリサイズ) watermark.resize(Magick::Geometry(baseImage.columns() / 4, baseImage.rows() / 4)); // 透かしの不透明度を設定 watermark.opacity(static_cast<unsigned int>(65535 * (1.0 - opacity))); // 透かしを右下に配置 baseImage.composite(watermark, baseImage.columns() - watermark.columns() - 10, baseImage.rows() - watermark.rows() - 10, Magick::OverCompositeOp); baseImage.write(outputPath); } catch (const Magick::Exception &e) { throw std::runtime_error("透かし処理でエラーが発生: " + std::string(e.what())); } } // 使用例 try { addWatermark("input.jpg", "watermark.png", "watermarked.jpg", // 透かし画像 0.7 // 透かしのOpacity ); } catch (const std::exception &e) { std::cerr << "エラーが発生: " << e.what() << std::endl; return -1; } </syntaxhighlight> <br><br> == バッチ処理 (画像の一括変換) == <syntaxhighlight lang="c++"> #include <Magick++.h> #include <filesystem> #include <vector> #include <stdexcept> /** * @brief 画像のバッチ処理(一括リサイズ)を行う * @param inputDir 入力ディレクトリ * @param outputDir 出力ディレクトリ * @param width 目標の幅 * @param height 目標の高さ * @param extensions 処理対象の拡張子リスト */ void batchResize(const std::string& inputDir, const std::string& outputDir, size_t width, size_t height, const std::vector<std::string>& extensions = {".jpg", ".jpeg", ".png"}) { namespace fs = std::filesystem; try { // 出力ディレクトリが存在しない場合は作成 if (!fs::exists(outputDir)) fs::create_directories(outputDir); // ディレクトリ内のファイルを走査 for (const auto& entry : fs::directory_iterator(inputDir)) { if (!entry.is_regular_file()) continue; // 拡張子のチェック std::string ext = entry.path().extension().string(); std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); if (std::find(extensions.begin(), extensions.end(), ext) != extensions.end()) { std::string outPath = (fs::path(outputDir) / entry.path().filename()).string(); resizeAndConvert(entry.path().string(), outPath, width, height); } } } catch (const std::exception &e) { throw std::runtime_error("バッチ処理でエラーが発生: " + std::string(e.what())); } } // 使用例 try { // 1024x768に変換 batchResize("input_folder", "output_folder", 1024, 768); } catch (const std::exception &e) { std::cerr << "エラーが発生: " << e.what() << std::endl; return -1; } </syntaxhighlight> <br><br> == 画像に効果を適用 (セピア、モノクロ等) == <syntaxhighlight lang="c++"> #include <Magick++.h> #include <stdexcept> /** * @brief 画像に効果を適用する(セピア、モノクロなど) * @param inputPath 入力画像のパス * @param outputPath 出力画像のパス * @param effectType 効果の種類(1:セピア, 2:モノクロ, 3:ネガティブ) */ void applyEffect(const std::string& inputPath, const std::string& outputPath, int effectType) { try { Magick::Image image(inputPath); switch (effectType) { case 1: // セピア image.modulate(100, 50, 100); // 彩度を下げる image.colorize(30, 30, 0, "rgb(112,66,20)"); break; case 2: // モノクロ image.type(Magick::GrayscaleType); break; case 3: // ネガティブ image.negate(); break; default: throw std::runtime_error("未知の効果タイプです"); break; } image.write(outputPath); } catch (const Magick::Exception &e) { throw std::runtime_error("効果の適用でエラーが発生: " + std::string(e.what())); } } // 使用例 try { applyEffect("input.jpg", "sepia.jpg", 1 // セピア効果 ); } catch (const std::exception &e) { std::cerr << "エラーが発生: " << e.what() << std::endl; return -1; } </syntaxhighlight> <br><br> == 画像形式の変換 == <syntaxhighlight lang="c++"> #include <Magick++.h> #include <stdexcept> /** * @brief 画像形式を変換する(例:JPG → PNG) * @param inputPath 入力画像のパス * @param outputPath 出力画像のパス(拡張子で形式を判断) * @param quality 出力画質(0-100) */ void convertFormat(const std::string& inputPath, const std::string& outputPath, int quality = 90) { try { Magick::Image image(inputPath); image.quality(quality); image.write(outputPath); } catch (const Magick::Exception &e) { throw std::runtime_error("形式変換でエラーが発生: " + std::string(e.what())); } } </syntaxhighlight> <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Qt]]
Qtの応用 - ImageMagick
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse