自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

RenderScript:Android平臺上高性能圖形計(jì)算框架

移動(dòng)開發(fā) Android
隨著Android平臺的不斷發(fā)展,一些新的API和框架(如Android的NDK,Vulkan和RenderEffect(Android12))也提供了類似的性能優(yōu)化能力。

RenderScript介紹

RenderScript是一種高性能的計(jì)算框架,用于在設(shè)備上執(zhí)行復(fù)雜的數(shù)學(xué)計(jì)算,尤其是在圖像處理方面。最初是為了解決Android平臺上圖形和計(jì)算密集型任務(wù)而設(shè)計(jì)的,可以在CPU或GPU上并行執(zhí)行,以利用多核處理器和圖形硬件的加速能力。

RenderScript的主要特點(diǎn):

  • 并行計(jì)算:RenderScript利用設(shè)備的多核處理器進(jìn)行并行計(jì)算,從而顯著提高計(jì)算密集型任務(wù)的性能。
  • 硬件加速:RenderScript能夠利用GPU進(jìn)行硬件加速計(jì)算,適用于圖形和圖像處理任務(wù)。
  • 易于使用:RenderScript使用C99樣式的語法,Android SDK提供了方便的Java/Kotlin綁定,使得可以在Android應(yīng)用中輕松集成RenderScript代碼。
  • 性能優(yōu)化:RenderScript編譯器會自動(dòng)優(yōu)化代碼,以充分利用目標(biāo)設(shè)備的硬件特性。

RenderScript使用場景:

  • 圖像處理:如模糊、銳化、顏色轉(zhuǎn)換等。
  • 計(jì)算機(jī)視覺:如特征檢測、邊緣識別等。
  • 物理模擬:如碰撞檢測、粒子系統(tǒng)等。

隨著Android平臺的不斷發(fā)展,一些新的API和框架(如Android的NDK,Vulkan和RenderEffect(Android12))也提供了類似的性能優(yōu)化能力。

Google在Android開發(fā)者博客中提到,其實(shí)早已不建議將RenderScript用于對性能需求至關(guān)重要的任務(wù),Android開發(fā)者應(yīng)該轉(zhuǎn)向可在GPU硬件層級上高效運(yùn)作、且具有出色的跨平臺體驗(yàn)的Vulkan API 。

RenderScript腳本

RenderScript .rs 腳本使用一種類似于C99的語法,允許開發(fā)者定義內(nèi)核函數(shù),這些函數(shù)可以在Android設(shè)備上高效地并行執(zhí)行。.rs 腳本的基本語法說明:

1.腳本頭

在腳本的開頭,通常會看到一些預(yù)處理指令,用于定義腳本的版本和Java包名:

#pragma version(1)
#pragma rs java_package_name(com.reathin.renderscript)
  • #pragma version(1):指定RenderScript的版本。
  • #pragma rs java_package_name(...):指定生成的Java類的包名。

2.數(shù)據(jù)類型

RenderScript使用了一些特殊的數(shù)據(jù)類型,如rs_allocation,是用于訪問內(nèi)存分配的引用類型。還有uchar4、float4等類型,用于表示包含四個(gè)無符號字符或浮點(diǎn)數(shù)的向量。

3.內(nèi)核函數(shù)

內(nèi)核函數(shù)是RenderScript腳本中的主要部分,定義了要在GPU或CPU上執(zhí)行的并行計(jì)算。

void blur(const uchar4 *v_in, uchar4 *v_out, const void *usrData, uint32_t x, uint32_t y) {
    // 內(nèi)核函數(shù)的實(shí)現(xiàn)
}
  • void blur(...):定義了一個(gè)名為blur的內(nèi)核函數(shù)。
  • const uchar4 *v_in 和 uchar4 *v_out:是輸入和輸出參數(shù)的指針。
  • const void *usrData:是傳遞給內(nèi)核的任意用戶數(shù)據(jù)。
  • uint32_t x, uint32_t y:是內(nèi)核的當(dāng)前執(zhí)行位置(例如,像素坐標(biāo))。

4.根函數(shù)

根函數(shù)是RenderScript腳本的入口點(diǎn)。當(dāng)RenderScript運(yùn)行時(shí)加載腳本時(shí),會調(diào)用根函數(shù)。

void root() {
    // 初始化代碼或調(diào)用其他內(nèi)核函數(shù)
}

5.訪問全局變量

在.rs腳本中,可以定義全局變量,并在內(nèi)核函數(shù)中訪問它們。

float mGlobalData;

void blur(...) {
    // 使用 mGlobalData
}

6.調(diào)用其他內(nèi)核

可以在根函數(shù)或其他內(nèi)核函數(shù)中調(diào)用其他內(nèi)核。

void blur(...) {
    // 另一個(gè)內(nèi)核的實(shí)現(xiàn)
}

void root() {
    // 調(diào)用另一個(gè)內(nèi)核
    blur(...);
}

7.分配和訪問內(nèi)存

