| /* |
| * Copyright (C) 2021 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.example.testapp |
| |
| import android.renderscript.toolkit.Range2d |
| |
| /** |
| * Reference implementation of a Histogram operation. |
| * |
| * Return an array of 4 * 256 ints. |
| * Position 0 is the number of R with a value of 0, |
| * Position 1 is the number of G with a value of 0, |
| * Position 2 is the number of B with a value of 0, |
| * Position 3 is the number of A with a value of 0, |
| * Position 4 is the number of R with a value of 1, |
| * etc. |
| */ |
| @ExperimentalUnsignedTypes |
| fun referenceHistogram( |
| inputArray: ByteArray, |
| vectorSize: Int, |
| sizeX: Int, |
| sizeY: Int, |
| restriction: Range2d? |
| ): IntArray { |
| val input = Vector2dArray(inputArray.asUByteArray(), vectorSize, sizeX, sizeY) |
| |
| val counts = IntArray(paddedSize(input.vectorSize) * 256) |
| input.forEach(restriction) { x, y -> |
| val value = input[x, y] |
| for (i in 0 until vectorSize) { |
| counts[value[i].toInt() * paddedSize(input.vectorSize) + i]++ |
| } |
| } |
| return counts |
| } |
| |
| /** |
| * Reference implementation of a HistogramDot operation. |
| * |
| * Each RGBA input value is dot-multiplied first by the specified coefficients. |
| * The resulting value is converted to an integer and used for the histogram. |
| */ |
| @ExperimentalUnsignedTypes |
| fun referenceHistogramDot( |
| inputArray: ByteArray, |
| vectorSize: Int, |
| sizeX: Int, |
| sizeY: Int, |
| coefficients: FloatArray?, |
| restriction: Range2d? |
| ): IntArray { |
| val floatCoefficients = coefficients ?: floatArrayOf(0.299f, 0.587f, 0.114f, 0f) |
| val input = Vector2dArray(inputArray.asUByteArray(), vectorSize, sizeX, sizeY) |
| var coefficientSum = 0f |
| for (c in floatCoefficients) { |
| require (c >= 0) { |
| "RenderScriptToolkit histogramDot. Coefficients must be positive. $c provided." |
| } |
| coefficientSum += c |
| } |
| require(coefficientSum <= 1f) { "RenderScriptToolkit histogramDot. Coefficients should " + |
| "add to 1.0 or less. $coefficientSum provided." } |
| |
| // Compute integer |
| val intCoefficients = IntArray(input.vectorSize) { (floatCoefficients[it] * 256f + 0.5f).toInt() } |
| |
| val counts = IntArray(256) |
| input.forEach(restriction) { x, y -> |
| val value = input[x, y] |
| // While we could do the computation using floats, we won't get the same results as |
| // the existing intrinsics. |
| var sum = 0 |
| // We don't use value.indices because we want to accumulate only 3 values, in the case |
| // of vectorSize == 3. |
| for (i in 0 until vectorSize) { |
| sum += intCoefficients[i] * value[i].toInt() |
| } |
| // Round up and normalize |
| val index = (sum + 0x7f) shr 8 |
| counts[index]++ |
| } |
| return counts |
| } |