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