Migracja z renderScriptu

Interfejsy RenderScript API zostaną wycofane w Androidzie 12. Urządzenie i komponent producenci już zaprzestali obsługi akceleracji sprzętowej, i obsługa języka RenderScript zostanie całkowicie wycofana w przyszłej wersji.

Wydajność C/C++ może być wystarczająca do wielu zastosowań, a jeśli chcesz Wykorzystując kod RenderScript na potrzeby zasobów wewnętrznych, możesz zastąpić te zastosowania RenderScript Intrinsics Replacement Toolkit, który jest łatwiejszy. może nawet dwukrotnie poprawić wydajność.

Jeśli chcesz w pełni wykorzystać akcelerację GPU, migracja skryptów do Vulkan, inne opcje przyspieszone dołącz migrację skryptów do OpenGL przy użyciu trybu Canvas-based operacji na obrazie lub korzystać z funkcji cieniowania grafik w Androidzie Język (AGSL).

Po wycofaniu technologii RenderScript na platformie Androida obsługa języka Usuwam kod RenderScript we wtyczce Androida do obsługi Gradle. Od Wtyczka Androida do obsługi Gradle w wersji 7.2, interfejsy RenderScript API zostały wycofane. Ta kontynuuj, ale wywołują ostrzeżenia. Przyszłe wersje pakietu AGP nie będą już obsługiwać Renderscript. W tym przewodniku wyjaśniamy, jak przeprowadzić migrację z RenderScript.

Migracja z elementów wewnętrznych

Chociaż funkcje wewnętrzne języka RenderScript nadal działają po zastosowaniu nie są obsługiwane przez kod RenderScript, są one wykonywane tylko na CPU GPU.

W przypadku niektórych z tych operacji wbudowane są bardziej wydajne opcje na platformie lub w bibliotekach Jetpack.

Wbudowane przyspieszone operacje na obrazach

Platforma Android obsługuje przyspieszone operacje przetwarzania obrazu, została zastosowana do obrazów niezależnie od elementów wewnętrznych kodu RenderScript. Przykłady:

  • Różne
  • Rozmycie
  • Matryca kolorów
  • Zmień rozmiar

Rozmycie obrazu w widoku danych na urządzeniach z Androidem 12 lub nowszym

Aplikacja RenderEffect z obsługą rozmycia została dodana do Androida 12. Interfejs API poziomu 31, który umożliwia rozmycie RenderNode. RenderNode to struktura listy wyświetlania, która pozwala Androidowi przyspieszyć grafiki platformy.

Android udostępnia skrót do zastosowania efektu do elementu RenderNode powiązanego dzięki View. Aby zamazać element View, zadzwoń View.setRenderEffect():

val blurRenderEffect = RenderEffect.createBlurEffect(radius, radius,
        Shader.TileMode.MIRROR
    )
view.setRenderEffect(blurRenderEffect)

Rozmycie obrazu na Androidzie 12 i nowszym renderowane w mapie bitowej

Jeśli potrzebujesz rozmytego obrazu renderowanego w Bitmap, obsługuje akcelerowane renderowanie za pomocą metody HardwareRenderer wspierane przez HardwareBuffer. Ten kod tworzy HardwareRenderer, RenderNode i RenderEffect do rozmycia:

val imageReader = ImageReader.newInstance(
    bitmap.width, bitmap.height,
    PixelFormat.RGBA_8888, numberOfOutputImages,
    HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE or HardwareBuffer.USAGE_GPU_COLOR_OUTPUT
)
val renderNode = RenderNode("BlurEffect")
val hardwareRenderer = HardwareRenderer()

hardwareRenderer.setSurface(imageReader.surface)
hardwareRenderer.setContentRoot(renderNode)
renderNode.setPosition(0, 0, imageReader.width, imageReader.height)
val blurRenderEffect = RenderEffect.createBlurEffect(
    radius, radius,
    Shader.TileMode.MIRROR
)
renderNode.setRenderEffect(blurRenderEffect)

Zastosowanie efektu wymaga użycia wewnętrznego RecordingCanvas na urządzeniu RenderNode. Następujący kod: rejestruje rysunek, tworzy żądanie renderowania, a następnie czeka na żądanie zakończenia:

val renderCanvas = it.renderNode.beginRecording()
renderCanvas.drawBitmap(it.bitmap, 0f, 0f, null)
renderNode.endRecording()
hardwareRenderer.createRenderRequest()
    .setWaitForPresent(true)
    .syncAndDraw()

