| /* |
| * 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. |
| */ |
| |
| #ifndef ANDROID_RENDERSCRIPT_TOOLKIT_TOOLKIT_H |
| #define ANDROID_RENDERSCRIPT_TOOLKIT_TOOLKIT_H |
| |
| #include <cstdint> |
| #include <memory> |
| |
| namespace android { |
| namespace renderscript { |
| |
| class TaskProcessor; |
| |
| /** |
| * Define a range of data to process. |
| * |
| * This class is used to restrict a Toolkit operation to a rectangular subset of the input |
| * tensor. |
| * |
| * @property startX The index of the first value to be included on the X axis. |
| * @property endX The index after the last value to be included on the X axis. |
| * @property startY The index of the first value to be included on the Y axis. |
| * @property endY The index after the last value to be included on the Y axis. |
| */ |
| struct Restriction { |
| size_t startX; |
| size_t endX; |
| size_t startY; |
| size_t endY; |
| }; |
| |
| /** |
| * A collection of high-performance graphic utility functions like blur and blend. |
| * |
| * This toolkit provides ten image manipulation functions: blend, blur, color matrix, convolve, |
| * histogram, histogramDot, lut, lut3d, resize, and YUV to RGB. These functions execute |
| * multithreaded on the CPU. |
| * |
| * These functions work over raw byte arrays. You'll need to specify the width and height of |
| * the data to be processed, as well as the number of bytes per pixel. For most use cases, |
| * this will be 4. |
| * |
| * You should instantiate the Toolkit once and reuse it throughout your application. |
| * On instantiation, the Toolkit creates a thread pool that's used for processing all the functions. |
| * You can limit the number of pool threads used by the Toolkit via the constructor. The pool |
| * threads are destroyed once the Toolkit is destroyed, after any pending work is done. |
| * |
| * This library is thread safe. You can call methods from different pool threads. The functions will |
| * execute sequentially. |
| * |
| * A Java/Kotlin Toolkit is available. It calls this library through JNI. |
| * |
| * This toolkit can be used as a replacement for most RenderScript Intrinsic functions. Compared |
| * to RenderScript, it's simpler to use and more than twice as fast on the CPU. However RenderScript |
| * Intrinsics allow more flexibility for the type of allocation supported. In particular, this |
| * toolkit does not support allocations of floats. |
| */ |
| class RenderScriptToolkit { |
| /** Each Toolkit method call is converted to a Task. The processor owns the thread pool. It |
| * tiles the tasks and schedule them over the pool threads. |
| */ |
| std::unique_ptr<TaskProcessor> processor; |
| |
| public: |
| /** |
| * Creates the pool threads that are used for processing the method calls. |
| */ |
| RenderScriptToolkit(int numberOfThreads = 0); |
| /** |
| * Destroys the thread pool. This stops any in-progress work; the Toolkit methods called from |
| * other pool threads will return without having completed the work. Because of the undefined |
| * state of the output buffers, an application should avoid destroying the Toolkit if other pool |
| * threads are executing Toolkit methods. |
| */ |
| ~RenderScriptToolkit(); |
| |
| /** |
| * Determines how a source buffer is blended into a destination buffer. |
| * |
| * See {@link RenderScriptToolkit::blend}. |
| * |
| * blend only works on 4 byte RGBA data. In the descriptions below, ".a" represents |
| * the alpha channel. |
| */ |
| enum class BlendingMode { |
| /** |
| * dest = 0 |
| * |
| * The destination is cleared, i.e. each pixel is set to (0, 0, 0, 0) |
| */ |
| CLEAR = 0, |
| /** |
| * dest = src |
| * |
| * Sets each pixel of the destination to the corresponding one in the source. |
| */ |
| SRC = 1, |
| /** |
| * dest = dest |
| * |
| * Leaves the destination untouched. This is a no-op. |
| */ |
| DST = 2, |
| /** |
| * dest = src + dest * (1.0 - src.a) |
| */ |
| SRC_OVER = 3, |
| /** |
| * dest = dest + src * (1.0 - dest.a) |
| */ |
| DST_OVER = 4, |
| /** |
| * dest = src * dest.a |
| */ |
| SRC_IN = 5, |
| /** |
| * dest = dest * src.a |
| */ |
| DST_IN = 6, |
| /** |
| * dest = src * (1.0 - dest.a) |
| */ |
| SRC_OUT = 7, |
| /** |
| * dest = dest * (1.0 - src.a) |
| */ |
| DST_OUT = 8, |
| /** |
| * dest.rgb = src.rgb * dest.a + (1.0 - src.a) * dest.rgb, dest.a = dest.a |
| */ |
| SRC_ATOP = 9, |
| /** |
| * dest = dest.rgb * src.a + (1.0 - dest.a) * src.rgb, dest.a = src.a |
| */ |
| DST_ATOP = 10, |
| /** |
| * dest = {src.r ^ dest.r, src.g ^ dest.g, src.b ^ dest.b, src.a ^ dest.a} |
| * |
| * Note: this is NOT the Porter/Duff XOR mode; this is a bitwise xor. |
| */ |
| XOR = 11, |
| /** |
| * dest = src * dest |
| */ |
| MULTIPLY = 12, |
| /** |
| * dest = min(src + dest, 1.0) |
| */ |
| ADD = 13, |
| /** |
| * dest = max(dest - src, 0.0) |
| */ |
| SUBTRACT = 14 |
| }; |
| |
| /** |
| * Blend a source buffer with the destination buffer. |
| * |
| * Blends a source buffer and a destination buffer, placing the result in the destination |
| * buffer. The blending is done pairwise between two corresponding RGBA values found in |
| * each buffer. The mode parameter specifies one of fifteen blending operations. |
| * See {@link BlendingMode}. |
| * |
| * An optional range parameter can be set to restrict the operation to a rectangular subset |
| * of each buffer. If provided, the range must be wholly contained with the dimensions |
| * described by sizeX and sizeY. |
| * |
| * The source and destination buffers must have the same dimensions. Both buffers should be |
| * large enough for sizeX * sizeY * 4 bytes. The buffers have a row-major layout. |
| * |
| * @param mode The specific blending operation to do. |
| * @param source The RGBA input buffer. |
| * @param dest The destination buffer. Used for input and output. |
| * @param sizeX The width of both buffers, as a number of RGBA values. |
| * @param sizeY The height of both buffers, as a number of RGBA values. |
| * @param restriction When not null, restricts the operation to a 2D range of pixels. |
| */ |
| void blend(BlendingMode mode, const uint8_t* _Nonnull source, uint8_t* _Nonnull dst, |
| size_t sizeX, size_t sizeY, const Restriction* _Nullable restriction = nullptr); |
| |
| /** |
| * Blur an image. |
| * |
| * Performs a Gaussian blur of the input image and stores the result in the out buffer. |
| * |
| * The radius determines which pixels are used to compute each blurred pixels. This Toolkit |
| * accepts values between 1 and 25. Larger values create a more blurred effect but also |
| * take longer to compute. When the radius extends past the edge, the edge pixel will |
| * be used as replacement for the pixel that's out off boundary. |
| * |
| * Each input pixel can either be represented by four bytes (RGBA format) or one byte |
| * for the less common blurring of alpha channel only image. |
| * |
| * An optional range parameter can be set to restrict the operation to a rectangular subset |
| * of each buffer. If provided, the range must be wholly contained with the dimensions |
| * described by sizeX and sizeY. |
| * |
| * The input and output buffers must have the same dimensions. Both buffers should be |
| * large enough for sizeX * sizeY * vectorSize bytes. The buffers have a row-major layout. |
| * |
| * @param in The buffer of the image to be blurred. |
| * @param out The buffer that receives the blurred image. |
| * @param sizeX The width of both buffers, as a number of 1 or 4 byte cells. |
| * @param sizeY The height of both buffers, as a number of 1 or 4 byte cells. |
| * @param vectorSize Either 1 or 4, the number of bytes in each cell, i.e. A vs. RGBA. |
| * @param radius The radius of the pixels used to blur. |
| * @param restriction When not null, restricts the operation to a 2D range of pixels. |
| */ |
| void blur(const uint8_t* _Nonnull in, uint8_t* _Nonnull out, size_t sizeX, size_t sizeY, |
| size_t vectorSize, int radius, const Restriction* _Nullable restriction = nullptr); |
| |
| /** |
| * Identity matrix that can be passed to the {@link RenderScriptToolkit::colorMatrix} method. |
| * |
| * Using this matrix will result in no change to the pixel through multiplication although |
| * the pixel value can still be modified by the add vector, or transformed to a different |
| * format. |
| */ |
| static constexpr float kIdentityMatrix[] = { |
| 1.0f, 0.0f, 0.0f, 0.0f, |
| 0.0f, 1.0f, 0.0f, 0.0f, |
| 0.0f, 0.0f, 1.0f, 0.0f, |
| 0.0f, 0.0f, 0.0f, 1.0f |
| }; |
| |
| /** |
| * Matrix to turn color pixels to a grey scale. |
| * |
| * Use this matrix with the {@link RenderScriptToolkit::colorMatrix} method to convert an |
| * image from color to greyscale. |
| */ |
| static constexpr float kGreyScaleColorMatrix[] = { |
| 0.299f, 0.299f, 0.299f, 0.0f, |
| 0.587f, 0.587f, 0.587f, 0.0f, |
| 0.114f, 0.114f, 0.114f, 0.0f, |
| 0.0f, 0.0f, 0.0f, 1.0f |
| }; |
| |
| /** |
| * Matrix to convert RGB to YUV. |
| * |
| * Use this matrix with the {@link RenderScriptToolkit::colorMatrix} method to convert the |
| * first three bytes of each pixel from RGB to YUV. This leaves the last byte (the alpha |
| * channel) untouched. |
| * |
| * This is a simplistic conversion. Most YUV buffers have more complicated format, not supported |
| * by this method. |
| */ |
| static constexpr float kRgbToYuvMatrix[] = { |
| 0.299f, -0.14713f, 0.615f, 0.0f, |
| 0.587f, -0.28886f, -0.51499f, 0.0f, |
| 0.114f, 0.436f, -0.10001f, 0.0f, |
| 0.0f, 0.0f, 0.0f, 1.0f |
| }; |
| |
| /** |
| * Matrix to convert YUV to RGB. |
| * |
| * Use this matrix with the {@link RenderScriptToolkit::colorMatrix} method to convert the |
| * first three bytes of each pixel from YUV to RGB. This leaves the last byte (the alpha |
| * channel) untouched. |
| * |
| * This is a simplistic conversion. Most YUV buffers have more complicated format, not supported |
| * by this method. Use {@link RenderScriptToolkit::yuvToRgb} to convert these buffers. |
| */ |
| static constexpr float kYuvToRgbMatrix[] = { |
| 1.0f, 1.0f, 1.0f, 0.0f, |
| 0.0f, -0.39465f, 2.03211f, 0.0f, |
| 1.13983f, -0.5806f, 0.0f, 0.0f, |
| 0.0f, 0.0f, 0.0f, 1.0f |
| }; |
| |
| /** |
| * Transform an image using a color matrix. |
| * |
| * Converts a 2D array of vectors of unsigned bytes, multiplying each vectors by a 4x4 matrix |
| * and adding an optional vector. |
| * |
| * Each input vector is composed of 1-4 unsigned bytes. If less than 4 bytes, it's extended to |
| * 4, padding with zeroes. The unsigned bytes are converted from 0-255 to 0.0-1.0 floats |
| * before the multiplication is done. |
| * |
| * The resulting value is normalized from 0.0-1.0 to a 0-255 value and stored in the output. |
| * If the output vector size is less than four, the unused channels are discarded. |
| * |
| * If addVector is null, a vector of zeroes is added, i.e. a noop. |
| * |
| * Check kIdentityMatrix, kGreyScaleColorMatrix, kRgbToYuvMatrix, and kYuvToRgbMatrix for sample |
| * matrices. The YUV conversion may not work for all color spaces. |
| * |
| * @param in The buffer of the image to be converted. |
| * @param out The buffer that receives the converted image. |
| * @param inputVectorSize The number of bytes in each input cell, a value from 1 to 4. |
| * @param outputVectorSize The number of bytes in each output cell, a value from 1 to 4. |
| * @param sizeX The width of both buffers, as a number of 1 to 4 byte cells. |
| * @param sizeY The height of both buffers, as a number of 1 to 4 byte cells. |
| * @param matrix The 4x4 matrix to multiply, in row major format. |
| * @param addVector A vector of four floats that's added to the result of the multiplication. |
| * @param restriction When not null, restricts the operation to a 2D range of pixels. |
| */ |
| void colorMatrix(const void* _Nonnull in, void* _Nonnull out, size_t inputVectorSize, |
| size_t outputVectorSize, size_t sizeX, size_t sizeY, |
| const float* _Nonnull matrix, const float* _Nullable addVector = nullptr, |
| const Restriction* _Nullable restriction = nullptr); |
| |
| /** |
| * Convolve a ByteArray. |
| * |
| * Applies a 3x3 or 5x5 convolution to the input array using the provided coefficients. |
| * |
| * For 3x3 convolutions, 9 coefficients must be provided. For 5x5, 25 coefficients are needed. |
| * The coefficients should be provided in row-major format. |
| * |
| * When the square extends past the edge, the edge values will be used as replacement for the |
| * values that's are off boundary. |
| * |
| * Each input cell can either be represented by one to four bytes. Each byte is multiplied |
| * and accumulated independently of the other bytes of the cell. |
| * |
| * An optional range parameter can be set to restrict the operation to a rectangular subset |
| * of each buffer. If provided, the range must be wholly contained with the dimensions |
| * described by sizeX and sizeY. |
| * |
| * The input and output buffers must have the same dimensions. Both buffers should be |
| * large enough for sizeX * sizeY * vectorSize bytes. The buffers have a row-major layout. |
| * |
| * @param in The buffer of the image to be blurred. |
| * @param out The buffer that receives the blurred image. |
| * @param vectorSize The number of bytes in each cell, a value from 1 to 4. |
| * @param sizeX The width of both buffers, as a number of 1 or 4 byte cells. |
| * @param sizeY The height of both buffers, as a number of 1 or 4 byte cells. |
| * @param coefficients 9 or 25 multipliers. |
| * @param restriction When not null, restricts the operation to a 2D range of pixels. |
| */ |
| void convolve3x3(const void* _Nonnull in, void* _Nonnull out, size_t vectorSize, size_t sizeX, |
| size_t sizeY, const float* _Nonnull coefficients, |
| const Restriction* _Nullable restriction = nullptr); |
| |
| void convolve5x5(const void* _Nonnull in, void* _Nonnull out, size_t vectorSize, size_t sizeX, |
| size_t sizeY, const float* _Nonnull coefficients, |
| const Restriction* _Nullable restriction = nullptr); |
| |
| /** |
| * Compute the histogram of an image. |
| * |
| * Tallies how many times each of the 256 possible values of a byte is found in the input. |
| * |
| * An input cell can be represented by one to four bytes. The tally is done independently |
| * for each of the bytes of the cell. Correspondingly, the out array will have |
| * 256 * vectorSize entries. The counts for value 0 are consecutive, followed by those for |
| * value 1, etc. |
| * |
| * An optional range parameter can be set to restrict the operation to a rectangular subset |
| * of each buffer. If provided, the range must be wholly contained with the dimensions |
| * described by sizeX and sizeY. |
| * |
| * The source buffers should be large enough for sizeX * sizeY * vectorSize bytes. The buffers |
| * have a row-major layout. The out buffer should be large enough for 256 * vectorSize ints. |
| * |
| * @param in The buffer of the image to be analyzed. |
| * @param out The resulting vector of counts. |
| * @param sizeX The width of the input buffers, as a number of 1 or 4 byte cells. |
| * @param sizeY The height of the input buffers, as a number of 1 or 4 byte cells. |
| * @param vectorSize The number of bytes in each cell, a value from 1 to 4. |
| * @param restriction When not null, restricts the operation to a 2D range of pixels. |
| */ |
| void histogram(const uint8_t* _Nonnull in, int32_t* _Nonnull out, size_t sizeX, size_t sizeY, |
| size_t vectorSize, const Restriction* _Nullable restriction = nullptr); |
| |
| /** |
| * Compute the histogram of the dot product of an image. |
| * |
| * This method supports cells of 1 to 4 bytes in length. For each cell of the array, |
| * the dot product of its bytes with the provided coefficients is computed. The resulting |
| * floating point value is converted to an unsigned byte and tallied in the histogram. |
| * |
| * If coefficients is null, the coefficients used for RGBA luminosity calculation will be used, |
| * i.e. the values [0.299f, 0.587f, 0.114f, 0.f]. |
| * |
| * Each coefficients must be >= 0 and their sum must be 1.0 or less. There must be the same |
| * number of coefficients as vectorSize. |
| * |
| * An optional range parameter can be set to restrict the operation to a rectangular subset |
| * of each buffer. If provided, the range must be wholly contained with the dimensions |
| * described by sizeX and sizeY. |
| * |
| * The source buffers should be large enough for sizeX * sizeY * vectorSize bytes. The buffers |
| * have a row-major layout. The out array should be large enough for 256 ints. |
| * |
| * @param in The buffer of the image to be analyzed. |
| * @param out The resulting vector of counts. |
| * @param sizeX The width of the input buffers, as a number of 1 or 4 byte cells. |
| * @param sizeY The height of the input buffers, as a number of 1 or 4 byte cells. |
| * @param vectorSize The number of bytes in each cell, a value from 1 to 4. |
| * @param coefficients The values used for the dot product. Can be nullptr. |
| * @param restriction When not null, restricts the operation to a 2D range of pixels. |
| */ |
| void histogramDot(const uint8_t* _Nonnull in, int32_t* _Nonnull out, size_t sizeX, size_t sizeY, |
| size_t vectorSize, const float* _Nullable coefficients, |
| const Restriction* _Nullable restriction = nullptr); |
| |
| /** |
| * Transform an image using a look up table |
| * |
| * Transforms an image by using a per-channel lookup table. Each channel of the input has an |
| * independent lookup table. The tables are 256 entries in size and can cover the full value |
| * range of a byte. |
| * |
| * The input array should be in RGBA format, where four consecutive bytes form an cell. |
| * |
| * An optional range parameter can be set to restrict the operation to a rectangular subset |
| * of each buffer. If provided, the range must be wholly contained with the dimensions |
| * described by sizeX and sizeY. |
| * |
| * The input and output buffers must have the same dimensions. Both buffers should be |
| * large enough for sizeX * sizeY * vectorSize bytes. The buffers have a row-major layout. |
| * |
| * @param in The buffer of the image to be transformed. |
| * @param out The buffer that receives the transformed image. |
| * @param sizeX The width of both buffers, as a number of 4 byte cells. |
| * @param sizeY The height of both buffers, as a number of 4 byte cells. |
| * @param red An array of 256 values that's used to convert the R channel. |
| * @param green An array of 256 values that's used to convert the G channel. |
| * @param blue An array of 256 values that's used to convert the B channel. |
| * @param alpha An array of 256 values that's used to convert the A channel. |
| * @param restriction When not null, restricts the operation to a 2D range of pixels. |
| */ |
| void lut(const uint8_t* _Nonnull in, uint8_t* _Nonnull out, size_t sizeX, size_t sizeY, |
| const uint8_t* _Nonnull red, const uint8_t* _Nonnull green, |
| const uint8_t* _Nonnull blue, const uint8_t* _Nonnull alpha, |
| const Restriction* _Nullable restriction = nullptr); |
| |
| /** |
| * Transform an image using a 3D look up table |
| * |
| * Transforms an image, converting RGB to RGBA by using a 3D lookup table. The incoming R, G, |
| * and B values are normalized to the dimensions of the provided 3D buffer. The eight nearest |
| * values in that 3D buffer are sampled and linearly interpolated. The resulting RGBA entry |
| * is stored in the output. |
| * |
| * The input array should be in RGBA format, where four consecutive bytes form an cell. |
| * The fourth byte of each input cell is ignored. |
| * |
| * An optional range parameter can be set to restrict the operation to a rectangular subset |
| * of each buffer. If provided, the range must be wholly contained with the dimensions |
| * described by sizeX and sizeY. |
| * |
| * The input and output buffers must have the same dimensions. Both buffers should be |
| * large enough for sizeX * sizeY * vectorSize bytes. The buffers have a row-major layout. |
| * |
| * @param in The buffer of the image to be transformed. |
| * @param out The buffer that receives the transformed image. |
| * @param sizeX The width of both buffers, as a number of 4 byte cells. |
| * @param sizeY The height of both buffers, as a number of 4 byte cells. |
| * @param cube The translation cube, in row major-format. |
| * @param cubeSizeX The number of RGBA entries in the cube in the X direction. |
| * @param cubeSizeY The number of RGBA entries in the cube in the Y direction. |
| * @param cubeSizeZ The number of RGBA entries in the cube in the Z direction. |
| * @param restriction When not null, restricts the operation to a 2D range of pixels. |
| */ |
| void lut3d(const uint8_t* _Nonnull in, uint8_t* _Nonnull out, size_t sizeX, size_t sizeY, |
| const uint8_t* _Nonnull cube, size_t cubeSizeX, size_t cubeSizeY, size_t cubeSizeZ, |
| const Restriction* _Nullable restriction = nullptr); |
| |
| /** |
| * Resize an image. |
| * |
| * Resizes an image using bicubic interpolation. |
| * |
| * This method supports cells of 1 to 4 bytes in length. Each byte of the cell is |
| * interpolated independently from the others. |
| * |
| * An optional range parameter can be set to restrict the operation to a rectangular subset |
| * of the output buffer. The corresponding scaled range of the input will be used. If provided, |
| * the range must be wholly contained with the dimensions described by outputSizeX and |
| * outputSizeY. |
| * |
| * The input and output buffers have a row-major layout. Both buffers should be |
| * large enough for sizeX * sizeY * vectorSize bytes. |
| * |
| * @param in The buffer of the image to be resized. |
| * @param out The buffer that receives the resized image. |
| * @param inputSizeX The width of the input buffer, as a number of 1-4 byte cells. |
| * @param inputSizeY The height of the input buffer, as a number of 1-4 byte cells. |
| * @param vectorSize The number of bytes in each cell of both buffers. A value from 1 to 4. |
| * @param outputSizeX The width of the output buffer, as a number of 1-4 byte cells. |
| * @param outputSizeY The height of the output buffer, as a number of 1-4 byte cells. |
| * @param restriction When not null, restricts the operation to a 2D range of pixels. |
| */ |
| void resize(const uint8_t* _Nonnull in, uint8_t* _Nonnull out, size_t inputSizeX, |
| size_t inputSizeY, size_t vectorSize, size_t outputSizeX, size_t outputSizeY, |
| const Restriction* _Nullable restriction = nullptr); |
| |
| /** |
| * The YUV formats supported by yuvToRgb. |
| */ |
| enum class YuvFormat { |
| NV21 = 0x11, |
| YV12 = 0x32315659, |
| }; |
| |
| /** |
| * Convert an image from YUV to RGB. |
| * |
| * Converts an Android YUV buffer to RGB. The input allocation should be |
| * supplied in a supported YUV format as a YUV cell Allocation. |
| * The output is RGBA; the alpha channel will be set to 255. |
| * |
| * Note that for YV12 and a sizeX that's not a multiple of 32, the |
| * RenderScript Intrinsic may not have converted the image correctly. |
| * This Toolkit method should. |
| * |
| * @param in The buffer of the image to be converted. |
| * @param out The buffer that receives the converted image. |
| * @param sizeX The width in pixels of the image. Must be even. |
| * @param sizeY The height in pixels of the image. |
| * @param format Either YV12 or NV21. |
| */ |
| void yuvToRgb(const uint8_t* _Nonnull in, uint8_t* _Nonnull out, size_t sizeX, size_t sizeY, |
| YuvFormat format); |
| }; |
| |
| } // namespace renderscript |
| } // namespace android |
| |
| #endif // ANDROID_RENDERSCRIPT_TOOLKIT_TOOLKIT_H |