RenderScript থেকে মাইগ্রেট করুন

রেন্ডারস্ক্রিপ্ট এপিআইগুলি অ্যান্ড্রয়েড 12 থেকে শুরু করে বন্ধ করা হয়েছে৷ ডিভাইস এবং উপাদান নির্মাতারা ইতিমধ্যে হার্ডওয়্যার ত্বরণ সমর্থন প্রদান করা বন্ধ করে দিয়েছে এবং ভবিষ্যতের রিলিজে রেন্ডারস্ক্রিপ্ট সমর্থন সম্পূর্ণরূপে সরিয়ে ফেলা হবে বলে আশা করা হচ্ছে৷

C/C++ কর্মক্ষমতা অনেক ব্যবহারের ক্ষেত্রে পর্যাপ্ত হতে পারে, এবং আপনি যদি শুধুমাত্র অন্তর্নিহিতের জন্য RenderScript-এর উপর নির্ভর করতেন, তাহলে আপনি RenderScript Intrinsics Replacement Toolkit- এর সাথে সেই ব্যবহারগুলি প্রতিস্থাপন করতে পারেন, যা ব্যবহার করা সহজ এবং সম্ভাব্য 2x কর্মক্ষমতা উন্নতির সাথে আসে!

আপনি যদি GPU ত্বরণের সম্পূর্ণ সুবিধা নিতে চান, তাহলে আমরা আপনার স্ক্রিপ্টগুলিকে Vulkan-এ স্থানান্তরিত করার পরামর্শ দিই, অন্যান্য ত্বরিত বিকল্পগুলির মধ্যে আপনার স্ক্রিপ্টগুলি OpenGL-এ স্থানান্তরিত করা , ক্যানভাস-ভিত্তিক ইমেজ অপারেশনগুলি ব্যবহার করা বা Android গ্রাফিক্স শেডিং ল্যাঙ্গুয়েজ (AGSL) ব্যবহার করা অন্তর্ভুক্ত৷

অ্যান্ড্রয়েড প্ল্যাটফর্মে রেন্ডারস্ক্রিপ্টের অবমূল্যায়নের পর, অ্যান্ড্রয়েড গ্রেডল প্লাগইনে রেন্ডারস্ক্রিপ্টের সমর্থন সরিয়ে দেওয়া হচ্ছে। অ্যান্ড্রয়েড গ্রেডল প্লাগইন 7.2 দিয়ে শুরু করে, রেন্ডারস্ক্রিপ্ট এপিআইগুলি বাতিল করা হয়েছে। তারা কাজ চালিয়ে যাচ্ছে, কিন্তু সতর্কতা আহ্বান করছে। AGP এর ভবিষ্যত সংস্করণে আর রেন্ডারস্ক্রিপ্ট সমর্থন অন্তর্ভুক্ত থাকবে না। রেন্ডারস্ক্রিপ্ট থেকে কীভাবে স্থানান্তর করা যায় তা এই নির্দেশিকাটি ব্যাখ্যা করে।

অন্তর্নিহিত থেকে স্থানান্তর

যদিও রেন্ডারস্ক্রিপ্টের অভ্যন্তরীণ ফাংশনগুলি রেন্ডারস্ক্রিপ্ট অবচয়নের পরেও কাজ করতে থাকে, তবে তারা GPU এর পরিবর্তে শুধুমাত্র CPU-তে কার্যকর করতে পারে।

এই ক্রিয়াকলাপের কিছুর জন্য, এখন প্ল্যাটফর্মে বা জেটপ্যাক লাইব্রেরিতে তৈরি আরও দক্ষ বিকল্প রয়েছে।

অন্তর্নির্মিত ত্বরিত ইমেজ অপারেশন

অ্যান্ড্রয়েড প্ল্যাটফর্মটি ত্বরিত চিত্র প্রক্রিয়াকরণ ক্রিয়াকলাপগুলিকে সমর্থন করে যা রেন্ডারস্ক্রিপ্টের অন্তর্নিহিত থেকে স্বাধীন, চিত্রগুলিতে প্রয়োগ করা যেতে পারে। উদাহরণ অন্তর্ভুক্ত:

  • মিশ্রিত করুন
  • ঝাপসা
  • কালার ম্যাট্রিক্স
  • আকার পরিবর্তন করুন

অ্যান্ড্রয়েড 12+ এ ছবিকে একটি ভিউতে ব্লার করুন

ব্লার সমর্থন সহ RenderEffect Android 12, API স্তর 31-এ যোগ করা হয়েছে, যা আপনাকে একটি RenderNode ব্লার করতে দেয়। RenderNode হল ডিসপ্লে তালিকার একটি গঠন যা অ্যান্ড্রয়েড প্ল্যাটফর্ম গ্রাফিক্সকে ত্বরান্বিত করতে সাহায্য করে।

