指定サイズで画像トリミング

指定サイズで画像トリミング

AndroidのBitmap処理は
android.graphics パッケージの
BitmapFactoryクラスを使う

BitmapFactory.decodeStream()で
Bitmapを読み込み
BitmapFactory.Optionsのインスタンスに読み込み時の振る舞いを設定する

指定サイズでのトリミングをするには
一旦画像をBitmapとして読み込んで
その後でトリミング領域を設定
そして
Bitmap.createBitmap()で新しいBitmapを作成する

excelとかで、ファイルを開いて
編集したら、別ファイルで保存するようなかんじ

まず、Bitmap画像の読み込み

例外発生に備え、try catchで行う

InputStream input = null;

try{

//振る舞いの設定
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

//画像の読み込み
input = getContentResolver().openInputStream(imageUri);
BitmapFactory.decodeStream(input, null, options);
int inSampleSize = calculateInSampleSize(options, MAX_IMAGE_SIZE, MAX_IMAGE_SIZE);

input.close();
input = null;

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

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

mImageView.setImageBitmap(mSourceBitmap);

}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
if(input != null){
try{
input.close();
}catch(IOException e){
e.printStackTrace();
}
}
}

次に、画像をトリミングしてからBitmapを作成

//幅と高さの取得
int imageWidth = mSourceBitmap.getWidth();
int imageHeight = mSourceBitmap.getHeight();

//トリミングする幅、高さ、座標の設定
int nWidth = (int)(imageWidth * 0.7f);
int nHeight = (int)(imageHeight * 0.7f);
int startX = (imageWidth - nWidth) /2;
int startY = (imageHeight - nHeight)/2;

//トリミングしたBitmapの作成
mSourceBitmap = Bitmap.createBitmap(mSourceBitmap, startX, startY, nWidth, nHeight, null, true);

Bitmap.createBitmap()の引数は
第一引数のmSourceBitmapがコピー元のBitmap

第2 の startX
第3 の startY
第4 の nWidth
第5 の nHeight
はトリミングの位置と大きさを指定している

Raspberry Pi でサウンド再生

Raspberry Pi でサウンド再生

Raspberry Pi には2種類のサウンド出力がある

HDMI
もしくは
3.5mm オーディオ出力
になる

ディスプレイへ HDMI のほうを接続しているので
今回は 3.5mm オーディオ出力のほうからサウンド再生

ちなみに今回利用したものオーディオは
LOGICOOL ステレオスピーカー Z120BW

まず、Ubuntu からリモートで操作したいので

ssh pi@192.168.1.198

でログイン

まずは音がでるかテストしたいので

 amixer cset numid=3 1


3.5mm オーディオ出力になるように指定

次に

alsamixer

で起動する

alsamixer

音量はキーボードの↑↓、もしくは数値で指定する

今回は8を入力し
8割の音の大きさに指定

指定できたら ESC キーで終了

次に、サンプルファイルを再生する

まずは wav ファイルの再生
これは aplay コマンドをつかう

aplay -q /usr/share/pyshared/pygame/examples/data/house_lo.wav 

-q オプションは画面に何も出力しないようにする

これをつけないとファイル情報が表示される

次に mp3 形式の再生だけど、これはソフトをインストールして行う
インストールするのは mpg321

sudo apt-get install mpg321 

でインストール

これもコマンドでファイルを再生する
-q オプションをつければファイル情報を表示せずに再生できる

mpg321 -q /usr/share/pyshared/pygame/examples/data/house_lo.mp3 

で再生

このコマンドは他にもオプションがあるので

 mpg321 -h

でみることができる

とりあえず、今のバージョンだと

mpg321: option requires an argument -- 'h'
High Performance MPEG 1.0/2.0/2.5 Audio Player for Layer 1, 2, and 3.
Version 0.3.2-1 (2012/03/25). Written and copyrights by Joe Drew,
now maintained by Nanakos Chrysostomos and others.
Uses code from various people. See 'README' for more!
THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! USE AT YOUR OWN RISK!

Usage: mpg321 [options] file(s) | URL(s) | -

Options supported:
   --verbose or -v          Increase verbosity
   --quiet or -q            Quiet mode (no title or boilerplate)
   --gain N or -g N         Set gain (audio volume) to N (0-100)
   --skip N or -k N         Skip N frames into the file
   --frames N or -n N       Play only the first N frames
   -o dt                    Set output devicetype to dt
                                [esd,alsa(09),arts,sun,oss]
   --audiodevice N or -a N  Use N for audio-out
   --stdout or -s           Use stdout for audio-out
   --au N                   Use au file N for output
   --cdr N                  Use cdr file N for output
   --wav N or -w N          Use wave file N for output
   --test or -t             Test only; do no audio output
   --list N or -@ N         Use playlist N as list of MP3 files
   --random or -Z           Play files randomly until interrupted
   --shuffle or -z          Shuffle list of files before playing
   --loop N or -l N         Play files N times. 0 means until
                            interrupted
   -R                       Use remote control interface
   -3                       Restart "remote shell". Used only when in "Remote control" mode.
   -F                       Turn on FFT analysis on PCM data. Remote mode only
   -B                       Read recursively the given directories
   -S                       Report mp3 file to AudioScrobbler
   -K                       Enable Basic Keys
   -x                       Set xterm title setting
   -b                       Number of decoded frames for the output buffer
   -p hostname:port         Use proxy server
   -u username:password     Use proxy server basic authentication
   -U username:password     Use proxy server basic authentication by using environment variables
   --aggressive             Try to get higher priority
   --help or --longhelp     Print this help screen
   --version or -V          Print version information
