画像のピンチイン、ピンチアウト

画像のピンチイン、ピンチアウト

これは、Viewの拡大、縮小に使う

画像をピンチイン、ピンチアウトするには
Bitmapクラスと
ScaleGestureDetectorクラスを
メンバ変数に持つ独自Viewクラスを作成する

独自Viewクラスでは、
コンストラクタの実装と
onDraw()
onTouchEvent()
のOverrideをする

まず、

class MyView extends View

でViewを継承

そして、メンバ変数の宣言 

private Bitmap mBitmap;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.0f;

そして、コンストラクタの実装

public MyView(Context context){

super(context);
try{
InputStream is = getResources().getAssets().open("test.jpg");
mBitmap = BitmapFactory.decodeStream(is);
}catch(Exception e){
}
mScaleDetector = new ScaleGestureDetector(context, 
new ScaleGestureDetector.SimpleOnScaleGestureListener(){

@Override
public boolean onScale(ScaleGestureDetector detector){

mScaleFactor *= detector.getScaleFactor();
invalidate();
return true;
}
}
);
}

次に、onDraw()の実装

protected void onDraw(Canvas canvas){

canvas.save();

canvas.scale(mScaleFactor, mScaleFactor);

canvas.drawBitmap(mBitmap, 0,0, null);

canvas.restore();
}

そして、onTouchEvent()のOverride

public boolean onTouchEvent(MotionEvent e){
mScaleDetector.onTouchEvent(e);
return true;
}

コンストラクタでは、画像読み込みと
ScaleGestureDetectorクラスの生成をする

ScaleGestureDetectorクラスの
コンストラクタに
SimpleOnScaleGestureListenerクラスをパラメーター指定することで
スケール変更に関するイベントを処理できるようになる

SimpleOnScaleListenerクラスの
onScale()で
スケール計算と
再描画を促すために
Viewクラスのinvalidate()を呼び出す

そして、onDraw()で
スケール設定と
画像の描画を実装

onTouchEvent()では、
ScaleGestureDetectorクラスの
onTouchEvent()を呼び出す

画像のピンチイン、ピンチアウト

画像のピンチイン、ピンチアウト

これは、Viewの拡大、縮小に使う

画像をピンチイン、ピンチアウトするには
Bitmapクラスと
ScaleGestureDetectorクラスを
メンバ変数に持つ独自Viewクラスを作成する

独自Viewクラスでは、
コンストラクタの実装と
onDraw()
onTouchEvent()
のOverrideをする

まず、

class MyView extends View

でViewを継承

そして、メンバ変数の宣言 

private Bitmap mBitmap;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.0f;

そして、コンストラクタの実装

public MyView(Context context){

super(context);
try{
InputStream is = getResources().getAssets().open("test.jpg");
mBitmap = BitmapFactory.decodeStream(is);
}catch(Exception e){
}
mScaleDetector = new ScaleGestureDetector(context, 
new ScaleGestureDetector.SimpleOnScaleGestureListener(){

@Override
public boolean onScale(ScaleGestureDetector detector){

mScaleFactor *= detector.getScaleFactor();
invalidate();
return true;
}
}
);
}

次に、onDraw()の実装

protected void onDraw(Canvas canvas){

canvas.save();

canvas.scale(mScaleFactor, mScaleFactor);

canvas.drawBitmap(mBitmap, 0,0, null);

canvas.restore();
}

そして、onTouchEvent()のOverride

public boolean onTouchEvent(MotionEvent e){
mScaleDetector.onTouchEvent(e);
return true;
}

コンストラクタでは、画像読み込みと
ScaleGestureDetectorクラスの生成をする

ScaleGestureDetectorクラスの
コンストラクタに
SimpleOnScaleGestureListenerクラスをパラメーター指定することで
スケール変更に関するイベントを処理できるようになる

SimpleOnScaleListenerクラスの
onScale()で
スケール計算と
再描画を促すために
Viewクラスのinvalidate()を呼び出す

そして、onDraw()で
スケール設定と
画像の描画を実装

