xref: /aosp_15_r20/frameworks/rs/toolkit/java/Toolkit.kt (revision e1eccf28f96817838ad6867f7f39d2351ec11f56)
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.google.android.renderscript
18*e1eccf28SAndroid Build Coastguard Worker 
19*e1eccf28SAndroid Build Coastguard Worker import android.graphics.Bitmap
20*e1eccf28SAndroid Build Coastguard Worker import java.lang.IllegalArgumentException
21*e1eccf28SAndroid Build Coastguard Worker 
22*e1eccf28SAndroid Build Coastguard Worker // This string is used for error messages.
23*e1eccf28SAndroid Build Coastguard Worker private const val externalName = "RenderScript Toolkit"
24*e1eccf28SAndroid Build Coastguard Worker 
25*e1eccf28SAndroid Build Coastguard Worker /**
26*e1eccf28SAndroid Build Coastguard Worker  * A collection of high-performance graphic utility functions like blur and blend.
27*e1eccf28SAndroid Build Coastguard Worker  *
28*e1eccf28SAndroid Build Coastguard Worker  * This toolkit provides ten image manipulation functions: blend, blur, color matrix, convolve,
29*e1eccf28SAndroid Build Coastguard Worker  * histogram, histogramDot, lut, lut3d, resize, and YUV to RGB. These functions execute
30*e1eccf28SAndroid Build Coastguard Worker  * multithreaded on the CPU.
31*e1eccf28SAndroid Build Coastguard Worker  *
32*e1eccf28SAndroid Build Coastguard Worker  * Most of the functions have two variants: one that manipulates Bitmaps, the other ByteArrays.
33*e1eccf28SAndroid Build Coastguard Worker  * For ByteArrays, you need to specify the width and height of the data to be processed, as
34*e1eccf28SAndroid Build Coastguard Worker  * well as the number of bytes per pixel. For most use cases, this will be 4.
35*e1eccf28SAndroid Build Coastguard Worker  *
36*e1eccf28SAndroid Build Coastguard Worker  * The Toolkit creates a thread pool that's used for processing the functions. The threads live
37*e1eccf28SAndroid Build Coastguard Worker  * for the duration of the application. They can be destroyed by calling the method shutdown().
38*e1eccf28SAndroid Build Coastguard Worker  *
39*e1eccf28SAndroid Build Coastguard Worker  * This library is thread safe. You can call methods from different poolThreads. The functions will
40*e1eccf28SAndroid Build Coastguard Worker  * execute sequentially.
41*e1eccf28SAndroid Build Coastguard Worker  *
42*e1eccf28SAndroid Build Coastguard Worker  * A native C++ version of this Toolkit is available. Check the RenderScriptToolkit.h file in the
43*e1eccf28SAndroid Build Coastguard Worker  * cpp directory.
44*e1eccf28SAndroid Build Coastguard Worker  *
45*e1eccf28SAndroid Build Coastguard Worker  * This toolkit can be used as a replacement for most RenderScript Intrinsic functions. Compared
46*e1eccf28SAndroid Build Coastguard Worker  * to RenderScript, it's simpler to use and more than twice as fast on the CPU. However RenderScript
47*e1eccf28SAndroid Build Coastguard Worker  * Intrinsics allow more flexibility for the type of allocation supported. In particular, this
48*e1eccf28SAndroid Build Coastguard Worker  * toolkit does not support allocations of floats.
49*e1eccf28SAndroid Build Coastguard Worker  */
50*e1eccf28SAndroid Build Coastguard Worker object Toolkit {
51*e1eccf28SAndroid Build Coastguard Worker     /**
52*e1eccf28SAndroid Build Coastguard Worker      * Blends a source buffer with the destination buffer.
53*e1eccf28SAndroid Build Coastguard Worker      *
54*e1eccf28SAndroid Build Coastguard Worker      * Blends a source buffer and a destination buffer, placing the result in the destination
55*e1eccf28SAndroid Build Coastguard Worker      * buffer. The blending is done pairwise between two corresponding RGBA values found in
56*e1eccf28SAndroid Build Coastguard Worker      * each buffer. The mode parameter specifies one of fifteen supported blending operations.
57*e1eccf28SAndroid Build Coastguard Worker      * See {@link BlendingMode}.
58*e1eccf28SAndroid Build Coastguard Worker      *
59*e1eccf28SAndroid Build Coastguard Worker      * A variant of this method is also available to blend Bitmaps.
60*e1eccf28SAndroid Build Coastguard Worker      *
61*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
62*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
63*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY.
64*e1eccf28SAndroid Build Coastguard Worker      *
65*e1eccf28SAndroid Build Coastguard Worker      * The source and destination buffer must have the same dimensions. Both arrays should have
66*e1eccf28SAndroid Build Coastguard Worker      * a size greater or equal to sizeX * sizeY * 4. The buffers have a row-major layout.
67*e1eccf28SAndroid Build Coastguard Worker      *
68*e1eccf28SAndroid Build Coastguard Worker      * @param mode The specific blending operation to do.
69*e1eccf28SAndroid Build Coastguard Worker      * @param sourceArray The RGBA input buffer.
70*e1eccf28SAndroid Build Coastguard Worker      * @param destArray The destination buffer. Used for input and output.
71*e1eccf28SAndroid Build Coastguard Worker      * @param sizeX The width of both buffers, as a number of RGBA values.
72*e1eccf28SAndroid Build Coastguard Worker      * @param sizeY The height of both buffers, as a number of RGBA values.
73*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
74*e1eccf28SAndroid Build Coastguard Worker      */
75*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
blendnull76*e1eccf28SAndroid Build Coastguard Worker     fun blend(
77*e1eccf28SAndroid Build Coastguard Worker         mode: BlendingMode,
78*e1eccf28SAndroid Build Coastguard Worker         sourceArray: ByteArray,
79*e1eccf28SAndroid Build Coastguard Worker         destArray: ByteArray,
80*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
81*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
82*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
83*e1eccf28SAndroid Build Coastguard Worker     ) {
84*e1eccf28SAndroid Build Coastguard Worker         require(sourceArray.size >= sizeX * sizeY * 4) {
85*e1eccf28SAndroid Build Coastguard Worker             "$externalName blend. sourceArray is too small for the given dimensions. " +
86*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX*$sizeY*4 < ${sourceArray.size}."
87*e1eccf28SAndroid Build Coastguard Worker         }
88*e1eccf28SAndroid Build Coastguard Worker         require(destArray.size >= sizeX * sizeY * 4) {
89*e1eccf28SAndroid Build Coastguard Worker             "$externalName blend. sourceArray is too small for the given dimensions. " +
90*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX*$sizeY*4 < ${sourceArray.size}."
91*e1eccf28SAndroid Build Coastguard Worker         }
92*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("blend", sizeX, sizeY, restriction)
93*e1eccf28SAndroid Build Coastguard Worker 
94*e1eccf28SAndroid Build Coastguard Worker         nativeBlend(nativeHandle, mode.value, sourceArray, destArray, sizeX, sizeY, restriction)
95*e1eccf28SAndroid Build Coastguard Worker     }
96*e1eccf28SAndroid Build Coastguard Worker 
97*e1eccf28SAndroid Build Coastguard Worker     /**
98*e1eccf28SAndroid Build Coastguard Worker      * Blends a source bitmap with the destination bitmap.
99*e1eccf28SAndroid Build Coastguard Worker      *
100*e1eccf28SAndroid Build Coastguard Worker      * Blends a source bitmap and a destination bitmap, placing the result in the destination
101*e1eccf28SAndroid Build Coastguard Worker      * bitmap. The blending is done pairwise between two corresponding RGBA values found in
102*e1eccf28SAndroid Build Coastguard Worker      * each bitmap. The mode parameter specify one of fifteen supported blending operations.
103*e1eccf28SAndroid Build Coastguard Worker      * See {@link BlendingMode}.
104*e1eccf28SAndroid Build Coastguard Worker      *
105*e1eccf28SAndroid Build Coastguard Worker      * A variant of this method is available to blend ByteArrays.
106*e1eccf28SAndroid Build Coastguard Worker      *
107*e1eccf28SAndroid Build Coastguard Worker      * The bitmaps should have identical width and height, and have a config of ARGB_8888.
108*e1eccf28SAndroid Build Coastguard Worker      * Bitmaps with a stride different than width * vectorSize are not currently supported.
109*e1eccf28SAndroid Build Coastguard Worker      *
110*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
111*e1eccf28SAndroid Build Coastguard Worker      * of each bitmap. If provided, the range must be wholly contained with the dimensions
112*e1eccf28SAndroid Build Coastguard Worker      * of the bitmap.
113*e1eccf28SAndroid Build Coastguard Worker      *
114*e1eccf28SAndroid Build Coastguard Worker      * @param mode The specific blending operation to do.
115*e1eccf28SAndroid Build Coastguard Worker      * @param sourceBitmap The RGBA input buffer.
116*e1eccf28SAndroid Build Coastguard Worker      * @param destBitmap The destination buffer. Used for input and output.
117*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
118*e1eccf28SAndroid Build Coastguard Worker      */
119*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
blendnull120*e1eccf28SAndroid Build Coastguard Worker     fun blend(
121*e1eccf28SAndroid Build Coastguard Worker         mode: BlendingMode,
122*e1eccf28SAndroid Build Coastguard Worker         sourceBitmap: Bitmap,
123*e1eccf28SAndroid Build Coastguard Worker         destBitmap: Bitmap,
124*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
125*e1eccf28SAndroid Build Coastguard Worker     ) {
126*e1eccf28SAndroid Build Coastguard Worker         validateBitmap("blend", sourceBitmap)
127*e1eccf28SAndroid Build Coastguard Worker         validateBitmap("blend", destBitmap)
128*e1eccf28SAndroid Build Coastguard Worker         require(
129*e1eccf28SAndroid Build Coastguard Worker             sourceBitmap.width == destBitmap.width &&
130*e1eccf28SAndroid Build Coastguard Worker                     sourceBitmap.height == destBitmap.height
131*e1eccf28SAndroid Build Coastguard Worker         ) {
132*e1eccf28SAndroid Build Coastguard Worker             "$externalName blend. Source and destination bitmaps should be the same size. " +
133*e1eccf28SAndroid Build Coastguard Worker                     "${sourceBitmap.width}x${sourceBitmap.height} and " +
134*e1eccf28SAndroid Build Coastguard Worker                     "${destBitmap.width}x${destBitmap.height} provided."
135*e1eccf28SAndroid Build Coastguard Worker         }
136*e1eccf28SAndroid Build Coastguard Worker         require(sourceBitmap.config == destBitmap.config) {
137*e1eccf28SAndroid Build Coastguard Worker             "RenderScript Toolkit blend. Source and destination bitmaps should have the same " +
138*e1eccf28SAndroid Build Coastguard Worker                     "config. ${sourceBitmap.config} and ${destBitmap.config} provided."
139*e1eccf28SAndroid Build Coastguard Worker         }
140*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("blend", sourceBitmap.width, sourceBitmap.height, restriction)
141*e1eccf28SAndroid Build Coastguard Worker 
142*e1eccf28SAndroid Build Coastguard Worker         nativeBlendBitmap(nativeHandle, mode.value, sourceBitmap, destBitmap, restriction)
143*e1eccf28SAndroid Build Coastguard Worker     }
144*e1eccf28SAndroid Build Coastguard Worker 
145*e1eccf28SAndroid Build Coastguard Worker     /**
146*e1eccf28SAndroid Build Coastguard Worker      * Blurs an image.
147*e1eccf28SAndroid Build Coastguard Worker      *
148*e1eccf28SAndroid Build Coastguard Worker      * Performs a Gaussian blur of an image and returns result in a ByteArray buffer. A variant of
149*e1eccf28SAndroid Build Coastguard Worker      * this method is available to blur Bitmaps.
150*e1eccf28SAndroid Build Coastguard Worker      *
151*e1eccf28SAndroid Build Coastguard Worker      * The radius determines which pixels are used to compute each blurred pixels. This Toolkit
152*e1eccf28SAndroid Build Coastguard Worker      * accepts values between 1 and 25. Larger values create a more blurred effect but also
153*e1eccf28SAndroid Build Coastguard Worker      * take longer to compute. When the radius extends past the edge, the edge pixel will
154*e1eccf28SAndroid Build Coastguard Worker      * be used as replacement for the pixel that's out off boundary.
155*e1eccf28SAndroid Build Coastguard Worker      *
156*e1eccf28SAndroid Build Coastguard Worker      * Each input pixel can either be represented by four bytes (RGBA format) or one byte
157*e1eccf28SAndroid Build Coastguard Worker      * for the less common blurring of alpha channel only image.
158*e1eccf28SAndroid Build Coastguard Worker      *
159*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
160*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
161*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY. NOTE: The output buffer will still be full size, with the
162*e1eccf28SAndroid Build Coastguard Worker      * section that's not blurred all set to 0. This is to stay compatible with RenderScript.
163*e1eccf28SAndroid Build Coastguard Worker      *
164*e1eccf28SAndroid Build Coastguard Worker      * The source buffer should be large enough for sizeX * sizeY * mVectorSize bytes. It has a
165*e1eccf28SAndroid Build Coastguard Worker      * row-major layout.
166*e1eccf28SAndroid Build Coastguard Worker      *
167*e1eccf28SAndroid Build Coastguard Worker      * @param inputArray The buffer of the image to be blurred.
168*e1eccf28SAndroid Build Coastguard Worker      * @param vectorSize Either 1 or 4, the number of bytes in each cell, i.e. A vs. RGBA.
169*e1eccf28SAndroid Build Coastguard Worker      * @param sizeX The width of both buffers, as a number of 1 or 4 byte cells.
170*e1eccf28SAndroid Build Coastguard Worker      * @param sizeY The height of both buffers, as a number of 1 or 4 byte cells.
171*e1eccf28SAndroid Build Coastguard Worker      * @param radius The radius of the pixels used to blur, a value from 1 to 25.
172*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
173*e1eccf28SAndroid Build Coastguard Worker      * @return The blurred pixels, a ByteArray of size.
174*e1eccf28SAndroid Build Coastguard Worker      */
175*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
blurnull176*e1eccf28SAndroid Build Coastguard Worker     fun blur(
177*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
178*e1eccf28SAndroid Build Coastguard Worker         vectorSize: Int,
179*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
180*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
181*e1eccf28SAndroid Build Coastguard Worker         radius: Int = 5,
182*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
183*e1eccf28SAndroid Build Coastguard Worker     ): ByteArray {
184*e1eccf28SAndroid Build Coastguard Worker         require(vectorSize == 1 || vectorSize == 4) {
185*e1eccf28SAndroid Build Coastguard Worker             "$externalName blur. The vectorSize should be 1 or 4. $vectorSize provided."
186*e1eccf28SAndroid Build Coastguard Worker         }
187*e1eccf28SAndroid Build Coastguard Worker         require(inputArray.size >= sizeX * sizeY * vectorSize) {
188*e1eccf28SAndroid Build Coastguard Worker             "$externalName blur. inputArray is too small for the given dimensions. " +
189*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX*$sizeY*$vectorSize < ${inputArray.size}."
190*e1eccf28SAndroid Build Coastguard Worker         }
191*e1eccf28SAndroid Build Coastguard Worker         require(radius in 1..25) {
192*e1eccf28SAndroid Build Coastguard Worker             "$externalName blur. The radius should be between 1 and 25. $radius provided."
193*e1eccf28SAndroid Build Coastguard Worker         }
194*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("blur", sizeX, sizeY, restriction)
195*e1eccf28SAndroid Build Coastguard Worker 
196*e1eccf28SAndroid Build Coastguard Worker         val outputArray = ByteArray(inputArray.size)
197*e1eccf28SAndroid Build Coastguard Worker         nativeBlur(
198*e1eccf28SAndroid Build Coastguard Worker             nativeHandle, inputArray, vectorSize, sizeX, sizeY, radius, outputArray, restriction
199*e1eccf28SAndroid Build Coastguard Worker         )
200*e1eccf28SAndroid Build Coastguard Worker         return outputArray
201*e1eccf28SAndroid Build Coastguard Worker     }
202*e1eccf28SAndroid Build Coastguard Worker 
203*e1eccf28SAndroid Build Coastguard Worker     /**
204*e1eccf28SAndroid Build Coastguard Worker      * Blurs an image.
205*e1eccf28SAndroid Build Coastguard Worker      *
206*e1eccf28SAndroid Build Coastguard Worker      * Performs a Gaussian blur of a Bitmap and returns result as a Bitmap. A variant of
207*e1eccf28SAndroid Build Coastguard Worker      * this method is available to blur ByteArrays.
208*e1eccf28SAndroid Build Coastguard Worker      *
209*e1eccf28SAndroid Build Coastguard Worker      * The radius determines which pixels are used to compute each blurred pixels. This Toolkit
210*e1eccf28SAndroid Build Coastguard Worker      * accepts values between 1 and 25. Larger values create a more blurred effect but also
211*e1eccf28SAndroid Build Coastguard Worker      * take longer to compute. When the radius extends past the edge, the edge pixel will
212*e1eccf28SAndroid Build Coastguard Worker      * be used as replacement for the pixel that's out off boundary.
213*e1eccf28SAndroid Build Coastguard Worker      *
214*e1eccf28SAndroid Build Coastguard Worker      * This method supports input Bitmap of config ARGB_8888 and ALPHA_8. Bitmaps with a stride
215*e1eccf28SAndroid Build Coastguard Worker      * different than width * vectorSize are not currently supported. The returned Bitmap has the
216*e1eccf28SAndroid Build Coastguard Worker      * same config.
217*e1eccf28SAndroid Build Coastguard Worker      *
218*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
219*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
220*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY. NOTE: The output Bitmap will still be full size, with the
221*e1eccf28SAndroid Build Coastguard Worker      * section that's not blurred all set to 0. This is to stay compatible with RenderScript.
222*e1eccf28SAndroid Build Coastguard Worker      *
223*e1eccf28SAndroid Build Coastguard Worker      * @param inputBitmap The buffer of the image to be blurred.
224*e1eccf28SAndroid Build Coastguard Worker      * @param radius The radius of the pixels used to blur, a value from 1 to 25. Default is 5.
225*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
226*e1eccf28SAndroid Build Coastguard Worker      * @return The blurred Bitmap.
227*e1eccf28SAndroid Build Coastguard Worker      */
228*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
blurnull229*e1eccf28SAndroid Build Coastguard Worker     fun blur(inputBitmap: Bitmap, radius: Int = 5, restriction: Range2d? = null): Bitmap {
230*e1eccf28SAndroid Build Coastguard Worker         validateBitmap("blur", inputBitmap)
231*e1eccf28SAndroid Build Coastguard Worker         require(radius in 1..25) {
232*e1eccf28SAndroid Build Coastguard Worker             "$externalName blur. The radius should be between 1 and 25. $radius provided."
233*e1eccf28SAndroid Build Coastguard Worker         }
234*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("blur", inputBitmap.width, inputBitmap.height, restriction)
235*e1eccf28SAndroid Build Coastguard Worker 
236*e1eccf28SAndroid Build Coastguard Worker         val outputBitmap = createCompatibleBitmap(inputBitmap)
237*e1eccf28SAndroid Build Coastguard Worker         nativeBlurBitmap(nativeHandle, inputBitmap, outputBitmap, radius, restriction)
238*e1eccf28SAndroid Build Coastguard Worker         return outputBitmap
239*e1eccf28SAndroid Build Coastguard Worker     }
240*e1eccf28SAndroid Build Coastguard Worker 
241*e1eccf28SAndroid Build Coastguard Worker     /**
242*e1eccf28SAndroid Build Coastguard Worker      * Identity matrix that can be passed to the {@link RenderScriptToolkit::colorMatrix} method.
243*e1eccf28SAndroid Build Coastguard Worker      *
244*e1eccf28SAndroid Build Coastguard Worker      * Using this matrix will result in no change to the pixel through multiplication although
245*e1eccf28SAndroid Build Coastguard Worker      * the pixel value can still be modified by the add vector, or transformed to a different
246*e1eccf28SAndroid Build Coastguard Worker      * format.
247*e1eccf28SAndroid Build Coastguard Worker      */
248*e1eccf28SAndroid Build Coastguard Worker     val identityMatrix: FloatArray
249*e1eccf28SAndroid Build Coastguard Worker         get() = floatArrayOf(
250*e1eccf28SAndroid Build Coastguard Worker             1f, 0f, 0f, 0f,
251*e1eccf28SAndroid Build Coastguard Worker             0f, 1f, 0f, 0f,
252*e1eccf28SAndroid Build Coastguard Worker             0f, 0f, 1f, 0f,
253*e1eccf28SAndroid Build Coastguard Worker             0f, 0f, 0f, 1f
254*e1eccf28SAndroid Build Coastguard Worker         )
255*e1eccf28SAndroid Build Coastguard Worker 
256*e1eccf28SAndroid Build Coastguard Worker     /**
257*e1eccf28SAndroid Build Coastguard Worker      * Matrix to turn color pixels to a grey scale.
258*e1eccf28SAndroid Build Coastguard Worker      *
259*e1eccf28SAndroid Build Coastguard Worker      * Use this matrix with the {@link RenderScriptToolkit::colorMatrix} method to convert an
260*e1eccf28SAndroid Build Coastguard Worker      * image from color to greyscale.
261*e1eccf28SAndroid Build Coastguard Worker      */
262*e1eccf28SAndroid Build Coastguard Worker     val greyScaleColorMatrix: FloatArray
263*e1eccf28SAndroid Build Coastguard Worker         get() = floatArrayOf(
264*e1eccf28SAndroid Build Coastguard Worker             0.299f, 0.299f, 0.299f, 0f,
265*e1eccf28SAndroid Build Coastguard Worker             0.587f, 0.587f, 0.587f, 0f,
266*e1eccf28SAndroid Build Coastguard Worker             0.114f, 0.114f, 0.114f, 0f,
267*e1eccf28SAndroid Build Coastguard Worker             0f, 0f, 0f, 1f
268*e1eccf28SAndroid Build Coastguard Worker         )
269*e1eccf28SAndroid Build Coastguard Worker 
270*e1eccf28SAndroid Build Coastguard Worker     /**
271*e1eccf28SAndroid Build Coastguard Worker      * Matrix to convert RGB to YUV.
272*e1eccf28SAndroid Build Coastguard Worker      *
273*e1eccf28SAndroid Build Coastguard Worker      * Use this matrix with the {@link RenderScriptToolkit::colorMatrix} method to convert the
274*e1eccf28SAndroid Build Coastguard Worker      * first three bytes of each pixel from RGB to YUV. This leaves the last byte (the alpha
275*e1eccf28SAndroid Build Coastguard Worker      * channel) untouched.
276*e1eccf28SAndroid Build Coastguard Worker      *
277*e1eccf28SAndroid Build Coastguard Worker      * This is a simplistic conversion. Most YUV buffers have more complicated format, not supported
278*e1eccf28SAndroid Build Coastguard Worker      * by this method.
279*e1eccf28SAndroid Build Coastguard Worker      */
280*e1eccf28SAndroid Build Coastguard Worker     val rgbToYuvMatrix: FloatArray
281*e1eccf28SAndroid Build Coastguard Worker         get() = floatArrayOf(
282*e1eccf28SAndroid Build Coastguard Worker             0.299f, -0.14713f, 0.615f, 0f,
283*e1eccf28SAndroid Build Coastguard Worker             0.587f, -0.28886f, -0.51499f, 0f,
284*e1eccf28SAndroid Build Coastguard Worker             0.114f, 0.436f, -0.10001f, 0f,
285*e1eccf28SAndroid Build Coastguard Worker             0f, 0f, 0f, 1f
286*e1eccf28SAndroid Build Coastguard Worker         )
287*e1eccf28SAndroid Build Coastguard Worker 
288*e1eccf28SAndroid Build Coastguard Worker     /**
289*e1eccf28SAndroid Build Coastguard Worker      * Matrix to convert YUV to RGB.
290*e1eccf28SAndroid Build Coastguard Worker      *
291*e1eccf28SAndroid Build Coastguard Worker      * Use this matrix with the {@link RenderScriptToolkit::colorMatrix} method to convert the
292*e1eccf28SAndroid Build Coastguard Worker      * first three bytes of each pixel from YUV to RGB. This leaves the last byte (the alpha
293*e1eccf28SAndroid Build Coastguard Worker      * channel) untouched.
294*e1eccf28SAndroid Build Coastguard Worker      *
295*e1eccf28SAndroid Build Coastguard Worker      * This is a simplistic conversion. Most YUV buffers have more complicated format, not supported
296*e1eccf28SAndroid Build Coastguard Worker      * by this method. Use {@link RenderScriptToolkit::yuvToRgb} to convert these buffers.
297*e1eccf28SAndroid Build Coastguard Worker      */
298*e1eccf28SAndroid Build Coastguard Worker     val yuvToRgbMatrix: FloatArray
299*e1eccf28SAndroid Build Coastguard Worker         get() = floatArrayOf(
300*e1eccf28SAndroid Build Coastguard Worker             1f, 1f, 1f, 0f,
301*e1eccf28SAndroid Build Coastguard Worker             0f, -0.39465f, 2.03211f, 0f,
302*e1eccf28SAndroid Build Coastguard Worker             1.13983f, -0.5806f, 0f, 0f,
303*e1eccf28SAndroid Build Coastguard Worker             0f, 0f, 0f, 1f
304*e1eccf28SAndroid Build Coastguard Worker         )
305*e1eccf28SAndroid Build Coastguard Worker 
306*e1eccf28SAndroid Build Coastguard Worker     /**
307*e1eccf28SAndroid Build Coastguard Worker      * Transform an image using a color matrix.
308*e1eccf28SAndroid Build Coastguard Worker      *
309*e1eccf28SAndroid Build Coastguard Worker      * Converts a 2D array of vectors of unsigned bytes, multiplying each vectors by a 4x4 matrix
310*e1eccf28SAndroid Build Coastguard Worker      * and adding an optional vector.
311*e1eccf28SAndroid Build Coastguard Worker      *
312*e1eccf28SAndroid Build Coastguard Worker      * Each input vector is composed of 1-4 unsigned bytes. If less than 4 bytes, it's extended to
313*e1eccf28SAndroid Build Coastguard Worker      * 4, padding with zeroes. The unsigned bytes are converted from 0-255 to 0.0-1.0 floats
314*e1eccf28SAndroid Build Coastguard Worker      * before the multiplication is done.
315*e1eccf28SAndroid Build Coastguard Worker      *
316*e1eccf28SAndroid Build Coastguard Worker      * The resulting value is normalized from 0.0-1.0 to a 0-255 value and stored in the output.
317*e1eccf28SAndroid Build Coastguard Worker      * If the output vector size is less than four, the unused channels are discarded.
318*e1eccf28SAndroid Build Coastguard Worker      *
319*e1eccf28SAndroid Build Coastguard Worker      * If addVector is not specified, a vector of zeroes is added, i.e. a noop.
320*e1eccf28SAndroid Build Coastguard Worker      *
321*e1eccf28SAndroid Build Coastguard Worker      * Like the RenderScript Intrinsics, vectorSize of size 3 are padded to occupy 4 bytes.
322*e1eccf28SAndroid Build Coastguard Worker      *
323*e1eccf28SAndroid Build Coastguard Worker      * Check identityMatrix, greyScaleColorMatrix, rgbToYuvMatrix, and yuvToRgbMatrix for sample
324*e1eccf28SAndroid Build Coastguard Worker      * matrices. The YUV conversion may not work for all color spaces.
325*e1eccf28SAndroid Build Coastguard Worker      *
326*e1eccf28SAndroid Build Coastguard Worker      * @param inputArray The buffer of the image to be converted.
327*e1eccf28SAndroid Build Coastguard Worker      * @param inputVectorSize The number of bytes in each input cell, a value from 1 to 4.
328*e1eccf28SAndroid Build Coastguard Worker      * @param sizeX The width of both buffers, as a number of 1 to 4 byte cells.
329*e1eccf28SAndroid Build Coastguard Worker      * @param sizeY The height of both buffers, as a number of 1 to 4 byte cells.
330*e1eccf28SAndroid Build Coastguard Worker      * @param outputVectorSize The number of bytes in each output cell, a value from 1 to 4.
331*e1eccf28SAndroid Build Coastguard Worker      * @param matrix The 4x4 matrix to multiply, in row major format.
332*e1eccf28SAndroid Build Coastguard Worker      * @param addVector A vector of four floats that's added to the result of the multiplication.
333*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
334*e1eccf28SAndroid Build Coastguard Worker      * @return The converted buffer.
335*e1eccf28SAndroid Build Coastguard Worker      */
336*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
colorMatrixnull337*e1eccf28SAndroid Build Coastguard Worker     fun colorMatrix(
338*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
339*e1eccf28SAndroid Build Coastguard Worker         inputVectorSize: Int,
340*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
341*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
342*e1eccf28SAndroid Build Coastguard Worker         outputVectorSize: Int,
343*e1eccf28SAndroid Build Coastguard Worker         matrix: FloatArray,
344*e1eccf28SAndroid Build Coastguard Worker         addVector: FloatArray = floatArrayOf(0f, 0f, 0f, 0f),
345*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
346*e1eccf28SAndroid Build Coastguard Worker     ): ByteArray {
347*e1eccf28SAndroid Build Coastguard Worker         require(inputVectorSize in 1..4) {
348*e1eccf28SAndroid Build Coastguard Worker             "$externalName colorMatrix. The inputVectorSize should be between 1 and 4. " +
349*e1eccf28SAndroid Build Coastguard Worker                     "$inputVectorSize provided."
350*e1eccf28SAndroid Build Coastguard Worker         }
351*e1eccf28SAndroid Build Coastguard Worker         require(outputVectorSize in 1..4) {
352*e1eccf28SAndroid Build Coastguard Worker             "$externalName colorMatrix. The outputVectorSize should be between 1 and 4. " +
353*e1eccf28SAndroid Build Coastguard Worker                     "$outputVectorSize provided."
354*e1eccf28SAndroid Build Coastguard Worker         }
355*e1eccf28SAndroid Build Coastguard Worker         require(inputArray.size >= sizeX * sizeY * inputVectorSize) {
356*e1eccf28SAndroid Build Coastguard Worker             "$externalName colorMatrix. inputArray is too small for the given dimensions. " +
357*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX*$sizeY*$inputVectorSize < ${inputArray.size}."
358*e1eccf28SAndroid Build Coastguard Worker         }
359*e1eccf28SAndroid Build Coastguard Worker         require(matrix.size == 16) {
360*e1eccf28SAndroid Build Coastguard Worker             "$externalName colorMatrix. matrix should have 16 entries. ${matrix.size} provided."
361*e1eccf28SAndroid Build Coastguard Worker         }
362*e1eccf28SAndroid Build Coastguard Worker         require(addVector.size == 4) {
363*e1eccf28SAndroid Build Coastguard Worker             "$externalName colorMatrix. addVector should have 4 entries. " +
364*e1eccf28SAndroid Build Coastguard Worker                     "${addVector.size} provided."
365*e1eccf28SAndroid Build Coastguard Worker         }
366*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("colorMatrix", sizeX, sizeY, restriction)
367*e1eccf28SAndroid Build Coastguard Worker 
368*e1eccf28SAndroid Build Coastguard Worker         val outputArray = ByteArray(sizeX * sizeY * paddedSize(outputVectorSize))
369*e1eccf28SAndroid Build Coastguard Worker         nativeColorMatrix(
370*e1eccf28SAndroid Build Coastguard Worker             nativeHandle, inputArray, inputVectorSize, sizeX, sizeY, outputArray, outputVectorSize,
371*e1eccf28SAndroid Build Coastguard Worker             matrix, addVector, restriction
372*e1eccf28SAndroid Build Coastguard Worker         )
373*e1eccf28SAndroid Build Coastguard Worker         return outputArray
374*e1eccf28SAndroid Build Coastguard Worker     }
375*e1eccf28SAndroid Build Coastguard Worker 
376*e1eccf28SAndroid Build Coastguard Worker     /**
377*e1eccf28SAndroid Build Coastguard Worker      * Transform an image using a color matrix.
378*e1eccf28SAndroid Build Coastguard Worker      *
379*e1eccf28SAndroid Build Coastguard Worker      * Converts a bitmap, multiplying each RGBA value by a 4x4 matrix and adding an optional vector.
380*e1eccf28SAndroid Build Coastguard Worker      * Each byte of the RGBA is converted from 0-255 to 0.0-1.0 floats before the multiplication
381*e1eccf28SAndroid Build Coastguard Worker      * is done.
382*e1eccf28SAndroid Build Coastguard Worker      *
383*e1eccf28SAndroid Build Coastguard Worker      * Bitmaps with a stride different than width * vectorSize are not currently supported.
384*e1eccf28SAndroid Build Coastguard Worker      *
385*e1eccf28SAndroid Build Coastguard Worker      * The resulting value is normalized from 0.0-1.0 to a 0-255 value and stored in the output.
386*e1eccf28SAndroid Build Coastguard Worker      *
387*e1eccf28SAndroid Build Coastguard Worker      * If addVector is not specified, a vector of zeroes is added, i.e. a noop.
388*e1eccf28SAndroid Build Coastguard Worker      *
389*e1eccf28SAndroid Build Coastguard Worker      * Check identityMatrix, greyScaleColorMatrix, rgbToYuvMatrix, and yuvToRgbMatrix for sample
390*e1eccf28SAndroid Build Coastguard Worker      * matrices. The YUV conversion may not work for all color spaces.
391*e1eccf28SAndroid Build Coastguard Worker      *
392*e1eccf28SAndroid Build Coastguard Worker      * @param inputBitmap The image to be converted.
393*e1eccf28SAndroid Build Coastguard Worker      * @param matrix The 4x4 matrix to multiply, in row major format.
394*e1eccf28SAndroid Build Coastguard Worker      * @param addVector A vector of four floats that's added to the result of the multiplication.
395*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
396*e1eccf28SAndroid Build Coastguard Worker      * @return The converted buffer.
397*e1eccf28SAndroid Build Coastguard Worker      */
398*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
colorMatrixnull399*e1eccf28SAndroid Build Coastguard Worker     fun colorMatrix(
400*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
401*e1eccf28SAndroid Build Coastguard Worker         matrix: FloatArray,
402*e1eccf28SAndroid Build Coastguard Worker         addVector: FloatArray = floatArrayOf(0f, 0f, 0f, 0f),
403*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
404*e1eccf28SAndroid Build Coastguard Worker     ): Bitmap {
405*e1eccf28SAndroid Build Coastguard Worker         validateBitmap("colorMatrix", inputBitmap)
406*e1eccf28SAndroid Build Coastguard Worker         require(matrix.size == 16) {
407*e1eccf28SAndroid Build Coastguard Worker             "$externalName colorMatrix. matrix should have 16 entries. ${matrix.size} provided."
408*e1eccf28SAndroid Build Coastguard Worker         }
409*e1eccf28SAndroid Build Coastguard Worker         require(addVector.size == 4) {
410*e1eccf28SAndroid Build Coastguard Worker             "$externalName colorMatrix. addVector should have 4 entries."
411*e1eccf28SAndroid Build Coastguard Worker         }
412*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("colorMatrix", inputBitmap.width, inputBitmap.height, restriction)
413*e1eccf28SAndroid Build Coastguard Worker 
414*e1eccf28SAndroid Build Coastguard Worker         val outputBitmap = createCompatibleBitmap(inputBitmap)
415*e1eccf28SAndroid Build Coastguard Worker         nativeColorMatrixBitmap(
416*e1eccf28SAndroid Build Coastguard Worker             nativeHandle,
417*e1eccf28SAndroid Build Coastguard Worker             inputBitmap,
418*e1eccf28SAndroid Build Coastguard Worker             outputBitmap,
419*e1eccf28SAndroid Build Coastguard Worker             matrix,
420*e1eccf28SAndroid Build Coastguard Worker             addVector,
421*e1eccf28SAndroid Build Coastguard Worker             restriction
422*e1eccf28SAndroid Build Coastguard Worker         )
423*e1eccf28SAndroid Build Coastguard Worker         return outputBitmap
424*e1eccf28SAndroid Build Coastguard Worker     }
425*e1eccf28SAndroid Build Coastguard Worker 
426*e1eccf28SAndroid Build Coastguard Worker     /**
427*e1eccf28SAndroid Build Coastguard Worker      * Convolve a ByteArray.
428*e1eccf28SAndroid Build Coastguard Worker      *
429*e1eccf28SAndroid Build Coastguard Worker      * Applies a 3x3 or 5x5 convolution to the input array using the provided coefficients.
430*e1eccf28SAndroid Build Coastguard Worker      * A variant of this method is available to convolve Bitmaps.
431*e1eccf28SAndroid Build Coastguard Worker      *
432*e1eccf28SAndroid Build Coastguard Worker      * For 3x3 convolutions, 9 coefficients must be provided. For 5x5, 25 coefficients are needed.
433*e1eccf28SAndroid Build Coastguard Worker      * The coefficients should be provided in row-major format.
434*e1eccf28SAndroid Build Coastguard Worker      *
435*e1eccf28SAndroid Build Coastguard Worker      * When the square extends past the edge, the edge values will be used as replacement for the
436*e1eccf28SAndroid Build Coastguard Worker      * values that's are off boundary.
437*e1eccf28SAndroid Build Coastguard Worker      *
438*e1eccf28SAndroid Build Coastguard Worker      * Each input cell can either be represented by one to four bytes. Each byte is multiplied
439*e1eccf28SAndroid Build Coastguard Worker      * and accumulated independently of the other bytes of the cell.
440*e1eccf28SAndroid Build Coastguard Worker      *
441*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the convolve operation to a rectangular
442*e1eccf28SAndroid Build Coastguard Worker      * subset of each buffer. If provided, the range must be wholly contained with the dimensions
443*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY. NOTE: The output buffer will still be full size, with the
444*e1eccf28SAndroid Build Coastguard Worker      * section that's not convolved all set to 0. This is to stay compatible with RenderScript.
445*e1eccf28SAndroid Build Coastguard Worker      *
446*e1eccf28SAndroid Build Coastguard Worker      * The source array should be large enough for sizeX * sizeY * vectorSize bytes. It has a
447*e1eccf28SAndroid Build Coastguard Worker      * row-major layout. The output array will have the same dimensions.
448*e1eccf28SAndroid Build Coastguard Worker      *
449*e1eccf28SAndroid Build Coastguard Worker      * Like the RenderScript Intrinsics, vectorSize of size 3 are padded to occupy 4 bytes.
450*e1eccf28SAndroid Build Coastguard Worker      *
451*e1eccf28SAndroid Build Coastguard Worker      * @param inputArray The buffer of the image to be blurred.
452*e1eccf28SAndroid Build Coastguard Worker      * @param vectorSize The number of bytes in each cell, a value from 1 to 4.
453*e1eccf28SAndroid Build Coastguard Worker      * @param sizeX The width of both buffers, as a number of 1 or 4 byte cells.
454*e1eccf28SAndroid Build Coastguard Worker      * @param sizeY The height of both buffers, as a number of 1 or 4 byte cells.
455*e1eccf28SAndroid Build Coastguard Worker      * @param coefficients A FloatArray of size 9 or 25, containing the multipliers.
456*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
457*e1eccf28SAndroid Build Coastguard Worker      * @return The convolved array.
458*e1eccf28SAndroid Build Coastguard Worker      */
459*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
convolvenull460*e1eccf28SAndroid Build Coastguard Worker     fun convolve(
461*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
462*e1eccf28SAndroid Build Coastguard Worker         vectorSize: Int,
463*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
464*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
465*e1eccf28SAndroid Build Coastguard Worker         coefficients: FloatArray,
466*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
467*e1eccf28SAndroid Build Coastguard Worker     ): ByteArray {
468*e1eccf28SAndroid Build Coastguard Worker         require(vectorSize in 1..4) {
469*e1eccf28SAndroid Build Coastguard Worker             "$externalName convolve. The vectorSize should be between 1 and 4. " +
470*e1eccf28SAndroid Build Coastguard Worker                     "$vectorSize provided."
471*e1eccf28SAndroid Build Coastguard Worker         }
472*e1eccf28SAndroid Build Coastguard Worker         require(inputArray.size >= sizeX * sizeY * vectorSize) {
473*e1eccf28SAndroid Build Coastguard Worker             "$externalName convolve. inputArray is too small for the given dimensions. " +
474*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX*$sizeY*$vectorSize < ${inputArray.size}."
475*e1eccf28SAndroid Build Coastguard Worker         }
476*e1eccf28SAndroid Build Coastguard Worker         require(coefficients.size == 9 || coefficients.size == 25) {
477*e1eccf28SAndroid Build Coastguard Worker             "$externalName convolve. Only 3x3 or 5x5 convolutions are supported. " +
478*e1eccf28SAndroid Build Coastguard Worker                     "${coefficients.size} coefficients provided."
479*e1eccf28SAndroid Build Coastguard Worker         }
480*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("convolve", sizeX, sizeY, restriction)
481*e1eccf28SAndroid Build Coastguard Worker 
482*e1eccf28SAndroid Build Coastguard Worker         val outputArray = ByteArray(inputArray.size)
483*e1eccf28SAndroid Build Coastguard Worker         nativeConvolve(
484*e1eccf28SAndroid Build Coastguard Worker             nativeHandle,
485*e1eccf28SAndroid Build Coastguard Worker             inputArray,
486*e1eccf28SAndroid Build Coastguard Worker             vectorSize,
487*e1eccf28SAndroid Build Coastguard Worker             sizeX,
488*e1eccf28SAndroid Build Coastguard Worker             sizeY,
489*e1eccf28SAndroid Build Coastguard Worker             outputArray,
490*e1eccf28SAndroid Build Coastguard Worker             coefficients,
491*e1eccf28SAndroid Build Coastguard Worker             restriction
492*e1eccf28SAndroid Build Coastguard Worker         )
493*e1eccf28SAndroid Build Coastguard Worker         return outputArray
494*e1eccf28SAndroid Build Coastguard Worker     }
495*e1eccf28SAndroid Build Coastguard Worker 
496*e1eccf28SAndroid Build Coastguard Worker     /**
497*e1eccf28SAndroid Build Coastguard Worker      * Convolve a Bitmap.
498*e1eccf28SAndroid Build Coastguard Worker      *
499*e1eccf28SAndroid Build Coastguard Worker      * Applies a 3x3 or 5x5 convolution to the input Bitmap using the provided coefficients.
500*e1eccf28SAndroid Build Coastguard Worker      * A variant of this method is available to convolve ByteArrays. Bitmaps with a stride different
501*e1eccf28SAndroid Build Coastguard Worker      * than width * vectorSize are not currently supported.
502*e1eccf28SAndroid Build Coastguard Worker      *
503*e1eccf28SAndroid Build Coastguard Worker      * For 3x3 convolutions, 9 coefficients must be provided. For 5x5, 25 coefficients are needed.
504*e1eccf28SAndroid Build Coastguard Worker      * The coefficients should be provided in row-major format.
505*e1eccf28SAndroid Build Coastguard Worker      *
506*e1eccf28SAndroid Build Coastguard Worker      * Each input cell can either be represented by one to four bytes. Each byte is multiplied
507*e1eccf28SAndroid Build Coastguard Worker      * and accumulated independently of the other bytes of the cell.
508*e1eccf28SAndroid Build Coastguard Worker      *
509*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the convolve operation to a rectangular
510*e1eccf28SAndroid Build Coastguard Worker      * subset of each buffer. If provided, the range must be wholly contained with the dimensions
511*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY. NOTE: The output Bitmap will still be full size, with the
512*e1eccf28SAndroid Build Coastguard Worker      * section that's not convolved all set to 0. This is to stay compatible with RenderScript.
513*e1eccf28SAndroid Build Coastguard Worker      *
514*e1eccf28SAndroid Build Coastguard Worker      * @param inputBitmap The image to be blurred.
515*e1eccf28SAndroid Build Coastguard Worker      * @param coefficients A FloatArray of size 9 or 25, containing the multipliers.
516*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
517*e1eccf28SAndroid Build Coastguard Worker      * @return The convolved Bitmap.
518*e1eccf28SAndroid Build Coastguard Worker      */
519*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
convolvenull520*e1eccf28SAndroid Build Coastguard Worker     fun convolve(
521*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
522*e1eccf28SAndroid Build Coastguard Worker         coefficients: FloatArray,
523*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
524*e1eccf28SAndroid Build Coastguard Worker     ): Bitmap {
525*e1eccf28SAndroid Build Coastguard Worker         validateBitmap("convolve", inputBitmap)
526*e1eccf28SAndroid Build Coastguard Worker         require(coefficients.size == 9 || coefficients.size == 25) {
527*e1eccf28SAndroid Build Coastguard Worker             "$externalName convolve. Only 3x3 or 5x5 convolutions are supported. " +
528*e1eccf28SAndroid Build Coastguard Worker                     "${coefficients.size} coefficients provided."
529*e1eccf28SAndroid Build Coastguard Worker         }
530*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("convolve", inputBitmap, restriction)
531*e1eccf28SAndroid Build Coastguard Worker 
532*e1eccf28SAndroid Build Coastguard Worker         val outputBitmap = createCompatibleBitmap(inputBitmap)
533*e1eccf28SAndroid Build Coastguard Worker         nativeConvolveBitmap(nativeHandle, inputBitmap, outputBitmap, coefficients, restriction)
534*e1eccf28SAndroid Build Coastguard Worker         return outputBitmap
535*e1eccf28SAndroid Build Coastguard Worker     }
536*e1eccf28SAndroid Build Coastguard Worker 
537*e1eccf28SAndroid Build Coastguard Worker     /**
538*e1eccf28SAndroid Build Coastguard Worker      * Compute the histogram of an image.
539*e1eccf28SAndroid Build Coastguard Worker      *
540*e1eccf28SAndroid Build Coastguard Worker      * Tallies how many times each of the 256 possible values of a byte is found in the input.
541*e1eccf28SAndroid Build Coastguard Worker      * A variant of this method is available to do the histogram of a Bitmap.
542*e1eccf28SAndroid Build Coastguard Worker      *
543*e1eccf28SAndroid Build Coastguard Worker      * An input cell can be represented by one to four bytes. The tally is done independently
544*e1eccf28SAndroid Build Coastguard Worker      * for each of the bytes of the cell. Correspondingly, the returned IntArray will have
545*e1eccf28SAndroid Build Coastguard Worker      * 256 * vectorSize entries. The counts for value 0 are consecutive, followed by those for
546*e1eccf28SAndroid Build Coastguard Worker      * value 1, etc.
547*e1eccf28SAndroid Build Coastguard Worker      *
548*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
549*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
550*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY.
551*e1eccf28SAndroid Build Coastguard Worker      *
552*e1eccf28SAndroid Build Coastguard Worker      * The source buffer should be large enough for sizeX * sizeY * vectorSize bytes. It has a
553*e1eccf28SAndroid Build Coastguard Worker      * row-major layout.
554*e1eccf28SAndroid Build Coastguard Worker      *
555*e1eccf28SAndroid Build Coastguard Worker      * Like the RenderScript Intrinsics, vectorSize of size 3 are padded to occupy 4 bytes.
556*e1eccf28SAndroid Build Coastguard Worker      *
557*e1eccf28SAndroid Build Coastguard Worker      * @param inputArray The buffer of the image to be analyzed.
558*e1eccf28SAndroid Build Coastguard Worker      * @param vectorSize The number of bytes in each cell, a value from 1 to 4.
559*e1eccf28SAndroid Build Coastguard Worker      * @param sizeX The width of the input buffers, as a number of 1 to 4 byte cells.
560*e1eccf28SAndroid Build Coastguard Worker      * @param sizeY The height of the input buffers, as a number of 1 to 4 byte cells.
561*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
562*e1eccf28SAndroid Build Coastguard Worker      * @return The resulting array of counts.
563*e1eccf28SAndroid Build Coastguard Worker      */
564*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
histogramnull565*e1eccf28SAndroid Build Coastguard Worker     fun histogram(
566*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
567*e1eccf28SAndroid Build Coastguard Worker         vectorSize: Int,
568*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
569*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
570*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
571*e1eccf28SAndroid Build Coastguard Worker     ): IntArray {
572*e1eccf28SAndroid Build Coastguard Worker         require(vectorSize in 1..4) {
573*e1eccf28SAndroid Build Coastguard Worker             "$externalName histogram. The vectorSize should be between 1 and 4. " +
574*e1eccf28SAndroid Build Coastguard Worker                     "$vectorSize provided."
575*e1eccf28SAndroid Build Coastguard Worker         }
576*e1eccf28SAndroid Build Coastguard Worker         require(inputArray.size >= sizeX * sizeY * vectorSize) {
577*e1eccf28SAndroid Build Coastguard Worker             "$externalName histogram. inputArray is too small for the given dimensions. " +
578*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX*$sizeY*$vectorSize < ${inputArray.size}."
579*e1eccf28SAndroid Build Coastguard Worker         }
580*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("histogram", sizeX, sizeY, restriction)
581*e1eccf28SAndroid Build Coastguard Worker 
582*e1eccf28SAndroid Build Coastguard Worker         val outputArray = IntArray(256 * paddedSize(vectorSize))
583*e1eccf28SAndroid Build Coastguard Worker         nativeHistogram(
584*e1eccf28SAndroid Build Coastguard Worker             nativeHandle,
585*e1eccf28SAndroid Build Coastguard Worker             inputArray,
586*e1eccf28SAndroid Build Coastguard Worker             vectorSize,
587*e1eccf28SAndroid Build Coastguard Worker             sizeX,
588*e1eccf28SAndroid Build Coastguard Worker             sizeY,
589*e1eccf28SAndroid Build Coastguard Worker             outputArray,
590*e1eccf28SAndroid Build Coastguard Worker             restriction
591*e1eccf28SAndroid Build Coastguard Worker         )
592*e1eccf28SAndroid Build Coastguard Worker         return outputArray
593*e1eccf28SAndroid Build Coastguard Worker     }
594*e1eccf28SAndroid Build Coastguard Worker 
595*e1eccf28SAndroid Build Coastguard Worker     /**
596*e1eccf28SAndroid Build Coastguard Worker      * Compute the histogram of an image.
597*e1eccf28SAndroid Build Coastguard Worker      *
598*e1eccf28SAndroid Build Coastguard Worker      * Tallies how many times each of the 256 possible values of a byte is found in the bitmap.
599*e1eccf28SAndroid Build Coastguard Worker      * This method supports Bitmaps of config ARGB_8888 and ALPHA_8.
600*e1eccf28SAndroid Build Coastguard Worker      *
601*e1eccf28SAndroid Build Coastguard Worker      * For ARGB_8888, the tally is done independently of the four bytes. Correspondingly, the
602*e1eccf28SAndroid Build Coastguard Worker      * returned IntArray will have 4 * 256 entries. The counts for value 0 are consecutive,
603*e1eccf28SAndroid Build Coastguard Worker      * followed by those for value 1, etc.
604*e1eccf28SAndroid Build Coastguard Worker      *
605*e1eccf28SAndroid Build Coastguard Worker      * For ALPHA_8, an IntArray of size 256 is returned.
606*e1eccf28SAndroid Build Coastguard Worker      *
607*e1eccf28SAndroid Build Coastguard Worker      * Bitmaps with a stride different than width * vectorSize are not currently supported.
608*e1eccf28SAndroid Build Coastguard Worker      *
609*e1eccf28SAndroid Build Coastguard Worker      * A variant of this method is available to do the histogram of a ByteArray.
610*e1eccf28SAndroid Build Coastguard Worker      *
611*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
612*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
613*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY.
614*e1eccf28SAndroid Build Coastguard Worker      *
615*e1eccf28SAndroid Build Coastguard Worker      * @param inputBitmap The bitmap to be analyzed.
616*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
617*e1eccf28SAndroid Build Coastguard Worker      * @return The resulting array of counts.
618*e1eccf28SAndroid Build Coastguard Worker      */
619*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
histogramnull620*e1eccf28SAndroid Build Coastguard Worker     fun histogram(
621*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
622*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
623*e1eccf28SAndroid Build Coastguard Worker     ): IntArray {
624*e1eccf28SAndroid Build Coastguard Worker         validateBitmap("histogram", inputBitmap)
625*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("histogram", inputBitmap, restriction)
626*e1eccf28SAndroid Build Coastguard Worker 
627*e1eccf28SAndroid Build Coastguard Worker         val outputArray = IntArray(256 * vectorSize(inputBitmap))
628*e1eccf28SAndroid Build Coastguard Worker         nativeHistogramBitmap(nativeHandle, inputBitmap, outputArray, restriction)
629*e1eccf28SAndroid Build Coastguard Worker         return outputArray
630*e1eccf28SAndroid Build Coastguard Worker     }
631*e1eccf28SAndroid Build Coastguard Worker 
632*e1eccf28SAndroid Build Coastguard Worker     /**
633*e1eccf28SAndroid Build Coastguard Worker      * Compute the histogram of the dot product of an image.
634*e1eccf28SAndroid Build Coastguard Worker      *
635*e1eccf28SAndroid Build Coastguard Worker      * This method supports cells of 1 to 4 bytes in length. For each cell of the array,
636*e1eccf28SAndroid Build Coastguard Worker      * the dot product of its bytes with the provided coefficients is computed. The resulting
637*e1eccf28SAndroid Build Coastguard Worker      * floating point value is converted to an unsigned byte and tallied in the histogram.
638*e1eccf28SAndroid Build Coastguard Worker      *
639*e1eccf28SAndroid Build Coastguard Worker      * If coefficients is null, the coefficients used for RGBA luminosity calculation will be used,
640*e1eccf28SAndroid Build Coastguard Worker      * i.e. the values [0.299f, 0.587f, 0.114f, 0.f].
641*e1eccf28SAndroid Build Coastguard Worker      *
642*e1eccf28SAndroid Build Coastguard Worker      * Each coefficients must be >= 0 and their sum must be 1.0 or less. There must be the same
643*e1eccf28SAndroid Build Coastguard Worker      * number of coefficients as vectorSize.
644*e1eccf28SAndroid Build Coastguard Worker      *
645*e1eccf28SAndroid Build Coastguard Worker      * A variant of this method is available to do the histogram of a Bitmap.
646*e1eccf28SAndroid Build Coastguard Worker      *
647*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
648*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
649*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY.
650*e1eccf28SAndroid Build Coastguard Worker      *
651*e1eccf28SAndroid Build Coastguard Worker      * The source buffer should be large enough for sizeX * sizeY * vectorSize bytes. The returned
652*e1eccf28SAndroid Build Coastguard Worker      * array will have 256 ints.
653*e1eccf28SAndroid Build Coastguard Worker      *
654*e1eccf28SAndroid Build Coastguard Worker      * Like the RenderScript Intrinsics, vectorSize of size 3 are padded to occupy 4 bytes.
655*e1eccf28SAndroid Build Coastguard Worker      *
656*e1eccf28SAndroid Build Coastguard Worker      * @param inputArray The buffer of the image to be analyzed.
657*e1eccf28SAndroid Build Coastguard Worker      * @param vectorSize The number of bytes in each cell, a value from 1 to 4.
658*e1eccf28SAndroid Build Coastguard Worker      * @param sizeX The width of the input buffers, as a number of 1 to 4 byte cells.
659*e1eccf28SAndroid Build Coastguard Worker      * @param sizeY The height of the input buffers, as a number of 1 to 4 byte cells.
660*e1eccf28SAndroid Build Coastguard Worker      * @param coefficients The dot product multipliers. Size should equal vectorSize. Can be null.
661*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
662*e1eccf28SAndroid Build Coastguard Worker      * @return The resulting vector of counts.
663*e1eccf28SAndroid Build Coastguard Worker      */
664*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
histogramDotnull665*e1eccf28SAndroid Build Coastguard Worker     fun histogramDot(
666*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
667*e1eccf28SAndroid Build Coastguard Worker         vectorSize: Int,
668*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
669*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
670*e1eccf28SAndroid Build Coastguard Worker         coefficients: FloatArray? = null,
671*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
672*e1eccf28SAndroid Build Coastguard Worker     ): IntArray {
673*e1eccf28SAndroid Build Coastguard Worker         require(vectorSize in 1..4) {
674*e1eccf28SAndroid Build Coastguard Worker             "$externalName histogramDot. The vectorSize should be between 1 and 4. " +
675*e1eccf28SAndroid Build Coastguard Worker                     "$vectorSize provided."
676*e1eccf28SAndroid Build Coastguard Worker         }
677*e1eccf28SAndroid Build Coastguard Worker         require(inputArray.size >= sizeX * sizeY * vectorSize) {
678*e1eccf28SAndroid Build Coastguard Worker             "$externalName histogramDot. inputArray is too small for the given dimensions. " +
679*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX*$sizeY*$vectorSize < ${inputArray.size}."
680*e1eccf28SAndroid Build Coastguard Worker         }
681*e1eccf28SAndroid Build Coastguard Worker         validateHistogramDotCoefficients(coefficients, vectorSize)
682*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("histogramDot", sizeX, sizeY, restriction)
683*e1eccf28SAndroid Build Coastguard Worker 
684*e1eccf28SAndroid Build Coastguard Worker         val outputArray = IntArray(256)
685*e1eccf28SAndroid Build Coastguard Worker         val actualCoefficients = coefficients ?: floatArrayOf(0.299f, 0.587f, 0.114f, 0f)
686*e1eccf28SAndroid Build Coastguard Worker         nativeHistogramDot(
687*e1eccf28SAndroid Build Coastguard Worker             nativeHandle,
688*e1eccf28SAndroid Build Coastguard Worker             inputArray,
689*e1eccf28SAndroid Build Coastguard Worker             vectorSize,
690*e1eccf28SAndroid Build Coastguard Worker             sizeX,
691*e1eccf28SAndroid Build Coastguard Worker             sizeY,
692*e1eccf28SAndroid Build Coastguard Worker             outputArray,
693*e1eccf28SAndroid Build Coastguard Worker             actualCoefficients,
694*e1eccf28SAndroid Build Coastguard Worker             restriction
695*e1eccf28SAndroid Build Coastguard Worker         )
696*e1eccf28SAndroid Build Coastguard Worker         return outputArray
697*e1eccf28SAndroid Build Coastguard Worker     }
698*e1eccf28SAndroid Build Coastguard Worker 
699*e1eccf28SAndroid Build Coastguard Worker     /**
700*e1eccf28SAndroid Build Coastguard Worker      * Compute the histogram of the dot product of an image.
701*e1eccf28SAndroid Build Coastguard Worker      *
702*e1eccf28SAndroid Build Coastguard Worker      * This method supports Bitmaps of config ARGB_8888 and ALPHA_8. For each pixel of the bitmap,
703*e1eccf28SAndroid Build Coastguard Worker      * the dot product of its bytes with the provided coefficients is computed. The resulting
704*e1eccf28SAndroid Build Coastguard Worker      * floating point value is converted to an unsigned byte and tallied in the histogram.
705*e1eccf28SAndroid Build Coastguard Worker      *
706*e1eccf28SAndroid Build Coastguard Worker      * If coefficients is null, the coefficients used for RGBA luminosity calculation will be used,
707*e1eccf28SAndroid Build Coastguard Worker      * i.e. the values [0.299f, 0.587f, 0.114f, 0.f].
708*e1eccf28SAndroid Build Coastguard Worker      *
709*e1eccf28SAndroid Build Coastguard Worker      * Each coefficients must be >= 0 and their sum must be 1.0 or less. For ARGB_8888, four values
710*e1eccf28SAndroid Build Coastguard Worker      * must be provided; for ALPHA_8, one.
711*e1eccf28SAndroid Build Coastguard Worker      *
712*e1eccf28SAndroid Build Coastguard Worker      * Bitmaps with a stride different than width * vectorSize are not currently supported.
713*e1eccf28SAndroid Build Coastguard Worker      *
714*e1eccf28SAndroid Build Coastguard Worker      * A variant of this method is available to do the histogram of a ByteArray.
715*e1eccf28SAndroid Build Coastguard Worker      *
716*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
717*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
718*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY.
719*e1eccf28SAndroid Build Coastguard Worker      *
720*e1eccf28SAndroid Build Coastguard Worker      * The returned array will have 256 ints.
721*e1eccf28SAndroid Build Coastguard Worker      *
722*e1eccf28SAndroid Build Coastguard Worker      * @param inputBitmap The bitmap to be analyzed.
723*e1eccf28SAndroid Build Coastguard Worker      * @param coefficients The one or four values used for the dot product. Can be null.
724*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
725*e1eccf28SAndroid Build Coastguard Worker      * @return The resulting vector of counts.
726*e1eccf28SAndroid Build Coastguard Worker      */
727*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
histogramDotnull728*e1eccf28SAndroid Build Coastguard Worker     fun histogramDot(
729*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
730*e1eccf28SAndroid Build Coastguard Worker         coefficients: FloatArray? = null,
731*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
732*e1eccf28SAndroid Build Coastguard Worker     ): IntArray {
733*e1eccf28SAndroid Build Coastguard Worker         validateBitmap("histogramDot", inputBitmap)
734*e1eccf28SAndroid Build Coastguard Worker         validateHistogramDotCoefficients(coefficients, vectorSize(inputBitmap))
735*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("histogramDot", inputBitmap, restriction)
736*e1eccf28SAndroid Build Coastguard Worker 
737*e1eccf28SAndroid Build Coastguard Worker         val outputArray = IntArray(256)
738*e1eccf28SAndroid Build Coastguard Worker         val actualCoefficients = coefficients ?: floatArrayOf(0.299f, 0.587f, 0.114f, 0f)
739*e1eccf28SAndroid Build Coastguard Worker         nativeHistogramDotBitmap(
740*e1eccf28SAndroid Build Coastguard Worker             nativeHandle, inputBitmap, outputArray, actualCoefficients, restriction
741*e1eccf28SAndroid Build Coastguard Worker         )
742*e1eccf28SAndroid Build Coastguard Worker         return outputArray
743*e1eccf28SAndroid Build Coastguard Worker     }
744*e1eccf28SAndroid Build Coastguard Worker 
745*e1eccf28SAndroid Build Coastguard Worker     /**
746*e1eccf28SAndroid Build Coastguard Worker      * Transform an image using a look up table
747*e1eccf28SAndroid Build Coastguard Worker      *
748*e1eccf28SAndroid Build Coastguard Worker      * Transforms an image by using a per-channel lookup table. Each channel of the input has an
749*e1eccf28SAndroid Build Coastguard Worker      * independent lookup table. The tables are 256 entries in size and can cover the full value
750*e1eccf28SAndroid Build Coastguard Worker      * range of a byte.
751*e1eccf28SAndroid Build Coastguard Worker      *
752*e1eccf28SAndroid Build Coastguard Worker      * The input array should be in RGBA format, where four consecutive bytes form an cell.
753*e1eccf28SAndroid Build Coastguard Worker      * A variant of this method is available to transform a Bitmap.
754*e1eccf28SAndroid Build Coastguard Worker      *
755*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
756*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
757*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY. NOTE: The output Bitmap will still be full size, with the
758*e1eccf28SAndroid Build Coastguard Worker      * section that's not convolved all set to 0. This is to stay compatible with RenderScript.
759*e1eccf28SAndroid Build Coastguard Worker      *
760*e1eccf28SAndroid Build Coastguard Worker      * The source array should be large enough for sizeX * sizeY * vectorSize bytes. The returned
761*e1eccf28SAndroid Build Coastguard Worker      * ray has the same dimensions as the input. The arrays have a row-major layout.
762*e1eccf28SAndroid Build Coastguard Worker      *
763*e1eccf28SAndroid Build Coastguard Worker      * @param inputArray The buffer of the image to be transformed.
764*e1eccf28SAndroid Build Coastguard Worker      * @param sizeX The width of both buffers, as a number of 4 byte cells.
765*e1eccf28SAndroid Build Coastguard Worker      * @param sizeY The height of both buffers, as a number of 4 byte cells.
766*e1eccf28SAndroid Build Coastguard Worker      * @param table The four arrays of 256 values that's used to convert each channel.
767*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
768*e1eccf28SAndroid Build Coastguard Worker      * @return The transformed image.
769*e1eccf28SAndroid Build Coastguard Worker      */
770*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
lutnull771*e1eccf28SAndroid Build Coastguard Worker     fun lut(
772*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
773*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
774*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
775*e1eccf28SAndroid Build Coastguard Worker         table: LookupTable,
776*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
777*e1eccf28SAndroid Build Coastguard Worker     ): ByteArray {
778*e1eccf28SAndroid Build Coastguard Worker         require(inputArray.size >= sizeX * sizeY * 4) {
779*e1eccf28SAndroid Build Coastguard Worker             "$externalName lut. inputArray is too small for the given dimensions. " +
780*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX*$sizeY*4 < ${inputArray.size}."
781*e1eccf28SAndroid Build Coastguard Worker         }
782*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("lut", sizeX, sizeY, restriction)
783*e1eccf28SAndroid Build Coastguard Worker 
784*e1eccf28SAndroid Build Coastguard Worker         val outputArray = ByteArray(inputArray.size)
785*e1eccf28SAndroid Build Coastguard Worker         nativeLut(
786*e1eccf28SAndroid Build Coastguard Worker             nativeHandle,
787*e1eccf28SAndroid Build Coastguard Worker             inputArray,
788*e1eccf28SAndroid Build Coastguard Worker             outputArray,
789*e1eccf28SAndroid Build Coastguard Worker             sizeX,
790*e1eccf28SAndroid Build Coastguard Worker             sizeY,
791*e1eccf28SAndroid Build Coastguard Worker             table.red,
792*e1eccf28SAndroid Build Coastguard Worker             table.green,
793*e1eccf28SAndroid Build Coastguard Worker             table.blue,
794*e1eccf28SAndroid Build Coastguard Worker             table.alpha,
795*e1eccf28SAndroid Build Coastguard Worker             restriction
796*e1eccf28SAndroid Build Coastguard Worker         )
797*e1eccf28SAndroid Build Coastguard Worker         return outputArray
798*e1eccf28SAndroid Build Coastguard Worker     }
799*e1eccf28SAndroid Build Coastguard Worker 
800*e1eccf28SAndroid Build Coastguard Worker     /**
801*e1eccf28SAndroid Build Coastguard Worker      * Transform an image using a look up table
802*e1eccf28SAndroid Build Coastguard Worker      *
803*e1eccf28SAndroid Build Coastguard Worker      * Transforms an image by using a per-channel lookup table. Each channel of the input has an
804*e1eccf28SAndroid Build Coastguard Worker      * independent lookup table. The tables are 256 entries in size and can cover the full value
805*e1eccf28SAndroid Build Coastguard Worker      * range of a byte.
806*e1eccf28SAndroid Build Coastguard Worker      *
807*e1eccf28SAndroid Build Coastguard Worker      * The input Bitmap should be in config ARGB_8888. A variant of this method is available to
808*e1eccf28SAndroid Build Coastguard Worker      * transform a ByteArray. Bitmaps with a stride different than width * vectorSize are not
809*e1eccf28SAndroid Build Coastguard Worker      * currently supported.
810*e1eccf28SAndroid Build Coastguard Worker      *
811*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
812*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
813*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY. NOTE: The output Bitmap will still be full size, with the
814*e1eccf28SAndroid Build Coastguard Worker      * section that's not convolved all set to 0. This is to stay compatible with RenderScript.
815*e1eccf28SAndroid Build Coastguard Worker      *
816*e1eccf28SAndroid Build Coastguard Worker      * @param inputBitmap The buffer of the image to be transformed.
817*e1eccf28SAndroid Build Coastguard Worker      * @param table The four arrays of 256 values that's used to convert each channel.
818*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
819*e1eccf28SAndroid Build Coastguard Worker      * @return The transformed image.
820*e1eccf28SAndroid Build Coastguard Worker      */
821*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
lutnull822*e1eccf28SAndroid Build Coastguard Worker     fun lut(
823*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
824*e1eccf28SAndroid Build Coastguard Worker         table: LookupTable,
825*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
826*e1eccf28SAndroid Build Coastguard Worker     ): Bitmap {
827*e1eccf28SAndroid Build Coastguard Worker         validateBitmap("lut", inputBitmap)
828*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("lut", inputBitmap, restriction)
829*e1eccf28SAndroid Build Coastguard Worker 
830*e1eccf28SAndroid Build Coastguard Worker         val outputBitmap = createCompatibleBitmap(inputBitmap)
831*e1eccf28SAndroid Build Coastguard Worker         nativeLutBitmap(
832*e1eccf28SAndroid Build Coastguard Worker             nativeHandle,
833*e1eccf28SAndroid Build Coastguard Worker             inputBitmap,
834*e1eccf28SAndroid Build Coastguard Worker             outputBitmap,
835*e1eccf28SAndroid Build Coastguard Worker             table.red,
836*e1eccf28SAndroid Build Coastguard Worker             table.green,
837*e1eccf28SAndroid Build Coastguard Worker             table.blue,
838*e1eccf28SAndroid Build Coastguard Worker             table.alpha,
839*e1eccf28SAndroid Build Coastguard Worker             restriction
840*e1eccf28SAndroid Build Coastguard Worker         )
841*e1eccf28SAndroid Build Coastguard Worker         return outputBitmap
842*e1eccf28SAndroid Build Coastguard Worker     }
843*e1eccf28SAndroid Build Coastguard Worker 
844*e1eccf28SAndroid Build Coastguard Worker     /**
845*e1eccf28SAndroid Build Coastguard Worker      * Transform an image using a 3D look up table
846*e1eccf28SAndroid Build Coastguard Worker      *
847*e1eccf28SAndroid Build Coastguard Worker      * Transforms an image, converting RGB to RGBA by using a 3D lookup table. The incoming R, G,
848*e1eccf28SAndroid Build Coastguard Worker      * and B values are normalized to the dimensions of the provided 3D buffer. The eight nearest
849*e1eccf28SAndroid Build Coastguard Worker      * values in that 3D buffer are sampled and linearly interpolated. The resulting RGBA entry
850*e1eccf28SAndroid Build Coastguard Worker      * is returned in the output array.
851*e1eccf28SAndroid Build Coastguard Worker      *
852*e1eccf28SAndroid Build Coastguard Worker      * The input array should be in RGBA format, where four consecutive bytes form an cell.
853*e1eccf28SAndroid Build Coastguard Worker      * The fourth byte of each input cell is ignored. A variant of this method is also available
854*e1eccf28SAndroid Build Coastguard Worker      * to transform Bitmaps.
855*e1eccf28SAndroid Build Coastguard Worker      *
856*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
857*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
858*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY. NOTE: The output array will still be full size, with the
859*e1eccf28SAndroid Build Coastguard Worker      * section that's not convolved all set to 0. This is to stay compatible with RenderScript.
860*e1eccf28SAndroid Build Coastguard Worker      *
861*e1eccf28SAndroid Build Coastguard Worker      * The source array should be large enough for sizeX * sizeY * vectorSize bytes. The returned
862*e1eccf28SAndroid Build Coastguard Worker      * array will have the same dimensions. The arrays have a row-major layout.
863*e1eccf28SAndroid Build Coastguard Worker      *
864*e1eccf28SAndroid Build Coastguard Worker      * @param inputArray The buffer of the image to be transformed.
865*e1eccf28SAndroid Build Coastguard Worker      * @param sizeX The width of both buffers, as a number of 4 byte cells.
866*e1eccf28SAndroid Build Coastguard Worker      * @param sizeY The height of both buffers, as a number of 4 byte cells.
867*e1eccf28SAndroid Build Coastguard Worker      * @param cube The translation cube.
868*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
869*e1eccf28SAndroid Build Coastguard Worker      * @return The transformed image.
870*e1eccf28SAndroid Build Coastguard Worker      */
871*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
lut3dnull872*e1eccf28SAndroid Build Coastguard Worker     fun lut3d(
873*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
874*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
875*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
876*e1eccf28SAndroid Build Coastguard Worker         cube: Rgba3dArray,
877*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
878*e1eccf28SAndroid Build Coastguard Worker     ): ByteArray {
879*e1eccf28SAndroid Build Coastguard Worker         require(inputArray.size >= sizeX * sizeY * 4) {
880*e1eccf28SAndroid Build Coastguard Worker             "$externalName lut3d. inputArray is too small for the given dimensions. " +
881*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX*$sizeY*4 < ${inputArray.size}."
882*e1eccf28SAndroid Build Coastguard Worker         }
883*e1eccf28SAndroid Build Coastguard Worker         require(
884*e1eccf28SAndroid Build Coastguard Worker             cube.sizeX >= 2 && cube.sizeY >= 2 && cube.sizeZ >= 2 &&
885*e1eccf28SAndroid Build Coastguard Worker                     cube.sizeX <= 256 && cube.sizeY <= 256 && cube.sizeZ <= 256
886*e1eccf28SAndroid Build Coastguard Worker         ) {
887*e1eccf28SAndroid Build Coastguard Worker             "$externalName lut3d. The dimensions of the cube should be between 2 and 256. " +
888*e1eccf28SAndroid Build Coastguard Worker                     "(${cube.sizeX}, ${cube.sizeY}, ${cube.sizeZ}) provided."
889*e1eccf28SAndroid Build Coastguard Worker         }
890*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("lut3d", sizeX, sizeY, restriction)
891*e1eccf28SAndroid Build Coastguard Worker 
892*e1eccf28SAndroid Build Coastguard Worker         val outputArray = ByteArray(inputArray.size)
893*e1eccf28SAndroid Build Coastguard Worker         nativeLut3d(
894*e1eccf28SAndroid Build Coastguard Worker             nativeHandle, inputArray, outputArray, sizeX, sizeY, cube.values, cube.sizeX,
895*e1eccf28SAndroid Build Coastguard Worker             cube.sizeY, cube.sizeZ, restriction
896*e1eccf28SAndroid Build Coastguard Worker         )
897*e1eccf28SAndroid Build Coastguard Worker         return outputArray
898*e1eccf28SAndroid Build Coastguard Worker     }
899*e1eccf28SAndroid Build Coastguard Worker 
900*e1eccf28SAndroid Build Coastguard Worker     /**
901*e1eccf28SAndroid Build Coastguard Worker      * Transform an image using a 3D look up table
902*e1eccf28SAndroid Build Coastguard Worker      *
903*e1eccf28SAndroid Build Coastguard Worker      * Transforms an image, converting RGB to RGBA by using a 3D lookup table. The incoming R, G,
904*e1eccf28SAndroid Build Coastguard Worker      * and B values are normalized to the dimensions of the provided 3D buffer. The eight nearest
905*e1eccf28SAndroid Build Coastguard Worker      * values in that 3D buffer are sampled and linearly interpolated. The resulting RGBA entry
906*e1eccf28SAndroid Build Coastguard Worker      * is returned in the output array.
907*e1eccf28SAndroid Build Coastguard Worker      *
908*e1eccf28SAndroid Build Coastguard Worker      * The input bitmap should be in RGBA_8888 format. The A channel is preserved. A variant of this
909*e1eccf28SAndroid Build Coastguard Worker      * method is also available to transform ByteArray. Bitmaps with a stride different than
910*e1eccf28SAndroid Build Coastguard Worker      * width * vectorSize are not currently supported.
911*e1eccf28SAndroid Build Coastguard Worker      *
912*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
913*e1eccf28SAndroid Build Coastguard Worker      * of each buffer. If provided, the range must be wholly contained with the dimensions
914*e1eccf28SAndroid Build Coastguard Worker      * described by sizeX and sizeY. NOTE: The output array will still be full size, with the
915*e1eccf28SAndroid Build Coastguard Worker      * section that's not convolved all set to 0. This is to stay compatible with RenderScript.
916*e1eccf28SAndroid Build Coastguard Worker      *
917*e1eccf28SAndroid Build Coastguard Worker      * The source array should be large enough for sizeX * sizeY * vectorSize bytes. The returned
918*e1eccf28SAndroid Build Coastguard Worker      * array will have the same dimensions. The arrays have a row-major layout.
919*e1eccf28SAndroid Build Coastguard Worker      *
920*e1eccf28SAndroid Build Coastguard Worker      * @param inputBitmap The image to be transformed.
921*e1eccf28SAndroid Build Coastguard Worker      * @param cube The translation cube.
922*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
923*e1eccf28SAndroid Build Coastguard Worker      * @return The transformed image.
924*e1eccf28SAndroid Build Coastguard Worker      */
925*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
lut3dnull926*e1eccf28SAndroid Build Coastguard Worker     fun lut3d(
927*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
928*e1eccf28SAndroid Build Coastguard Worker         cube: Rgba3dArray,
929*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
930*e1eccf28SAndroid Build Coastguard Worker     ): Bitmap {
931*e1eccf28SAndroid Build Coastguard Worker         validateBitmap("lut3d", inputBitmap)
932*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("lut3d", inputBitmap, restriction)
933*e1eccf28SAndroid Build Coastguard Worker 
934*e1eccf28SAndroid Build Coastguard Worker         val outputBitmap = createCompatibleBitmap(inputBitmap)
935*e1eccf28SAndroid Build Coastguard Worker         nativeLut3dBitmap(
936*e1eccf28SAndroid Build Coastguard Worker             nativeHandle, inputBitmap, outputBitmap, cube.values, cube.sizeX,
937*e1eccf28SAndroid Build Coastguard Worker             cube.sizeY, cube.sizeZ, restriction
938*e1eccf28SAndroid Build Coastguard Worker         )
939*e1eccf28SAndroid Build Coastguard Worker         return outputBitmap
940*e1eccf28SAndroid Build Coastguard Worker     }
941*e1eccf28SAndroid Build Coastguard Worker 
942*e1eccf28SAndroid Build Coastguard Worker     /**
943*e1eccf28SAndroid Build Coastguard Worker      * Resize an image.
944*e1eccf28SAndroid Build Coastguard Worker      *
945*e1eccf28SAndroid Build Coastguard Worker      * Resizes an image using bicubic interpolation.
946*e1eccf28SAndroid Build Coastguard Worker      *
947*e1eccf28SAndroid Build Coastguard Worker      * This method supports elements of 1 to 4 bytes in length. Each byte of the element is
948*e1eccf28SAndroid Build Coastguard Worker      * interpolated independently from the others.
949*e1eccf28SAndroid Build Coastguard Worker      *
950*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
951*e1eccf28SAndroid Build Coastguard Worker      * of the output buffer. The corresponding scaled range of the input will be used. If provided,
952*e1eccf28SAndroid Build Coastguard Worker      * the range must be wholly contained with the dimensions described by outputSizeX and
953*e1eccf28SAndroid Build Coastguard Worker      * outputSizeY.
954*e1eccf28SAndroid Build Coastguard Worker      *
955*e1eccf28SAndroid Build Coastguard Worker      * The input and output arrays have a row-major layout. The input array should be
956*e1eccf28SAndroid Build Coastguard Worker      * large enough for sizeX * sizeY * vectorSize bytes.
957*e1eccf28SAndroid Build Coastguard Worker      *
958*e1eccf28SAndroid Build Coastguard Worker      * Like the RenderScript Intrinsics, vectorSize of size 3 are padded to occupy 4 bytes.
959*e1eccf28SAndroid Build Coastguard Worker      *
960*e1eccf28SAndroid Build Coastguard Worker      * @param inputArray The buffer of the image to be resized.
961*e1eccf28SAndroid Build Coastguard Worker      * @param vectorSize The number of bytes in each element of both buffers. A value from 1 to 4.
962*e1eccf28SAndroid Build Coastguard Worker      * @param inputSizeX The width of the input buffer, as a number of 1-4 byte elements.
963*e1eccf28SAndroid Build Coastguard Worker      * @param inputSizeY The height of the input buffer, as a number of 1-4 byte elements.
964*e1eccf28SAndroid Build Coastguard Worker      * @param outputSizeX The width of the output buffer, as a number of 1-4 byte elements.
965*e1eccf28SAndroid Build Coastguard Worker      * @param outputSizeY The height of the output buffer, as a number of 1-4 byte elements.
966*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
967*e1eccf28SAndroid Build Coastguard Worker      * @return An array that contains the rescaled image.
968*e1eccf28SAndroid Build Coastguard Worker      */
969*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
resizenull970*e1eccf28SAndroid Build Coastguard Worker     fun resize(
971*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
972*e1eccf28SAndroid Build Coastguard Worker         vectorSize: Int,
973*e1eccf28SAndroid Build Coastguard Worker         inputSizeX: Int,
974*e1eccf28SAndroid Build Coastguard Worker         inputSizeY: Int,
975*e1eccf28SAndroid Build Coastguard Worker         outputSizeX: Int,
976*e1eccf28SAndroid Build Coastguard Worker         outputSizeY: Int,
977*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
978*e1eccf28SAndroid Build Coastguard Worker     ): ByteArray {
979*e1eccf28SAndroid Build Coastguard Worker         require(vectorSize in 1..4) {
980*e1eccf28SAndroid Build Coastguard Worker             "$externalName resize. The vectorSize should be between 1 and 4. $vectorSize provided."
981*e1eccf28SAndroid Build Coastguard Worker         }
982*e1eccf28SAndroid Build Coastguard Worker         require(inputArray.size >= inputSizeX * inputSizeY * vectorSize) {
983*e1eccf28SAndroid Build Coastguard Worker             "$externalName resize. inputArray is too small for the given dimensions. " +
984*e1eccf28SAndroid Build Coastguard Worker                     "$inputSizeX*$inputSizeY*$vectorSize < ${inputArray.size}."
985*e1eccf28SAndroid Build Coastguard Worker         }
986*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("resize", outputSizeX, outputSizeY, restriction)
987*e1eccf28SAndroid Build Coastguard Worker 
988*e1eccf28SAndroid Build Coastguard Worker         val outputArray = ByteArray(outputSizeX * outputSizeY * paddedSize(vectorSize))
989*e1eccf28SAndroid Build Coastguard Worker         nativeResize(
990*e1eccf28SAndroid Build Coastguard Worker             nativeHandle,
991*e1eccf28SAndroid Build Coastguard Worker             inputArray,
992*e1eccf28SAndroid Build Coastguard Worker             vectorSize,
993*e1eccf28SAndroid Build Coastguard Worker             inputSizeX,
994*e1eccf28SAndroid Build Coastguard Worker             inputSizeY,
995*e1eccf28SAndroid Build Coastguard Worker             outputArray,
996*e1eccf28SAndroid Build Coastguard Worker             outputSizeX,
997*e1eccf28SAndroid Build Coastguard Worker             outputSizeY,
998*e1eccf28SAndroid Build Coastguard Worker             restriction
999*e1eccf28SAndroid Build Coastguard Worker         )
1000*e1eccf28SAndroid Build Coastguard Worker         return outputArray
1001*e1eccf28SAndroid Build Coastguard Worker     }
1002*e1eccf28SAndroid Build Coastguard Worker 
1003*e1eccf28SAndroid Build Coastguard Worker     /**
1004*e1eccf28SAndroid Build Coastguard Worker      * Resize an image.
1005*e1eccf28SAndroid Build Coastguard Worker      *
1006*e1eccf28SAndroid Build Coastguard Worker      * Resizes an image using bicubic interpolation.
1007*e1eccf28SAndroid Build Coastguard Worker      *
1008*e1eccf28SAndroid Build Coastguard Worker      * This method supports input Bitmap of config ARGB_8888 and ALPHA_8. The returned Bitmap
1009*e1eccf28SAndroid Build Coastguard Worker      * has the same config. Bitmaps with a stride different than width * vectorSize are not
1010*e1eccf28SAndroid Build Coastguard Worker      * currently supported.
1011*e1eccf28SAndroid Build Coastguard Worker      *
1012*e1eccf28SAndroid Build Coastguard Worker      * An optional range parameter can be set to restrict the operation to a rectangular subset
1013*e1eccf28SAndroid Build Coastguard Worker      * of the output buffer. The corresponding scaled range of the input will be used. If provided,
1014*e1eccf28SAndroid Build Coastguard Worker      * the range must be wholly contained with the dimensions described by outputSizeX and
1015*e1eccf28SAndroid Build Coastguard Worker      * outputSizeY.
1016*e1eccf28SAndroid Build Coastguard Worker      *
1017*e1eccf28SAndroid Build Coastguard Worker      * @param inputBitmap The Bitmap to be resized.
1018*e1eccf28SAndroid Build Coastguard Worker      * @param outputSizeX The width of the output buffer, as a number of 1-4 byte elements.
1019*e1eccf28SAndroid Build Coastguard Worker      * @param outputSizeY The height of the output buffer, as a number of 1-4 byte elements.
1020*e1eccf28SAndroid Build Coastguard Worker      * @param restriction When not null, restricts the operation to a 2D range of pixels.
1021*e1eccf28SAndroid Build Coastguard Worker      * @return A Bitmap that contains the rescaled image.
1022*e1eccf28SAndroid Build Coastguard Worker      */
1023*e1eccf28SAndroid Build Coastguard Worker     @JvmOverloads
resizenull1024*e1eccf28SAndroid Build Coastguard Worker     fun resize(
1025*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
1026*e1eccf28SAndroid Build Coastguard Worker         outputSizeX: Int,
1027*e1eccf28SAndroid Build Coastguard Worker         outputSizeY: Int,
1028*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d? = null
1029*e1eccf28SAndroid Build Coastguard Worker     ): Bitmap {
1030*e1eccf28SAndroid Build Coastguard Worker         validateBitmap("resize", inputBitmap)
1031*e1eccf28SAndroid Build Coastguard Worker         validateRestriction("resize", outputSizeX, outputSizeY, restriction)
1032*e1eccf28SAndroid Build Coastguard Worker 
1033*e1eccf28SAndroid Build Coastguard Worker         val outputBitmap = Bitmap.createBitmap(outputSizeX, outputSizeY, Bitmap.Config.ARGB_8888)
1034*e1eccf28SAndroid Build Coastguard Worker         nativeResizeBitmap(nativeHandle, inputBitmap, outputBitmap, restriction)
1035*e1eccf28SAndroid Build Coastguard Worker         return outputBitmap
1036*e1eccf28SAndroid Build Coastguard Worker     }
1037*e1eccf28SAndroid Build Coastguard Worker 
1038*e1eccf28SAndroid Build Coastguard Worker     /**
1039*e1eccf28SAndroid Build Coastguard Worker      * Convert an image from YUV to RGB.
1040*e1eccf28SAndroid Build Coastguard Worker      *
1041*e1eccf28SAndroid Build Coastguard Worker      * Converts a YUV buffer to RGB. The input array should be supplied in a supported YUV format.
1042*e1eccf28SAndroid Build Coastguard Worker      * The output is RGBA; the alpha channel will be set to 255.
1043*e1eccf28SAndroid Build Coastguard Worker      *
1044*e1eccf28SAndroid Build Coastguard Worker      * Note that for YV12 and a sizeX that's not a multiple of 32, the RenderScript Intrinsic may
1045*e1eccf28SAndroid Build Coastguard Worker      * not have converted the image correctly. This Toolkit method should.
1046*e1eccf28SAndroid Build Coastguard Worker      *
1047*e1eccf28SAndroid Build Coastguard Worker      * @param inputArray The buffer of the image to be converted.
1048*e1eccf28SAndroid Build Coastguard Worker      * @param sizeX The width in pixels of the image.
1049*e1eccf28SAndroid Build Coastguard Worker      * @param sizeY The height in pixels of the image.
1050*e1eccf28SAndroid Build Coastguard Worker      * @param format Either YV12 or NV21.
1051*e1eccf28SAndroid Build Coastguard Worker      * @return The converted image as a byte array.
1052*e1eccf28SAndroid Build Coastguard Worker      */
yuvToRgbnull1053*e1eccf28SAndroid Build Coastguard Worker     fun yuvToRgb(inputArray: ByteArray, sizeX: Int, sizeY: Int, format: YuvFormat): ByteArray {
1054*e1eccf28SAndroid Build Coastguard Worker         require(sizeX % 2 == 0 && sizeY % 2 == 0) {
1055*e1eccf28SAndroid Build Coastguard Worker             "$externalName yuvToRgb. Non-even dimensions are not supported. " +
1056*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX and $sizeY were provided."
1057*e1eccf28SAndroid Build Coastguard Worker         }
1058*e1eccf28SAndroid Build Coastguard Worker 
1059*e1eccf28SAndroid Build Coastguard Worker         val outputArray = ByteArray(sizeX * sizeY * 4)
1060*e1eccf28SAndroid Build Coastguard Worker         nativeYuvToRgb(nativeHandle, inputArray, outputArray, sizeX, sizeY, format.value)
1061*e1eccf28SAndroid Build Coastguard Worker         return outputArray
1062*e1eccf28SAndroid Build Coastguard Worker     }
1063*e1eccf28SAndroid Build Coastguard Worker 
1064*e1eccf28SAndroid Build Coastguard Worker     /**
1065*e1eccf28SAndroid Build Coastguard Worker      * Convert an image from YUV to an RGB Bitmap.
1066*e1eccf28SAndroid Build Coastguard Worker      *
1067*e1eccf28SAndroid Build Coastguard Worker      * Converts a YUV buffer to an RGB Bitmap. The input array should be supplied in a supported
1068*e1eccf28SAndroid Build Coastguard Worker      * YUV format. The output is RGBA; the alpha channel will be set to 255.
1069*e1eccf28SAndroid Build Coastguard Worker      *
1070*e1eccf28SAndroid Build Coastguard Worker      * Note that for YV12 and a sizeX that's not a multiple of 32, the RenderScript Intrinsic may
1071*e1eccf28SAndroid Build Coastguard Worker      * not have converted the image correctly. This Toolkit method should.
1072*e1eccf28SAndroid Build Coastguard Worker      *
1073*e1eccf28SAndroid Build Coastguard Worker      * @param inputArray The buffer of the image to be converted.
1074*e1eccf28SAndroid Build Coastguard Worker      * @param sizeX The width in pixels of the image.
1075*e1eccf28SAndroid Build Coastguard Worker      * @param sizeY The height in pixels of the image.
1076*e1eccf28SAndroid Build Coastguard Worker      * @param format Either YV12 or NV21.
1077*e1eccf28SAndroid Build Coastguard Worker      * @return The converted image.
1078*e1eccf28SAndroid Build Coastguard Worker      */
yuvToRgbBitmapnull1079*e1eccf28SAndroid Build Coastguard Worker     fun yuvToRgbBitmap(inputArray: ByteArray, sizeX: Int, sizeY: Int, format: YuvFormat): Bitmap {
1080*e1eccf28SAndroid Build Coastguard Worker         require(sizeX % 2 == 0 && sizeY % 2 == 0) {
1081*e1eccf28SAndroid Build Coastguard Worker             "$externalName yuvToRgbBitmap. Non-even dimensions are not supported. " +
1082*e1eccf28SAndroid Build Coastguard Worker                     "$sizeX and $sizeY were provided."
1083*e1eccf28SAndroid Build Coastguard Worker         }
1084*e1eccf28SAndroid Build Coastguard Worker 
1085*e1eccf28SAndroid Build Coastguard Worker         val outputBitmap = Bitmap.createBitmap(sizeX, sizeY, Bitmap.Config.ARGB_8888)
1086*e1eccf28SAndroid Build Coastguard Worker         nativeYuvToRgbBitmap(nativeHandle, inputArray, sizeX, sizeY, outputBitmap, format.value)
1087*e1eccf28SAndroid Build Coastguard Worker         return outputBitmap
1088*e1eccf28SAndroid Build Coastguard Worker     }
1089*e1eccf28SAndroid Build Coastguard Worker 
1090*e1eccf28SAndroid Build Coastguard Worker     init {
1091*e1eccf28SAndroid Build Coastguard Worker         System.loadLibrary("renderscript-toolkit")
1092*e1eccf28SAndroid Build Coastguard Worker         nativeHandle = createNative()
1093*e1eccf28SAndroid Build Coastguard Worker     }
1094*e1eccf28SAndroid Build Coastguard Worker 
1095*e1eccf28SAndroid Build Coastguard Worker     /**
1096*e1eccf28SAndroid Build Coastguard Worker      * Shutdown the thread pool.
1097*e1eccf28SAndroid Build Coastguard Worker      *
1098*e1eccf28SAndroid Build Coastguard Worker      * Waits for the threads to complete their work and destroys them.
1099*e1eccf28SAndroid Build Coastguard Worker      *
1100*e1eccf28SAndroid Build Coastguard Worker      * An application should call this method only if it is sure that it won't call the
1101*e1eccf28SAndroid Build Coastguard Worker      * toolkit again, as it is irreversible.
1102*e1eccf28SAndroid Build Coastguard Worker      */
shutdownnull1103*e1eccf28SAndroid Build Coastguard Worker     fun shutdown() {
1104*e1eccf28SAndroid Build Coastguard Worker         destroyNative(nativeHandle)
1105*e1eccf28SAndroid Build Coastguard Worker         nativeHandle = 0
1106*e1eccf28SAndroid Build Coastguard Worker     }
1107*e1eccf28SAndroid Build Coastguard Worker 
1108*e1eccf28SAndroid Build Coastguard Worker     private var nativeHandle: Long = 0
1109*e1eccf28SAndroid Build Coastguard Worker 
createNativenull1110*e1eccf28SAndroid Build Coastguard Worker     private external fun createNative(): Long
1111*e1eccf28SAndroid Build Coastguard Worker 
1112*e1eccf28SAndroid Build Coastguard Worker     private external fun destroyNative(nativeHandle: Long)
1113*e1eccf28SAndroid Build Coastguard Worker 
1114*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeBlend(
1115*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1116*e1eccf28SAndroid Build Coastguard Worker         mode: Int,
1117*e1eccf28SAndroid Build Coastguard Worker         sourceArray: ByteArray,
1118*e1eccf28SAndroid Build Coastguard Worker         destArray: ByteArray,
1119*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
1120*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
1121*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1122*e1eccf28SAndroid Build Coastguard Worker     )
1123*e1eccf28SAndroid Build Coastguard Worker 
1124*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeBlendBitmap(
1125*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1126*e1eccf28SAndroid Build Coastguard Worker         mode: Int,
1127*e1eccf28SAndroid Build Coastguard Worker         sourceBitmap: Bitmap,
1128*e1eccf28SAndroid Build Coastguard Worker         destBitmap: Bitmap,
1129*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1130*e1eccf28SAndroid Build Coastguard Worker     )
1131*e1eccf28SAndroid Build Coastguard Worker 
1132*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeBlur(
1133*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1134*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
1135*e1eccf28SAndroid Build Coastguard Worker         vectorSize: Int,
1136*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
1137*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
1138*e1eccf28SAndroid Build Coastguard Worker         radius: Int,
1139*e1eccf28SAndroid Build Coastguard Worker         outputArray: ByteArray,
1140*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1141*e1eccf28SAndroid Build Coastguard Worker     )
1142*e1eccf28SAndroid Build Coastguard Worker 
1143*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeBlurBitmap(
1144*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1145*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
1146*e1eccf28SAndroid Build Coastguard Worker         outputBitmap: Bitmap,
1147*e1eccf28SAndroid Build Coastguard Worker         radius: Int,
1148*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1149*e1eccf28SAndroid Build Coastguard Worker     )
1150*e1eccf28SAndroid Build Coastguard Worker 
1151*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeColorMatrix(
1152*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1153*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
1154*e1eccf28SAndroid Build Coastguard Worker         inputVectorSize: Int,
1155*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
1156*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
1157*e1eccf28SAndroid Build Coastguard Worker         outputArray: ByteArray,
1158*e1eccf28SAndroid Build Coastguard Worker         outputVectorSize: Int,
1159*e1eccf28SAndroid Build Coastguard Worker         matrix: FloatArray,
1160*e1eccf28SAndroid Build Coastguard Worker         addVector: FloatArray,
1161*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1162*e1eccf28SAndroid Build Coastguard Worker     )
1163*e1eccf28SAndroid Build Coastguard Worker 
1164*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeColorMatrixBitmap(
1165*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1166*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
1167*e1eccf28SAndroid Build Coastguard Worker         outputBitmap: Bitmap,
1168*e1eccf28SAndroid Build Coastguard Worker         matrix: FloatArray,
1169*e1eccf28SAndroid Build Coastguard Worker         addVector: FloatArray,
1170*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1171*e1eccf28SAndroid Build Coastguard Worker     )
1172*e1eccf28SAndroid Build Coastguard Worker 
1173*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeConvolve(
1174*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1175*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
1176*e1eccf28SAndroid Build Coastguard Worker         vectorSize: Int,
1177*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
1178*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
1179*e1eccf28SAndroid Build Coastguard Worker         outputArray: ByteArray,
1180*e1eccf28SAndroid Build Coastguard Worker         coefficients: FloatArray,
1181*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1182*e1eccf28SAndroid Build Coastguard Worker     )
1183*e1eccf28SAndroid Build Coastguard Worker 
1184*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeConvolveBitmap(
1185*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1186*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
1187*e1eccf28SAndroid Build Coastguard Worker         outputBitmap: Bitmap,
1188*e1eccf28SAndroid Build Coastguard Worker         coefficients: FloatArray,
1189*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1190*e1eccf28SAndroid Build Coastguard Worker     )
1191*e1eccf28SAndroid Build Coastguard Worker 
1192*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeHistogram(
1193*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1194*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
1195*e1eccf28SAndroid Build Coastguard Worker         vectorSize: Int,
1196*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
1197*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
1198*e1eccf28SAndroid Build Coastguard Worker         outputArray: IntArray,
1199*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1200*e1eccf28SAndroid Build Coastguard Worker     )
1201*e1eccf28SAndroid Build Coastguard Worker 
1202*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeHistogramBitmap(
1203*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1204*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
1205*e1eccf28SAndroid Build Coastguard Worker         outputArray: IntArray,
1206*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1207*e1eccf28SAndroid Build Coastguard Worker     )
1208*e1eccf28SAndroid Build Coastguard Worker 
1209*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeHistogramDot(
1210*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1211*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
1212*e1eccf28SAndroid Build Coastguard Worker         vectorSize: Int,
1213*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
1214*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
1215*e1eccf28SAndroid Build Coastguard Worker         outputArray: IntArray,
1216*e1eccf28SAndroid Build Coastguard Worker         coefficients: FloatArray,
1217*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1218*e1eccf28SAndroid Build Coastguard Worker     )
1219*e1eccf28SAndroid Build Coastguard Worker 
1220*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeHistogramDotBitmap(
1221*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1222*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
1223*e1eccf28SAndroid Build Coastguard Worker         outputArray: IntArray,
1224*e1eccf28SAndroid Build Coastguard Worker         coefficients: FloatArray,
1225*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1226*e1eccf28SAndroid Build Coastguard Worker     )
1227*e1eccf28SAndroid Build Coastguard Worker 
1228*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeLut(
1229*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1230*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
1231*e1eccf28SAndroid Build Coastguard Worker         outputArray: ByteArray,
1232*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
1233*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
1234*e1eccf28SAndroid Build Coastguard Worker         red: ByteArray,
1235*e1eccf28SAndroid Build Coastguard Worker         green: ByteArray,
1236*e1eccf28SAndroid Build Coastguard Worker         blue: ByteArray,
1237*e1eccf28SAndroid Build Coastguard Worker         alpha: ByteArray,
1238*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1239*e1eccf28SAndroid Build Coastguard Worker     )
1240*e1eccf28SAndroid Build Coastguard Worker 
1241*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeLutBitmap(
1242*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1243*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
1244*e1eccf28SAndroid Build Coastguard Worker         outputBitmap: Bitmap,
1245*e1eccf28SAndroid Build Coastguard Worker         red: ByteArray,
1246*e1eccf28SAndroid Build Coastguard Worker         green: ByteArray,
1247*e1eccf28SAndroid Build Coastguard Worker         blue: ByteArray,
1248*e1eccf28SAndroid Build Coastguard Worker         alpha: ByteArray,
1249*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1250*e1eccf28SAndroid Build Coastguard Worker     )
1251*e1eccf28SAndroid Build Coastguard Worker 
1252*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeLut3d(
1253*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1254*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
1255*e1eccf28SAndroid Build Coastguard Worker         outputArray: ByteArray,
1256*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
1257*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
1258*e1eccf28SAndroid Build Coastguard Worker         cube: ByteArray,
1259*e1eccf28SAndroid Build Coastguard Worker         cubeSizeX: Int,
1260*e1eccf28SAndroid Build Coastguard Worker         cubeSizeY: Int,
1261*e1eccf28SAndroid Build Coastguard Worker         cubeSizeZ: Int,
1262*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1263*e1eccf28SAndroid Build Coastguard Worker     )
1264*e1eccf28SAndroid Build Coastguard Worker 
1265*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeLut3dBitmap(
1266*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1267*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
1268*e1eccf28SAndroid Build Coastguard Worker         outputBitmap: Bitmap,
1269*e1eccf28SAndroid Build Coastguard Worker         cube: ByteArray,
1270*e1eccf28SAndroid Build Coastguard Worker         cubeSizeX: Int,
1271*e1eccf28SAndroid Build Coastguard Worker         cubeSizeY: Int,
1272*e1eccf28SAndroid Build Coastguard Worker         cubeSizeZ: Int,
1273*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1274*e1eccf28SAndroid Build Coastguard Worker     )
1275*e1eccf28SAndroid Build Coastguard Worker 
1276*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeResize(
1277*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1278*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
1279*e1eccf28SAndroid Build Coastguard Worker         vectorSize: Int,
1280*e1eccf28SAndroid Build Coastguard Worker         inputSizeX: Int,
1281*e1eccf28SAndroid Build Coastguard Worker         inputSizeY: Int,
1282*e1eccf28SAndroid Build Coastguard Worker         outputArray: ByteArray,
1283*e1eccf28SAndroid Build Coastguard Worker         outputSizeX: Int,
1284*e1eccf28SAndroid Build Coastguard Worker         outputSizeY: Int,
1285*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1286*e1eccf28SAndroid Build Coastguard Worker     )
1287*e1eccf28SAndroid Build Coastguard Worker 
1288*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeResizeBitmap(
1289*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1290*e1eccf28SAndroid Build Coastguard Worker         inputBitmap: Bitmap,
1291*e1eccf28SAndroid Build Coastguard Worker         outputBitmap: Bitmap,
1292*e1eccf28SAndroid Build Coastguard Worker         restriction: Range2d?
1293*e1eccf28SAndroid Build Coastguard Worker     )
1294*e1eccf28SAndroid Build Coastguard Worker 
1295*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeYuvToRgb(
1296*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1297*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
1298*e1eccf28SAndroid Build Coastguard Worker         outputArray: ByteArray,
1299*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
1300*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
1301*e1eccf28SAndroid Build Coastguard Worker         format: Int
1302*e1eccf28SAndroid Build Coastguard Worker     )
1303*e1eccf28SAndroid Build Coastguard Worker 
1304*e1eccf28SAndroid Build Coastguard Worker     private external fun nativeYuvToRgbBitmap(
1305*e1eccf28SAndroid Build Coastguard Worker         nativeHandle: Long,
1306*e1eccf28SAndroid Build Coastguard Worker         inputArray: ByteArray,
1307*e1eccf28SAndroid Build Coastguard Worker         sizeX: Int,
1308*e1eccf28SAndroid Build Coastguard Worker         sizeY: Int,
1309*e1eccf28SAndroid Build Coastguard Worker         outputBitmap: Bitmap,
1310*e1eccf28SAndroid Build Coastguard Worker         value: Int
1311*e1eccf28SAndroid Build Coastguard Worker     )
1312*e1eccf28SAndroid Build Coastguard Worker }
1313*e1eccf28SAndroid Build Coastguard Worker 
1314*e1eccf28SAndroid Build Coastguard Worker /**
1315*e1eccf28SAndroid Build Coastguard Worker  * Determines how a source buffer is blended into a destination buffer.
1316*e1eccf28SAndroid Build Coastguard Worker  * See {@link RenderScriptToolkit::blend}.
1317*e1eccf28SAndroid Build Coastguard Worker  *
1318*e1eccf28SAndroid Build Coastguard Worker  * blend only works on 4 byte RGBA data. In the descriptions below, ".a" represents
1319*e1eccf28SAndroid Build Coastguard Worker  * the alpha channel.
1320*e1eccf28SAndroid Build Coastguard Worker  */
1321*e1eccf28SAndroid Build Coastguard Worker enum class BlendingMode(val value: Int) {
1322*e1eccf28SAndroid Build Coastguard Worker     /**
1323*e1eccf28SAndroid Build Coastguard Worker      * dest = 0
1324*e1eccf28SAndroid Build Coastguard Worker      *
1325*e1eccf28SAndroid Build Coastguard Worker      * The destination is cleared, i.e. each pixel is set to (0, 0, 0, 0)
1326*e1eccf28SAndroid Build Coastguard Worker      */
1327*e1eccf28SAndroid Build Coastguard Worker     CLEAR(0),
1328*e1eccf28SAndroid Build Coastguard Worker 
1329*e1eccf28SAndroid Build Coastguard Worker     /**
1330*e1eccf28SAndroid Build Coastguard Worker      * dest = src
1331*e1eccf28SAndroid Build Coastguard Worker      *
1332*e1eccf28SAndroid Build Coastguard Worker      * Sets each pixel of the destination to the corresponding one in the source.
1333*e1eccf28SAndroid Build Coastguard Worker      */
1334*e1eccf28SAndroid Build Coastguard Worker     SRC(1),
1335*e1eccf28SAndroid Build Coastguard Worker 
1336*e1eccf28SAndroid Build Coastguard Worker     /**
1337*e1eccf28SAndroid Build Coastguard Worker      * dest = dest
1338*e1eccf28SAndroid Build Coastguard Worker      *
1339*e1eccf28SAndroid Build Coastguard Worker      * Leaves the destination untouched. This is a no-op.
1340*e1eccf28SAndroid Build Coastguard Worker      */
1341*e1eccf28SAndroid Build Coastguard Worker     DST(2),
1342*e1eccf28SAndroid Build Coastguard Worker 
1343*e1eccf28SAndroid Build Coastguard Worker     /**
1344*e1eccf28SAndroid Build Coastguard Worker      * dest = src + dest * (1.0 - src.a)
1345*e1eccf28SAndroid Build Coastguard Worker      */
1346*e1eccf28SAndroid Build Coastguard Worker     SRC_OVER(3),
1347*e1eccf28SAndroid Build Coastguard Worker 
1348*e1eccf28SAndroid Build Coastguard Worker     /**
1349*e1eccf28SAndroid Build Coastguard Worker      * dest = dest + src * (1.0 - dest.a)
1350*e1eccf28SAndroid Build Coastguard Worker      */
1351*e1eccf28SAndroid Build Coastguard Worker     DST_OVER(4),
1352*e1eccf28SAndroid Build Coastguard Worker 
1353*e1eccf28SAndroid Build Coastguard Worker     /**
1354*e1eccf28SAndroid Build Coastguard Worker      * dest = src * dest.a
1355*e1eccf28SAndroid Build Coastguard Worker      */
1356*e1eccf28SAndroid Build Coastguard Worker     SRC_IN(5),
1357*e1eccf28SAndroid Build Coastguard Worker 
1358*e1eccf28SAndroid Build Coastguard Worker     /**
1359*e1eccf28SAndroid Build Coastguard Worker      * dest = dest * src.a
1360*e1eccf28SAndroid Build Coastguard Worker      */
1361*e1eccf28SAndroid Build Coastguard Worker     DST_IN(6),
1362*e1eccf28SAndroid Build Coastguard Worker 
1363*e1eccf28SAndroid Build Coastguard Worker     /**
1364*e1eccf28SAndroid Build Coastguard Worker      * dest = src * (1.0 - dest.a)
1365*e1eccf28SAndroid Build Coastguard Worker      */
1366*e1eccf28SAndroid Build Coastguard Worker     SRC_OUT(7),
1367*e1eccf28SAndroid Build Coastguard Worker 
1368*e1eccf28SAndroid Build Coastguard Worker     /**
1369*e1eccf28SAndroid Build Coastguard Worker      * dest = dest * (1.0 - src.a)
1370*e1eccf28SAndroid Build Coastguard Worker      */
1371*e1eccf28SAndroid Build Coastguard Worker     DST_OUT(8),
1372*e1eccf28SAndroid Build Coastguard Worker 
1373*e1eccf28SAndroid Build Coastguard Worker     /**
1374*e1eccf28SAndroid Build Coastguard Worker      * dest.rgb = src.rgb * dest.a + (1.0 - src.a) * dest.rgb, dest.a = dest.a
1375*e1eccf28SAndroid Build Coastguard Worker      */
1376*e1eccf28SAndroid Build Coastguard Worker     SRC_ATOP(9),
1377*e1eccf28SAndroid Build Coastguard Worker 
1378*e1eccf28SAndroid Build Coastguard Worker     /**
1379*e1eccf28SAndroid Build Coastguard Worker      * dest = dest.rgb * src.a + (1.0 - dest.a) * src.rgb, dest.a = src.a
1380*e1eccf28SAndroid Build Coastguard Worker      */
1381*e1eccf28SAndroid Build Coastguard Worker     DST_ATOP(10),
1382*e1eccf28SAndroid Build Coastguard Worker 
1383*e1eccf28SAndroid Build Coastguard Worker     /**
1384*e1eccf28SAndroid Build Coastguard Worker      * dest = {src.r ^ dest.r, src.g ^ dest.g, src.b ^ dest.b, src.a ^ dest.a}
1385*e1eccf28SAndroid Build Coastguard Worker      *
1386*e1eccf28SAndroid Build Coastguard Worker      * Note: this is NOT the Porter/Duff XOR mode; this is a bitwise xor.
1387*e1eccf28SAndroid Build Coastguard Worker      */
1388*e1eccf28SAndroid Build Coastguard Worker     XOR(11),
1389*e1eccf28SAndroid Build Coastguard Worker 
1390*e1eccf28SAndroid Build Coastguard Worker     /**
1391*e1eccf28SAndroid Build Coastguard Worker      * dest = src * dest
1392*e1eccf28SAndroid Build Coastguard Worker      */
1393*e1eccf28SAndroid Build Coastguard Worker     MULTIPLY(12),
1394*e1eccf28SAndroid Build Coastguard Worker 
1395*e1eccf28SAndroid Build Coastguard Worker     /**
1396*e1eccf28SAndroid Build Coastguard Worker      * dest = min(src + dest, 1.0)
1397*e1eccf28SAndroid Build Coastguard Worker      */
1398*e1eccf28SAndroid Build Coastguard Worker     ADD(13),
1399*e1eccf28SAndroid Build Coastguard Worker 
1400*e1eccf28SAndroid Build Coastguard Worker     /**
1401*e1eccf28SAndroid Build Coastguard Worker      * dest = max(dest - src, 0.0)
1402*e1eccf28SAndroid Build Coastguard Worker      */
1403*e1eccf28SAndroid Build Coastguard Worker     SUBTRACT(14)
1404*e1eccf28SAndroid Build Coastguard Worker }
1405*e1eccf28SAndroid Build Coastguard Worker 
1406*e1eccf28SAndroid Build Coastguard Worker /**
1407*e1eccf28SAndroid Build Coastguard Worker  * A translation table used by the lut method. For each potential red, green, blue, and alpha
1408*e1eccf28SAndroid Build Coastguard Worker  * value, specifies it's replacement value.
1409*e1eccf28SAndroid Build Coastguard Worker  *
1410*e1eccf28SAndroid Build Coastguard Worker  * The fields are initialized to be a no-op operation, i.e. replace 1 by 1, 2 by 2, etc.
1411*e1eccf28SAndroid Build Coastguard Worker  * You can modify just the values you're interested in having a translation.
1412*e1eccf28SAndroid Build Coastguard Worker  */
1413*e1eccf28SAndroid Build Coastguard Worker class LookupTable {
<lambda>null1414*e1eccf28SAndroid Build Coastguard Worker     var red = ByteArray(256) { it.toByte() }
<lambda>null1415*e1eccf28SAndroid Build Coastguard Worker     var green = ByteArray(256) { it.toByte() }
<lambda>null1416*e1eccf28SAndroid Build Coastguard Worker     var blue = ByteArray(256) { it.toByte() }
<lambda>null1417*e1eccf28SAndroid Build Coastguard Worker     var alpha = ByteArray(256) { it.toByte() }
1418*e1eccf28SAndroid Build Coastguard Worker }
1419*e1eccf28SAndroid Build Coastguard Worker 
1420*e1eccf28SAndroid Build Coastguard Worker /**
1421*e1eccf28SAndroid Build Coastguard Worker  * The YUV formats supported by yuvToRgb.
1422*e1eccf28SAndroid Build Coastguard Worker  */
1423*e1eccf28SAndroid Build Coastguard Worker enum class YuvFormat(val value: Int) {
1424*e1eccf28SAndroid Build Coastguard Worker     NV21(0x11),
1425*e1eccf28SAndroid Build Coastguard Worker     YV12(0x32315659),
1426*e1eccf28SAndroid Build Coastguard Worker }
1427*e1eccf28SAndroid Build Coastguard Worker 
1428*e1eccf28SAndroid Build Coastguard Worker /**
1429*e1eccf28SAndroid Build Coastguard Worker  * Define a range of data to process.
1430*e1eccf28SAndroid Build Coastguard Worker  *
1431*e1eccf28SAndroid Build Coastguard Worker  * This class is used to restrict a [Toolkit] operation to a rectangular subset of the input
1432*e1eccf28SAndroid Build Coastguard Worker  * tensor.
1433*e1eccf28SAndroid Build Coastguard Worker  *
1434*e1eccf28SAndroid Build Coastguard Worker  * @property startX The index of the first value to be included on the X axis.
1435*e1eccf28SAndroid Build Coastguard Worker  * @property endX The index after the last value to be included on the X axis.
1436*e1eccf28SAndroid Build Coastguard Worker  * @property startY The index of the first value to be included on the Y axis.
1437*e1eccf28SAndroid Build Coastguard Worker  * @property endY The index after the last value to be included on the Y axis.
1438*e1eccf28SAndroid Build Coastguard Worker  */
1439*e1eccf28SAndroid Build Coastguard Worker data class Range2d(
1440*e1eccf28SAndroid Build Coastguard Worker     val startX: Int,
1441*e1eccf28SAndroid Build Coastguard Worker     val endX: Int,
1442*e1eccf28SAndroid Build Coastguard Worker     val startY: Int,
1443*e1eccf28SAndroid Build Coastguard Worker     val endY: Int
1444*e1eccf28SAndroid Build Coastguard Worker ) {
1445*e1eccf28SAndroid Build Coastguard Worker     constructor() : this(0, 0, 0, 0)
1446*e1eccf28SAndroid Build Coastguard Worker }
1447*e1eccf28SAndroid Build Coastguard Worker 
1448*e1eccf28SAndroid Build Coastguard Worker class Rgba3dArray(val values: ByteArray, val sizeX: Int, val sizeY: Int, val sizeZ: Int) {
1449*e1eccf28SAndroid Build Coastguard Worker     init {
1450*e1eccf28SAndroid Build Coastguard Worker         require(values.size >= sizeX * sizeY * sizeZ * 4)
1451*e1eccf28SAndroid Build Coastguard Worker     }
1452*e1eccf28SAndroid Build Coastguard Worker 
getnull1453*e1eccf28SAndroid Build Coastguard Worker     operator fun get(x: Int, y: Int, z: Int): ByteArray {
1454*e1eccf28SAndroid Build Coastguard Worker         val index = indexOfVector(x, y, z)
1455*e1eccf28SAndroid Build Coastguard Worker         return ByteArray(4) { values[index + it] }
1456*e1eccf28SAndroid Build Coastguard Worker     }
1457*e1eccf28SAndroid Build Coastguard Worker 
setnull1458*e1eccf28SAndroid Build Coastguard Worker     operator fun set(x: Int, y: Int, z: Int, value: ByteArray) {
1459*e1eccf28SAndroid Build Coastguard Worker         require(value.size == 4)
1460*e1eccf28SAndroid Build Coastguard Worker         val index = indexOfVector(x, y, z)
1461*e1eccf28SAndroid Build Coastguard Worker         for (i in 0..3) {
1462*e1eccf28SAndroid Build Coastguard Worker             values[index + i] = value[i]
1463*e1eccf28SAndroid Build Coastguard Worker         }
1464*e1eccf28SAndroid Build Coastguard Worker     }
1465*e1eccf28SAndroid Build Coastguard Worker 
indexOfVectornull1466*e1eccf28SAndroid Build Coastguard Worker     private fun indexOfVector(x: Int, y: Int, z: Int): Int {
1467*e1eccf28SAndroid Build Coastguard Worker         require(x in 0 until sizeX)
1468*e1eccf28SAndroid Build Coastguard Worker         require(y in 0 until sizeY)
1469*e1eccf28SAndroid Build Coastguard Worker         require(z in 0 until sizeZ)
1470*e1eccf28SAndroid Build Coastguard Worker         return ((z * sizeY + y) * sizeX + x) * 4
1471*e1eccf28SAndroid Build Coastguard Worker     }
1472*e1eccf28SAndroid Build Coastguard Worker }
1473*e1eccf28SAndroid Build Coastguard Worker 
validateBitmapnull1474*e1eccf28SAndroid Build Coastguard Worker internal fun validateBitmap(
1475*e1eccf28SAndroid Build Coastguard Worker     function: String,
1476*e1eccf28SAndroid Build Coastguard Worker     inputBitmap: Bitmap,
1477*e1eccf28SAndroid Build Coastguard Worker     alphaAllowed: Boolean = true
1478*e1eccf28SAndroid Build Coastguard Worker ) {
1479*e1eccf28SAndroid Build Coastguard Worker     if (alphaAllowed) {
1480*e1eccf28SAndroid Build Coastguard Worker         require(
1481*e1eccf28SAndroid Build Coastguard Worker             inputBitmap.config == Bitmap.Config.ARGB_8888 ||
1482*e1eccf28SAndroid Build Coastguard Worker                     inputBitmap.config == Bitmap.Config.ALPHA_8
1483*e1eccf28SAndroid Build Coastguard Worker         ) {
1484*e1eccf28SAndroid Build Coastguard Worker             "$externalName. $function supports only ARGB_8888 and ALPHA_8 bitmaps. " +
1485*e1eccf28SAndroid Build Coastguard Worker                     "${inputBitmap.config} provided."
1486*e1eccf28SAndroid Build Coastguard Worker         }
1487*e1eccf28SAndroid Build Coastguard Worker     } else {
1488*e1eccf28SAndroid Build Coastguard Worker         require(inputBitmap.config == Bitmap.Config.ARGB_8888) {
1489*e1eccf28SAndroid Build Coastguard Worker             "$externalName. $function supports only ARGB_8888. " +
1490*e1eccf28SAndroid Build Coastguard Worker                     "${inputBitmap.config} provided."
1491*e1eccf28SAndroid Build Coastguard Worker         }
1492*e1eccf28SAndroid Build Coastguard Worker     }
1493*e1eccf28SAndroid Build Coastguard Worker     require(inputBitmap.width * vectorSize(inputBitmap) == inputBitmap.rowBytes) {
1494*e1eccf28SAndroid Build Coastguard Worker         "$externalName $function. Only bitmaps with rowSize equal to the width * vectorSize are " +
1495*e1eccf28SAndroid Build Coastguard Worker                 "currently supported. Provided were rowBytes=${inputBitmap.rowBytes}, " +
1496*e1eccf28SAndroid Build Coastguard Worker                 "width={${inputBitmap.width}, and vectorSize=${vectorSize(inputBitmap)}."
1497*e1eccf28SAndroid Build Coastguard Worker     }
1498*e1eccf28SAndroid Build Coastguard Worker }
1499*e1eccf28SAndroid Build Coastguard Worker 
createCompatibleBitmapnull1500*e1eccf28SAndroid Build Coastguard Worker internal fun createCompatibleBitmap(inputBitmap: Bitmap) =
1501*e1eccf28SAndroid Build Coastguard Worker     Bitmap.createBitmap(inputBitmap.width, inputBitmap.height, inputBitmap.config)
1502*e1eccf28SAndroid Build Coastguard Worker 
1503*e1eccf28SAndroid Build Coastguard Worker internal fun validateHistogramDotCoefficients(
1504*e1eccf28SAndroid Build Coastguard Worker     coefficients: FloatArray?,
1505*e1eccf28SAndroid Build Coastguard Worker     vectorSize: Int
1506*e1eccf28SAndroid Build Coastguard Worker ) {
1507*e1eccf28SAndroid Build Coastguard Worker     require(coefficients == null || coefficients.size == vectorSize) {
1508*e1eccf28SAndroid Build Coastguard Worker         "$externalName histogramDot. The coefficients should be null or have $vectorSize values."
1509*e1eccf28SAndroid Build Coastguard Worker     }
1510*e1eccf28SAndroid Build Coastguard Worker     if (coefficients !== null) {
1511*e1eccf28SAndroid Build Coastguard Worker         var sum = 0f
1512*e1eccf28SAndroid Build Coastguard Worker         for (i in 0 until vectorSize) {
1513*e1eccf28SAndroid Build Coastguard Worker             require(coefficients[i] >= 0.0f) {
1514*e1eccf28SAndroid Build Coastguard Worker                 "$externalName histogramDot. Coefficients should not be negative. " +
1515*e1eccf28SAndroid Build Coastguard Worker                         "Coefficient $i was ${coefficients[i]}."
1516*e1eccf28SAndroid Build Coastguard Worker             }
1517*e1eccf28SAndroid Build Coastguard Worker             sum += coefficients[i]
1518*e1eccf28SAndroid Build Coastguard Worker         }
1519*e1eccf28SAndroid Build Coastguard Worker         require(sum <= 1.0f) {
1520*e1eccf28SAndroid Build Coastguard Worker             "$externalName histogramDot. Coefficients should add to 1 or less. Their sum is $sum."
1521*e1eccf28SAndroid Build Coastguard Worker         }
1522*e1eccf28SAndroid Build Coastguard Worker     }
1523*e1eccf28SAndroid Build Coastguard Worker }
1524*e1eccf28SAndroid Build Coastguard Worker 
validateRestrictionnull1525*e1eccf28SAndroid Build Coastguard Worker internal fun validateRestriction(tag: String, bitmap: Bitmap, restriction: Range2d? = null) {
1526*e1eccf28SAndroid Build Coastguard Worker     validateRestriction(tag, bitmap.width, bitmap.height, restriction)
1527*e1eccf28SAndroid Build Coastguard Worker }
1528*e1eccf28SAndroid Build Coastguard Worker 
validateRestrictionnull1529*e1eccf28SAndroid Build Coastguard Worker internal fun validateRestriction(
1530*e1eccf28SAndroid Build Coastguard Worker     tag: String,
1531*e1eccf28SAndroid Build Coastguard Worker     sizeX: Int,
1532*e1eccf28SAndroid Build Coastguard Worker     sizeY: Int,
1533*e1eccf28SAndroid Build Coastguard Worker     restriction: Range2d? = null
1534*e1eccf28SAndroid Build Coastguard Worker ) {
1535*e1eccf28SAndroid Build Coastguard Worker     if (restriction == null) return
1536*e1eccf28SAndroid Build Coastguard Worker     require(restriction.startX < sizeX && restriction.endX <= sizeX) {
1537*e1eccf28SAndroid Build Coastguard Worker         "$externalName $tag. sizeX should be greater than restriction.startX and greater " +
1538*e1eccf28SAndroid Build Coastguard Worker                 "or equal to restriction.endX. $sizeX, ${restriction.startX}, " +
1539*e1eccf28SAndroid Build Coastguard Worker                 "and ${restriction.endX} were provided respectively."
1540*e1eccf28SAndroid Build Coastguard Worker     }
1541*e1eccf28SAndroid Build Coastguard Worker     require(restriction.startY < sizeY && restriction.endY <= sizeY) {
1542*e1eccf28SAndroid Build Coastguard Worker         "$externalName $tag. sizeY should be greater than restriction.startY and greater " +
1543*e1eccf28SAndroid Build Coastguard Worker                 "or equal to restriction.endY. $sizeY, ${restriction.startY}, " +
1544*e1eccf28SAndroid Build Coastguard Worker                 "and ${restriction.endY} were provided respectively."
1545*e1eccf28SAndroid Build Coastguard Worker     }
1546*e1eccf28SAndroid Build Coastguard Worker     require(restriction.startX < restriction.endX) {
1547*e1eccf28SAndroid Build Coastguard Worker         "$externalName $tag. Restriction startX should be less than endX. " +
1548*e1eccf28SAndroid Build Coastguard Worker                 "${restriction.startX} and ${restriction.endX} were provided respectively."
1549*e1eccf28SAndroid Build Coastguard Worker     }
1550*e1eccf28SAndroid Build Coastguard Worker     require(restriction.startY < restriction.endY) {
1551*e1eccf28SAndroid Build Coastguard Worker         "$externalName $tag. Restriction startY should be less than endY. " +
1552*e1eccf28SAndroid Build Coastguard Worker                 "${restriction.startY} and ${restriction.endY} were provided respectively."
1553*e1eccf28SAndroid Build Coastguard Worker     }
1554*e1eccf28SAndroid Build Coastguard Worker }
1555*e1eccf28SAndroid Build Coastguard Worker 
vectorSizenull1556*e1eccf28SAndroid Build Coastguard Worker internal fun vectorSize(bitmap: Bitmap): Int {
1557*e1eccf28SAndroid Build Coastguard Worker     return when (bitmap.config) {
1558*e1eccf28SAndroid Build Coastguard Worker         Bitmap.Config.ARGB_8888 -> 4
1559*e1eccf28SAndroid Build Coastguard Worker         Bitmap.Config.ALPHA_8 -> 1
1560*e1eccf28SAndroid Build Coastguard Worker         else -> throw IllegalArgumentException(
1561*e1eccf28SAndroid Build Coastguard Worker             "$externalName. Only ARGB_8888 and ALPHA_8 Bitmap are supported."
1562*e1eccf28SAndroid Build Coastguard Worker         )
1563*e1eccf28SAndroid Build Coastguard Worker     }
1564*e1eccf28SAndroid Build Coastguard Worker }
1565*e1eccf28SAndroid Build Coastguard Worker 
paddedSizenull1566*e1eccf28SAndroid Build Coastguard Worker internal fun paddedSize(vectorSize: Int) = if (vectorSize == 3) 4 else vectorSize
1567