APIهای RenderScript از Android 12 منسوخ شدهاند. سازندگان دستگاهها و قطعات قبلاً ارائه پشتیبانی از شتاب سختافزاری را متوقف کردهاند و انتظار میرود پشتیبانی RenderScript در نسخههای آینده به طور کامل حذف شود.
عملکرد C/C++ ممکن است برای بسیاری از موارد استفاده کافی باشد، و اگر فقط به RenderScript برای Intrinsics متکی بودید، میتوانید آن استفادهها را با RenderScript Intrinsics Replacement Toolkit جایگزین کنید، که استفاده آسانتر است و با بهبود عملکرد ۲ برابری همراه است!
اگر نیاز به استفاده کامل از شتاب GPU دارید، توصیه میکنیم اسکریپتهای خود را به Vulkan منتقل کنید ، سایر گزینههای تسریعشده عبارتند از انتقال اسکریپتهای خود به OpenGL ، استفاده از عملیات تصویر مبتنی بر Canvas ، یا استفاده از زبان سایهزنی گرافیک اندروید (AGSL) .
پس از منسوخ شدن RenderScript در پلتفرم اندروید، پشتیبانی از RenderScript در افزونه Android Gradle حذف می شود. با شروع پلاگین Android Gradle 7.2، API های RenderScript منسوخ شده اند. آنها به کار خود ادامه می دهند، اما هشدارها را فرا می خوانند. نسخه های آینده AGP دیگر شامل پشتیبانی Renderscript نخواهد بود. این راهنما نحوه مهاجرت از RenderScript را توضیح می دهد.
اگرچه توابع ذاتی RenderScript پس از منسوخ شدن RenderScript همچنان به کار خود ادامه می دهند، اما ممکن است به جای GPU فقط روی CPU اجرا شوند.
برای برخی از این عملیات، اکنون گزینه های کارآمدتری در پلتفرم یا کتابخانه های Jetpack تعبیه شده است.
پلتفرم اندروید از عملیات پردازش تصویر سریع پشتیبانی میکند که میتوان آنها را مستقل از ذاتی RenderScript روی تصاویر اعمال کرد. مثالها عبارتند از:
- مخلوط کنید
- محو کردن
- ماتریس رنگ
- تغییر اندازه
RenderEffect
با پشتیبانی از blur به اندروید 12، سطح API 31 اضافه شد و به شما امکان می دهد یک RenderNode
محو کنید. RenderNode
ساختاری از لیست نمایشگر است که اندروید از آن برای کمک به سرعت بخشیدن به گرافیک پلت فرم استفاده می کند.
Android یک میانبر برای اعمال یک افکت در RenderNode
مرتبط با یک View
ارائه می دهد. برای محو کردن یک View
، View.setRenderEffect()
را فراخوانی کنید:
val blurRenderEffect = RenderEffect.createBlurEffect(radius, radius,
Shader.TileMode.MIRROR
)
view.setRenderEffect(blurRenderEffect)
اگر به تصویر تار رندر شده در Bitmap
نیاز دارید، این فریم ورک از رندر سریع با یک HardwareRenderer
که توسط HardwareBuffer
پشتیبانی می شود، پشتیبانی می کند. کد زیر HardwareRenderer
، RenderNode
و RenderEffect
برای تاری ایجاد می کند:
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)
اعمال افکت شامل استفاده از RecordingCanvas
داخلی برای RenderNode
است. کد زیر ترسیم را ضبط می کند، درخواست رندر را ایجاد می کند و سپس منتظر می ماند تا درخواست به پایان برسد:
val renderCanvas = it.renderNode.beginRecording()
renderCanvas.drawBitmap(it.bitmap, 0f, 0f, null)
renderNode.endRecording()
hardwareRenderer.createRenderRequest()
.setWaitForPresent(true)
.syncAndDraw()
تصویر ارائه شده در یک HardwareBuffer
مرتبط با ImageReader
است. کد زیر Image
دریافت میکند و یک Bitmap
برمیگرداند که 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")
کد زیر پس از رندر کردن تصویر پاک می شود. توجه داشته باشید که ImageReader
، RenderNode
، RenderEffect
و HardwareRenderer
را می توان برای پردازش چندین تصویر استفاده کرد.
hardwareBuffer.close()
image.close()
imageReader.close()
renderNode.discardDisplayList()
hardwareRenderer.destroy()
Android Graphics Shading Language (AGSL) توسط Android 13+ برای تعریف رفتار اشیاء RuntimeShader
قابل برنامه ریزی استفاده می شود. AGSL قسمت اعظم نحو خود را با شیدرهای قطعه GLSL به اشتراک می گذارد، اما در سیستم رندر گرافیکی اندروید کار می کند تا هم نقاشی را در Canvas
سفارشی کند و هم محتوای View
فیلتر کند. این می تواند برای افزودن پردازش تصویر سفارشی در طول عملیات ترسیم یا با استفاده از RenderNode
به طور مستقیم برای رندر یک تصویر در بوم Bitmap
استفاده شود. مثال زیر نحوه اعمال یک سایه زن سفارشی برای جایگزینی افکت تاری تصویر را نشان می دهد.
با ایجاد یک RuntimeShader
شروع کنید و آن را با کد سایه زن AGSL مثال بزنید. این سایه زن برای اعمال یک ماتریس رنگ برای چرخش رنگ استفاده می شود:
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;
}
""")
سایه زن را می توان مانند هر RenderEffect
دیگری روی یک RenderNode
اعمال کرد. مثال زیر نحوه تنظیم یونیفرم ها را در 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)
برای بدست آوردن Bitmap
، از همان تکنیکی که در نمونه تاری تصویر قبلی استفاده شده است استفاده می شود.
-
RecordingCanvas
داخلی برایRenderNode
سایه زن را اعمال می کند. -
Image
بدست میآید و یکBitmap
برمیگرداند کهHardwareBuffer
آن را میپیچد.
تبدیل از YUV مسطح به RGB برای استفاده در پردازش تصویر به عنوان بخشی از مورد استفاده ImageAnalysis در CameraX Jetpack پشتیبانی می شود.
منابعی در مورد استفاده از ImageAnalysis
به عنوان بخشی از شروع به کار با Codelab CameraX و در مخزن نمونه دوربین اندروید وجود دارد.
اگر برنامه شما از Intrinsics استفاده می کند، می توانید از کتابخانه جایگزین مستقل استفاده کنید. آزمایشهای ما نشان میدهد که سریعتر از اجرای CPU RenderScript موجود است.
جعبه ابزار شامل توابع زیر است:
- مخلوط کنید
- محو کردن
- ماتریس رنگ
- در هم بپیچید
- هیستوگرام و هیستوگرام نقطه
- جدول جستجو (LUT) و LUT 3D
- تغییر اندازه
- YUV به RGB
برای جزئیات کامل و محدودیتها، به README.md
و Toolkit.kt
جعبه ابزار مراجعه کنید. فایل ها
برای دانلود، افزودن و استفاده از کتابخانه مراحل زیر را انجام دهید:
پروژه را از گیت هاب دانلود کنید.
renderscript-toolkit module
را بیابید و بسازید.با تغییر فایل
build.gradle
برنامه، کتابخانه را به پروژه Android Studio خود اضافه کنید.روش مناسب جعبه ابزار را فراخوانی کنید.
برای جایگزینی تابع ScriptIntrinsicBlur
:
برای محو کردن یک بیت مپ، با
Toolkit.blur
تماس بگیرید.var blurredBitmap = Toolkit.blur(myBitmap, radius)
اگر می خواهید تصویری را که با آرایه ای از بایت ها نمایش داده می شود تار کنید، عرض، ارتفاع و تعداد بایت ها در هر پیکسل را مشخص کنید.
val outArray = Toolkit.blur(inputArray, bytesPerPixel, width, height, radius)
اگر مورد استفاده شما با موارد زیر قابل حل نیست:
- RenderScript Intrinsics Replacement Toolkit
- APIهای جدید در پلتفرم اندروید مانند
RenderEffect
وAGSL
- APIهای کتابخانه Android Jetpack مانند
CameraX
و، مورد استفاده شما می تواند از شتاب GPU بهره مند شود، Android از محاسبه GPU در بین پلتفرم های Vulkan و OpenGL ES (GLES) API پشتیبانی می کند. ممکن است این کار را غیرضروری بدانید زیرا در اکثر دستگاهها اسکریپتهای شما از قبل به جای GPU بر روی CPU اجرا میشوند: C/C++ ممکن است برای برخی موارد استفاده سریعتر از محاسبه RenderScript، GLES یا Vulkan باشد. (یا حداقل به اندازه کافی سریع برای مورد استفاده شما)
برای درک بهتر نحوه انتقال، برنامه نمونه را مرور کنید. نمونه نشان می دهد که چگونه یک بیت مپ را محو کنید و یک تبدیل ماتریس رنگ را در RenderScript انجام دهید، و دارای کد معادل در Vulkan و OpenGL است.
اگر برنامه شما نیاز به پشتیبانی از طیف وسیعی از نسخهها دارد، از RenderScript برای دستگاههای دارای Android 6 (سطح API 23) و پایینتر و Vulkan یا GLES در دستگاههای پشتیبانیشده با Android 7 (سطح API 24) و بالاتر استفاده کنید. اگر minSdkVersion
شما 24 یا بالاتر است، ممکن است نیازی به استفاده از RenderScript نباشد. Vulkan یا GLES 3.1 را می توان در هر جایی که به پشتیبانی محاسباتی GPU نیاز دارید استفاده کرد.
Android اتصالات SDK را برای GLES API ارائه میکند، بنابراین استفاده از NDK هنگام کار در OpenGL ES ضروری نیست.
Vulkan اتصالات SDK را ارائه نمی دهد، بنابراین هیچ نقشه مستقیمی از RenderScript به Vulkan وجود ندارد. شما کد Vulkan را با استفاده از NDK می نویسید و توابع JNI را برای دسترسی به این کد از Kotlin یا Java ایجاد می کنید.
صفحات زیر جنبه های مهاجرت از RenderScript را پوشش می دهند. برنامه نمونه تقریباً همه این ملاحظات را اجرا می کند. برای درک بهتر آنها، کدهای معادل RenderScript و Vulkan را با هم مقایسه کنید.