onTouchEvent()では、
ScaleGestureDetectorクラスの
onTouchEvent()を呼び出す


から送られてきた高速メモ帳

raspberry pi で無線LAN

raspberry pi で無線LAN

Raspberry Pi には有線LANのポートしかないけど
USBアダプタタイプのWiFiアダプタを使えば
Raspberry Pi でも無線LANが使える

注意点としては WiFi アダプタを使うには
消費電力が大きいため
Raspberry Pi へ直接さすのではなく
セルフパワー形式のUSBハブ経由で接続する

今回使用した部品は
【Amazon.co.jp限定】PLANEX 無線LAN子機 (USBアダプター型) 11n/g/b 150Mbps GW-USNANO2A (FFP)

iBUFFALO USB2.0ハブ セルフ&バスパワー 4ポート ACアダプタ付 ブラック 【PlayStation4,PS4 動作確認済】 パソコン/液晶TV[REGZA][AQUOS]対応 BSH4A01BK

使用した本体は
Raspberry Pi Type B 512MB ケースセット Pi Tin for the Raspberry Pi – Clear

まずは WiFiアダプタが Raspberry Pi で使えるか確認する

sudo tail -f /var/log/messages 

で直近のログ10項目を出力できる

ログは

Aug 10 20:28:52 raspberrypi kernel: [    4.536558] usb 1-1.3.1: Product: GW-USNANO2
Aug 10 20:28:52 raspberrypi kernel: [    4.536566] usb 1-1.3.1: Manufacturer: Planex Communications Inc.
Aug 10 20:28:52 raspberrypi kernel: [    4.536574] usb 1-1.3.1: SerialNumber: 00e04c000001
Aug 10 20:28:52 raspberrypi kernel: [    6.950191] bcm2708-i2s bcm2708-i2s.0: Failed to create debugfs directory
Aug 10 20:28:52 raspberrypi kernel: [    8.706115] usbcore: registered new interface driver rtl8192cu
Aug 10 20:28:52 raspberrypi kernel: [   11.921089] EXT4-fs (mmcblk0p6): re-mounted. Opts: (null)
Aug 10 20:28:52 raspberrypi kernel: [   12.605644] EXT4-fs (mmcblk0p6): re-mounted. Opts: (null)
Aug 10 20:28:52 raspberrypi kernel: [   22.039343] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
Aug 10 20:28:52 raspberrypi kernel: [   23.661375] smsc95xx 1-1.1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
Aug 10 20:28:54 raspberrypi kernel: [   28.335735] Adding 102396k swap on /var/swap.  Priority:-1 extents:1 across:102396k SSFS

この中で確認するべきは
raspberrypi kernel: [ 4.536558] usb 1-1.3.1: Product: GW-USNANO2

raspberrypi kernel: [ 8.706115] usbcore: registered new interface driver rtl8192cu
の部分

Product: GW-USNANO2
が製品名

driver rtl8192cu
がドライバになる

なおログ出力状態からでるには
Ctrl + c
ででれる

次に、無線LANのデバイスを認識しているか調べるために

iwconfig

を実行

これで

wlan0     unassociated  Nickname:"<WIFI@REALTEK>"
          Mode:Managed  Frequency=2.412 GHz  Access Point: Not-Associated   
          Sensitivity:0/0  
          Retry:off   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality:0  Signal level:0  Noise level:0
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

lo        no wireless extensions.

eth0      no wireless extensions.

というように
wlan0 がでていればOK

もし有線LANだけしか認識していないなら
eth0 しかでない

次にコマンドラインから無線LANへの接続

デスクトップ環境をたちあげることで設定もできるけど
コマンドラインで設定できる方法をしっていれば
SSH経由で設定もできる

まずはSSIDを調べる

sudo iwlist wlan0 scan

これで
実行結果の中で ESSID のところにアクセスポイントがでるのでこれを覚えておく

次に、SSIDとパスワードの設定

sudo sh -c "wpa_passphrase SSID名 無線LANのパスワード >> /etc/wpa_supplicant/wpa_supplicant.conf"