অ্যান্ড্রয়েড একটি View সাথে সম্পর্কিত RenderNode একটি প্রভাব প্রয়োগ করার জন্য একটি শর্টকাট প্রদান করে। একটি View অস্পষ্ট করতে, View.setRenderEffect() কল করুন :

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

একটি বিটম্যাপে রেন্ডার করা Android 12+ এ ছবি ব্লার করা হয়েছে

আপনার যদি একটি Bitmap রেন্ডার করা অস্পষ্ট চিত্রের প্রয়োজন হয়, তাহলে ফ্রেমওয়ার্কটি HardwareBuffer দ্বারা সমর্থিত একটিHardwareRenderer সাথে ত্বরান্বিত রেন্ডারিং সমর্থন করে। নিম্নোক্ত কোডটি 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)

RenderNode জন্য অভ্যন্তরীণ RecordingCanvas ব্যবহার করে প্রভাব প্রয়োগ করা জড়িত। নিম্নলিখিত কোডটি অঙ্কন রেকর্ড করে, রেন্ডার অনুরোধ তৈরি করে এবং তারপর অনুরোধটি শেষ হওয়ার জন্য অপেক্ষা করে:

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

রেন্ডার করা চিত্রটি ImageReader এর সাথে যুক্ত একটি HardwareBuffer এ রয়েছে। নিম্নলিখিত কোডটি 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

অ্যান্ড্রয়েড গ্রাফিক্স শেডিং ল্যাঙ্গুয়েজ (AGSL) Android 13+ দ্বারা প্রোগ্রামেবল RuntimeShader অবজেক্টের আচরণ সংজ্ঞায়িত করতে ব্যবহার করা হয়। AGSL এর বেশিরভাগ সিনট্যাক্স GLSL ফ্র্যাগমেন্ট শেডারের সাথে শেয়ার করে, কিন্তু Canvas মধ্যে পেইন্টিং কাস্টমাইজ করতে এবং View ফিল্টার করতে অ্যান্ড্রয়েড গ্রাফিক্স রেন্ডারিং সিস্টেমের মধ্যে কাজ করে। এটি অঙ্কন ক্রিয়াকলাপের সময় কাস্টম চিত্র প্রক্রিয়াকরণ যোগ করতে ব্যবহার করা যেতে পারে, বা একটি Bitmap ক্যানভাসে একটি চিত্র রেন্ডার করার জন্য সরাসরি একটি RenderNode ব্যবহার করে। নিচের উদাহরণটি দেখায় কিভাবে একটি কাস্টম শেডার ইমেজ ব্লার ইফেক্ট প্রতিস্থাপন করতে হয়।

একটি RuntimeShader তৈরি করে শুরু করুন, এটিকে AGSL shader কোড দিয়ে ইনস্ট্যান্টিয়েটিং করুন। এই শেডারটি হিউ রোটেশনের জন্য একটি রঙ ম্যাট্রিক্স প্রয়োগ করতে ব্যবহৃত হয়:

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 পেতে, আগের চিত্র ব্লার নমুনার মতো একই কৌশল ব্যবহার করা হয়।

  • RenderNode জন্য অভ্যন্তরীণ RecordingCanvas শেডার প্রয়োগ করে।
  • Image অর্জিত হয়েছে, একটি Bitmap প্রদান করে যা এর HardwareBuffer মোড়ানো হয়।

CameraX ব্যবহার করে planar YUV থেকে RGB তে রূপান্তর করুন

ইমেজ প্রসেসিং-এ ব্যবহারের জন্য প্ল্যানার YUV থেকে RGB-তে রূপান্তর করা Jetpack-এর CameraX-এর মধ্যে ImageAnalysis ব্যবহারের ক্ষেত্রের অংশ হিসেবে সমর্থিত।

ক্যামেরাএক্স কোডল্যাবের সাথে শুরু করার অংশ হিসাবে এবং অ্যান্ড্রয়েড ক্যামেরার নমুনা সংগ্রহস্থলে ImageAnalysis ব্যবহার করার জন্য সংস্থান রয়েছে৷

রেন্ডারস্ক্রিপ্ট ইনট্রিনসিক প্রতিস্থাপন টুলকিট

যদি আপনার অ্যাপ্লিকেশনটি অন্তর্নিহিত ব্যবহার করে, আপনি স্বতন্ত্র প্রতিস্থাপন লাইব্রেরি ব্যবহার করতে পারেন; আমাদের পরীক্ষাগুলি নির্দেশ করে যে এটি বিদ্যমান রেন্ডারস্ক্রিপ্ট CPU বাস্তবায়ন ব্যবহার করার চেয়ে দ্রুত।

টুলকিটে নিম্নলিখিত ফাংশন রয়েছে:

  • মিশ্রিত করুন
  • ঝাপসা
  • রঙ ম্যাট্রিক্স
  • কনভল
  • হিস্টোগ্রাম এবং হিস্টোগ্রাম ডট
  • লুকআপ টেবিল (LUT) এবং LUT 3D
  • আকার পরিবর্তন করুন
  • YUV থেকে RGB

