a. BREW 支持哪些圖像格式?
適用版本: 1.0, 1.1, 2.0
BREW 支持顏色深度達到運行設備上提供的值的任何 BMP 文件。 BREW 目前尚不支持 GIF 和 JPEG 圖像。 有些設備可以支持 GIF 和 JPEG 圖像,請參閱設備數據表來查看 OEM 是否提供了支持以上格式或其它格式圖像的擴展。 BREW SDK® 1.1 以上版本都支持 PNG 格式和 BREW Compressed Image (BCI) 格式。 SDK 2.0 以上版本都支持 IDIB。 使用 IDIB 將免除您調用 CONVERTBMP 的工作,從而提高屏幕更新速度。 BREW SDK® 2.1 以上版本將支持 WBMP 格式。
在 BREW SDK® 1.0 中,模擬器只能模擬 1 位、4 位和 8 位顏色深度的 BMP。 SDK 1.1 增加了對 2 位顏色深度 BMP 的模擬器支持;2.0 SDK 增加了對 16 位顏色深度 BMP 圖像的模擬器支持。
b. 如何生成 2 位圖像?
適用版本: 1.0, 1.1, 2.0
2.0 SDK 中包含的 2 Bit Tool可以進行 2 位位圖和 4 位位圖之間的轉換。 要構建采用灰度顯示的手持設備使用的 2 位位圖,可以使用 MS Paint 從調色板中選擇白色、黑色、淡灰和深灰條目(通常為第一行和第二行的前兩種顏色)來構建位圖。 并將其保存為 16 色圖像,然后使用 2Bit Tool 將其轉換為 2 位位圖。
c. 彩色和單色電話上的透明色是什么?
適用版本: 1.0, 1.1, 2.0
BREW 1.x 中紫色為彩色設備的透明色,白色是單色和 4 級灰度設備上的透明色。
BREW 2.0 以上版本中,可以通過 IBITMAP_SetTransparencyColor 更改透明色。 CONVERTBMP 可以將透明色初始化為兼容舊版本 BREW 的透明色(即紫色和白色)。 但通過其它方式獲得的位圖圖像則沒有固定的透明色。
d. 如何使用內存中的位圖創建 IIMAGE 對象?
適用版本: 1.0, 1.1, 2.0
使用 ISHELL 接口 ISHELL_LoadResImage(用于資源)和 ISHELL_LoadImage(用于文件)完成作為資源或從文件中加載位圖。 但是,有時可能必須從內存中初始化 IIMAGE 對象 - 例如顯示前修改位圖的內容時,或者不先將數據緩存到文件而通過套接字連接檢索圖像時。
在必須用內存中的位圖初始化 IIMAGE 對象的情況下,應該使用 IIMAGE 接口 IIMAGE_SetStream。 下面的代碼示例說明了這種技術。它通過調用 ISHELL_GetHandler 獲得 BMP 圖像處理程序的 Class ID,然后創建一個 MemAStream 對象并將其用作內存中位圖的流。 注意:本例中的圖像格式是 Windows BMP,“pMe->pBmpData”指向 Windows 文件格式 BMP 的開始 (BITMAPFILEHEADER)。
代碼示例:
AEECLSID cls;
IImage *pIImage = NULL;
IMemAStream *pMemStream = NULL;
// 決定 BMP處理程序函數的類 ID,然后
// 創建此 BREW 類的實例
cls = ISHELL_GetHandler(pMe->a.m_pIShell, HTYPE_VIEWER, "image/bmp");
if (cls) {
ISHELL_CreateInstance(pMe->a.m_pIShell, cls, (void **)(&pIImage));
}
if (pMe->pBmpData) {
ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_MEMASTREAM, (void **)(&pMemStream));
if (pMemStream) {
//創建 MEMSTREAM 后將其作為內存中的位圖的流。
IMEMASTREAM_Set(pMemStream, pMe->pBmpData, sizeof(pMe->pBmpData), 0, 0);
IIMAGE_SetStream(pIImage, (IAStream*)pMemStream);
// 現在以正常方式使用您的 IIMAGE 方法
IIMAGE_Draw(pIImage, ..., ...);
IDISPLAY_UpdateEx(pMe->a.m_pIDisplay, TRUE);
}
}
e. 如何從文件或資源文件加載圖像?
通過使用 ISHELL 接口 ISHELL_LoadResImage(用于資源)或 ISHELL_LoadImage(用于文件),后跟 IIMAGE_Draw,很容易從文件或資源中加載和繪制圖像。本文演示了使用 ISHELL 和 IIMAGE 接口加載和顯示位圖所需的基本步驟。
從資源中顯示圖像的步驟:
1. 創建位圖。
2. 將其添加到資源編輯器中。
3. 在資源編輯器中編譯 .bar 和 .h 文件。
4. 將 .h 文件添加到您的項目中。
5. 使用 ISHELL_LoadResImage 加載圖像。
6. 如果加載操作返回非空值,這說明加載操作已啟動,指向圖像的指針已返
回。這并不表示圖像加載已完成。要了解圖像操作的完成時間,您需要使
用 IIMAGE_Notify() 回調。
7. 圖像加載完成時,就會觸發回調。
8. 在回調過程中,使用 IIMAGE_Draw() 顯示圖像。
9. 使用 IDISPLAY_Update() 更新屏幕。
10. 釋放 IImage 指針。
從文件中顯示圖像的步驟:
1. 使用 ISHELL_LoadImage 從文件中加載圖像。
2. 如果加載操作返回非空值,這說明加載操作已啟動,指向圖像的指針已返
回。這并不表示圖像加載已完成。要了解圖像操作的完成時間,您需要使
用 IIMAGE_Notify() 回調。
3. 圖像加載完成時,就會觸發回調。
4. 在回調過程中,使用 IIMAGE_Draw() 顯示圖像。
5. 使用 IDISPLAY_Update() 更新屏幕。
6. 釋放 IImage 指針。
代碼示例:
typedef struct mystruct
{
AEEApplet a;
IImage *m_pImage;
......
}MyData;
enum ResType
{
LOAD_RES_FROM_FILE,
LOAD_RES_FROM_RES
};
#define MY_RES_FILE "myres.bar"
#define MY_IMAGE_FILE "myimg.bmp"
// Load and display a bitmap from a resource and file
int MyDisplayResImage(MyData *pMe, ResType rType)
{
AEEDeviceInfo dm;
if (!pMe)
Return EFAILED;
if (rType == LOAD_RES_FROM_RES)
{
// Load image from Resources
pMe->m_pImage = ISHELL_LoadResImage (
pMe->a.m_pIShell,
MY_RES_FILE,
IDB_MY_COLOR_BITMAP);
}
else // LOAD_RES_FROM_FILE
{
pMe->m_pImage = ISHELL_LoadImage(pMe->a.m_pIShell,
MY_IMAGE_FILE);
}
if (pMe->m_pImage) {
IIMAGE_Notify(pMe->m_pImage, DrawRoutineCB,
(void *)pMe);
}
else
{
return EFAILED; // Failed to load image
}
return SUCCESS;
}
// Notify Callback
void DrawRoutineCB(void *pUser, IImage *pImage,
AEEImageInfo *pi, int nErr)
{
MyData *pMe = (MyData *)pUser;
if( !pMe || !(pMe->m_pImage)
return; // image pointer is NULL
if (nErr == AEE_SUCCESS)
{
// Draw image at 0,0 coordinates
IIMAGE_Draw(pMe->m_pImage, 0, 0);
// Update the screen
IDISPLAY_Update(pMe->a.m_pIDisplay);
// Free the IIMAGE object
IIMAGE_Release(pMe->m_pImage );
}
}
注意:回調(通過 IIMAGE_Notify() 進行)之前,不得釋放 IImage 接口。在應用程序需要在回調文件之前釋放接口的情況下,建議改設會表明應該在回調(上例中的 DrawRoutineCB)中釋放接口的布爾標記。
f. 我用 ISHELL_LoadResImage() 加載圖像并調用 IIMAGE_Draw() 后為什么看不到屏幕圖像?
加載圖像為異步操作。ISHELL_ LoadResImage() 操作返回時,圖像未完全加載,可能無法成功繪制。
返回圖像加載的非空值時,說明加載操作已啟動,指向圖像的指針已返回。這并不表示加載操作已完成。要了解加載操作的完成時間,用戶應使用 IIMAGE_Notify()回調。該回調會在圖像成功加載并準備繪制到屏幕上時觸發。此時,用戶應使用 IIMAGE_Draw() 在屏幕上顯示圖像。
從文件或資源正確加載和繪制圖像的示例如下:
從資源中顯示圖像的步驟:
1. 創建位圖。
2. 將其添加到資源編輯器中。
3. 在資源編輯器中編譯 .bar 和 .h 文件。
4. 將 .h 文件添加到您的項目中。
5. 使用 ISHELL_LoadResImage 加載圖像。
6. 如果加載操作返回非空值,這說明加載操作已啟動,指向圖像的指針已返
回。這并不表示圖像加載已完成。要了解圖像操作的完成時間,您需要使
用 IIMAGE_Notify() 回調。
7. 圖像加載完成時,就會觸發回調。
8. 在回調過程中,使用 IIMAGE_ Draw() 顯示圖像。
9. 使用 IDISPLAY_Update() 更新屏幕。
10. 釋放 IImage 指針。
從文件中顯示圖像的步驟:
1. 使用 ISHELL_LoadImage 從文件中加載圖像。
2. 如果加載操作返回非空值,這說明加載操作已啟動,指向圖像的指針已返
回。這并不表示圖像加載已完成。要了解圖像操作的完成時間,您需要使
用 IIMAGE_Notify() 回調。
3. 圖像加載完成時,就會觸發回調。
4. 在回調過程中,使用 IIMAGE_ Draw() 顯示圖像。
5. 使用 IDISPLAY_Update() 更新屏幕。
6. 釋放 IImage 指針。
代碼示例:
typedef struct mystruct
{
AEEApplet a;
IImage *m_pImage;
......
}MyData;
enum ResType
{
LOAD_RES_FROM_FILE,
LOAD_RES_FROM_RES
};
#define MY_RES_FILE "myres.bar"
#define MY_IMAGE_FILE "myimg.bmp"
// Load and display a bitmap from a resource and file
int MyDisplayResImage(MyData *pMe, ResType rType)
{
AEEDeviceInfo dm;
if (!pMe)
Return EFAILED;
if (rType == LOAD_RES_FROM_RES)
{
// Load image from Resources
pMe->m_pImage = ISHELL_LoadResImage (
pMe->a.m_pIShell,
MY_RES_FILE,
IDB_MY_COLOR_BITMAP);
}
else // LOAD_RES_FROM_FILE
{
pMe->m_pImage = ISHELL_LoadImage(pMe->a.m_pIShell,
MY_IMAGE_FILE);
}
if (pMe->m_pImage) {
IIMAGE_Notify(pMe->m_pImage, DrawRoutineCB,
(void *)pMe);
}
else
{
return EFAILED; // Failed to load image
}
return SUCCESS;
}
// Notify Callback
void DrawRoutineCB(void *pUser, IImage *pImage,
AEEImageInfo *pi, int nErr)
{
MyData *pMe = (MyData *)pUser;
if( !pMe || !(pMe->m_pImage)
return; // image pointer is NULL
if (nErr == AEE_SUCCESS)
{
// Draw image at 0,0 coordinates
IIMAGE_Draw(pMe->m_pImage, 0, 0);
// Update the screen
IDISPLAY_Update(pMe->a.m_pIDisplay);
// Free the IIMAGE object
IIMAGE_Release(pMe->m_pImage );
}
}
注意:回調(通過 IIMAGE_Notify() 進行)之前,不得釋放 IImage 接口。在應用程序需要在回調文件之前釋放接口的情況下,建議改設會表明應該在回調(上例中的 DrawRoutineCB)中釋放接口的布爾標記。
g. BREW 是否支持動畫?
適用版本: 1.0, 1.1, 2.0
BREW SDK® 版本 1.0 支持動畫 BMP。 這是通過并列放置所有幀并使用帶 IPARM-CXFRAME 標記的 IIMAGE_SetParm 指定每幀的寬度實現的。 請參閱 Examples 目錄中的 IIMAGE 示例。
BREW SDK® 版本 1.1 增加了對 BREW Compressed Image (BCI) 動畫的支持。 BCI 文件包含一個或多個壓縮的小圖像,每個圖像都有一個以毫秒指定的持續時間。 持續時間表示每一幅圖像被該系列下一幅圖像取代之前可顯示的時間。 您可以使用 BREW SDK® 版本 1.1 隨附的 BCI 編輯工具來創建 BCI 文件。 有關詳細信息,請參閱 SDK 隨附的“使用 BREW Compressed Image 編輯工具”文檔。
BREW 當前不支持 PNG 和 MNG 格式的動畫。
h. 為什么一段時間后所有動畫都會變慢?
適用版本: 1.0, 1.1, 2.0
大多數 OEM 都使用了睡眠計時器。 它控制設備在何時進入睡眠狀態。 如果在 OEM 指定的時間段內無按鍵活動,手持設備將進入睡眠狀態。 設備處于睡眠狀態時幀速率將大大降低。 按下任意鍵將喚醒設備并恢復到以前的幀速率。
在 BREW 2.0 中,應用程序可選擇是否要進入睡眠狀態。 如果在應用程序收到 EVT_APP_NO_SLEEP 事件時返回 TRUE,應用程序將不會進入睡眠狀態。 例如:
case EVT_APP_NO_SLEEP:
//不要睡眠
return TRUE;
i. 是否可以獲取/操縱設備的調色板信息?
適用版本: 1.0, 1.1, 2.0
不可以。調色板由生產商進行硬編碼,隨設備不同而有異。
j. 是否可以直接修改顯示緩沖區?
適用版本: 1.0, 1.1, 2.0
BREW 1.x 無法訪問這些緩沖區,而且顯示數據使用生產商的專有格式存儲。
從 BREW 2.0 開始,如果位圖的像素布局兼容 BREW 設備無關位圖規格,則這些位圖會支持 IDIB 接口。 也可以通過 IDIB 結構的 pBmp 成員訪問像素緩沖區。 要確定位圖是否支持 IDIB 以及要獲取 IDIB 指針,可以使用 Class ID 為 AEECLSID_DIB 的 IBITMAP_QueryInterface 函數。
k. 是否可以進行后臺渲染?
適用版本: 1.0, 1.1, 2.0
可以使用 IDISPLAY_Set/GetDestination 或 IGRAPHICS_Set/GetDestination 進行后臺渲染。 BREW 1.2 以上版本將提供這些函數。
不提供 1.2 BREW SDK®。 要使用 BREW 1.2 功能,可以使用 2.0 SDK 開發面向 BREW 1.2 的應用程序。 您應該注意不要使用 1.2 版本中不支持的 2.0 版本的功能。 此功能列表編寫在 FAQ 文檔目標設備安裝了 BREW SDK® 1.2,但我找不到 BREW 1.2 SDK。 我應該使用什么 SDK 開發 BREW 應用程序?中。
雖然文檔中含有 IGRAPHICS_EnableDoubleBuffer API,但它不受任何 BREW 版本的支持。
l. 如何繪制特定顏色的線段?
適用版本: 1.0, 1.1, 2.0
IDISPLAY_DrawHLine() 和 IDISPLAY_DrawVLine() 始終繪制黑色線段。 因此,將 CLR_USER_LINE 設置為所需顏色,然后調用 IDISPLAY_DrawHLine() 或 IDISPLAY_DrawVLine() 會變無效。
這兩個 IDISPLAY 宏的定義如下。 要繪制除黑色外的顏色的線段,請使用宏定義中所含的代碼并更改為所需填充顏色。
#define IDISPLAY_DrawHLine(p,x,y,len) \
{AEERect rc;SETAEERECT(&rc,(x),(y),(len),1); IDISPLAY_FillRect((p),&rc, RGB_BLACK);}
#define IDISPLAY_DrawVLine(p,x,y,len) \
{AEERect rc;SETAEERECT(&rc,(x),(y),1,(len)); IDISPLAY_FillRect((p),&rc, RGB_BLACK);}
m. 如何確定在電話上顯示應用程序名的字符限制?
適用版本: 1.0, 1.1, 2.0
不同的電話具有不同的顯示特性,因此對此問題沒有唯一答案。 您可以通過比較應用程序名的寬度和顯示寬度來確定應用程序名是否適合電話顯示。
使用 IDISPLAY_MeasureText() 確定應用程序名字符串的像素寬度。 使用 ISHELL_GetDeviceInfo() 確定屏幕的像素寬度。
n. 如何將圖像保存到電話的墻紙目錄?
適用版本: 1.0, 1.1, 2.0
雖然當前版本的 SDK 不包含墻紙 API,但有些 OEM 通過共享內容目錄來支持將圖像保存到本地 UI 的墻紙目錄中。
您可以使用以下代碼片斷來創建/下載圖像到共享目錄:
// 請注意,為了使這個代碼起作用,應用程序必須
//在 MIF 文件中有"Access to Shared Directory(使用共享目錄)" 和 "File(文件)" 的權限。
STRCAT( filename, AEE_SHARED_DIR );
STRCAT( filename, "/" );
STRCAT( filename, "test.gif" );
IFILEMGR_OpenFile( m_pIFileMgr, filename, _OFM_CREATE );
AEE_SHARED_DIR 由 OEM 定義并映射到各設備的特定共享目錄路徑。 如果 OEM 支持將圖像保存至墻紙目錄,則保存在 AEE_SHARED_DIR 中的圖像會顯示在本地 UI 的墻紙目錄中。 要查看特定手持設備是否支持通過共享目錄保存墻紙圖像及支持的圖像類型,請參閱手持設備的設備數據表。
目前還沒有 BREW API 可以用于將特定圖像設為手持設備墻紙。 這必須要通過本地 UI 才能完成。
o. 使用 IDISPLAY_BitBlt() 繪制位圖時為什么會收到內存錯誤,如“memheap.c 0696”?
適用版本: 1.0, 1.1, 2.0
請確保釋放 CONVERTBMP 分配的內存。 檢查 CONVERTBMP 的最后一個布爾型參數。 如果為 True,則重新分配已完成,必須使用 SYSFREE 來釋放內存。
例如:
pBmp = CONVERTBMP (pDataBytes, &imageInfo, &bVal);
IDISPLAY_BitBlt (pIDisplay, xDest, yDest, cxDest, cyDest, pBmp,
xSrc, ySrc, dwRopCode);
IDISPLAY_Update (pIDisplay);
if(bVal) //僅在完成重新分配時釋放
SYSFREE (pBmp);
請參閱 API 參考文檔中的 CONVERTBMP 助手函數說明。 若需示例代碼,可以參閱 IDisplay 用法示例。
p. 為什么 Emulator 上顯示的顏色比預期少?
適用版本: 1.0, 1.1, 2.0
如果您在 2.0 模擬器上顯示 16 位圖像時,圖像的分辨率較低,請使用 Device Configurator 檢查設備屬性并將顏色深度設置為 16 位。 如果圖像分辨率仍然很差(相對 8 位或 16 位而言),請檢查您是否使用 IIMAGE_SetParm() 函數為要顯示的圖像設置了不正確的參數。
q. 為什么有些 PNG 圖像不能正確顯示?
適用版本: 1.0, 1.1, 2.0
在 BREW 中使用 PNG 圖像需要注意兩個問題。
1) 版本 1.0、1.1 和 2.0 不支持 Alpha 通道,但 3.0 SDK 版本應該會支持。
2) BREW 只會選擇文件中的第一種透明色對 PNG 進行透明處理。 所有其它顏色都會顯示。 請檢查文件以確保您創建文件時只使用了一種透明顏色。
r. 為什么創建 PNG 圖像使用的內存大小遠遠大于圖像的實際大小?
BREW 應用程序使用 ISHELL_LoadResData 加載 PNG 圖像時,需要大量的額外空間來解碼圖像。 例如,要加載 217 字節的 PNG 圖像需要 45,177 字節空間