RenderScript使用Allocation對象來管理內(nèi)存。在Java代碼中,會創(chuàng)建Allocation對象,并將其傳遞給RenderScript內(nèi)核。在.rs腳本中,可以使用rsGetAllocationAddress函數(shù)來獲取指向這些分配的內(nèi)存的指針。

const uchar4 *in = rsGetAllocationAddress(inAllocation);
uchar4 *out = rsGetAllocationAddress(outAllocation);

8.內(nèi)置函數(shù)和API

RenderScript提供了一些內(nèi)置函數(shù)和API,用于執(zhí)行常見的操作,如數(shù)學(xué)運(yùn)算、內(nèi)存操作、類型轉(zhuǎn)換等。

9.編譯和鏈接

.rs 腳本文件在構(gòu)建過程中會被編譯成字節(jié)碼,并與應(yīng)用一起打包。當(dāng)應(yīng)用運(yùn)行時(shí),RenderScript運(yùn)行時(shí)會加載這些字節(jié)碼,并在適當(dāng)?shù)挠布蠄?zhí)行它們。

10.注意事項(xiàng)

  • 確保你的RenderScript腳本遵循Android NDK的C/C++編碼規(guī)范。
  • 由于RenderScript是并行執(zhí)行的,要避免在內(nèi)核函數(shù)中使用可能導(dǎo)致競態(tài)條件的全局變量或狀態(tài)。
  • 對于涉及復(fù)雜計(jì)算或大量數(shù)據(jù)的任務(wù),RenderScript可以顯著提高性能,也要小心管理內(nèi)存和避免不必要的復(fù)制操作。

使用RenderScript實(shí)現(xiàn)模糊效果

在Android中實(shí)現(xiàn)模糊效果通常使用RenderScript或者自定義的OpenGL著色器。RenderScript和OpenGL都是相對底層的API,需要一定的圖形編程知識。對于更簡單的模糊效果,可以考慮使用第三方庫,如Glide或Picasso,提供了更高級的API來實(shí)現(xiàn)圖像模糊和其他效果。

下面使用RenderScript實(shí)現(xiàn)模糊效果。

添加RenderScript支持:

android {  
      
    //高版本Studio
    buildFeatures {
        renderScript true
    }
    
    defaultConfig {    
        renderscriptTargetApi 21  
        renderscriptSupportModeEnabled true  
    }  
  
}

使用RenderScript實(shí)現(xiàn)圖片高斯模糊效果

public static Bitmap scriptBlur(Context context, Bitmap origin, int outWidth, int outHeight, float radius) {
    if (origin == null || origin.isRecycled()) {
        return null;
    }
    mStartTime = System.currentTimeMillis();
    RenderScript renderScript = RenderScript.create(context.getApplicationContext(), RenderScript.ContextType.NORMAL, RenderScript.CREATE_FLAG_NONE);
    Allocation blurInput = Allocation.createFromBitmap(renderScript, origin);
    Allocation blurOutput = Allocation.createTyped(renderScript, blurInput.getType());
    ScriptIntrinsicBlur blur = null;
    try {
        blur = ScriptIntrinsicBlur.create(renderScript, blurInput.getElement());
    } catch (RSIllegalArgumentException e) {
        if (e.getMessage().contains("Unsuported element type")) {
            blur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
        }
    }
    if (blur == null) {
        //腳本模糊失敗
        return null;
    }
    blur.setRadius(range(radius, 0, 20));
    blur.setInput(blurInput);
    blur.forEach(blurOutput);
    
    Bitmap result = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);
    blurOutput.copyTo(result);

    //釋放
    renderScript.destroy();
    blurInput.destroy();
    blurOutput.destroy();

    origin.recycle();
    long time = (System.currentTimeMillis() - mStartTime);
    Log.i("BlurUtils", "模糊用時(shí):[" + time + "ms]");
    return result;
}

調(diào)用高斯模糊方法

val bitmap = BitmapFactory.decodeResource(resources, R.mipmap.image_beauty)

val bitmap1 = BlurUtils.scriptBlur(this, bitmap, bitmap.getWidth(), bitmap.getHeight(), 10f)
val bitmap2 = BlurUtils.scriptBlur(this, bitmap, bitmap.getWidth(), bitmap.getHeight(), 15f)
val bitmap3 = BlurUtils.scriptBlur(this, bitmap, bitmap.getWidth(), bitmap.getHeight(), 20f)
val bitmap4 = BlurUtils.scriptBlur(this, bitmap, bitmap.getWidth(), bitmap.getHeight(), 25f)

imageView1.setImageBitmap(bitmap)
imageView2.setImageBitmap(bitmap2)
imageView3.setImageBitmap(bitmap3)
imageView4.setImageBitmap(bitmap4)

運(yùn)行效果:

在Android中,RenderScript .rs 腳本是一種用C99語法編寫的文件,定義了可以在設(shè)備上并行執(zhí)行的計(jì)算任務(wù)。通常用于圖形和計(jì)算密集型任務(wù),例如圖像處理、物理模擬等。.rs 腳本編譯后會生成二進(jìn)制代碼,代碼可以在Android設(shè)備的CPU或GPU上執(zhí)行。

