Help us understand the problem. What is going on with this article?

Binary Builderを使っていろいろ埋め込んでみた

More than 1 year has passed since last update.

はじめに

JUCE Advent Calendar 2017 8日目 二回目の参加になります。 kawaです。
今回はJUCEライブラリにこっそりついてくる BinaryBuilder について調べてみました。
間違っている部分はコメント欄にてご教授いただけると嬉しいです。
( JUCE v5.11 でこの記事を書いています。)

Binary Builderとは?

  • 画像やフォント、リソースファイルをバイナリデータとしてC++ソースに出力するコンソールアプリ。

リソースファイルをバイナリソースにする方法は Projucer アプリでも可能。

今回は ProJucer を使わずに BinaryBuilder を使用してみたいと思います。

Binary Builder の準備

Binary BuilderのプロジェクトファイルはJUCEの extras フォルダにこっそり入っています。

01_BinaryBuilder.png

プロジェクトファイルを使ってコンパイルを終えたところ。

02_BinaryBuilder_2.PNG

使い方の説明

Binary Builder はコンソールアプリなので、
コマンドプロンプト、ターミナル の中で使用していきます。

$binaryBuilder  sourceDirectory  destDirectory  (targetClassName)

第1引数 : バイナリにしたいファイルをまとめたフォルダのディレクトリ
第2引数 : 出力するディレクトリの場所 (ディレクトリが存在しない場合はエラーが出るようです。)
第3引数 : 出力するソースファイルの名前
ヘルプは -help オプションで表示できるようです。

Buinary Builderを使ってみた

テスト用として あらかじめ TestResource フォルダの中に猫画像を3枚 、そして出力先の OutPut フォルダを準備して実行してみました。

$binaryBuilder  TestResource OutPut TestResource

第1引数 : TestResource : バイナリソースにしたいフォルダパス
第2引数 : OutPut : 出力先のフォルダパス
第3引数 : TestResource : 出力するソースの名前

[画像] OutPutフォルダの中身

TestResource.h
/* (Auto-generated binary data file). */

#pragma once

namespace TestResource
{
    extern const char*  img_koma_01_jpg;               // 1枚目の画像のデータ
    const int           img_koma_01_jpgSize = 87341;   // 1枚目の画像のデータのサイズ

    extern const char*  img_koma_02_jpg;               // 2枚目の画像のデータ
    const int           img_koma_02_jpgSize = 126548;  // 2枚目の画像のデータのサイズ

    extern const char*  img_koma_03_jpg;               // 3枚目の画像のデータ
    const int           img_koma_03_jpgSize = 87332;   // 3枚目の画像のデータのサイズ

}

無事にOutPutフォルダに出力できているようです。ソースの中身を見てみると3枚分の画像のデータが書き出されていました。
実際にJUCEの中で使ってみたいと思います。

実際にいろいろ使ってみた

1. 画像を埋め込んでみた

Koma_2.PNG

// 1枚目 : Binary Builder を使って出力したソースと
// ImageCacheクラスを経由してImageクラスを作成
this->m_img1 = juce::ImageCache::getFromMemory( TestResource::img_koma_01_jpg         // データ(1枚目)
                                              , TestResource::img_koma_01_jpgSize  ); // サイズ(1枚目)
this->m_img1 = m_img1.rescaled( m_img1.getWidth()  * 0.2 
                              , m_img1.getHeight() * 0.2 ); // 画像が大きかったので縮小

// 2枚目
this->m_img2 = juce::ImageCache::getFromMemory( TestResource::img_koma_02_jpg         // データ(2枚目)
                                              , TestResource::img_koma_02_jpgSize  ); // サイズ(2枚目)
this->m_img2 = m_img2.rescaled( m_img2.getWidth()  * 0.2 
                              , m_img2.getHeight() * 0.2 ); // rescale

// 3枚目 省略 ... 

//=============================================================================
// 描画するとき
// g.drawImageAt( m_img1 , x ,y , false );
// x += m_img1.getWidth() + 5; //margin 5 2枚目の座標
// ....

2. フォントを埋め込んでみた

06_BinaryBuilder_Font.PNG

今度はフォントを BinaryBuilder でC++ソースにして、日本語を表示してみました。

//=========================================================================  
// ソースファイル自体をUTF-8(BOMありで保存しておく。) 
juce::String text = JUCE_T( "春はあけぼの\nやうやう白くなりゆく山ぎは\n少しあかりて" );
//=========================================================================  

// Binary Builder を使って出力したソースと
// TypeFaceクラスを経由してFontクラスを作成
this->m_font1 = juce::Font( juce::Typeface::createSystemTypefaceFor( TestResource::VLGothicRegular_ttf          // データ ( フォント)
                                                                   , TestResource::VLGothicRegular_ttfSize ) ); // サイズ ( フォント)
this->m_font1.setHeight( 40.0f ); //フォントのサイズ変更

//=========================================================================                                                                 
// 描画するとき
// g.setFont ( this->m_font1 ); 
// g.drawFittedText( text ...
  • 細かい部分は未検証ですが、もしも読み込んだフォントで表示できない場合は Regular 体 を含むフォントで試してみると解決するかもしれないです。

使用したフォント

3. zipファイルを埋め込んでみた