とする

もし
SSIDが test
パスワードが password なら

sudo sh -c "wpa_passphrase test password >> /etc/wpa_supplicant/wpa_supplicant.conf"

となる

これで設定できたかを調べるには

sudo cat /etc/wpa_supplicant/wpa_supplicant.conf 

とすればOK

ここまでできたら、無線LAN機能を再起動する

sudo ifdown wlan0
sudo ifup wlan0

これで無線LAN機能が再起動するので

iwconfig

で状態を確認する

もし無線LANの IP アドレスなどを知りたいのなら

ifconfig

とすれば無線LANでのIPも見ることができる

大きい画像の表示

大きい画像の表示

大きな画像は、リサンプルして読み込むことで
読み込み速度の向上
大きな画像を読み込むときに問題になる
OutOfMemoryを未然に防ぐことができる

まずは、画像情報の取得

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds();

input = getContentResolver().openInputStream(imageUri);
BitmapFactory.decodeStream(input,null,options);

次に、リサンプルの計算

int inSampleSize = calculateInSampleSize(options,MAX_IMAGE_SIZE, MAX_IMAGE_SIZE);

そして、ユーザー関数 calculateInImageSize()の定義

これは、必要な画像サイズを渡すと
そのサイズにあったリサンプル値を返す

private int calculateInSampleSize(BitmapFactory.Options, int reqWidth, int reqHeight){

final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if(height > reqHeight || width > reqWidth){

if(width > height){

inSampleSize = Math.round((float)height / (float)reqHeight);

}else{

inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}

これで、値の算出ができるので
次に、リサンプルして画像を読み込む

options.inJustDecodeBounds = false;
options.inSampleSize = inSampleSize;

input = getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(input,null,options);

大きな画像を読み込むと
画像が端末のメモリに入りきらず
OutOfMemoryが発生してアプリが終了することがある

これをふせぐため
画像の情報を事前に読み込み 
幅、高さからリサンプル値を求め
画像に適切な大きさにすることで
OutOfMemoryを防止できる

今回、画像情報を読み込むため
BitmapFactory.Optionsの
inJustDecodeBoundsフラグを trueにして
画像のヘッダ情報だけ読み込む

この場合、画像本体は読み込んでないので高速に処理できる

その後に、画像情報からリサンプル値を求め
再度
inJustDecodeBoundsにfalseを設定することで
画像全体を読み込む

つまり、
inJustDecodeBoundsが
trueならヘッダ情報だけ
falseなら全部読み込む

このときにinSampleSizeにリサンプル値を設定することで
適切な解像度で画像を読み込める

画像の反射表示

画像の反射表示

画像の反射は、オリジナル画像と反転した画像を縦に並ぶように配置し
反転画像の部分に
グラデーションを重ねるように描画することで実現する

まずは、Bitmap画像の読み込み
今回は loadBitmap()を定義し
引数として画像のURIを渡すと
ContentProvider経由で取得した画像のBitmapインスタンスを返す

Bitmap bitmapOriginal = loadBitmap(imageUri);

そして、反射された画像を作成するMatrixを生成

Matrix matrix = new Matrix();
matrix.preScale(1,-1);
int height = bitmapOriginal.getHeight();
int width = bitmapOriginal.getWidth();

そして、反転された画像を書き込むBitmapの作成

Bitmap reflectionImage = Bitmap.createBitmap(bitmapOriginal,0, height/2, width,height/2,matrix, false);

そして、オリジナル画像に反転した画像を合成したイメージを書き込むBitmapを作成

Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height/2), Config.ARGB_8888);

そして、オリジナル画像と反転画像をもとに反射画像を生成

//最終的なイメージを書き込むBitmap作成
Canvas canvas = new Canvas(bitmapWithReflection);

//オリジナル画像描画
canvas.drawBitmap(bitmapOriginal, 0,0,null);
Paint defaultPaint = new Paint();

