xref: /aosp_15_r20/frameworks/rs/toolkit/test/ReferenceBlend.kt (revision e1eccf28f96817838ad6867f7f39d2351ec11f56)
1*e1eccf28SAndroid Build Coastguard Worker /*
<lambda>null2*e1eccf28SAndroid Build Coastguard Worker  * Copyright (C) 2021 The Android Open Source Project
3*e1eccf28SAndroid Build Coastguard Worker  *
4*e1eccf28SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*e1eccf28SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*e1eccf28SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*e1eccf28SAndroid Build Coastguard Worker  *
8*e1eccf28SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*e1eccf28SAndroid Build Coastguard Worker  *
10*e1eccf28SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*e1eccf28SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*e1eccf28SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e1eccf28SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*e1eccf28SAndroid Build Coastguard Worker  * limitations under the License.
15*e1eccf28SAndroid Build Coastguard Worker  */
16*e1eccf28SAndroid Build Coastguard Worker 
17*e1eccf28SAndroid Build Coastguard Worker package com.example.testapp
18*e1eccf28SAndroid Build Coastguard Worker 
19*e1eccf28SAndroid Build Coastguard Worker import android.renderscript.toolkit.BlendingMode
20*e1eccf28SAndroid Build Coastguard Worker import android.renderscript.toolkit.Range2d
21*e1eccf28SAndroid Build Coastguard Worker 
22*e1eccf28SAndroid Build Coastguard Worker /**
23*e1eccf28SAndroid Build Coastguard Worker  * Reference implementation of a Blend operation.
24*e1eccf28SAndroid Build Coastguard Worker  *
25*e1eccf28SAndroid Build Coastguard Worker  * See the class Rgba for details of arithmetic operation using that class.
26*e1eccf28SAndroid Build Coastguard Worker  */
27*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes
28*e1eccf28SAndroid Build Coastguard Worker fun referenceBlend(
29*e1eccf28SAndroid Build Coastguard Worker     mode: BlendingMode,
30*e1eccf28SAndroid Build Coastguard Worker     sourceArray: ByteArray,
31*e1eccf28SAndroid Build Coastguard Worker     destArray: ByteArray,
32*e1eccf28SAndroid Build Coastguard Worker     sizeX: Int,
33*e1eccf28SAndroid Build Coastguard Worker     sizeY: Int,
34*e1eccf28SAndroid Build Coastguard Worker     restriction: Range2d?
35*e1eccf28SAndroid Build Coastguard Worker ) {
36*e1eccf28SAndroid Build Coastguard Worker     val source = Rgba2dArray(sourceArray, sizeX, sizeY)
37*e1eccf28SAndroid Build Coastguard Worker     val dest = Rgba2dArray(destArray, sizeX, sizeY)
38*e1eccf28SAndroid Build Coastguard Worker 
39*e1eccf28SAndroid Build Coastguard Worker     /**
40*e1eccf28SAndroid Build Coastguard Worker      * For each corresponding RGBA value of the source and destination arrays, invoke the blend
41*e1eccf28SAndroid Build Coastguard Worker      * function and store the result in the destination array.
42*e1eccf28SAndroid Build Coastguard Worker      */
43*e1eccf28SAndroid Build Coastguard Worker     fun blendEachPair(blendFunction: (src: Rgba, dst: Rgba) -> Rgba) {
44*e1eccf28SAndroid Build Coastguard Worker         dest.forEachCell(restriction) { x, y ->
45*e1eccf28SAndroid Build Coastguard Worker             dest[x, y] = blendFunction(source[x, y], dest[x, y])
46*e1eccf28SAndroid Build Coastguard Worker         }
47*e1eccf28SAndroid Build Coastguard Worker     }
48*e1eccf28SAndroid Build Coastguard Worker 
49*e1eccf28SAndroid Build Coastguard Worker     when (mode) {
50*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.CLEAR -> blendEachPair { _, _ -> Rgba(0, 0, 0, 0) }
51*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.SRC -> blendEachPair { src, _ -> src }
52*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.DST -> { /* This doesn't do anything. */ }
53*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.SRC_OVER -> blendEachPair { src, dst -> blendOver(src, dst) }
54*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.DST_OVER -> blendEachPair { src, dst -> blendOver(dst, src) }
55*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.SRC_IN -> blendEachPair { src, dst -> blendIn(src, dst) }
56*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.DST_IN -> blendEachPair { src, dst -> blendIn(dst, src) }
57*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.SRC_OUT -> blendEachPair { src, dst -> blendOut(src, dst) }
58*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.DST_OUT -> blendEachPair { src, dst -> blendOut(dst, src) }
59*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.SRC_ATOP -> blendEachPair { src, dst -> blendAtop(src, dst) }
60*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.DST_ATOP -> blendEachPair { src, dst -> blendAtop(dst, src) }
61*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.XOR -> blendEachPair { src, dst -> src xor dst }
62*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.MULTIPLY -> blendEachPair { src, dst -> src * dst }
63*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.ADD -> blendEachPair { src, dst -> dst + src }
64*e1eccf28SAndroid Build Coastguard Worker         BlendingMode.SUBTRACT -> blendEachPair { src, dst -> dst - src }
65*e1eccf28SAndroid Build Coastguard Worker     }
66*e1eccf28SAndroid Build Coastguard Worker }
67*e1eccf28SAndroid Build Coastguard Worker 
68*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes
blendOvernull69*e1eccf28SAndroid Build Coastguard Worker private fun blendOver(src: Rgba, dst: Rgba) = src + (dst * (255 - src.a))
70*e1eccf28SAndroid Build Coastguard Worker 
71*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes
72*e1eccf28SAndroid Build Coastguard Worker private fun blendIn(src: Rgba, dst: Rgba) = src * dst.a
73*e1eccf28SAndroid Build Coastguard Worker 
74*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes
75*e1eccf28SAndroid Build Coastguard Worker private fun blendOut(src: Rgba, dst: Rgba) = src * (255 - dst.a)
76*e1eccf28SAndroid Build Coastguard Worker 
77*e1eccf28SAndroid Build Coastguard Worker @ExperimentalUnsignedTypes
78*e1eccf28SAndroid Build Coastguard Worker private fun blendAtop(src: Rgba, dst: Rgba): Rgba {
79*e1eccf28SAndroid Build Coastguard Worker     val value = src * dst.a + dst * (255 - src.a)
80*e1eccf28SAndroid Build Coastguard Worker     value.a = dst.a
81*e1eccf28SAndroid Build Coastguard Worker     return value
82*e1eccf28SAndroid Build Coastguard Worker }
83