Basic keys:                                            
* or /   Increase or decrease volume.                  
m        Mute/unmute                                   
n        Skip song.                                    

This version of mpg321 has been configured with the libao default as its default
libao output device.

となる

サンプルファイルはいくつか格納されており
/usr/share/scratch/Media/Sounds/
/usr/share/sounds/alsa/
/usr/share/pyshared/pygame/examples/data/
の中にも格納されている

ボリュームボタンの検出

ボリュームボタンの検出

ハードウェアのボリュームボタンを使えば
音量のコントロールができる

このボリュームボタンの検出するには
KeyEventクラスの
getKeyCode()で
キーコードを取得すれぱいい

KEYCODE_VOLUME_UP
なら音量アップ

KEYCODE_VOLUME_DOWN
なら音量ダウン

KEYCODE_VOLUME_MUTE
ならミュート、つまり音を消す

@Override
public boolean dispatchKeyEvent(KeyEvent event){

if(event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP){
Toast.makeText(getApplicationContext(),"音量アップ", Toast.LENGTH_SHORT).show();
}

if(event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN){
Toast.makeText(getApplicationContext(),"音量ダウン", Toast.LENGTH_SHORT).show();
}

if(event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_MUTE){
Toast.makeText(getApplicationContext(),"ミュートにしたよ", Toast.LENGTH_SHORT).show();
}
return super.dispatchKeyEvent(event);
}

ホームボタンの検出

ホームボタンの検出

ハードウェアのホームボタンを押したのを検出するには
onUserLeaveHint()
を使う

これを使えば
アプリがハックグラウンドになったときとか
Notificationとかの通知領域への移動
ほかのアプリに遷移したときにも使える

自動保存アプリの場合、このタイミングで保存しました
とでるとわかりやすい

とりあえず、わかりやすくトースト表示するなら

@Override
public void onUserLeaveHint(){

Toast.makeText(getApplicationContext(),"HOMEボタン押したよ", Toast.LENGTH_SHORT).show();
}

戻るボタンの検出

戻るボタンの検出

ハードウェアの戻るボタンの検出には
キーイベントの
KEYCODE_BACK
を取得すれぱ検出できる

戻るボタンを押したら検出し、トースト表示するなら

@Override
public boolean dispatchKeyEvent(KeyEvent event){

if(event.getKeyCode() == event.KEYCODE_BACK){
Toast.makeText(getApplicationContext(), "戻るボタン押したよ", Toast.LENGTH_SHORT).show();
}
return super.dispatchKeyEvent(event);
}

これで、戻るボタンを押すとトースト表示される

メモ帳アプリとかで、自動保存したときに表示するというように使える

raspberry piリモート操作

raspberry piリモート操作

今回は、MacBookAirからリモート操作

MacBookAirの場合、標準でSSHクライアントがあるので
ターミナルを起動し

ssh pi@raspberrypi のIPアドレス

でリモート操作できる

ちなみに、Ubuntuでも同じ

また、ファイル転送にはSFTPを使う

今回使ったのはCyberduck

アプリストアからでもインストールできるけど
こちらは有料で結構値段がするので
とりあえずサイトから無料のほうをダウンロード

ダウンロードできたらCyberduckを起動し
接続方法を
FTP
から
SFTP
へ変更

あとは、サーバーの欄へ Raspberry PiのIPアドレス

ユーザー名には pi

パスワードは自分で設定したRaspberry Piのユーザーパスワード

これで接続すればつながる

Ubuntuなら、sftpコマンドや
Filezillaなどが使える

ファイル転送なら
Androidでも可能で、AndFTPを使えば転送できるし
SSHでのリモート操作も
ConnectBot
を使うことで操作可能

ただし、リモート操作には
スマートフォンだと画面が小さいためタブレットがおすすめ

画像の任意の領域のクリック判定

画像の任意の領域のクリック判定

これは、Viewの拡大、縮小などに使われる

画像の任意の領域のタッチ判定するには
Viewクラスを拡張する