//継ぎ目を目立たなくするため、デフォルトの色を描画
canvas.drawRect(0, height, width, height + REFLECTIONGAP, defaultPaint);

//反転イメージの描画
canvas.drawBitmap(reflectionImage, 0, height+ REFLECTIONGAP,null);

//反転されたイメージ画像を下へいくごとに白くなるグラデーションを設定
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(
0,
bitmapOriginal.getHeight(), 
0,
bitmapWidthReflection.getHeight()+ REFLECTIONGAP,
0x70ffffff,
0x00ffffff,
TileMode.CLAMP
);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));

//グラデーション描画
canvas.drawRect(0,height,width,bitmapWithReflection.getHeight(),REFLECTIONGAP,paint);

反転画像は、
Bitmap.createBitmap()の第6引数の
Matrixで、回転行列
つまり角度みたいなのを設定することで
反転画像をつくれる

反転画像は、画面の下側に反射したかんじで表現する

色を変えないのなら
湖とかに写るような演出もできる

さらに、遠くになるほどぼやけるようにすれば
さらにそれっぽい
例えば、反転画像を下へいくほど
白のグラデーションを上乗せするなど

グラデーションのやり方は
PaintクラスのsetShader()で行い

setXfermode()で、グラデーションのピクセル単位の計算方法を指定して描画する

Raspberry Pi をDLNAサーバーに

Raspberry Pi をDLNAサーバーに

DLNA
(Divital Living Network Alliance)

異なるメーカーのAV機器を
LANを介して相互接続できるようにした規格

最近のネット対応TVのほとんどは
DLNA機能が備わっているため
DLNA対応NASをLANに追加すれば
NASに保存した動画や音楽を離れたTVなどでも再生できる

これを利用して Raspberry Pi へDLNAサーバーをインストールすれば
TVなどからRasberrt Pi にアクセスして動画などをみることができる

起動ディスクに使っているSDカードだと容量が少ないけどUSBに外付けHDDをつければ、
この問題も解決できる

まずは Raspberry PI にDLNAサーバーインストール
インストールするのはMiniDLNA

[shell]
sudo apt-get install minidlna
[/shell]
でインストール

次にDLNAサーバーの設定
動画や音声ファイルを保存するディレクトリを作成する

現在ホームディレクトリにいるので、ここへ作成する

 mkdir Video Music Photo

そして、作成したディレクトリにSFTPでメディアを転送する

クライアントソフトは Filezilla を利用
音楽なら Music
動画なら Video
写真なら Photo
に転送する

次に設定ファイルを編集する

sudo vim /etc/minidlna.conf 

で変更できるけどバックアップとってから編集したほうが無難

26行めの
media_dir=/var/lib/minidlna
が保存先を指定しているので

#media_dir=/var/lib/minidlna
media_dir=V,/home/pi/Video
media_dir=A,/home/pi/Music
media_dir=P,/home/pi/Photo

とする
#のついているのはコメントアウト

これで設定できたのでDLNAサーバーの起動

sudo /etc/init.d/minidlna start

で起動できる

設定ファイルを書き換えた場合

sudo /etc/init.d/minidlna force-reload

で設定ファイルを再読み込みする

起動できたら、まずは ipod touch でアクセス

しかしアクセスできても再生できないので
権限を確認
-rw-r–r–
となっているので
chmod 755 で変更したけど結果は変わらず

原因を調べるため
raspberry pi minidlna で検索

RPi miniDLNA


を元にログをチェック

less /var/log/minidlna.log 

で確認すると

inotify.c:195: warn: WARNING: Inotify max_user_watches [8192] is low or close to the number of used watches [8] and I do not have permission to increase this limit.  Please do so manually by writing a higher value into /proc/sys/fs/inotify/max_user_watches.

となっていたので

sudo sysctl fs.inotify.max_user_watches=81920

を実行し

sudo /etc/init.d/minidlna force-reload

で miniDLNAを再起動

しかしまだ再生はできなかった
どうやらログをみるとポート関連の問題のよう

minidlna.c:1006: warn: HTTP listening on port 8200

