2011年3月30日星期三

圖像處理

上文描述了如何"從 drawable 文件夾中加載位圖", 本文會對所加載的位圖進行一些簡單處理.

通過 Bitmap 類的 getPixels() 方法可以把 Bitmap 複製到一個整數矩陣. 每個元素對應 Bitmap 的一點. 而 32 bit 分別代表 alpha, 紅, 綠, 藍. 這樣我們便可以處理每個點. 本例子中, 每次用戶點擊按鈕, 便把圖像的紅, 綠, 藍迴轉一次(r->b, b->g, g->r), 然後利用 createBitmap() 和 setPixels() 方法創建新的 Bitmap.

圖像處理

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<ImageView
android:id="@+id/myimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/myimagewidth"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/myimageheight"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/process"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Process"
/>
</LinearLayout>


package com.AndroidBtmap;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class AndroidBtmap extends Activity {

Bitmap bitmap;
ImageView myImage;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

myImage = (ImageView)findViewById(R.id.myimage);
TextView myImageWidth = (TextView)findViewById(R.id.myimagewidth);
TextView myImageHeight = (TextView)findViewById(R.id.myimageheight);
Button buttonProcess = (Button)findViewById(R.id.process);

bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.androidbiancheng);
int bitmapWidth = bitmap.getWidth();
int bitmapHeight = bitmap.getHeight();

myImage.setImageBitmap(bitmap);
myImageWidth.setText("Width: " + String.valueOf(bitmapWidth));
myImageHeight.setText("Height: " + String.valueOf(bitmapHeight));

buttonProcess.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
bitmap = doProcess(bitmap);
myImage.setImageBitmap(bitmap);
myImage.invalidate();


}});
}

private Bitmap doProcess(Bitmap src){
int bmWidth = src.getWidth();
int bmHeight = src.getHeight();
int[] newBitmap = new int[bmWidth * bmHeight];

src.getPixels(newBitmap, 0, bmWidth, 0, 0, bmWidth, bmHeight);

for (int h = 0; h < bmHeight; h++){
for (int w = 0; w < bmWidth; w++){
int index = h * bmWidth + w;
int alpha = newBitmap[index] & 0xff000000;
int r = (newBitmap[index] >> 16) & 0xff;
int g = (newBitmap[index] >> 8) & 0xff;
int b = newBitmap[index] & 0xff;

int t = r; //Swap the color
r = g;
g = b;
b = t;

newBitmap[index] = alpha | (r << 16) | (g << 8) | b;
}
}

Bitmap bm = Bitmap.createBitmap(bmWidth, bmHeight, Bitmap.Config.ARGB_8888);
bm.setPixels(newBitmap, 0, bmWidth, 0, 0, bmWidth, bmHeight);

return bm;
}
}


2011年3月28日星期一

儲存位圖檔案

Android OS 為每個應用程序保留獨立的文件結構.

例如:
com.AndroidBtmap 應用程序包的文件位於:
/data/data/com.AndroidBtmap/files/

修改上文"從 drawable 文件夾中加載位圖"程序, 把位圖檔案以 JPG 格式儲存於 /data/data/com.AndroidBtmap/files/ 中.

儲存位圖檔案
儲存位圖檔案

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<ImageView
android:id="@+id/myimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/myimagewidth"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/myimageheight"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/save"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Save"
/>
</LinearLayout>


package com.AndroidBtmap;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class AndroidBtmap extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

ImageView myImage = (ImageView)findViewById(R.id.myimage);
TextView myImageWidth = (TextView)findViewById(R.id.myimagewidth);
TextView myImageHeight = (TextView)findViewById(R.id.myimageheight);
Button buttonSave = (Button)findViewById(R.id.save);

final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.androidbiancheng);
int bitmapWidth = bitmap.getWidth();
int bitmapHeight = bitmap.getHeight();

myImage.setImageBitmap(bitmap);
myImageWidth.setText("Width: " + String.valueOf(bitmapWidth));
myImageHeight.setText("Height: " + String.valueOf(bitmapHeight));

buttonSave.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
FileOutputStream fos;
try {
fos = openFileOutput("MyBitmap.jpg", MODE_WORLD_READABLE);
bitmap.compress(CompressFormat.JPEG, 80, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}});
}
}


從 drawable 文件夾中加載位圖

首先把一個位圖檔案儲存於 drawable 文件夾中, Android SDK 會為它分配一個 ID, 可以通過 "R.drawable.xxx" 被存取.

例如:
/res/drawable/androidbiancheng.png 的 ID 是 R.drawable.androidbiancheng

從 drawable 文件夾中加載位圖

佈局文件, main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<ImageView
android:id="@+id/myimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/myimagewidth"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/myimageheight"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>


package com.AndroidBtmap;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;

public class AndroidBtmap extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

ImageView myImage = (ImageView)findViewById(R.id.myimage);
TextView myImageWidth = (TextView)findViewById(R.id.myimagewidth);
TextView myImageHeight = (TextView)findViewById(R.id.myimageheight);

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.androidbiancheng);
int bitmapWidth = bitmap.getWidth();
int bitmapHeight = bitmap.getHeight();

myImage.setImageBitmap(bitmap);
myImageWidth.setText("Width: " + String.valueOf(bitmapWidth));
myImageHeight.setText("Height: " + String.valueOf(bitmapHeight));
}
}


下一篇文章:
- 儲存位圖檔案
- 圖像處理

控制 Android 內置閃光燈

從 API level 5 開始, 應用軟件可以調用函數 setFlashMode()控制 Android 設備的內置閃光燈, 充當臨時手電筒.

開啟內置閃光燈:
 Camera camera;
Parameters parameters;

camera = Camera.open();
parameters = camera.getParameters();
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);


關閉內置閃光燈:
 parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
camera.release();


注意:
當應用程序終止時, 不要忘記調用函數 camera.release() 釋放相機功能.



2011年3月25日星期五

分析Android應用程式的內存

Dalvik 虛擬機運行時可能會進行垃圾收集(garbage-collection),但是,這並不意味著你可以忽略內存管理。作為一名 Android 應用程序開發人員,因應移動設備中更多的內存限制, 應該特別留意內存的使用。

Android開發者博客(Android Developers Blog)剛剛發布一分文章談到一些 Android SDK 中的內存分析工具,可以幫助你微調應用程序的內存使用 - 值得一看。

在文章中,展示 Allocation Tracker 和 heap dumps 如何可以幫助更加了解應用程序的內存使用情況。還展示了 Eclipse Memory Analyzer (MAT) 如何可以幫助追踪應用程序中的內存洩漏(memory leaks)。

- Android Developers Blog: Memory Analysis for Android Applications

2011年3月24日星期四

roottools: 開源的 Root 工具包項目


roottools 使開發人員方便地使用共同的 rooted 工具,更容易地編寫 rooted 應用軟件, 使東西標準化和優化.

這項目的長遠目標,是通過創建應用程序庫, 方便開發者編寫 rooted 應用程序,而不必不斷地重新編寫代碼。

http://code.google.com/p/roottools/

2011年3月19日星期六

MATCH_PARENT

從API Level 8(即Android 2.2)開始, Android API 的 layout_width 和 layout_height 新增 "MATCH_PARENT", 其實"MATCH_PARENT"基本上與"FILL_PARENT"相同("FILL_PARENT"已過時); 它們的數值都是-1(0xffffffff), 意味著該視圖盡可能填滿它的父對象減去padding的寬度或高度.