Wyrenderowany obraz znajduje się w folderze HardwareBuffer powiązanym z ImageReader. Ten kod pobiera Image oraz zwraca parametr Bitmap, który otacza parametr HardwareBuffer.

val image = imageReader.acquireNextImage() ?: throw RuntimeException("No Image")
val hardwareBuffer = image.hardwareBuffer ?: throw RuntimeException("No HardwareBuffer")
val bitmap = Bitmap.wrapHardwareBuffer(hardwareBuffer, null)
    ?: throw RuntimeException("Create Bitmap Failed")

Ten kod czyści dane po wyrenderowaniu obrazu. Pamiętaj, że parametr Można użyć ImageReader, RenderNode, RenderEffect i HardwareRenderer wiele obrazów.

hardwareBuffer.close()
image.close()
imageReader.close()
renderNode.discardDisplayList()
hardwareRenderer.destroy()

Zgodność z zasadami AGSL do przetwarzania obrazów

Język cieniowania grafiki Androida (AGSL) jest używany w Androidzie 13 i nowszych do: zdefiniować zachowanie programowalnych RuntimeShader obiektów. Amerykański język migowy Ma znaczną część wspólnej składni z programami do cieniowania fragmentów GLSL, ale działa w ramach system renderowania grafiki na Androidzie, umożliwiający dostosowywanie obrazów w aplikacji Canvas; i filtruj treści z View. Można jej użyć do dodania niestandardowego przetwarzania obrazu podczas wykonywania operacji rysowania lub przez bezpośrednie użycie RenderNode do renderowania obraz w obszarze roboczym Bitmap. Poniższy przykład pokazuje, jak zastosować niestandardowy program do cieniowania, który zastąpi efekt rozmycia obrazu.

Zacznij od utworzenia instancji RuntimeShader i utwórz jej instancję za pomocą cieniowania AGSL w kodzie. Ten cieniowanie służy do stosowania matrycy kolorów do zmiany odcieni:

val hueShader = RuntimeShader("""
    uniform float2 iResolution;       // Viewport resolution (pixels)
    uniform float2 iImageResolution;  // iImage1 resolution (pixels)
    uniform float iRadian;            // radian to rotate things around
    uniform shader iImage1;           // An input image
    half4 main(float2 fragCoord) {
    float cosR = cos(iRadian);
    float sinR = sin(iRadian);
        mat4 hueRotation =
        mat4 (
                0.299 + 0.701 * cosR + 0.168 * sinR, //0
                0.587 - 0.587 * cosR + 0.330 * sinR, //1
                0.114 - 0.114 * cosR - 0.497 * sinR, //2
                0.0,                                 //3
                0.299 - 0.299 * cosR - 0.328 * sinR, //4
                0.587 + 0.413 * cosR + 0.035 * sinR, //5
                0.114 - 0.114 * cosR + 0.292 * sinR, //6
                0.0,                                 //7
                0.299 - 0.300 * cosR + 1.25 * sinR,  //8
                0.587 - 0.588 * cosR - 1.05 * sinR,  //9
                0.114 + 0.886 * cosR - 0.203 * sinR, //10
                0.0,                                 //11
                0.0, 0.0, 0.0, 1.0 );                //12,13,14,15
        float2 scale = iImageResolution.xy / iResolution.xy;
        return iImage1.eval(fragCoord * scale)*hueRotation;
    }
""")

Ściemniacz można zastosować na urządzeniu RenderNode tak samo jak z innym urządzeniem RenderEffect. Ten przykład pokazuje, jak ustawić uniformy w HueShader:

hueShader.setFloatUniform("iImageResolution", bitmap.width.toFloat(),
    bitmap.height.toFloat())
hueShader.setFloatUniform("iResolution", bitmap.width.toFloat(),
    bitmap.height.toFloat())
hueShader.setFloatUniform("iRadian", radian)
hueShader.setInputShader( "iImage1", BitmapShader(bitmap, Shader.TileMode.MIRROR,
    Shader.TileMode.MIRROR))
val colorFilterEffect = RenderEffect.createShaderEffect(it.hueShader)
renderNode.setRenderEffect(colorFilterEffect)

Aby uzyskać Bitmap, użyj tej samej metody co przy poprzednim rozmyciu obrazu przykład.

  • Mechanizm RecordingCanvas na urządzeniu RenderNode stosuje cieniowanie.
  • Pozyskany element Image jest zwracany Bitmap, który opakowuje HardwareBuffer