সম্পূর্ণ বিবরণ এবং সীমাবদ্ধতার জন্য, টুলকিটের README.md এবং Toolkit.kt দেখুন। ফাইল

লাইব্রেরি ডাউনলোড, যোগ এবং ব্যবহার করতে নিম্নলিখিত পদক্ষেপগুলি সম্পাদন করুন:

  1. GitHub থেকে প্রকল্পটি ডাউনলোড করুন।

  2. renderscript-toolkit module সনাক্ত করুন এবং তৈরি করুন।

  3. অ্যাপের build.gradle ফাইলটি পরিবর্তন করে আপনার Android Studio প্রকল্পে লাইব্রেরি যোগ করুন।

  4. টুলকিটের উপযুক্ত পদ্ধতি ব্যবহার করুন।

উদাহরণ: ScriptIntrinsicBlur ফাংশন থেকে মাইগ্রেট করুন

ScriptIntrinsicBlur ফাংশন প্রতিস্থাপন করতে:

  • একটি বিটম্যাপ অস্পষ্ট করতে, Toolkit.blur এ কল করুন।

    var blurredBitmap = Toolkit.blur(myBitmap, radius)
    
  • আপনি যদি বাইটের অ্যারে দ্বারা উপস্থাপিত একটি চিত্রকে অস্পষ্ট করতে চান তবে প্রতি পিক্সেলের প্রস্থ, উচ্চতা এবং বাইটের সংখ্যা নির্দিষ্ট করুন।

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

স্ক্রিপ্ট থেকে স্থানান্তর

আপনার ব্যবহারের ক্ষেত্রে যদি এর সাথে সমাধান করা না যায়:

এবং, আপনার ব্যবহারের ক্ষেত্রে GPU ত্বরণ থেকে উপকৃত হতে পারে, Android ক্রস-প্ল্যাটফর্ম Vulkan এবং OpenGL ES (GLES) APIগুলিতে GPU গণনা সমর্থন করে। আপনি এটিকে অপ্রয়োজনীয় মনে করতে পারেন কারণ বেশিরভাগ ডিভাইসে আপনার স্ক্রিপ্টগুলি ইতিমধ্যেই GPU-এর পরিবর্তে CPU-তে চলছে: কিছু ব্যবহারের ক্ষেত্রে C/C++ RenderScript, GLES বা Vulkan কম্পিউটের চেয়ে দ্রুততর হতে পারে। (বা অন্তত আপনার ব্যবহারের ক্ষেত্রে যথেষ্ট দ্রুত)

কীভাবে স্থানান্তর করতে হয় তা আরও ভালভাবে বুঝতে, নমুনা অ্যাপটি পর্যালোচনা করুন। নমুনাটি দেখায় যে কীভাবে একটি বিটম্যাপ অস্পষ্ট করা যায় এবং রেন্ডারস্ক্রিপ্টে একটি রঙ-ম্যাট্রিক্স রূপান্তর করা যায় এবং ভলকান এবং ওপেনজিএল-এ এর সমতুল্য কোড রয়েছে।

যদি আপনার অ্যাপ্লিকেশানের রিলিজের একটি পরিসর সমর্থন করার প্রয়োজন হয়, তাহলে Android 6 (API স্তর 23) এবং তার নিচের ডিভাইসগুলির জন্য RenderScript ব্যবহার করুন এবং Android 7 (API স্তর 24) এবং উচ্চতর সমর্থিত ডিভাইসগুলিতে Vulkan বা GLES ব্যবহার করুন৷ যদি আপনার minSdkVersion 24 বা তার বেশি হয়, তাহলে আপনাকে RenderScript ব্যবহার করতে হবে না; Vulkan বা GLES 3.1 আপনার যেখানে GPU কম্পিউট সমর্থন প্রয়োজন সেখানে ব্যবহার করা যেতে পারে।

Android GLES API-এর জন্য SDK বাইন্ডিং প্রদান করে, তাই OpenGL ES-এ কাজ করার সময় NDK ব্যবহার করার প্রয়োজন নেই।

ভলকান SDK বাইন্ডিং প্রদান করে না, তাই রেন্ডারস্ক্রিপ্ট থেকে ভলকানে সরাসরি ম্যাপিং নেই; আপনি NDK ব্যবহার করে Vulkan কোড লিখুন এবং Kotlin বা Java থেকে এই কোড অ্যাক্সেস করতে JNI ফাংশন তৈরি করুন।

নিম্নলিখিত পৃষ্ঠাগুলি রেন্ডারস্ক্রিপ্ট থেকে স্থানান্তরের দিকগুলি কভার করে৷ নমুনা অ্যাপ্লিকেশন এই বিবেচনার প্রায় সব প্রয়োগ করে। সেগুলি আরও ভালভাবে বোঝার জন্য, রেন্ডারস্ক্রিপ্ট এবং ভলকান সমতুল্য কোড তুলনা করুন।