ממשקי ה-API של RenderScript הוצאו משימוש החל מ-Android 12. מכשיר ורכיב יצרנים כבר הפסיקו לספק תמיכה בהאצת חומרה, והתמיכה ב-RenderScript צפויה להיות מוסרת לחלוטין בגרסה עתידית.
ביצועי C/C++ עשויים להספיק לתרחישי שימוש רבים, ואם שמסתמך על RenderScript לערכי הפנימיים, אפשר להחליף את השימושים האלה את RenderScript Intrinsics Replacement Toolkit, וקל יותר להשתמש בערכת הכלים לשימוש והוא מגיע עם שיפור אפשרי של פי 2 בביצועים!
אם אתה צריך להפיק את המרב מהאצת ה-GPU, העברת סקריפטים ל-Vulkan, אפשרויות מהירות אחרות כולל העברת הסקריפטים שלך ל-OpenGL, באמצעות גרסה מבוססת-לוח הציור פעולות תמונה, או שימוש בהצללה של הגרפיקה של Android שפה (AGSL).
לאחר ההוצאה משימוש של RenderScript בפלטפורמת Android, תמיכה ב אנחנו מסירים את RenderScript בפלאגין של Android Gradle. מתחיל ב- הפלאגין Android Gradle גרסה 7.2, ממשקי ה-API של RenderScript הוצאו משימוש. הם ימשיכו לפעול, אבל להפעיל אזהרות. גרסאות עתידיות של AGP לא יהיו יותר זמינות כולל תמיכה ב-Renderscript. במדריך הזה מוסבר איך להעביר מ- RenderScript.
העברה מפנימי
למרות שהפונקציות intrinsics של RenderScript ממשיכות לפעול אחרי להוצאה משימוש של RenderScript, יכול להיות שהם יופעלו רק ב-CPU, GPU.
בחלק מהפעולות האלה, יש עכשיו אפשרויות יעילות יותר שמובנות בפלטפורמה או בספריות Jetpack.
פעולות תמונה מואצות מובנות
פלטפורמת Android תומכת בפעולות עיבוד תמונות מואצות שיכולות להיות רלוונטיות לתמונות, ללא קשר למאפייני RenderScript. דוגמאות:
- שילוב
- טשטוש הרקע
- מטריצת צבעים
- שינוי הגודל
טשטוש תמונה ב-Android 12 ואילך בתצוגה
הסרטון RenderEffect
עם תמיכה בטשטוש נוסף ל-Android 12,
רמת API 31 מאפשרת לטשטש RenderNode
. RenderNode
הוא מבנה של רשימת תצוגה ש-Android משתמש בו כדי להאיץ
גרפיקת פלטפורמה.
ב-Android יש קיצור דרך להחלת אפקט על RenderNode
שמשויך למכשיר
עם View
. כדי לטשטש View
, צריך להתקשר
View.setRenderEffect()
:
val blurRenderEffect = RenderEffect.createBlurEffect(radius, radius,
Shader.TileMode.MIRROR
)
view.setRenderEffect(blurRenderEffect)
טשטוש תמונה ב-Android 12 ואילך שעבר רינדור למפת סיביות (bitmap)
אם אתם צריכים שהתמונה המטושטשת תעבור רינדור ל-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()
AGSL לעיבוד תמונה
מערכת Android 13 ואילך משמשת את Android Graphics Shading Language (AGSL) כדי:
להגדיר את ההתנהגות של
RuntimeShader
אובייקטים. AGSL
משתף חלק גדול מהתחביר שלו עם תוכנות הצללה של מקטעים ב-GLSL, אבל הוא פועל
מערכת רינדור גרפיקה ב-Android להתאמה אישית של ציור בתוך Canvas
ולסנן View
תוכן. אפשר להשתמש באפשרות הזו כדי להוסיף עיבוד תמונה בהתאמה אישית
במהלך פעולות שרטוט, או על ידי שימוש ישירות ב-RenderNode
כדי לעבד
את התמונה בתוך אזור עריכה של Bitmap
. הדוגמה הבאה ממחישה איך להחיל את התג
כלי הצללה בהתאמה אישית שיחליף את אפקט טשטוש התמונה.
התחל על ידי יצירת RuntimeShader
, יצירת מופע כזה באמצעות תוכנת ההצללה (shader) של 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;
}
""")
אפשר להחיל את תוכנת ההצללה על RenderNode
, בדיוק כמו על כל RenderEffect
אחר.
הדוגמה הבאה ממחישה איך להגדיר את המדים ב-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 באמצעות CameraX
המרה מ-YUV מישור ל-RGB לשימוש בעיבוד תמונות. תרחיש לדוגמה של ImageAnalysis ב-Jetpack מצלמהX.
יש משאבים בנושא השימוש ב-ImageAnalysis
כחלק
תחילת העבודה עם Codelab של CameraX ובתוך
מצלמת Android
דוגמאות.
ערכת הכלים להחלפה של רכיב Renderscript
אם האפליקציה שלך משתמשת בעקרונות פנימיים, אפשר להשתמש בהחלפה העצמאית. ספרייה; לפי הבדיקות שלנו, הוא מהיר יותר משימוש במעבד (CPU) הקיים של RenderScript יישום בפועל.
ערכת הכלים כוללת את הפונקציות הבאות:
- שילוב
- טשטוש הרקע
- מטריצת צבעים
- קעור
- היסטוגרמה והיסטוגרמה
- טבלת חיפוש (LUT) ו-LUT 3D
- שינוי הגודל
- YUV ל-RGB
לקבלת פרטים מלאים ומגבלות, אפשר לעיין בREADME.md
ובToolkit.kt
של ערכת הכלים.
.
מבצעים את השלבים הבאים כדי להוריד את הספרייה, להוסיף אותה ולהשתמש בה:
מורידים את הפרויקט. מ-GitHub.
מאתרים ובונים את
renderscript-toolkit module
.כדי להוסיף את הספרייה לפרויקט Android Studio, משנים את הגדרות האפליקציה קובץ
build.gradle
.מפעילים את השיטה המתאימה של ערכת הכלים.
דוגמה: העברה מהפונקציה ScriptIntrinsicBlur
כדי להחליף את הפונקציה ScriptIntrinsicBlur
:
כדי לטשטש מפת סיביות, צריך להתקשר למספר
Toolkit.blur
.var blurredBitmap = Toolkit.blur(myBitmap, radius)
אם רוצים לטשטש תמונה שמיוצגת על ידי מערך של בייטים, מציינים את הערך הרוחב, הגובה ומספר הבייטים לכל פיקסל.
val outArray = Toolkit.blur(inputArray, bytesPerPixel, width, height, radius)
העברה מסקריפטים
אם לא ניתן לפתור את התרחיש לדוגמה באמצעות:
- ערכת הכלים להחלפה של RenderScript Intrinsics
- ממשקי API חדשים בפלטפורמת Android, כמו
RenderEffect
ו-AGSL
- ממשקי API של ספריית Android Jetpack כמו
CameraX
בנוסף, האצת GPU ב-Android יכולה להועיל לתרחיש לדוגמה שלכם מחשב בממשקי API של Vulkan ו-OpenGL ES (GLES) בפלטפורמות שונות. המידע הזה יכול להופיע אין צורך, כי ברוב המכשירים הסקריפטים כבר מריצים על המעבד במקום ה-GPU: 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 עבור ממשקי API של GLES, לכן לא צריך להשתמש NDK כשעובדים ב-OpenGL ES.
Vulkan לא מספק קישורי SDK, ולכן אין מיפוי ישיר מ- RenderScript ל-Vulkan; כותבים את קוד ה-Vulkan באמצעות ה-NDK ויוצרים JNI כדי לגשת לקוד הזה מ-Kotlin או Java.
בדפים הבאים מתוארים היבטים של המעבר מ-RenderScript. הדוגמה מטמיעים את כל השיקולים האלה. כדי להבין אותם טוב יותר, להשוות בין הקוד RenderScript ו-Vulkan המקביל.