當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式云IOT技術(shù)圈
[導(dǎo)讀]點(diǎn)擊上方嵌入式開(kāi)發(fā)圈 記得關(guān)注我們哦! ??在上一篇文章中,我們大致的介紹了recovery的啟動(dòng)流程,那么,recovery升級(jí)或者做雙清的時(shí)候,那些圖形動(dòng)畫又是如何實(shí)現(xiàn)的呢?我們來(lái)看看代碼。 ?? ? 以下這段代碼位于recovery/screen_ui.cpp 1void?ScreenRecoveryU

點(diǎn)擊上方嵌入式開(kāi)發(fā)圈 記得關(guān)注我們哦!

  在上一篇文章中,我們大致的介紹了recovery的啟動(dòng)流程,那么,recovery升級(jí)或者做雙清的時(shí)候,那些圖形動(dòng)畫又是如何實(shí)現(xiàn)的呢?我們來(lái)看看代碼。   

  以下這段代碼位于recovery/screen_ui.cpp

1void ScreenRecoveryUI::Init()
2{
3    gr_init();
4
5    gr_font_size(&char_width, &char_height);
6
7    text_col = text_row = 0;
8    text_rows = gr_fb_height() / char_height;
9    if (text_rows > kMaxRows) text_rows = kMaxRows;
10    text_top = 1;
11
12    text_cols = gr_fb_width() / char_width;
13    if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;
14
15    backgroundIcon[NONE] = NULL;
16    LoadBitmapArray("icon_installing", &installing_frames, &installation);
17    backgroundIcon[INSTALLING_UPDATE] = installing_frames ? installation[0] : NULL;
18    backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
19    LoadBitmap("icon_error", &backgroundIcon[ERROR]);
20    backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
21
22    LoadBitmap("progress_empty", &progressBarEmpty);
23    LoadBitmap("progress_fill", &progressBarFill);
24    LoadBitmap("stage_empty", &stageMarkerEmpty);
25    LoadBitmap("stage_fill", &stageMarkerFill);
26
27    LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);
28    LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);
29    LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);
30    LoadLocalizedBitmap("error_text", &backgroundText[ERROR]);
31
32    pthread_create(&progress_tNULL, progress_thread, NULL);
33
34    RecoveryUI::Init();
35}

這段代碼都做了哪些事情呢?這些recovery初始化圖形顯示最開(kāi)始的部分:(1)調(diào)用了miniui中的gr_init初始化顯示圖形相關(guān)的步驟,因?yàn)閞ecovery是基于framebuffer機(jī)制顯示的。

(2)調(diào)用gr_font_size設(shè)置字體顯示的大小,然后計(jì)算文本顯示行列。

(3)接下來(lái)就是裝載圖片了,會(huì)調(diào)用到LoadBitmapArray和LoadBitmap這兩個(gè)函數(shù)。其中,我們會(huì)看到這些函數(shù)里圖片的名稱:

將上面的字符串與下面的圖片一一對(duì)應(yīng):

    那么這些分別是怎么顯示的?其中erasing_text是用來(lái)顯示做清除的時(shí)候顯示的文字,放大后如下:

    這上面有許許多多的語(yǔ)言版本,我們可以根據(jù)需要來(lái)選擇,這些主要要看接下來(lái)初始化文字的代碼邏輯。

    其余的圖片中,后綴帶text的,也和這些是類似的,有出現(xiàn)錯(cuò)誤顯示的字體error_text,更新系統(tǒng)顯示的字體installing_text,沒(méi)有命令的時(shí)候顯示的字體no_command_text。

    除了文字顯示,我們最關(guān)心的就是icon_installing這張圖片了,在做系統(tǒng)更新的時(shí)候,這個(gè)機(jī)器人會(huì)轉(zhuǎn)動(dòng)。這不是動(dòng)畫嗎?怎么只有一張圖片呢?我們找到Android官方網(wǎng)站看看是為什么?原因如下:

 1# Copyright (C) 2014 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Script to take a set of frames (PNG files) for a recovery animation