class MyView extends View{

というように、extends View で継承する

次に、画像の読み込みに
Bitmap

PaintクラスとPathクラスで短形の描画

Regionクラスであたり判定
というように、使う

private Bitmap mBitmap;
private Path mPath = new Path();
private Paint mPaint = new Paint();
private Region mRegion = new Region();

で、メンバ変数と初期化宣言

そして、画像の読み込みと枠の設定

読み込みでは、例外発生に備え
try catchで行う

public MyView(Context context){

super(context);

//画像の取得
try{
InputStream is = getResources().getAssets().open("test.jpg");
mBitmap = BitmapFactory.decodeStream(is);

}catch(Exception e){
}


//クリックしたときの赤い枠の設定
//色の指定
mPaint.setColor(Color.RED);
//枠の幅
mPaint.setStrokeWidth(3);
//枠の描画方法
mPaint.setStyle(Style.STROKE);

//枠の大きさ設定
Rect rect = new Rect(100, 100, 300, 300);

mPath.addRect(new RectF(rect), Path.Direction.CW);
mRegion.set(rect);

}

そして、描画処理

protected void onDraw(Canvas canvas){

canvas.save();

canvas.drawBitmap(mBitmap,0,0,null);
canvas.drawPath(mPath, mPaint);

canvas.restore();
}

そして、タッチイベントの実装
今回は、トーストを表示する

@Override
public void onTouchEvent(MotionEvent e){

if(e.getAction() == MotionEvent.ACTION_UP){

if(mRegion.contains((int) e.getX(), e.getY())){

Toast.makeText(getContext(), "タッチしたよ",Toast.LENGTH_SHORT).show();
}
}
return false;
}

onTouchEvent()では、
Regionクラスの
contains()を使うことであたり判定をしてる

そして、タッチした座標が
e.getX()
e.getY()
で取得できてるので
領域内ならトーストを表示するようにしている

Raspberry Piのデスクトップ環境

Raspberry Piのデスクトップ環境

raspberry piのデスクトップ環境を起動するには
ログインしてから

startx

で起動する

このあたりは、Backtrack5 とかと似ている

デスクトップ環境の終了は、ログアウトボタンからログアウトする
もしくは
ショートカットキーで
ctrk + Alt + Backspace
でデスクトップ環境を終了できる

raspberry Piの日本語化

raspberry Piの日本語化

raspberry piは最初は日本語環境がないため
日本語フォント
日本語入力メソッド
をインストールする必要がある

まず、電源を入れて

pi

とユーザー名を入れて、パスワード入力

ログインできたら

sudo raspi-config

で設定画面を表示

ここで、
Internationalisation Options >
Change Locale
で表示される画面で

ja_JP .EUC-JP EUC-JP

ja_JP .UTF-8 UTF-8
にチェックがついているのを確認

これで、okを押すと次の画面で
デフォルト言語を聞かれるので
en_GB.UTF-8
から
ja_JP.UTF-8
へ変更する

言語設定には時間がかかるため、気長に待つ

変更が適用されると
設定画面のトップページの
Setup Options
の画面になるので、Finishを選択して終了する

言語設定はできたので
次に、日本語表示に必要な日本語フォントをインストール

sudo apt-get install ttf-kochi-gothic xfonts-intl-Japanese xfonts-intl-Japanese-big xfonts-kaname

次に、日本語入力メソッドをインストール
日本語入力メソッドは、ATOKとかみたいに、日本語を入力するためのソフト

sudo apt-get install uim uim-anthy

これで、デスクトップ環境では日本語が使えるようになるけど
今度は、端末画面が文字化けする

なので、対策としてjfbterm をインストールする

sudo apt-get install jfbterm

これで準備できたので、設定反映のため、シェルにログインしなおす
つまり、一度ログアウトして、再度ログインする

再度ログインすると、設定が有効になりデフォルト言語が日本語化する
ただし、文字化けするため

jfbterm

で切り替える必要がある

日本語ではなく英語にしたいというのなら

export LANG=en

とすればログアウトするまで英語設定になる

長押しの検出

長押しの検出

長押しの検出は、onLongPress()で処理を記述する

ガラケーのボタン押しっぱなし処理のようなものを作るときとかの実装に使えそう

まず、

implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener

を追加

そして、アクセスしやすいように、メンバ変数の宣言

GestureDetector mGestureDetector;

次に、onCreate()の中でインスタンス作成

mGestureDetector = new GestureDetector(this,this);

次に、タッチイベント実装
ここで、タッチイベントの判別振り分けをする

public boolean onTouchEvent(MotionEvent e){
mGestureDetector.onTouchEvent(e);
return false;
}

そして、それぞれのタッチイベントを定義する
今回は、長押しのときだけ検出するので
onLongPress()のときに
トーストで表示

public boolean onLongPress(MotionEvent e){
Toast.makeText(this, "長押し検出しました",Toast.LENGTH_SHORT).show();
return false;
}

これで、画面長押しすると、トーストで表示される

ちなみに、他の動作をメモると

//シングルタップ
@Override
public boolean onSingleTapUp(MotionEvent e){
return false;
}

//ダブルタップ
public boolean onDoubleTap(MotionEvent e){
return false;
}

//画面を押したとき
public boolean onDown(MotionEvent e){
return false;
}

//スワイプ
@Override
public boolean onFing(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){
return false;
}

//スクロール
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){
return false;
}