如何在Android RenderScript中旋转YUV_420_888数据至90度适配竖屏
Got it, let's fix this rotation directly in your RenderScript YUV-to-RGBA converter—perfect for keeping performance high, which is critical for camera preview scenarios like your HdrViewfinder-style app.
Core Idea
When rotating 90 degrees clockwise, the output image swaps width and height (original width becomes new height, original height becomes new width). We need to adjust how we sample the Y, U, and V planes to map each output pixel back to the correct position in the original YUV buffer.
Modified RenderScript Code
Here's the updated script with rotation logic integrated:
// Needed directive for RS to work #pragma version(1) // The java_package_name directive needs to use your Activity's package path #pragma rs java_package_name(net.hydex11.cameracaptureexample) rs_allocation inputAllocation; int wIn, hIn; int numTotalPixels; // Function to invoke before applying conversion void setInputImageSize(int _w, int _h) { wIn = _w; hIn = _h; numTotalPixels = wIn * hIn; } // Kernel that converts a YUV element to a RGBA one, with 90-degree clockwise rotation uchar4 __attribute__((kernel)) convert(uint32_t x, uint32_t y) { // 90-degree clockwise rotation: map output (x,y) to original YUV coordinates uint32_t srcX = y; // Original X = output Y uint32_t srcY = hIn - 1 - x;// Original Y = (input height - 1) - output X // Sample Y component from planar Y plane int yIdx = srcX + srcY * wIn; uchar _y = rsGetElementAt_uchar(inputAllocation, yIdx); // Sample U/V components from interleaved chroma plane (4:2:0 subsampled) uint32_t srcX_uv = srcX >> 1; // Downscale X by 2 for chroma subsampling uint32_t srcY_uv = srcY >> 1; // Downscale Y by 2 for chroma subsampling int uvIdx = numTotalPixels + srcY_uv * wIn + (srcX_uv << 1); uchar _u = rsGetElementAt_uchar(inputAllocation, uvIdx); uchar _v = rsGetElementAt_uchar(inputAllocation, uvIdx + 1); // YUV to RGBA conversion (unchanged from your original logic) _y = _y < 16 ? 16 : _y; short Y = ((short)_y) - 16; short U = ((short)_u) - 128; short V = ((short)_v) - 128; uchar4 out; out.r = (uchar) clamp((float)( (Y * 298 + V * 409 + 128) >> 8), 0.f, 255.f); out.g = (uchar) clamp((float)( (Y * 298 - U * 100 - V * 208 + 128) >> 8), 0.f, 255.f); out.b = (uchar) clamp((float)( (Y * 298 + U * 516 + 128) >> 8), 0.f, 255.f); out.a = 255; // Ensure full opacity (uncommented for correct rendering) return out; }
Key Changes Explained
Coordinate Mapping for Rotation:
- For each output pixel
(x,y), we calculate the corresponding position in the original YUV buffer:srcX = y: The X position in the original image matches the Y position of the output (since we're rotating clockwise, width and height swap).srcY = hIn - 1 - x: The Y position in the original image is flipped along the vertical axis to maintain correct orientation after rotation.
- For each output pixel
Chroma Plane Sampling Adjustment:
- Since YUV_420_888 uses 2x2 subsampling for U/V, we downscale the original
srcXandsrcYby 2 (using bit shifts>>1) to get the correct chroma block position. - The UV index calculation is adjusted to use the rotated subsampled coordinates, ensuring we pick the right U/V pair for each output pixel.
- Since YUV_420_888 uses 2x2 subsampling for U/V, we downscale the original
Opacity Fix:
- Uncommented
out.a = 255to ensure the output image is fully opaque (critical for correct rendering in your preview Surface).
- Uncommented
Java Layer Adjustment
Don't forget to update your Java code to create the output Allocation with swapped dimensions:
- If your input YUV buffer is
wIn x hIn, the output RGBA buffer should behIn x wIn(since rotation swaps width and height). For example:// After calling setInputImageSize(w, h) on the RenderScript script Allocation outputAllocation = Allocation.createTyped(rs, new Type.Builder(rs, Element.RGBA_8888(rs)).setX(h).setY(w).create());
Performance Note
By handling rotation directly in RenderScript, you leverage hardware acceleration (GPU or optimized CPU) which is far faster than doing this conversion/rotation in Java bytecode—perfect for real-time camera preview use cases like your HdrViewfinder project.
内容的提问来源于stack exchange,提问作者aminakoy

