Skip to content

Commit 71f6cee

Browse files
Refactor Android Halide learning path content for clarity and consistency
- Updated learning objectives and prerequisites for the Android Halide index. - Revised titles and section headings for better readability in Android integration and AOT compilation documents. - Enhanced descriptions and explanations throughout the Android Halide materials, focusing on clarity and user engagement. - Improved code comments and documentation in processing workflow and fusion sections to better illustrate concepts. - Streamlined the introduction to Halide, emphasizing its advantages and foundational concepts. - Added performance measurement details and clarified scheduling strategies in the camera processing workflow.
1 parent 99578aa commit 71f6cee

File tree

6 files changed

+110
-110
lines changed

6 files changed

+110
-110
lines changed

content/learning-paths/mobile-graphics-and-gaming/android_halide/_index.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ minutes_to_complete: 180
66
who_is_this_for: This is an introductory topic for developers interested in learning how to use Halide for image processing.
77

88
learning_objectives:
9-
- Understand Halide fundamentals and set up your development environment
10-
- Create a basic real-time image processing pipeline using Halide
11-
- Optimize image processing workflows by applying operation fusion in Halide
12-
- Integrate Halide pipelines into Android applications developed with Kotlin
9+
- Learn the basics of Halide and set up your development environment
10+
- Build a simple real-time image processing pipeline with Halide
11+
- Make your image processing faster by combining operations in Halide
12+
- Use Halide pipelines in Android apps written with Kotlin
1313

1414
prerequisites:
1515
- Basic C++ knowledge
@@ -36,11 +36,11 @@ tools_software_languages:
3636

3737
further_reading:
3838
- resource:
39-
title: Halide 19.0.0
39+
title: Halide documentation
4040
link: https://halide-lang.org/docs/index.html
4141
type: website
4242
- resource:
43-
title: Halide GitHub
43+
title: Halide GitHub repository
4444
link: https://github.com/halide/Halide
4545
type: repository
4646
- resource:

content/learning-paths/mobile-graphics-and-gaming/android_halide/android.md

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
---
22
# User change
3-
title: "Integrating Halide into an Android (Kotlin) Project"
3+
title: "Integrate Halide into an Android project with Kotlin"
44

55
weight: 6
66

77
layout: "learningpathall"
88
---
99

10-
## Objective
11-
In this lesson, we’ll learn how to integrate a high-performance Halide image-processing pipeline into an Android application using Kotlin.
10+
## What you'll build
11+
In this section you'll integrate a high-performance Halide image-processing pipeline into an Android application using Kotlin.
1212

13-
## Overview of mobile integration with Halide
13+
## Learn about mobile integration with Halide
1414
Android is the world’s most widely-used mobile operating system, powering billions of devices across diverse markets. This vast user base makes Android an ideal target platform for developers aiming to reach a broad audience, particularly in applications requiring sophisticated image and signal processing, such as augmented reality, photography, video editing, and real-time analytics.
1515

1616
Kotlin, now the preferred programming language for Android development, combines concise syntax with robust language features, enabling developers to write maintainable, expressive, and safe code. It offers seamless interoperability with existing Java codebases and straightforward integration with native code via JNI, simplifying the development of performant mobile applications.
1717

18-
## Benefits of using Halide on mobile
18+
## Explore the benefits of using Halide on mobile
1919
Integrating Halide into Android applications brings several key advantages:
2020
- Performance - Halide enables significant acceleration of complex image processing algorithms, often surpassing the speed of traditional Java or Kotlin implementations by leveraging optimized code generation. By generating highly optimized native code tailored for Arm CPUs or GPUs, Halide can dramatically increase frame rates and responsiveness, essential for real-time or interactive applications.
2121
- Efficiency - on mobile devices, resource efficiency translates directly to improved battery life and reduced thermal output. Halide's scheduling strategies (such as operation fusion, tiling, parallelization, and vectorization) minimize unnecessary memory transfers, CPU usage, and GPU overhead. This optimization substantially reduces overall power consumption, extending battery life and enhancing the user experience by preventing overheating.
@@ -24,7 +24,7 @@ Integrating Halide into Android applications brings several key advantages:
2424