ふと、zipファイルも埋め込んで解凍できるかもしれない。と気になって試してみました。

//=========================================================================
// あらかじめBinary Builder を使って出力したソースと
// MemoryInputStream を経由して ZipFileクラスを作成。
juce::MemoryInputStream stream ( TestResource::test_zip      // データ
                               , TestResource::test_zipSize  // サイズ
                               , false );                    
juce::ZipFile zip( stream ); // ZipFile クラスをInputStreamクラスから作成
//=========================================================================

const int totalEntryNum = zip.getNumEntries();//zipファイル内のすべてのエントリー数を取得
for ( int i = 0; i < totalEntryNum; ++i)
{
    const juce::ZipFile::ZipEntry* entry = zip.getEntry( i );
    DBG( entry->filename  ); // ファイル名をコンソールに出力。( デバッグ表示用
}
//=========================================================================
出力(デバッグ)
img_koma_01.jpg
img_koma_02.jpg
img_koma_03.jpg
makuranosousi.txt
VL-Gothic-Regular.ttf

無事に埋め込んだzipファイルを読み込んでいるようです。
( zipファイルの中に猫画像とフォント、サンプルテキストを入れてみました。)

4. zipファイルから画像を表示してみた

07.PNG

今度は、zipファイルの中にある画像の表示について調べてみました。

//=============================================================================
// MemoryInputStream を経由して ZipFileクラスを作成。
juce::MemoryInputStream stream ( TestResource::test_zip     // データ
                               , TestResource::test_zipSize // サイズ
                               , false);
juce::ZipFile zip( stream );
//=============================================================================

// zipファイルのインデックスを zip内のファイルパスから取得。
const int targetZipEntryIndex = zip.getIndexOfFileName( "img_koma_01.jpg" ); 
//=============================================================================
if( targetZipEntryIndex != -1) // ファイルが見つかった場合.
{
    // 画像 を InputStreamクラス、MemoryBlock クラスを経由して Imageクラス を作成
    juce::ScopedPointer<juce::InputStream> inputStream = zip.createStreamForEntry( targetZipEntryIndex );
    juce::MemoryBlock memoryBlock;
    inputStream->readIntoMemoryBlock( memoryBlock );
    this->m_img = juce::ImageCache::getFromMemory( memoryBlock.getData()    // データ
                                                 , memoryBlock.getSize() ); // サイズ
    //=========================================================================
    this->m_img = m_img.rescaled( m_img.getWidth() *0.2, m_img.getHeight() *0.2 );// rescale
}

//=============================================================================
// 描画する時
// g.drawImageAt( m_img, 10, 10, false );

5. zipファイルからフォントを使ってみた

07.PNG

画像が表示できるなら、きっとzipファイルの中にあるフォントも読み込めるはず、と調べてみました。

//=========================================================================
// MemoryInputStream クラスを作成して ZipFileクラスを作成。
juce::MemoryInputStream stream ( TestResource::test_zip      // データ
                               , TestResource::test_zipSize  // サイズ
                               , false);
juce::ZipFile zip( stream );
//=========================================================================

// 猫画像部分 省略
//=========================================================================
const int targetTextIndex = zip.getIndexOfFileName( "makuranosousi.txt" );     // テキストファイル 
const int targetFontIndex = zip.getIndexOfFileName( "VL-Gothic-Regular.ttf" ); // フォントファイル
//=========================================================================
if (  targetTextIndex != -1
   && targetFontIndex != -1 )
{
    // サンプルテキストとして InputStreamクラス、MemoryBlockクラスを経由して Stringクラス を作成
    //=====================================================================
    juce::ScopedPointer<juce::InputStream> inputStream_txt = zip.createStreamForEntry( targetTextIndex );
    juce::MemoryBlock memoryBlock_txt;
    inputStream_txt->readIntoMemoryBlock( memoryBlock_txt );
    this->m_drawText = memoryBlock_txt.toString();
    //=====================================================================

    // 日本語フォントを InputStreamクラス、MemoryBlock クラスを経由して Fontクラス を作成
    juce::ScopedPointer<juce::InputStream> inputStream_font = zip.createStreamForEntry( targetFontIndex );
    juce::MemoryBlock memoryBlock_font;
    inputStream_font->readIntoMemoryBlock( memoryBlock_font );
    this->m_font = juce::Font( juce::Typeface::createSystemTypefaceFor( memoryBlock_font.getData()
                                                                      , memoryBlock_font.getSize() ));
    this->m_font.setHeight( 30.f ); // フォントサイズ
    //=====================================================================
}

// 描画 するとき
//=========================================================================
// g.setColour( juce::Colours::black );
// g.setFont  ( m_font );
// g.drawFittedText( m_drawText , .... 
//=========================================================================

結び

もしも内容に間違いがありましたら、コメント欄にて教えていただけると嬉しいです。

JUCEライブラリを扱っていると、やっぱり「なるほど~」と納得する部分があります。
僕も見習いたいと思っています。

この投稿が公開される日は12月8日。そろそろ年賀状に取り掛かりたい、と思いつつ・・時間は過ぎていくのでした。
よい年末をお過ごしください。

それでは、明日の Astellon さんへバトンタッチ。
ありがとうございました!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away