1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.example.testapp
18
19 import android.renderscript.toolkit.YuvFormat
20 import java.lang.IllegalArgumentException
21
22 /**
23 * Reference implementation of a YUV to RGB operation.
24 */
25 @ExperimentalUnsignedTypes
referenceYuvToRgbnull26 fun referenceYuvToRgb(inputSignedArray: ByteArray, sizeX: Int, sizeY: Int, format: YuvFormat): ByteArray {
27 require(sizeX % 2 == 0) { "The width of the input should be even."}
28 val inputArray = inputSignedArray.asUByteArray()
29
30 val outputArray = ByteArray(sizeX * sizeY * 4)
31 val output = Vector2dArray(outputArray.asUByteArray(), 4, sizeX, sizeY)
32
33 when (format) {
34 YuvFormat.NV21 -> {
35 val startY = 0
36 val startU = sizeX * sizeY + 1
37 val startV = sizeX * sizeY
38
39 for (y in 0 until sizeY) {
40 for (x in 0 until sizeX) {
41 val offsetY = y * sizeX + x
42 val offsetU = ((y shr 1) * sizeX + (x shr 1) * 2)
43 val offsetV = ((y shr 1) * sizeX + (x shr 1) * 2)
44 output[x, y] = yuvToRGBA4(
45 inputArray[startY + offsetY],
46 inputArray[startU + offsetU],
47 inputArray[startV + offsetV]
48 )
49 }
50 }
51 }
52
53 YuvFormat.YV12 -> {
54 /* According to https://developer.android.com/reference/kotlin/android/graphics/ImageFormat#yv12,
55 * strideX and strideUV should be aligned to 16 byte boundaries. If we do this, we
56 * won't get the same results as RenderScript.
57 *
58 * We may want to test & require that sizeX is a multiple of 16/32.
59 */
60 val strideX = roundUpTo16(sizeX) // sizeX //
61 val strideUV = roundUpTo16(strideX / 2) // strideX / 2 //
62 val startY = 0
63 val startU = strideX * sizeY
64 val startV = startU + strideUV * sizeY / 2
65
66 for (y in 0 until sizeY) {
67 for (x in 0 until sizeX) {
68 val offsetY = y * sizeX + x
69 val offsetUV = (y shr 1) * strideUV + (x shr 1)
70 output[x, y] = yuvToRGBA4(
71 inputArray[startY + offsetY],
72 inputArray[startU + offsetUV],
73 inputArray[startV + offsetUV],
74 )
75 }
76 }
77 }
78 else -> throw IllegalArgumentException("Unknown YUV format $format")
79 }
80
81 return outputArray
82 }
83
84 @ExperimentalUnsignedTypes
yuvToRGBA4null85 private fun yuvToRGBA4(y: UByte, u: UByte, v: UByte): UByteArray {
86 val intY = y.toInt() - 16
87 val intU = u.toInt() - 128
88 val intV = v.toInt() - 128
89 val p = intArrayOf(
90 intY * 298 + intV * 409 + 128 shr 8,
91 intY * 298 - intU * 100 - intV * 208 + 128 shr 8,
92 intY * 298 + intU * 516 + 128 shr 8,
93 255
94 )
95 return UByteArray(4) { p[it].clampToUByte() }
96 }
97
98 /* To be used if we support Float
yuvToRGBA_f4null99 private fun yuvToRGBA_f4(y: UByte, u: UByte, v: UByte): UByteArray {
100 val yuv_U_values = floatArrayOf(0f, -0.392f * 0.003921569f, 2.02f * 0.003921569f, 0f)
101 val yuv_V_values = floatArrayOf(1.603f * 0.003921569f, -0.815f * 0.003921569f, 0f, 0f)
102
103 var color = FloatArray(4) {y.toFloat() * 0.003921569f}
104 val fU = FloatArray(4) {u.toFloat() - 128f}
105 val fV = FloatArray(4) {v.toFloat() - 128f}
106
107 color += fU * yuv_U_values;
108 color += fV * yuv_V_values;
109 //color = clamp(color, 0.f, 1.f);
110 return UByteArray(4) { unitFloatClampedToUByte(color[it]) }
111 }
112 */
113