とりあえずポート確認するため
ubuntu で

nmap 192.168.1.198

で確認

結果は

Starting Nmap 5.21 ( http://nmap.org ) at 2014-08-10 19:22 JST
Nmap scan report for raspberrypi (192.168.1.198)
Host is up (0.12s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
8200/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 1.23 seconds

ポートが開いているようなので
次に再生できる形式を調べることに

mp3 ファイルで実験するため

cp /usr/share/pyshared/pygame/examples/data/house_lo.mp3 Music/

で実験した結果、再生可能なことを確認

どうやら .ogg 形式が再生できないため
http://nanase.hatenablog.jp/entry/2013/11/08/193003
を参考に

sudo apt-get install mpg321 vorbis-tools

でインストール
これでもダメなので
http://linuxforums.org.uk/index.php?topic=9822.0
を元に

sudo apt-get install minidlna gstreamer0.10-ffmpeg

でさらにインストール

しかし未だに .ogg 形式ファイルの再生はできなかった

とりあえず .ogg はできないけど mp3 までなら
DLNAサーバーでの再生が可能になった

動画に関しても調べてみたけど
http://bty.sakura.ne.jp/wp/archives/377
に書いてあるように
動画ファイルはmpeg2のフォーマットじゃないと閲覧できない

raspberry pi の音声を女性にする

raspberry pi の音声を女性にする

音声データ(音響モデル)を追加すれば
別の声で喋らせることもできる

今回はMMDAjent メイちゃんの音声データを追加

http://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/

から
MMDAgent_Example-1.3.1.zip
をダウンロード

最新版は 1.4 だけど、残念ながらこれは使えない
ver1.4 以降は使えないらしい

ダウンロードできたら
SFTPでファイルを転送
今回は FileZilla で転送する

アップロードできたら

unzip MMDAgent_Example-1.3.1.zip 

で解凍

そして
/usr/share/hts-voice/

MMDAgent_Example-1.3.1/Voice/
以下のファイルをディレクトリごとコピーする

sudo cp -R MMDAgent_Example-1.3.1/Voice/* /usr/share/hts-voice/.

でコピーできる

ls /usr/share/hts-voice/mei_angry 

で確認すると

mei_bashful
mei_happy
mei_normal
mei_sad
nitech-jp-atr503-m001
となっている

nitech-jp-atr503-m001
は男性の声

女性の声は mei_ で始まるディレクトリのところ

これで音源が手に入ったので
スクリプトファイルを変更する

cp jtalk.sh jtalk.sh_bak

で念のためバックアップをとっておく

そしてファイルを変更
これなら失敗してもバックアップから戻せば直せる

とりあえず、音源を変更したいので
HV=/usr/share/hts-voice/nitech-jp-atr503-m001
のHV=の部分で指定している音源ディレクトリを変える

HV=/usr/share/hts-voice/mei_happy
として保存

これで再度

./jtalk.sh "今日はいい天気ですね"

とすると女性の高めの声になる

raspberry Pi で音声合成

raspberry Pi で音声合成

Open JTalk はオープンソースで開発されている日本語音声合成エンジンのこと

形態素解析のMeCab

形態素解析用辞書の naist-jdic

音声合成エンジン hts_engine
を使うことで英
日本語の文章を音声として出力できる

形態素解析では
文章の中から単語を最小の単位に分解し
辞書をもとに分類したりする

Raspberry Pi では 音声合成ソフトとして
AquesTalk Pi があるけど
無償で使えるのは非営利の個人だけで
それ以外はライセンス購入が必要になる

なお Open JTalk は apt-get で簡単にインストールできる

sudo apt-get install open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001 libhtsengine1

でインストールできる

さらに、今回は書籍にあったサンプルも使ってみた
http://v7.com/raspi2/
からダウンロード

ダウンロードしたファイルを
unzip sample.zip で解凍

この中にあるファイル jtalk.sh をFileZilla で
Raspberry PI へアップロード

アップしたら権限変更

chmod 755 jtalk.sh 

これでスクリプトを使うことができるようになったので

./jtalk.sh "今日はいい天気ですね"

とすると
今日はいい天気ですね
と音声がでる

つまり、
./jralk.sh “読み上げたい文章”
とすると読ませることができる

また、テキストファイルを指定して読ませることもできる

vim textfile.txt

で作成し
内容を

今日はラズベリーパイの音声入力を試した
次は音声の変更を実行してみよう

とする

これで

vim textfile.txt

とすると1行めは読まれるけど
2行めは読まれなかった

また

echo "読み上げる文章" | ./jtalk.sh 

というようにパイプを使えば
echo の文章を渡すことができる

また、コマンドをバッククオート
shift + @ で出せる ` で囲むと
コマンドの実行結果を含めることができる

よく使われるものとしては
現在時刻を読ませるという方法

echo "只今の時刻は `date +%k`時 `date +%-M` 分です" | ./jtalk.sh 

とすると現在時刻を読み上げる

今回は date の実行結果を “で囲むことで読み上げに使っている

画像のモノクロ表示

画像のモノクロ表示

画像をモノクロにすれば、白黒写真みたいなのが作れる

Bitmapのモノクロ表示は
描画用のPaintインスタンスに
ColorFilterを設定し
Canvas.drawBitmap()で描画することでできる

まずは、Bitmap画像の読み込み

loadBitmap()を定義し
画像のURIを渡せば
ContentProvider経由で取得した画像のBitmapインスタンスを返すようにする

Bitmap bitmapOriginal = loadBitmap(imageUri);

そして、モノクロ画像用のBitmapを生成

//元画像の高さ、幅の取得
int height = bitmapOriginal.getHeight();
int width = bitmapOriginal.getWidth();

//モノクロ画像用のBitmap作成
Bitmap bitmapGrayScale = Bitmap.createBitmap(width,height,Bitmap.Config.RGB_565);

そして、モノクロのカラーフィルターを設定し
Bitmapへ描画する

Canvas c = new Canvas(bitmapGrayScale);
Paint paint = new Paint();

//彩度を0に設定
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);

//グレースケールに変換されるColorFilterインスタンス設定
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);

//Bitmapの描画
c.drawBitmap(bitmapOriginal,0,0,paint);

モノクロ表示みたいに
画像の色を変更するには
ColorFilterを使えば簡単に実現できる

今回なら
ColorMatrixを作成して
setSaturation()で彩度を0に設定し
グレースケールに変換されるColorFilterインスタンスを作成している

raspberry pi で動画、ラジオの再生

raspberry pi で動画、ラジオの再生

Raspberry Pi のGPUには
H.264 対応の動画再生支援機構があるため
CPUにさほど負担をかけず再生が可能

動画再生はデフォルトインストールされている
omxplayer
で再生可能

ちなみに、これはコマンドで行う
デスクトップ環境を起動していると表示がおかしくなるので注意

再生のしかたは

omxplayer -p -o local ファイル名

となる

-o local オプションで
オーディオ出力端子に指定している

もしHDMIなら
-o hdmi
となる

これで音声関連はOK

次にインターネットラジオ

スマホアプリの radiko が有名だけど
Raspberry Pi では mplayer を使えばラジオをきくことができる

まずは mplayer のインストール

sudo apt-get install mplayer

次に、聞きたいラジオのURLを調べる

http://www.shoutcast.com/
が人気らしいので、この中から選ぶことにする

今回は
COOLfahrenheit 93
を選択

ダウンロードアイコンを右クリックして
リンクのURLをコピーする

radio

mplayer で再生するときもコマンドで行う

mplayer -playlist 視聴したいURL

とする

今回なら

 mplayer -playlist http://yp.shoutcast.com/sbin/tunein-station.pls?id=175821

で再生できる

操作はキーボードで行える
音量をあげるなら *
音量を下げるなら /
一時停止とその解除はスペースキー
終了は esc キー
となる

日本のものもやってみたかったけど
radiko がほとんどなのでやめました