2525
In short, Halide delivers high-performance image processing without sacrificing portability or efficiency, a balance particularly valuable on resource-constrained mobile devices.
2626

27-
### Android development ecosystem and challenges
27+
### Navigate Android development challenges
2828
While Android presents abundant opportunities for developers, the mobile development ecosystem brings its own set of challenges, especially for performance-intensive applications:
2929
1. Limited Hardware Resources. Unlike desktop or server environments, mobile devices have significant constraints on processing power, memory capacity, and battery life. Developers must optimize software meticulously to deliver smooth performance while carefully managing hardware resource consumption. Leveraging tools like Halide allows developers to overcome these constraints by optimizing computational workloads, making resource-intensive tasks feasible on constrained hardware.
3030
2. Cross-Compilation Complexities. Developing native code for Android requires handling multiple hardware architectures (such as armv8-a, ARM64, and sometimes x86/x86_64). Cross-compilation introduces complexities due to different instruction sets, CPU features, and performance characteristics. Managing this complexity involves careful use of the Android NDK, understanding toolchains, and correctly configuring build systems (e.g., Gradle, CMake). Halide helps mitigate these issues by abstracting away many platform-specific optimizations, automatically generating code optimized for target architectures.
@@ -37,8 +37,8 @@ Before integrating Halide into your Android application, ensure you have the nec
3737
1. Android Studio. [Download link](https://developer.android.com/studio).
3838
2. Android NDK (Native Development Kit). Can be easily installed from Android Studio (Tools → SDK Manager → SDK Tools → Android NDK).
3939

40-
## Setting up the Android project
41-
### Creating the project
40+
## Set up the Android project
41+
### Create the project
4242
1. Open Android Studio.
4343
2. Select New Project > Native C++.
4444
![img4](Figures/04.webp)
@@ -152,8 +152,9 @@ dependencies {
152152

153153
Click the Sync Now button at the top. To verify that everything is configured correctly, click Build > Make Project in Android Studio.
154154

155-
## UI
156-
Now, you'll define the application's User Interface, consisting of two buttons and an ImageView. One button loads the image, the other processes it, and the ImageView displays both the original and processed images.
155+
## Define the user interface
156+
Define the application's user interface, consisting of two buttons and an ImageView. One button loads the image, the other processes it, and the ImageView displays both the original and processed images.
157+
157158
1. Open the res/layout/activity_main.xml file, and modify it as follows:
158159
```XML
159160
<?xml version="1.0" encoding="utf-8"?>
@@ -204,8 +205,8 @@ Now you can run the app to view the UI:
204205

205206
![img7](Figures/07.webp)
206207

207-
## Processing
208-
You will now implement the image processing code. First, pick up an image you want to process. Here we use the camera man. Then, under the Arm.Halide.AndroidDemo/src/main create assets folder, and save the image under that folder as img.png.
208+
## Implement image processing
209+
Implement the image processing code. First, pick an image you want to process. This example uses the camera man image. Under Arm.Halide.AndroidDemo/src/main, create an assets folder and save the image as img.png.
209210

210211
Now, open MainActivity.kt and modify it as follows:
211212
```java
@@ -330,9 +331,9 @@ class MainActivity : AppCompatActivity() {
330331
}
331332
```
332333

333-
This Kotlin Android application demonstrates integrating a Halide-generated image-processing pipeline within an Android app. The main activity (MainActivity) manages loading and processing an image stored in the applications asset folder.
334+
This Kotlin Android application demonstrates integrating a Halide-generated image-processing pipeline within an Android app. The main activity (MainActivity) manages loading and processing an image stored in the application's asset folder.
334335

335-
When the app launches, the Process Image button is disabled. When a user taps Load Image, the app retrieves img.png from its assets directory and displays it within the ImageView, simultaneously enabling the Process Image button for further interaction.
336+
When the app launches, the app disables the Process Image button. When you tap Load Image, the app retrieves img.png from its assets directory and displays it within the ImageView, simultaneously enabling the Process Image button for further interaction.
336337

337338
Upon pressing the Process Image button, the following sequence occurs:
338339
1. Background Processing. A Kotlin coroutine initiates processing on a background thread, ensuring the application’s UI remains responsive.
@@ -346,11 +347,11 @@ The code defines three utility methods:
346347
2. extractGrayScaleBytes - converts a Bitmap into a grayscale byte array suitable for native processing.
347348
3. createBitmapFromGrayBytes - converts a grayscale byte array back into a Bitmap for display purposes.
348349

349-
Note that performing the grayscale conversion in Halide allows us to exploit operator fusion, further improving performance by avoiding intermediate memory accesses. This could be done as in our examples before (processing-workflow).
350+
Note that performing the grayscale conversion in Halide allows you to exploit operator fusion, further improving performance by avoiding intermediate memory accesses. You can do this as shown in the earlier processing-workflow examples.
350351

351352
The JNI integration occurs through an external method declaration, blurThresholdImage, loaded via the companion object at app startup. The native library (armhalideandroiddemo) containing this function is compiled separately and integrated into the application (native-lib.cpp).
352353

353-
You will now need to create blurThresholdImage function. To do so, in Android Studio put the cursor above blurThresholdImage function, and then click Create JNI function for blurThresholdImage:
354+
Create the blurThresholdImage function. In Android Studio, put the cursor above blurThresholdImage function, and then select Create JNI function for blurThresholdImage:
354355
![img8](Figures/08.webp)
355356

356357
This will generate a new function in the native-lib.cpp:
@@ -404,7 +405,7 @@ This C++ function acts as a bridge between Java (Kotlin) and native code. Specif
404405

405406
The input Java byte array (input_bytes) is accessed and pinned into native memory via GetByteArrayElements. This provides a direct pointer (inBytes) to the grayscale data sent from Kotlin. The raw grayscale byte data is wrapped into a Halide::Runtime::Buffer<uint8_t> object (inputBuffer). This buffer structure is required by the Halide pipeline. An output buffer (outputBuffer) is created with the same dimensions as the input image. This buffer will store the result produced by the Halide pipeline. The native function invokes the Halide-generated AOT function blur_threshold, passing in both the input and output buffers. After processing, a new Java byte array (outputArray) is allocated to hold the processed grayscale data. The processed data from the Halide output buffer is copied into this Java array using SetByteArrayRegion. The native input buffer (inBytes) is explicitly released using ReleaseByteArrayElements, specifying JNI_ABORT as no changes were made to the input array. Finally, the processed byte array (outputArray) is returned to Kotlin.
406407

407-
Through this JNI bridge, Kotlin can invoke high-performance native code. You can now re-run the application. Click the Load Image button, and then Process Image. You will see the following results:
408+
Through this JNI bridge, Kotlin can invoke high-performance native code. You can now re-run the application. Select the Load Image button, and then Process Image. You'll see the following results:
408409

409410
![img9](Figures/09.png)
410411
![img10](Figures/10.png)
@@ -416,4 +417,4 @@ jobject outputBuffer = env->NewDirectByteBuffer(output.data(), width * height);
416417
```
417418

418419
## Summary
419-
In this lesson, we’ve successfully integrated a Halide image-processing pipeline into an Android application using Kotlin. We started by setting up an Android project configured for native development with the Android NDK, employing Kotlin as the primary language. We then integrated Halide-generated static libraries and demonstrated their usage through Java Native Interface (JNI), bridging Kotlin and native code. This equips developers with the skills needed to harness Halide's capabilities for building sophisticated, performant mobile applications on Android.
420+
You've successfully integrated a Halide image-processing pipeline into an Android application using Kotlin. You started by setting up an Android project configured for native development with the Android NDK, using Kotlin as the primary language. You then integrated Halide-generated static libraries and demonstrated their usage through Java Native Interface (JNI), bridging Kotlin and native code. You now have the skills needed to harness Halide's capabilities for building sophisticated, performant mobile applications on Android.

0 commit comments

Comments
 (0)