• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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