//寫檔範例 ublic void writeDataToSD(){ try{ File file = new File(Environment.getExternalStorageDirectory(),"test.txt"); /* 判斷外部裝置是否可以讀寫 */ if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ /* 輸出資料緩衝區*/ FileOutputStream fos = new FileOutputStream(file); /* 寫入的資料*/ String message = "Test"; /* 將資料轉成byte 模式*/ byte[] buffer = message.getBytes(); /* 寫入資料*/ fos.write(buffer); /* 關閉緩衝*/ fos.close(); Toast.makeText(MainActivity.this, "檔案寫入成功", 1000).show(); } }catch(Exception ex){ Toast.makeText(MainActivity.this, "檔案寫入失败", 1000).show(); } //讀檔範例 public void readDataFromSD(){ try{ /* 設定檔案*/ File file = new File(Environment.getExternalStorageDirectory(),"test.txt"); /* 輸入資料緩衝區 */ FileInputStream fis = new FileInputStream(file); /* 準備一個byte biffer用來存讀入的資料*/ byte[] buffer = new byte[fis.available()]; /* 讀取資料*/ fis.read(buffer); /* 關閉緩衝 */ fis.close(); /* 將資料轉成UTF-8格式*/ String res = EncodingUtils.getString(buffer, "UTF-8"); Toast.makeText(MainActivity.this, "檔案讀取成功,data:"+res, 1000).show(); }catch(Exception ex){ Toast.makeText(MainActivity.this, "檔案讀取失败!", 1000).show(); } }
visited 13 states (5.77%)
Create your own visited map of The World or Triposo world travel guide for Android
2014-09-25
Android應用程式讀寫SD上的檔案
檔案讀寫的方式有很多種,這邊放了兩個函式範例可以測試讀寫SD卡上的檔案。
Android中File元件的各種應用
在File的運用當中, 若需要讀取到外部 憶體(SD卡), 得加入以下權限才不會crash//check SDCard is exist or not if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) Environment.getExternalStorageState(): mounted Environment.MEDIA_MOUNTED: mounted //取得SD卡路徑 File SDCardpath = Environment.getExternalStorageDirectory(); ex: /mnt/sdcard //建立資料夾 File mSDCardFile = new File( SDCardpath + "/mSDCardData" ); //判別該File 是否存在 boolean java.io.File.exists(); if( !mSDCardFile.exists() ) { //若該資料夾不存在, 則用mkdirs()建立 boolean java.io.File.mkdirs() //makirs上層資料夾若不 在則自動創建, mkdir則不會 mSDCardFile.mkdirs(); } <<建立檔案>> File mSDCardDoc = new File( SDCardpath + "/mSDCardData.txt" ); //判別該File是否存在 if( !mSDCardDoc.exists() ) { try { //若該檔案不存在, 則用createNewFile()建立 // boolean java.io.File.createNewFile() throws IOException mSDCardDoc.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } --------------------或-------------------- try { FileWriter mFileWriter = new FileWriter( SDCardpath.getAbsolutePath() + "/mSDCardData.txt" ); } catch (IOException e) { e.printStackTrace(); } //取得路徑(File→String) String java.io.File.getAbsolutePath(); mSDCardFile.getAbsolutePath() //取得上一層路徑(File→String) String java.io.File.getParent() mSDCardFile.getParent(); //判別是否為目錄 boolean isDirectory = mSDCardFile.isDirectory(); //判別是否為檔案 boolean isFile = mSDCardFile.isFile(); //將old.txt重新命名為new.txt String oldPath = "/mnt/sdcard/old.txt"; String newPath ="/mnt/sdcard/new.txt"; File oldFile = new File( oldPath ); oldPath.renameTo(new File(oldFile)); //刪除檔案 mSDCardFile.delete(); //判別是否可讀 boolean canRead = file.canRead(); //判別是否可寫 boolean canWrite = file.canWrite(); //檔案寫入內容 FileWriter vFile; try { vFile = new FileWriter( "/mnt/sdcard/new.txt" ); vFile.write("要寫一些內容"); vFile.close(); } catch (IOException e) { e.printStackTrace(); } //讀取檔案內容 try { String file = "/mnt/sdcard/new.txt"; InputStream input = new BufferedInputStream(new FileInputStream(file)); int res = input.available(); byte [] byte = new byte[res]; input.read(byte); //把類型設為UTF-8才能正常讀取中文字! String text = EncodingUtils.getString(byte, "UTF-8"); } catch (IOException e) { e.printStackTrace(); } //判別是否為隱藏檔 boolean isHidden = file.isHidden(); //以File[]儲存指定路徑下所有項目的路徑 File[] files=new File(SDCardpath.getAbsolutePath()).listFiles(); //列出所有項目的路徑 //用長度為files.length的迴圈找出 files[i]; --------------------或-------------------- for( File f : files ) { f.getPath(); } //列出所有項目 //用長度為files.length的迴圈找出 files[i].getName(); --------------------或-------------------- for( File f : files ) { // String java.io.File.getName() f.getName(); } //以關鍵字搜尋目標 //以result儲存搜尋結果 String result=""; for( File f : files ) { // int java.lang.String.indexOf(String string) if(f.getName().indexOf(keyword)>=0)//回傳在第幾個字找到keyword, 若都沒找到則回傳0 { result+=f.getPath()+"\n"; } } 補充:程式中可以java.io.File.separator來表示字串"/"
2014-09-24
Android應用程式中不預設focus於EditText元件的方法
加上兩行於 activity_main.xml (反正就是最主要的xml file)
android:focusableInTouchMode="true" //設定該內本身可以被 focus
android:descendantFocusability="beforeDescendants" //代表其取得 focus 的順序優先於其子物件
之後在主程式 protected void onCreate(Bundle savedInstanceState) 中加上
private EditText edit1;
edit1-> (EditText)findViewById(R.id.Edittext1);
edit1->clearFocus();
android:focusableInTouchMode="true" //設定該內本身可以被 focus
android:descendantFocusability="beforeDescendants" //代表其取得 focus 的順序優先於其子物件
之後在主程式 protected void onCreate(Bundle savedInstanceState) 中加上
private EditText edit1;
edit1-> (EditText)findViewById(R.id.Edittext1);
edit1->clearFocus();
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:focusableInTouchMode="true" android:descendantFocusability="beforeDescendants" >
得到Android裝置的銀幕解析度
此程式主要是得到銀幕的解析度並顯示出來
程式主要的重點在於
import android.util.DisplayMetrics;
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
example.java import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; public class example0305 extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); //全螢幕設定 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); TextView TextView1 = (TextView)findViewById(R.id.TextView01); TextView1.setText("手機銀幕大小為 "+metrics.widthPixels+" X "+metrics.heightPixels); } } 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:id="@+id/TextView01" android:textSize="20sp" /> </LinearLayout>
程式主要的重點在於
import android.util.DisplayMetrics;
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
2014-09-19
Android手機或平板ADB Interface Driver安裝與實機測試APK
有時候會需要把自行開放的Android APK放到手機或平板上測試,不必再使用模擬器消耗電腦效能,這時候就需要這套ADB Interface Driver讓手機或平板能與你電腦上的開發環境(大多數都是Eclipse)連結,將程式丟上裝置上執行。以下是幾個重要流程:
1. 將手機內的「開發人員選項」打開,如是找不到,請多點幾次「關於手機」裡面的「版本號碼」,將隱藏的「開發人員選項」打開。找到並開啟「USB除錯模式」與「安全性」中的「安裝來源不明的應用程式」。以上的設定位置會因各版本Android Kernel有些微差異,但選項應該都會有。
2. 將手機透過可以傳輸檔案的USB線與電腦連結,應該可以看到裝置管理員出現一個未知的裝置Android phone,select 「Update Driver Software」再選「Browse my computer for driver software」,然後選到你所下載解開的driver資料夾,裡面應該會有android_winusb.inf、androidwinusb86.cat、androidwinusba64.cat,與amd64、i386資料夾,當然也有人建議透過SKD manager來下載driver,不過我偏好自己另外安裝。
若是無法安裝,就用特殊技巧,打開裝置管理員看這支手機的PID/VID,例如MT65XX的手機,可從 Device Manager -> 選擇Android Device -> 右鍵 Properties Details-> Hardware Ids ->確認PID & VID,可以知道VID=0x19D2,PID=0x0C02,之後就可以編輯android_winusb.inf檔案,新增以下兩行於[Google.NTx86]或是[Google.NTamd64]下,視你的電腦系統而定,之後應該可以順利安裝。
1. 將手機內的「開發人員選項」打開,如是找不到,請多點幾次「關於手機」裡面的「版本號碼」,將隱藏的「開發人員選項」打開。找到並開啟「USB除錯模式」與「安全性」中的「安裝來源不明的應用程式」。以上的設定位置會因各版本Android Kernel有些微差異,但選項應該都會有。
2. 將手機透過可以傳輸檔案的USB線與電腦連結,應該可以看到裝置管理員出現一個未知的裝置Android phone,select 「Update Driver Software」再選「Browse my computer for driver software」,然後選到你所下載解開的driver資料夾,裡面應該會有android_winusb.inf、androidwinusb86.cat、androidwinusba64.cat,與amd64、i386資料夾,當然也有人建議透過SKD manager來下載driver,不過我偏好自己另外安裝。
若是無法安裝,就用特殊技巧,打開裝置管理員看這支手機的PID/VID,例如MT65XX的手機,可從 Device Manager -> 選擇Android Device -> 右鍵 Properties Details-> Hardware Ids ->確認PID & VID,可以知道VID=0x19D2,PID=0x0C02,之後就可以編輯android_winusb.inf檔案,新增以下兩行於[Google.NTx86]或是[Google.NTamd64]下,視你的電腦系統而定,之後應該可以順利安裝。
%SingleAdbInterface% = USB_Install, USB\VID_19D2&PID_0C02
%CompositeAdbInterface% = USB_Install, USB\VID_19D2&PID_0C02&MI_01
3. 在你的Eclipse開發環境上,將想要放在實體裝置執行的程式,在Run Configurations.. -> Target -> Always prompt to pick device。
4. 如果一切順利,在你Run As -> Android Application的時候,應該會跳出下圖選項,選擇你的手機,接著就可以在手機上看到你所寫的APK了。
2014-09-18
Android切換Activity與頁面layout
假設手機頁面切換只需要置換背景圖示、文字顏色及內容排版等等,只需要用到setContent就可以置換layout,但如果是要切換Activity就不能只換layout,需要移交主控權到另外一個Activity,移交主控權的方法,可在主程式裡使用startActivity()這方法來呼叫另外一個Activity,但是關鍵並不是在這一個startActivity這個方法,而是在Intent(就如同英文字意一樣,想要、企圖之意)這個物件,告訴主程式自己是什麼,想要到什麼地方去,這就是intent物件所處理的事。
XML檔 (兩個Activity兩個對應的layout)
第一個layout main001.xml
這就表示程式會先執行這一個Activity
Java檔 (兩個Activity兩個class)
第一個class TestExam001.java
import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.text.Editable; import android.view.View; import android.widget.Button; import android.widget.EditText; public class TestExam001 extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main001); Button button = (Button)findViewById(R.id.button01); button.setOnClickListener(new Button.OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(); intent.setClass(TestExam001.this, TestExam002.class); startActivity(intent); TestExam001.this.finish(); } }); } }第二個class TestExam002.java
import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class TestExam002 extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main002); Button button = (Button)findViewById(R.id.button02); button.setOnClickListener(new Button.OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(); intent.setClass(TestExam002.this, TestExam001.class); startActivity(intent); TestExam002.this.finish(); } }); } }
XML檔 (兩個Activity兩個對應的layout)
第一個layout main001.xml
以上的layout檔案可以類推出layout main002.xmlxml 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="wrap_content" android:layout_height="wrap_content" android:text=" Activity 001" android:textSize="50sp" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/button01" android:text="Go to Activity 002" android:textSize="17sp" /> </LinearLayout>
AndroidManifest.xml檔
Hint:請記得在AndroidManifest.xml添增一個新的activity並給予名字,否則會出錯喔!然而在一個程式內架設有多個Activity,系統要如何決定以哪一個為entry point呢?在AndroidManifest.xml內有一行為
<category android:name="android.intent.category.LAUNCHER" />
Ps.這兩個java程式在最後都使用finish()這方法,代表這個activity已經運行完畢,當系統接收到這一個指令的時候會關閉此activity,如果這時手機按下back按鍵,並不會回復到上一個Activity的畫面,如果需要讓使用者在按下back鍵可以回到之前的畫面,就必須將這一個finish()刪掉。xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.sam.test" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".TestExam001" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".TestExam002"></activity> </application> </manifest>
2014-09-11
Eclipse出現ADB server didn’t ACK的解決方案
解決辦法一般是在工作管理員中找出adb.exe程序,然後重啟eclipse,不過有時候會找不到adb.exe這個程序。這時候可以透過adb使用的port 5037,看是否被其他程序占用,比如:91助手或者豌豆莢等。
可以透過指令 netstat -a -o 5037,確認是否有程式占用這個port
如上圖最後一列,看到127.0.0.1:5037有一個PID為4236的程式占用了,
再用指令 tasklist /fi “pid eq 4236″ 去確認這支程式的內容
確認沒錯後,就直接在工作管理員刪除掉,之後可以重新啟動 eclipse或是重新啟動adb.exe
提供兩個指令協助:
adb kill-server:啟動adb.exe
adb start-server:終止adb.exe
2014-09-05
列舉出目錄下所有檔案與搜尋特定副檔名
How to use ?
call "FindFileInDir(char* rootDir, char* extname, BOOL recursive)" in your code base, the function can filter folder path and file path
rootDir:search root directory (EX:"D:\\test\\")
extname:filename extension (EX:".exe")
recursive:the decide to search sub-directory or not (EX:"true")
EX1:FindFileInDir("D:\\test\\", ".exe", true); // to search every *.exe file under "D:\test\" directory
EX2:FindFileInDir("D:\\", "", false); // to search every file under "D:\" directory , but don't search in sub-directory
function:
void FindFileInDir(char* rootDir, char* extname, BOOL recursive)//, char* strRet)
{
char fname[1024];
ZeroMemory(fname, 1024);
WIN32_FIND_DATA fd;
ZeroMemory(&fd, sizeof(WIN32_FIND_DATA));
HANDLE hSearch;
char filePathName[256];
char tmpPath[256];
ZeroMemory(filePathName, 256);
ZeroMemory(tmpPath, 256);
strcpy(filePathName, rootDir);
char extFileName[256];
ZeroMemory(extFileName, 256);
strcpy(extFileName, extname);
BOOL bSearchFinished = FALSE;
if( filePathName[strlen(filePathName) -1] != '\\' )
{
strcat(filePathName, "\\");
}
strcat(filePathName, "*");
hSearch = FindFirstFile(filePathName, &fd);
//Is directory
if( (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
{
strcpy(tmpPath, rootDir);
strcat(tmpPath, fd.cFileName);
if( tmpPath[strlen(tmpPath) -1] != '\\' )
{
strcat(tmpPath, "\\");
}
if(recursive == true)
{
FindFileInDir(tmpPath, extFileName, recursive);
}
}
while( !bSearchFinished )
{
if( FindNextFile(hSearch, &fd) )
{
if( (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
{
strcpy(tmpPath, rootDir);
strcat(tmpPath, fd.cFileName);
if( tmpPath[strlen(tmpPath) -1] != '\\' )
{
strcat(tmpPath, "\\");
}
printf("Folder : %s\n", tmpPath); // show folder path
if(recursive == true)
{
FindFileInDir(tmpPath, extFileName, recursive);
}
}
else if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
{
if(strstr(fd.cFileName, extFileName))
{
printf("File : %s%s\n",rootDir,fd.cFileName); // show file path
}
}
}
else
{
if( GetLastError() == ERROR_NO_MORE_FILES )
{
bSearchFinished = TRUE;
}
else
{
bSearchFinished = TRUE;
}
}
}
FindClose(hSearch);
}
call "FindFileInDir(char* rootDir, char* extname, BOOL recursive)" in your code base, the function can filter folder path and file path
rootDir:search root directory (EX:"D:\\test\\")
extname:filename extension (EX:".exe")
recursive:the decide to search sub-directory or not (EX:"true")
EX1:FindFileInDir("D:\\test\\", ".exe", true); // to search every *.exe file under "D:\test\" directory
EX2:FindFileInDir("D:\\", "", false); // to search every file under "D:\" directory , but don't search in sub-directory
function:
void FindFileInDir(char* rootDir, char* extname, BOOL recursive)//, char* strRet)
{
char fname[1024];
ZeroMemory(fname, 1024);
WIN32_FIND_DATA fd;
ZeroMemory(&fd, sizeof(WIN32_FIND_DATA));
HANDLE hSearch;
char filePathName[256];
char tmpPath[256];
ZeroMemory(filePathName, 256);
ZeroMemory(tmpPath, 256);
strcpy(filePathName, rootDir);
char extFileName[256];
ZeroMemory(extFileName, 256);
strcpy(extFileName, extname);
BOOL bSearchFinished = FALSE;
if( filePathName[strlen(filePathName) -1] != '\\' )
{
strcat(filePathName, "\\");
}
strcat(filePathName, "*");
hSearch = FindFirstFile(filePathName, &fd);
//Is directory
if( (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
{
strcpy(tmpPath, rootDir);
strcat(tmpPath, fd.cFileName);
if( tmpPath[strlen(tmpPath) -1] != '\\' )
{
strcat(tmpPath, "\\");
}
if(recursive == true)
{
FindFileInDir(tmpPath, extFileName, recursive);
}
}
while( !bSearchFinished )
{
if( FindNextFile(hSearch, &fd) )
{
if( (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
{
strcpy(tmpPath, rootDir);
strcat(tmpPath, fd.cFileName);
if( tmpPath[strlen(tmpPath) -1] != '\\' )
{
strcat(tmpPath, "\\");
}
printf("Folder : %s\n", tmpPath); // show folder path
if(recursive == true)
{
FindFileInDir(tmpPath, extFileName, recursive);
}
}
else if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
{
if(strstr(fd.cFileName, extFileName))
{
printf("File : %s%s\n",rootDir,fd.cFileName); // show file path
}
}
}
else
{
if( GetLastError() == ERROR_NO_MORE_FILES )
{
bSearchFinished = TRUE;
}
else
{
bSearchFinished = TRUE;
}
}
}
FindClose(hSearch);
}
2014-09-04
BCB應用於三種取出圖片像素之RGB值的方法與速度比較
1. 創立一 BCB project。
2. 拉出三個Button(命名可自訂或參考以下範例),一個Memo用來輸出訊息,一個Image物件輸入圖片影像。
3. 於Image物件中的picture屬性指定一個影像來源(BMP / JPG),當然還有很多可以載入圖片的方法,如用OpenDialog或是直接在程式內設定檔案路徑等,不過並不是本文重點。
以下為程式碼:
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Image1->Height = Image1->Picture->Bitmap->Height;
Image1->Width = Image1->Picture->Bitmap->Width;
Memo1->ScrollBars = ssVertical;
Image1->Picture->Bitmap->PixelFormat = pf24bit;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button_scanlineClick(TObject *Sender)
{
int cur_time, r, g, b;
String str;
BYTE *ptr;
cur_time = GetTickCount();
for (int i = 0; i < Image1->Height; i++)
{
ptr = (Byte*)Image1->Picture->Bitmap->ScanLine[i];
for (int j = 0; j < Image1->Width; j++)
{
b = ptr[3*j];
g = ptr[3*j+1];
r = ptr[3*j+2];
}
}
str.sprintf("processing time : %0.3f",(float)(GetTickCount()-cur_time)/1000);
Memo1->Lines->Add(str);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button_PixelsClick(TObject *Sender)
{
int cur_time, r, g, b, color;
String str;
cur_time = GetTickCount();
for (int i = 0; i < Image1->Height; i++)
{
for (int j = 0; j < Image1->Width; j++)
{
color = Image1->Canvas->Pixels[j][i];
b = (color&0xFF0000) >> 16;
g = (color&0x00FF00) >> 8;
r = (color&0x0000FF);
}
}
str.sprintf("processing time : %0.3f",(float)(GetTickCount()-cur_time)/1000);
Memo1->Lines->Add(str);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button_GetRGBClick(TObject *Sender)
{
int cur_time, r, g, b;
String str;
cur_time = GetTickCount();
for (int i = 0; i < Image1->Height; i++)
{
for (int j = 0; j < Image1->Width; j++)
{
b = GetBValue(Image1->Canvas->Pixels[j][i]);
g = GetGValue(Image1->Canvas->Pixels[j][i]);
r = GetRValue(Image1->Canvas->Pixels[j][i]);
}
}
str.sprintf("processing time : %0.3f",(float)(GetTickCount()-cur_time)/1000);
Memo1->Lines->Add(str);
}
//---------------------------------------------------------------------------
可以看出第一種方是用ScanLine[i]抓取每列像素的方式速度最快,然後用內建的GetBValue等函是最慢,應該是被包裝太多層的原因,所以導致執行效率較差,取出的RGB值看是要用動態二維陣列,還是另行處理後寫檔就各自發揮。另外要注意的是由於只需要RGB的資料,所以可以指定 Image1->Picture->Bitmap->PixelFormat = pf24bit,若是指定為pf32bit,則ScanLine讀回來的每組資料會由4 Bytes組成。
訂閱:
文章 (Atom)