Android Studio創(chuàng)建rs腳本目錄:

(1) 編寫.rs腳本

#pragma version(1)  
#pragma rs java_package_name(com.reathin.renderscript)  
  
// 輸入圖像  
rs_allocation inImage;  
// 輸出圖像  
rs_allocation outImage;  
// 模糊半徑  
float blurRadius;  
  
// 定義模糊函數(shù)  
void blur(const uchar4 *v_in, uchar4 *v_out, const void *usrData, uint32_t x, uint32_t y) {  
    // 計(jì)算模糊后的顏色值  
    float4 sum = 0.0f;  
    int count = 0;  
    for (float dx = -blurRadius; dx <= blurRadius; dx++) {  
        for (float dy = -blurRadius; dy <= blurRadius; dy++) {  
            int newX = x + (int)dx;  
            int newY = y + (int)dy;  
            if (newX >= 0 && newX < rsAllocationGetDimX(inImage) && newY >= 0 && newY < rsAllocationGetDimY(inImage)) {  
                sum += rsUnpackColor8888(*v_in + rsAllocationGetElementPtr(inImage, newX, newY));  
                count++;  
            }  
        }  
    }  
    *v_out = rsPackColor8888(sum / count);  
}  
  
// 根函數(shù),RenderScript執(zhí)行時(shí)的入口點(diǎn)  
void root() {  
    // 獲取輸入和輸出圖像的指針  
    const uchar4 *in = rsGetAllocationAddress(inImage);  
    uchar4 *out = rsGetAllocationAddress(outImage);  
      
    // 執(zhí)行模糊操作  
    blur(in, out, NULL, 0, 0);  
}

將 .rs 文件放在項(xiàng)目的 src/main/rs 目錄下。在Java或Kotlin代碼中加載這個(gè)腳本并設(shè)置輸入和輸出 Allocation 對象,最后調(diào)用RenderScript的內(nèi)核來執(zhí)行模糊操作。

(2) 調(diào)用RenderScript內(nèi)核進(jìn)行調(diào)用

import android.content.Context;  
import android.graphics.Bitmap;  
import android.renderscript.Allocation;  
import android.renderscript.Element;  
import android.renderscript.RenderScript;  
import android.renderscript.ScriptC;  
  
public Bitmap applyBlur(Context context, Bitmap inputBitmap, float blurRadius) {  
    // 創(chuàng)建RenderScript實(shí)例  
    RenderScript rs = RenderScript.create(context);  
      
    // 創(chuàng)建輸入和輸出Allocation  
    Allocation inputAllocation = Allocation.createFromBitmap(rs, inputBitmap);  
    Allocation outputAllocation = Allocation.createTyped(rs, inputAllocation.getType());  
      
    // 加載RenderScript腳本  
    ScriptC_Blur blurScript = new ScriptC_Blur(rs);  
    blurScript.set_inImage(inputAllocation);  
    blurScript.set_outImage(outputAllocation);  
    blurScript.set_blurRadius(blurRadius);  
      
    // 執(zhí)行模糊操作  
    blurScript.invoke_root();  
      
    // 創(chuàng)建輸出位圖并復(fù)制數(shù)據(jù)  
    Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap.getWidth(), inputBitmap.getHeight(), inputBitmap.getConfig());  
    outputAllocation.copyTo(outputBitmap);  
      
    // 銷毀資源和清理  
    inputAllocation.destroy();  
    outputAllocation.destroy();  
    rs.destroy();  
      
    return outputBitmap;  
}

ScriptC_Blur是根據(jù).rs腳本文件自動(dòng)生成的類。需要用實(shí)際的類名替換ScriptC_Blur應(yīng)該與.rs文件名相同(去掉.rs擴(kuò)展名,并將下劃線_替換為駝峰命名法的大寫字母)。

完整示例代碼: https://github.com/Reathin/Sample-Android

責(zé)任編輯:趙寧寧 來源: 沐雨花飛蝶
相關(guān)推薦

2015-12-15 12:59:17

阿里云HPC

2024-10-05 00:00:05

高性能分布式IM

2009-08-12 17:48:56

存儲高性能計(jì)算曙光

2011-05-30 10:53:45

2020-03-13 07:40:36

Plato數(shù)據(jù)分析

2013-10-24 10:10:21

Android支持庫

2024-04-25 10:09:02

2019-03-01 11:03:22

Lustre高性能計(jì)算

2022-08-15 08:01:35

微服務(wù)框架RPC

2012-09-24 10:12:22

高性能計(jì)算浪潮

2020-11-09 17:15:08

戴爾

2023-10-31 18:52:29

網(wǎng)絡(luò)框架XDP技術(shù)

2020-06-17 16:43:40

網(wǎng)絡(luò)IO框架

2011-05-18 11:02:55

2010-12-20 10:43:23

2009-01-08 18:05:27

服務(wù)器微軟云計(jì)算

2011-12-01 11:36:42

云計(jì)算蘋果谷歌

2010-05-25 10:08:41

虛擬化高性能計(jì)算
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號