Stay organized with collections
Save and categorize content based on your preferences.
ARCore now supports Electronic Image Stabilization (EIS), which helps produce a smooth camera preview. EIS achieves stabilization by observing phone movement using gyro and applying compensation homography mesh within the boundaries of camera texture that counters the minor shakes. EIS is only supported in the device's portrait orientation. All orientations will be supported in the 1.39.0 release of ARCore.
Query for EIS support and enable EIS
To enable EIS, configure your session to use AR_IMAGE_STABILIZATION_MODE_EIS. If the device doesn't support the EIS feature, this will cause an exception to be thrown from ARCore.
intkNumVertices=4;// Positions of the quad vertices in clip space (X, Y).constGLfloatkVertices[]={-1.0f,-1.0f,+1.0f,-1.0f,-1.0f,+1.0f,+1.0f,+1.0f,};floattransformed_vertices_[4*3];floattransformed_uvs_[4*3];ArFrame_transformCoordinates3d(session,frame,AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,kNumVertices,kVertices,AR_COORDINATES_3D_EIS_NORMALIZED_DEVICE_COORDINATES,transformed_vertices_);ArFrame_transformCoordinates3d(session,frame,AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,kNumVertices,kVertices,AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED,transformed_uvs_);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_EXTERNAL_OES,camera_texture_id_);glUseProgram(camera_program_);glUniform1i(camera_texture_uniform_,0);// Set the vertex positions and texture coordinates.glVertexAttribPointer(camera_position_attrib_,3,GL_FLOAT,false,0,transformed_vertices_);glVertexAttribPointer(camera_tex_coord_attrib_,3,GL_FLOAT,false,0,transformed_uvs_);glEnableVertexAttribArray(camera_position_attrib_);glEnableVertexAttribArray(camera_tex_coord_attrib_);
When EIS is off, the output 3D coordinates are equivalent to their 2D counterparts, with z values set to produce no change.
Modify shaders
The 3D coordinates calculated about should be passed to background rendering shaders. The vertex buffers are now 3D with EIS:
layout(location = 0) in vec4 a_Position;
layout(location = 1) in vec3 a_CameraTexCoord;
out vec3 v_CameraTexCoord;
void main() {
gl_Position = a_Position;
v_CameraTexCoord = a_CameraTexCoord;
}
Additionally, the fragment shader needs to apply perspective correction:
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-07-14 UTC."],[[["\u003cp\u003eARCore now utilizes Electronic Image Stabilization (EIS) to create a smoother camera preview by compensating for minor shakes using gyro data.\u003c/p\u003e\n"],["\u003cp\u003eEIS support can be queried, and enabled if available, through specific ARCore session configuration settings using \u003ccode\u003eAR_IMAGE_STABILIZATION_MODE_EIS\u003c/code\u003e.\u003c/p\u003e\n"],["\u003cp\u003eWhen EIS is active, developers should utilize \u003ccode\u003eArFrame_transformCoordinates3d\u003c/code\u003e to acquire the modified device and texture coordinates for accurate camera background rendering.\u003c/p\u003e\n"],["\u003cp\u003eBackground rendering shaders must be adjusted to accommodate the 3D coordinates and apply perspective correction when EIS is enabled.\u003c/p\u003e\n"],["\u003cp\u003eCurrently, EIS is only supported in portrait orientation, with full orientation support planned for the upcoming ARCore 1.39.0 release.\u003c/p\u003e\n"]]],["ARCore's Electronic Image Stabilization (EIS) smooths the camera preview by compensating for minor shakes, using gyro-detected phone movement. To use EIS, enable it via `AR_IMAGE_STABILIZATION_MODE_EIS` after checking for device support. When EIS is on, utilize `ArFrame_transformCoordinates3d` with specified input and output coordinate types to get modified device and texture coordinates for rendering. Renderers must use these compensated coordinates in vertex buffers, which are now 3D. Shaders also require modification to handle 3D coordinates and perspective correction. EIS is currently only supported in portrait mode.\n"],null,["# Stabilize camera images on Android NDK (C)\n\nARCore now supports Electronic Image Stabilization (EIS), which helps produce a smooth camera preview. EIS achieves stabilization by observing phone movement using gyro and applying compensation homography mesh within the boundaries of camera texture that counters the minor shakes. EIS is only supported in the device's portrait orientation. All orientations will be supported in the 1.39.0 release of ARCore.\n\nQuery for EIS support and enable EIS\n------------------------------------\n\nTo enable EIS, configure your session to use [`AR_IMAGE_STABILIZATION_MODE_EIS`](/ar/reference/c/group/ar-config#ar_image_stabilization_mode_eis). If the device doesn't support the EIS feature, this will cause an exception to be thrown from ARCore. \n\n```c\nint enableEis = 0;\nArSession_isImageStabilizationModeSupported(\n ar_session, AR_IMAGE_STABILIZATION_MODE_EIS, &enableEis);\nif (!enableEis) {\n return;\n}\n// Create a session config.\nArConfig* ar_config = NULL;\nArConfig_create(ar_session, &ar_config);\n\n// Enable Electronic Image Stabilization.\nArConfig_setImageStabilizationMode(ar_session, ar_config, AR_IMAGE_STABILIZATION_MODE_EIS);\nCHECK(ArSession_configure(ar_session, ar_config) == AR_SUCCESS);\n\n// Release config resources.\nArConfig_destroy(ar_config);\n```\n\nTransform coordinates\n---------------------\n\nWhen EIS is on, the renderer needs to use the modified device coordinates and matching texture coordinates that incorporate the EIS compensation when rendering the camera background. To get the EIS compensated coordinates, use [`ArFrame_transformCoordinates3d`](/ar/reference/c/group/ar-frame#arframe_transformcoordinates3d), using [`AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES`](/ar/reference/c/group/ar-frame#ar_coordinates_2d_opengl_normalized_device_coordinates) as input and [`AR_COORDINATES_3D_EIS_NORMALIZED_DEVICE_COORDINATES`](/ar/reference/c/group/ar-frame#ar_coordinates_3d_eis_normalized_device_coordinates) as output to get 3D device coordinates and [`AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED`](/ar/reference/c/group/ar-frame#ar_coordinates_3d_eis_texture_normalized) as output to get 3D texture coordinates. For now, the only supported input coordinate type for `ArFrame_transformCoordinates3d` is `AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES`. \n\n```c\nint kNumVertices = 4;\n// Positions of the quad vertices in clip space (X, Y).\nconst GLfloat kVertices[] = {\n -1.0f, -1.0f, +1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f,\n};\nfloat transformed_vertices_[4 * 3];\nfloat transformed_uvs_[4 * 3];\n\nArFrame_transformCoordinates3d(\n session, frame, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,\n kNumVertices, kVertices,\n AR_COORDINATES_3D_EIS_NORMALIZED_DEVICE_COORDINATES,\n transformed_vertices_);\nArFrame_transformCoordinates3d(\n session, frame, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,\n kNumVertices, kVertices, AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED,\n transformed_uvs_);\n\nglActiveTexture(GL_TEXTURE0);\nglBindTexture(GL_TEXTURE_EXTERNAL_OES, camera_texture_id_);\nglUseProgram(camera_program_);\nglUniform1i(camera_texture_uniform_, 0);\n\n// Set the vertex positions and texture coordinates.\nglVertexAttribPointer(camera_position_attrib_, 3, GL_FLOAT, false, 0,\n transformed_vertices_);\nglVertexAttribPointer(camera_tex_coord_attrib_, 3, GL_FLOAT, false, 0,\n transformed_uvs_);\nglEnableVertexAttribArray(camera_position_attrib_);\nglEnableVertexAttribArray(camera_tex_coord_attrib_);\n```\n\nWhen EIS is off, the output 3D coordinates are equivalent to their 2D counterparts, with z values set to produce no change.\n\nModify shaders\n--------------\n\nThe 3D coordinates calculated about should be passed to background rendering shaders. The vertex buffers are now 3D with EIS: \n\n layout(location = 0) in vec4 a_Position;\n layout(location = 1) in vec3 a_CameraTexCoord;\n out vec3 v_CameraTexCoord;\n void main() {\n gl_Position = a_Position;\n v_CameraTexCoord = a_CameraTexCoord;\n }\n\nAdditionally, the fragment shader needs to apply perspective correction: \n\n precision mediump float;\n uniform samplerExternalOES u_CameraColorTexture;\n in vec3 v_CameraTexCoord;\n layout(location = 0) out vec4 o_FragColor;\n void main() {\n vec3 tc = (v_CameraTexCoord / v_CameraTexCoord.z);\n o_FragColor = texture(u_CameraColorTexture, tc.xy);\n }\n\nSee the [hello_eis_kotlin](https://github.com/google-ar/arcore-android-sdk/tree/master/samples/hello_eis_kotlin) sample app for more details."]]