15and turn it into a single output image which contains the input frames
16interlaced by row.  Run with the names of all the input frames on the
17command line, in order, followed by the name of the output file."""

18import sys
19try:
20  import Image
21  import PngImagePlugin
22except ImportError:
23  print "This script requires the Python Imaging Library to be installed."
24  sys.exit(1)
25frames = [Image.open(fn).convert("RGB"for fn in sys.argv[1:-1]]
26assert len(frames) > 0"Must have at least one input frame."
27sizes = set()
28for fr in frames:
29  sizes.add(fr.size)
30assert len(sizes) == 1"All input images must have the same size."
31w, h = sizes.pop()
32N = len(frames)
33out = Image.new("RGB", (w, h*N))
34for j in range(h):
35  for i in range(w):
36    for fn, f in enumerate(frames):
37      out.putpixel((i, j*N+fn), f.getpixel((i, j)))
38# When loading this image, the graphics library expects to find a text
39# chunk that specifies how many frames this animation represents.  If
40# you post-process the output of this script with some kind of
41# optimizer tool (eg pngcrush or zopflipng) make sure that your
42# optimizer preserves this text chunk.
43meta = PngImagePlugin.PngInfo()
44meta.add_text("Frames", str(N))
45out.save(sys.argv[-1], pnginfo=meta)

    這也就是為什么,調(diào)用這張圖片需要用到LoadBitmapArray這個(gè)函數(shù)的原因。

1void ScreenRecoveryUI::LoadBitmapArray(const char* filename, int* frames, gr_surface** surface) {
2    int result = res_create_multi_display_surface(filename, frames, surface);
3    if (result < 0) {
4        LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
5    }
6}

調(diào)完這個(gè)函數(shù)后會(huì)調(diào)用

resources.cpp中的res_create_multi_display_surface函數(shù)用于顯示,源碼如下:

1int res_create_multi_display_surface(const char* name, int* frames, GRSurface*** pSurface) {
2    GRSurface** surface = NULL;
3    int result = 0;
4    png_structp png_ptr = NULL;
5    png_infop info_ptr = NULL;
6    png_uint_32 width, height;
7    png_byte channels;
8    int i;
9    png_textp text;
10    int num_text;
11    unsigned char* p_row;
12    unsigned int y;
13
14    *pSurface = NULL;
15    *frames = -1;
16
17    result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels);
18    if (result < 0return result;
19
20    *frames = 1;
21    if (png_get_text(png_ptr, info_ptr, &text, &num_text)) {
22        for (i = 0; i < num_text; ++i) {
23            if (text[i].key && strcmp(text[i].key, "Frames") == 0 && text[i].text) {
24                *frames = atoi(text[i].text);
25                break;
26            }
27        }
28        printf("  found frames = %d\n", *frames);
29    }
30
31    if (height % *frames != 0) {
32        printf("bad height (%d) for frame count (%d)\n", height, *frames);
33        result = -9;
34        goto exit;
35    }
36
37    surface = reinterpret_cast<GRSurface**>(malloc(*frames * sizeof(GRSurface*)));
38    if (surface == NULL) {
39        result = -8;
40        goto exit;
41    }
42    for (i = 0; i < *frames; ++i) {
43        surface[i] = init_display_surface(width, height / *frames);
44        if (surface[i] == NULL) {
45            result = -8;
46            goto exit;
47        }
48    }
49
50#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA)
51    png_set_bgr(png_ptr);
52#endif
53
54    p_row = reinterpret_cast<unsigned char*>(malloc(width * 4));
55    for (y = 0; y < height; ++y) {
56        png_read_row(png_ptr, p_row, NULL);
57        int frame = y % *frames;
58        unsigned char* out_row = surface[frame]->data +
59            (y / *frames) * surface[frame]->row_bytes;
60        transform_rgb_to_draw(p_row, out_row, channels, width);
61    }
62    free(p_row);
63
64    *pSurface = reinterpret_cast<GRSurface**>(surface);
65
66exit:
67    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
68
69    if (result < 0) {
70        if (surface) {
71            for (i = 0; i < *frames; ++i) {
72                if (surface[i]) free(surface[i]);
73            }
74            free(surface);
75        }
76    }
77    return result;
78}

其余的和text無(wú)關(guān)圖片,會(huì)用到LoadBitmap這個(gè)函數(shù):

1void ScreenRecoveryUI::LoadBitmapArray(const char* filename, int* frames, gr_surface** surface) {
2    int result = res_create_multi_display_surface(filename, frames, surface);
3    if (result < 0) {
4        LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
5    }
6}

同樣調(diào)用到以下函數(shù):

1int res_create_multi_display_surface(const char* name, int* frames, GRSurface*** pSurface) {
2    GRSurface** surface = NULL;
3    int result = 0;
4    png_structp png_ptr = NULL;
5    png_infop info_ptr = NULL;
6    png_uint_32 width, height;
7    png_byte channels;
8    int i;
9    png_textp text;
10    int num_text;
11    unsigned char* p_row;
12    unsigned int y;
13
14    *pSurface = NULL;
15    *frames = -1;
16
17    result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels);
18    if (result < 0return result;
19
20    *frames = 1;
21    if (png_get_text(png_ptr, info_ptr, &text, &num_text)) {
22        for (i = 0; i < num_text; ++i) {
23            if (text[i].key && strcmp(text[i].key, "Frames") == 0 && text[i].text) {
24                *frames = atoi(text[i].text);
25                break;
26            }
27        }
28        printf("  found frames = %d\n", *frames);
29    }
30
31    if (height % *frames != 0) {
32        printf("bad height (%d) for frame count (%d)\n", height, *frames);
33        result = -9;
34        goto exit;
35    }
36
37    surface = reinterpret_cast<GRSurface**>(malloc(*frames * sizeof(GRSurface*)));
38    if (surface == NULL) {
39        result = -8;
40        goto exit;
41    }
42    for (i = 0; i < *frames; ++i) {
43        surface[i] = init_display_surface(width, height / *frames);
44        if (surface[i] == NULL) {
45            result = -8;
46            goto exit;
47        }
48    }
49
50#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA)
51    png_set_bgr(png_ptr);
52#endif
53
54    p_row = reinterpret_cast<unsigned char*>(malloc(width * 4));
55    for (y = 0; y < height; ++y) {
56        png_read_row(png_ptr, p_row, NULL);
57        int frame = y % *frames;
58        unsigned char* out_row = surface[frame]->data +
59            (y / *frames) * surface[frame]->row_bytes;
60        transform_rgb_to_draw(p_row, out_row, channels, width);
61    }
62    free(p_row);
63
64    *pSurface = reinterpret_cast<GRSurface**>(surface);
65
66exit:
67    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
68
69    if (result < 0) {
70        if (surface) {
71            for (i = 0; i < *frames; ++i) {
72                if (surface[i]) free(surface[i]);
73            }
74            free(surface);
75        }
76    }
77    return result;
78}

    關(guān)于圖片我們大概都知道怎么來(lái)顯示的了,所以,現(xiàn)在我們可以替換Android原生態(tài)中的圖片,換成我們自己的圖片,當(dāng)然,也不是什么圖都可以的,在recovery中,所有的png圖片必須是RGB且不帶且不能帶alhpa通道信息。關(guān)于這一點(diǎn),我們可以看open_png這個(gè)函數(shù):

 1static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr,
2                    png_uint_32* width, png_uint_32* height, png_byte* channels)
 
{
3    char resPath[256];
4    unsigned char header[8];
5    int result = 0;
6    int color_type, bit_depth;
7    size_t bytesRead;
8
9    snprintf(resPath, sizeof(resPath)-1"/res/images/%s.png", name);
10    resPath[sizeof(resPath)-1] = '\0';
11    FILE* fp = fopen(resPath, "rb");
12    if (fp == NULL) {
13        result = -1;
14        goto exit;
15    }
16
17    bytesRead = fread(header, 1sizeof(header), fp);
18    if (bytesRead != sizeof(header)) {
19        result = -2;
20        goto exit;
21    }
22
23    if (png_sig_cmp(header, 0sizeof(header))) {
24        result = -3;
25        goto exit;
26    }
27
28    *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULLNULLNULL);
29    if (!*png_ptr) {
30        result = -4;
31        goto exit;
32    }
33
34    *info_ptr = png_create_info_struct(*png_ptr);
35    if (!*info_ptr) {
36        result = -5;
37        goto exit;
38    }
39
40    if (setjmp(png_jmpbuf(*png_ptr))) {
41        result = -6;
42        goto exit;
43    }
44
45    png_init_io(*png_ptr, fp);
46    png_set_sig_bytes(*png_ptr, sizeof(header));
47    png_read_info(*png_ptr, *info_ptr);
48
49    png_get_IHDR(*png_ptr, *info_ptr, width, height, &bit_depth,
50            &color_type, NULLNULLNULL);
51
52    *channels = png_get_channels(*png_ptr, *info_ptr);
53
54    if (bit_depth == 8 && *channels == 3 && color_type == PNG_COLOR_TYPE_RGB) {
55        // 8-bit RGB images: great, nothing to do.
56    } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_GRAY) {
57        // 1-, 2-, 4-, or 8-bit gray images: expand to 8-bit gray.
58        png_set_expand_gray_1_2_4_to_8(*png_ptr);
59    } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_PALETTE) {
60        // paletted images: expand to 8-bit RGB.  Note that we DON'T
61        // currently expand the tRNS chunk (if any) to an alpha
62        // channel, because minui doesn't support alpha channels in
63        // general.
64        png_set_palette_to_rgb(*png_ptr);
65        *channels = 3;
66    } else {
67        fprintf(stderr"minui doesn't support PNG depth %d channels %d color_type %d\n",
68                bit_depth, *channels, color_type);
69        result = -7;
70        goto exit;
71    }
72
73    return result;
74
75  exit:
76    if (result < 0) {
77        png_destroy_read_struct(png_ptr, info_ptr, NULL);
78    }
79    if (fp != NULL) {
80        fclose(fp);
81    }
82
83    return result;
84}

在代碼中,我們可以看到如下:

1 if (bit_depth == 8 && *channels == 3 && color_type == PNG_COLOR_TYPE_RGB) {
2        // 8-bit RGB images: great, nothing to do.
3    } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_GRAY) {
4        // 1-, 2-, 4-, or 8-bit gray images: expand to 8-bit gray.
5        png_set_expand_gray_1_2_4_to_8(*png_ptr);
6    } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_PALETTE) {
7        // paletted images: expand to 8-bit RGB.  Note that we DON'T
8        // currently expand the tRNS chunk (if any) to an alpha
9        // channel, because minui doesn't support alpha channels in
10        // general.
11        png_set_palette_to_rgb(*png_ptr);
12        *channels = 3;
13    } else {
14        fprintf(stderr"minui doesn't support PNG depth %d channels %d color_type %d\n",
15                bit_depth, *channels, color_type);
16        result = -7;
17        goto exit;
18    }

以下參考一位網(wǎng)友給出的解決方案。

    這個(gè)函數(shù)將圖片文件的數(shù)據(jù)讀取到內(nèi)存,我在其中輸出了一些調(diào)試信息,輸出圖片的 color_type, channels 等信息。查看LOG發(fā)現(xiàn),android原生的圖片 channels == 3,channels 即色彩通道個(gè)數(shù),等于 3 的話,意味著只有 R,G,B 三個(gè)通道的信息,沒(méi)有 ALPHA 通道信息!這段代碼的邏輯是如果channels 不等于3, 則按channels = 1 來(lái)處理,即灰度圖。美工給的圖片是帶 alpha通道信息的,即channels = 4,被當(dāng)成灰度圖像來(lái)處理了,怪不得顯示的效果是灰度圖像。我一直以為 png 圖像就只有一種格式,都是帶有 alpha通道的。。。使用圖像處理工具(photoshop 或者 gimp),將美工給的圖片去掉 alpha 通道信息,再替換recovery 的圖片,編譯,替換recovery.img ,reboot -r 。圖片終于正常顯示啦。

韋東山老師課程推薦








商務(wù)合作

支持我請(qǐng)給我在看!


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