Konwertuj z planarnych YUV na RGB za pomocą AparatuX

Przekształcanie z planalnego YUV na RGB, aby wykorzystywać je podczas przetwarzania obrazu. Przypadek użycia Analiza obrazu w Jetpack AparatX

Materiały dotyczące korzystania z usługi ImageAnalysis w ramach Ćwiczenia z programowania i Pierwsze kroki z AparatemX aparat Androida samples.

Wbudowany zestaw narzędzi do wymiany RenderScriptu

Jeśli Twoja aplikacja używa elementów wewnętrznych, możesz użyć samodzielnego zamiennika biblioteka; nasze testy wykazały, że jest to szybsze niż przy użyciu istniejącego procesora RenderScript. implementacji.

Pakiet narzędzi zawiera następujące funkcje:

  • Różne
  • Rozmycie
  • Matryca kolorów
  • Zwieranie
  • Histogram i histogramDot
  • Tabela przeglądowa (LUT) i LUT 3D
  • Zmień rozmiar
  • YUV na RGB

Szczegółowe informacje i ograniczenia znajdziesz w README.md i Toolkit.kt narzędzia. .

Wykonaj te czynności, aby pobrać i dodać bibliotekę oraz jej używać:

  1. Pobierz projekt. z GitHuba.

  2. Zlokalizuj i zbuduj renderscript-toolkit module.

  3. Dodaj ją do projektu w Android Studio, modyfikując bibliotekę build.gradle.

  4. Wywołaj odpowiednią metodę zestawu narzędzi.

Przykład: migracja z funkcji ScriptIntrinsicBlur

Aby zastąpić funkcję ScriptIntrinsicBlur:

  • Aby zamazać bitmapę, wywołaj Toolkit.blur.

    var blurredBitmap = Toolkit.blur(myBitmap, radius)
    
  • Jeśli chcesz zamazać obraz reprezentowany przez tablicę bajtów, użyj metody szerokości, wysokości i liczby bajtów na piksel.

    val outArray = Toolkit.blur(inputArray, bytesPerPixel, width, height, radius)
    
.

Migracja ze skryptów

Jeśli w Twoim przypadku użycia nie można zastosować rozwiązania:

W Twoim przypadku akceleracja za pomocą GPU może być korzystna, ponieważ Android obsługuje GPU i wykorzystywać wieloplatformowe interfejsy API Vulkan i OpenGL ES (GLES). Możesz znaleźć to zbędne, ponieważ na większości urządzeń skrypty są już uruchomione na procesorze zamiast GPU: kod C/C++ może być szybszy niż RenderScript, GLES lub Vulkan w niektórych przypadkach użycia. (lub przynajmniej wystarczająco szybko, by można było go wykorzystać)

Aby lepiej zrozumieć, jak przeprowadzić migrację, zapoznaj się z przykładowej aplikacji. przykład pokazuje, jak zamazać bitmapę i przeprowadzić konwersję matrycy kolorów w języku RenderScript i ma odpowiednik w językach Vulkan oraz OpenGL.

Jeśli Twoja aplikacja musi obsługiwać różne wersje, użyj RenderScriptu urządzenia z Androidem 6 (poziom interfejsu API 23) lub starszym oraz obsługą Vulkan lub GLES obsługiwanych urządzeniach z Androidem 7 (poziom interfejsu API 24) i nowszym. Jeśli minSdkVersion ma wersję 24 lub wyższą. Możliwe, że nie musisz używać RenderScriptu. Vulkan lub GLES 3.1 można używać wszędzie tam, gdzie potrzebujesz obsługi procesora graficznego.

Android udostępnia powiązania SDK dla interfejsów API GLES, nie trzeba więc używać NDK podczas pracy w środowisku OpenGL ES.

Interfejs Vulkan nie udostępnia powiązań SDK, nie ma więc bezpośredniego mapowania z RenderScriptu na język Vulkan; Napisać kod Vulkan za pomocą pakietu NDK i utworzyć JNI w celu uzyskania dostępu do tego kodu z języka Kotlin lub Javy.

Na kolejnych stronach omawiamy aspekty migracji z języka RenderScript. Przykład uwzględnia prawie wszystkie z nich. Aby lepiej je zrozumieć, kod RenderScript i jego odpowiednik w języku Vulkan.