diff options
author | 2023-02-14 19:40:20 -0500 | |
---|---|---|
committer | 2023-02-15 13:22:17 -0500 | |
commit | 9f85cd3b709a420933a53bee50cb3ce50efda491 (patch) | |
tree | 7967c43e7bbfb34f40d889257f63414d7b6e6b9e | |
parent | 01472127c059b8dc8c7a2cd15b7e515d47a5a758 (diff) |
SilkFX HDR demos
Test: this
Bug: 266628247
Change-Id: Ib41de2de8634e03dd6f7f6b3909e4e109793fa31
24 files changed, 868 insertions, 24 deletions
diff --git a/libs/hwui/effects/GainmapRenderer.cpp b/libs/hwui/effects/GainmapRenderer.cpp index a544ae88f9be..8977d3ce4da3 100644 --- a/libs/hwui/effects/GainmapRenderer.cpp +++ b/libs/hwui/effects/GainmapRenderer.cpp @@ -48,10 +48,7 @@ void DrawGainmapBitmap(SkCanvas* c, const sk_sp<const SkImage>& image, const SkR gainmapSrc.fRight *= sX; gainmapSrc.fTop *= sY; gainmapSrc.fBottom *= sY; - // TODO: Temporary workaround for SkGainmapShader::Make not having a const variant - sk_sp<SkImage> mutImage = sk_ref_sp(const_cast<SkImage*>(image.get())); - sk_sp<SkImage> mutGainmap = sk_ref_sp(const_cast<SkImage*>(gainmapImage.get())); - auto shader = SkGainmapShader::Make(mutImage, src, sampling, mutGainmap, gainmapSrc, + auto shader = SkGainmapShader::Make(image, src, sampling, gainmapImage, gainmapSrc, sampling, gainmapInfo, dst, targetSdrHdrRatio, c->imageInfo().refColorSpace()); gainmapPaint.setShader(shader); diff --git a/tests/SilkFX/Android.bp b/tests/SilkFX/Android.bp index 088d9a2d7f41..1e467db44545 100644 --- a/tests/SilkFX/Android.bp +++ b/tests/SilkFX/Android.bp @@ -25,13 +25,17 @@ package { android_test { name: "SilkFX", - srcs: ["**/*.java", "**/*.kt"], + srcs: [ + "**/*.java", + "**/*.kt", + ], platform_apis: true, certificate: "platform", - static_libs: [ + static_libs: [ "androidx.core_core", "androidx.appcompat_appcompat", "com.google.android.material_material", "androidx-constraintlayout_constraintlayout", + "subsampling-scale-image-view", ], } diff --git a/tests/SilkFX/AndroidManifest.xml b/tests/SilkFX/AndroidManifest.xml index 21256d8c9d0b..1b8e08bd009f 100644 --- a/tests/SilkFX/AndroidManifest.xml +++ b/tests/SilkFX/AndroidManifest.xml @@ -55,5 +55,15 @@ android:exported="true"> </activity> + <activity android:name=".app.HdrImageViewer" + android:label="HDR Gainmap Image Viewer" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="image/*"/> + </intent-filter> + </activity> + </application> </manifest> diff --git a/tests/SilkFX/assets/gainmaps/cave.jpg b/tests/SilkFX/assets/gainmaps/cave.jpg Binary files differnew file mode 100644 index 000000000000..fa7d3fc325d5 --- /dev/null +++ b/tests/SilkFX/assets/gainmaps/cave.jpg diff --git a/tests/SilkFX/res/drawable-nodpi/blue_sweep_gradient.xml b/tests/SilkFX/res/drawable-nodpi/blue_sweep_gradient.xml new file mode 100644 index 000000000000..c183c5deab4f --- /dev/null +++ b/tests/SilkFX/res/drawable-nodpi/blue_sweep_gradient.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <gradient + android:startColor="#000000" + android:endColor="#0000FF" + android:angle="0"/> +</shape>
\ No newline at end of file diff --git a/tests/SilkFX/res/drawable-nodpi/dark_gradient.xml b/tests/SilkFX/res/drawable-nodpi/dark_gradient.xml new file mode 100644 index 000000000000..d2653d0de0d4 --- /dev/null +++ b/tests/SilkFX/res/drawable-nodpi/dark_gradient.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <gradient + android:startColor="#000000" + android:endColor="#181818" + android:angle="0"/> +</shape>
\ No newline at end of file diff --git a/tests/SilkFX/res/drawable-nodpi/green_sweep_gradient.xml b/tests/SilkFX/res/drawable-nodpi/green_sweep_gradient.xml new file mode 100644 index 000000000000..c600d0f66325 --- /dev/null +++ b/tests/SilkFX/res/drawable-nodpi/green_sweep_gradient.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <gradient + android:startColor="#000000" + android:endColor="#00FF00" + android:angle="0"/> +</shape>
\ No newline at end of file diff --git a/tests/SilkFX/res/drawable-nodpi/grey_sweep_gradient.xml b/tests/SilkFX/res/drawable-nodpi/grey_sweep_gradient.xml new file mode 100644 index 000000000000..d0c17fa2e1b9 --- /dev/null +++ b/tests/SilkFX/res/drawable-nodpi/grey_sweep_gradient.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <gradient + android:startColor="#000000" + android:endColor="#FFFFFF" + android:angle="0"/> +</shape>
\ No newline at end of file diff --git a/tests/SilkFX/res/drawable-nodpi/light_gradient.xml b/tests/SilkFX/res/drawable-nodpi/light_gradient.xml new file mode 100644 index 000000000000..c75f925647e7 --- /dev/null +++ b/tests/SilkFX/res/drawable-nodpi/light_gradient.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <gradient + android:startColor="#E8E8E8" + android:endColor="#FFFFFF" + android:angle="0"/> +</shape>
\ No newline at end of file diff --git a/tests/SilkFX/res/drawable-nodpi/red_sweep_gradient.xml b/tests/SilkFX/res/drawable-nodpi/red_sweep_gradient.xml new file mode 100644 index 000000000000..e3b834a46406 --- /dev/null +++ b/tests/SilkFX/res/drawable-nodpi/red_sweep_gradient.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <gradient + android:startColor="#000000" + android:endColor="#FF0000" + android:angle="0"/> +</shape>
\ No newline at end of file diff --git a/tests/SilkFX/res/layout/color_grid.xml b/tests/SilkFX/res/layout/color_grid.xml new file mode 100644 index 000000000000..37242eee7195 --- /dev/null +++ b/tests/SilkFX/res/layout/color_grid.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<com.android.test.silkfx.hdr.ColorGrid xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" /> diff --git a/tests/SilkFX/res/layout/common_base.xml b/tests/SilkFX/res/layout/common_base.xml index 944c6846fbf7..c0eaf9bc1476 100644 --- a/tests/SilkFX/res/layout/common_base.xml +++ b/tests/SilkFX/res/layout/common_base.xml @@ -24,16 +24,6 @@ <FrameLayout android:id="@+id/demo_container" android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - <View - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" /> - - <com.android.test.silkfx.common.HDRIndicator - android:layout_width="match_parent" - android:layout_height="50dp" - android:layout_margin="8dp" /> + android:layout_height="match_parent" /> </LinearLayout>
\ No newline at end of file diff --git a/tests/SilkFX/res/layout/gainmap_decode_test.xml b/tests/SilkFX/res/layout/gainmap_decode_test.xml new file mode 100644 index 000000000000..e7ef61f8dac1 --- /dev/null +++ b/tests/SilkFX/res/layout/gainmap_decode_test.xml @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<com.android.test.silkfx.hdr.GainmapDecodeTest xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <Button + android:id="@+id/decode_full" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Decode full" /> + + <Button + android:id="@+id/decode_subsampled4" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Decode subsampled (1/4th)" /> + + <Button + android:id="@+id/decode_scaled66" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Decode scaled (66%)" /> + + <Button + android:id="@+id/decode_crop" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Decode croppedSquare" /> + + <Button + android:id="@+id/decode_cropScaled33" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="Decode croppedSquare(33%)" /> + + </LinearLayout> + + <TextView + android:id="@+id/source_info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal"> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:orientation="vertical" + android:layout_weight="1"> + + <TextView + android:id="@+id/sdr_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <ImageView + android:id="@+id/sdr_source" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_margin="8dp" + android:scaleType="fitStart" /> + </LinearLayout> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:orientation="vertical" + android:layout_weight="1"> + + <TextView + android:id="@+id/gainmap_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <ImageView + android:id="@+id/gainmap" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_margin="8dp" + android:scaleType="fitStart" /> + </LinearLayout> + + </LinearLayout> + +</com.android.test.silkfx.hdr.GainmapDecodeTest>
\ No newline at end of file diff --git a/tests/SilkFX/res/layout/gainmap_image.xml b/tests/SilkFX/res/layout/gainmap_image.xml new file mode 100644 index 000000000000..89bbb709d0bf --- /dev/null +++ b/tests/SilkFX/res/layout/gainmap_image.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<com.android.test.silkfx.hdr.GainmapImage xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:id="@+id/gainmap_image"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <RadioGroup android:id="@+id/output_mode" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <RadioButton android:id="@+id/output_sdr" + android:layout_width="wrap_content" + android:layout_weight="1" + android:layout_height="wrap_content" + android:text="SDR original" /> + + <RadioButton android:id="@+id/output_gainmap" + android:layout_width="wrap_content" + android:layout_weight="1" + android:layout_height="wrap_content" + android:text="Gainmap" /> + + <RadioButton android:id="@+id/output_hdr" + android:layout_width="wrap_content" + android:layout_weight="1" + android:layout_height="wrap_content" + android:text="HDR (sdr+gainmap)" /> + </RadioGroup> + + <Spinner + android:id="@+id/image_selection" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + <TextView + android:id="@+id/error_msg" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" /> + + <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView + android:id="@+id/image" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + + </LinearLayout> + +</com.android.test.silkfx.hdr.GainmapImage>
\ No newline at end of file diff --git a/tests/SilkFX/res/layout/gradient_sweep.xml b/tests/SilkFX/res/layout/gradient_sweep.xml new file mode 100644 index 000000000000..261022a40380 --- /dev/null +++ b/tests/SilkFX/res/layout/gradient_sweep.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <View android:background="@drawable/dark_gradient" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + + <View android:background="@drawable/light_gradient" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + + <View android:background="@drawable/grey_sweep_gradient" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + + <View android:background="@drawable/red_sweep_gradient" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + + <View android:background="@drawable/green_sweep_gradient" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + + <View android:background="@drawable/blue_sweep_gradient" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> + +</LinearLayout>
\ No newline at end of file diff --git a/tests/SilkFX/res/layout/hdr_image_viewer.xml b/tests/SilkFX/res/layout/hdr_image_viewer.xml new file mode 100644 index 000000000000..9816430cd915 --- /dev/null +++ b/tests/SilkFX/res/layout/hdr_image_viewer.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <include layout="@layout/color_mode_controls" /> + <include layout="@layout/gainmap_image" /> + +</LinearLayout>
\ No newline at end of file diff --git a/tests/SilkFX/src/com/android/test/silkfx/Main.kt b/tests/SilkFX/src/com/android/test/silkfx/Main.kt index 7132ae8772ea..a6cdbb9865bc 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/Main.kt +++ b/tests/SilkFX/src/com/android/test/silkfx/Main.kt @@ -26,6 +26,7 @@ import android.widget.BaseExpandableListAdapter import android.widget.ExpandableListView import android.widget.TextView import com.android.test.silkfx.app.CommonDemoActivity +import com.android.test.silkfx.app.EXTRA_COMMON_CONTROLS import com.android.test.silkfx.app.EXTRA_LAYOUT import com.android.test.silkfx.app.EXTRA_TITLE import com.android.test.silkfx.hdr.GlowActivity @@ -37,10 +38,11 @@ class Demo(val name: String, val makeIntent: (Context) -> Intent) { constructor(name: String, activity: KClass<out Activity>) : this(name, { context -> Intent(context, activity.java) }) - constructor(name: String, layout: Int) : this(name, { context -> + constructor(name: String, layout: Int, commonControls: Boolean = true) : this(name, { context -> Intent(context, CommonDemoActivity::class.java).apply { putExtra(EXTRA_LAYOUT, layout) putExtra(EXTRA_TITLE, name) + putExtra(EXTRA_COMMON_CONTROLS, commonControls) } }) } @@ -49,7 +51,11 @@ data class DemoGroup(val groupName: String, val demos: List<Demo>) private val AllDemos = listOf( DemoGroup("HDR", listOf( Demo("Glow", GlowActivity::class), - Demo("Blingy Notifications", R.layout.bling_notifications) + Demo("Blingy Notifications", R.layout.bling_notifications), + Demo("Color Grid", R.layout.color_grid), + Demo("Gradient Sweep", R.layout.gradient_sweep), + Demo("Gainmap Image", R.layout.gainmap_image), + Demo("Gainmap Decode Test", R.layout.gainmap_decode_test, commonControls = false) )), DemoGroup("Materials", listOf( Demo("Glass", GlassActivity::class), diff --git a/tests/SilkFX/src/com/android/test/silkfx/app/CommonDemoActivity.kt b/tests/SilkFX/src/com/android/test/silkfx/app/CommonDemoActivity.kt index e0a0a20bc0a0..e56ce40463f4 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/app/CommonDemoActivity.kt +++ b/tests/SilkFX/src/com/android/test/silkfx/app/CommonDemoActivity.kt @@ -22,6 +22,7 @@ import android.view.LayoutInflater const val EXTRA_LAYOUT = "layout" const val EXTRA_TITLE = "title" +const val EXTRA_COMMON_CONTROLS = "common_controls" class CommonDemoActivity : BaseDemoActivity() { @@ -38,8 +39,13 @@ class CommonDemoActivity : BaseDemoActivity() { val title = extras.getString(EXTRA_TITLE, "SilkFX") window.setTitle(title) - setContentView(R.layout.common_base) + if (extras.getBoolean(EXTRA_COMMON_CONTROLS, true)) { + setContentView(R.layout.common_base) + LayoutInflater.from(this).inflate(layout, findViewById(R.id.demo_container), true) + } else { + setContentView(layout) + } + actionBar?.title = title - LayoutInflater.from(this).inflate(layout, findViewById(R.id.demo_container), true) } }
\ No newline at end of file diff --git a/tests/SilkFX/src/com/android/test/silkfx/app/HdrImageViewer.kt b/tests/SilkFX/src/com/android/test/silkfx/app/HdrImageViewer.kt new file mode 100644 index 000000000000..f16f0e474db4 --- /dev/null +++ b/tests/SilkFX/src/com/android/test/silkfx/app/HdrImageViewer.kt @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.silkfx.app + +import android.content.Intent +import android.graphics.ImageDecoder +import android.os.Bundle +import com.android.test.silkfx.R +import com.android.test.silkfx.hdr.GainmapImage + +class HdrImageViewer : BaseDemoActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.hdr_image_viewer) + + val intent = this.intent ?: return finish() + if (Intent.ACTION_VIEW != intent.action) { + finish() + return + } + + val data = intent.data ?: return finish() + + val source = ImageDecoder.createSource(contentResolver, data) + findViewById<GainmapImage>(R.id.gainmap_image)!!.setImageSource(source) + } +}
\ No newline at end of file diff --git a/tests/SilkFX/src/com/android/test/silkfx/common/BaseDrawingView.kt b/tests/SilkFX/src/com/android/test/silkfx/common/BaseDrawingView.kt index 4b85953a24b9..f88e6b01483b 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/common/BaseDrawingView.kt +++ b/tests/SilkFX/src/com/android/test/silkfx/common/BaseDrawingView.kt @@ -23,8 +23,11 @@ import android.util.AttributeSet import android.view.View open class BaseDrawingView : View { + val sRGB = ColorSpace.get(ColorSpace.Named.SRGB) + val displayP3 = ColorSpace.get(ColorSpace.Named.DISPLAY_P3) val scRGB = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB) val bt2020 = ColorSpace.get(ColorSpace.Named.BT2020) + val bt2020_pq = ColorSpace.get(ColorSpace.Named.BT2020_PQ) val lab = ColorSpace.get(ColorSpace.Named.CIE_LAB) val density: Float diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/ColorGrid.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/ColorGrid.kt new file mode 100644 index 000000000000..6920f832333f --- /dev/null +++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/ColorGrid.kt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.silkfx.hdr + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.ColorSpace +import android.graphics.Paint +import android.graphics.Rect +import android.util.AttributeSet +import com.android.test.silkfx.common.BaseDrawingView + +class ColorGrid(context: Context, attrs: AttributeSet?) : BaseDrawingView(context, attrs) { + + init { + isClickable = true + setOnClickListener { + invalidate() + } + } + + fun toMaxColor(color: Int, colorspace: ColorSpace): Long { + val red = (Color.red(color) / 255f) * colorspace.getMaxValue(0) + val green = (Color.green(color) / 255f) * colorspace.getMaxValue(1) + val blue = (Color.blue(color) / 255f) * colorspace.getMaxValue(2) + val alpha = Color.alpha(color) / 255f + return Color.pack(red, green, blue, alpha, colorspace) + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + + val paint = Paint() + paint.isDither = true + paint.isAntiAlias = true + paint.textSize = 18.dp() + paint.textAlign = Paint.Align.LEFT + + val labels = arrayOf("sRGB", "Display P3", "BT2020_PQ", "scRGB(max)") + val colorSpaces = arrayOf(sRGB, displayP3, bt2020_pq, scRGB) + + val colWidth = width / colorSpaces.size.toFloat() + val rowHeight = minOf((height - 20.dp()) / 4f, colWidth) + + val dest = Rect(0, 0, rowHeight.toInt(), colWidth.toInt()) + + for (colIndex in labels.indices) { + canvas.save() + canvas.translate(colIndex * colWidth, 20.dp()) + + paint.color = Color.WHITE + canvas.drawText(labels[colIndex], 0f, 1f, paint) + + arrayOf(Color.WHITE, Color.RED, Color.BLUE, Color.GREEN).forEach { + paint.setColor(toMaxColor(it, colorSpaces[colIndex])) + canvas.drawRect(dest, paint) + canvas.translate(0f, rowHeight) + } + canvas.restore() + } + } +}
\ No newline at end of file diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt new file mode 100644 index 000000000000..db812ace0d85 --- /dev/null +++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapDecodeTest.kt @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.silkfx.hdr + +import android.content.Context +import android.graphics.ImageDecoder +import android.graphics.Rect +import android.util.AttributeSet +import android.widget.Button +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.TextView +import com.android.test.silkfx.R + +enum class DecodeMode { + Full, + Subsampled4, + Scaled66, + CropedSquared, + CropedSquaredScaled33 +} + +class GainmapDecodeTest(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { + + private fun decode(mode: DecodeMode) { + val source = ImageDecoder.createSource(resources.assets, + "gainmaps/cave.jpg") + + val sourceInfo = findViewById<TextView>(R.id.source_info)!! + + val gainmapImage = ImageDecoder.decodeBitmap(source) { decoder, info, source -> + decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE + sourceInfo.text = + "Original size ${info.size.width}x${info.size.height}; mime-type = ${info.mimeType}" + + when (mode) { + DecodeMode.Full -> {} + DecodeMode.Subsampled4 -> { + decoder.setTargetSampleSize(4) + } + DecodeMode.Scaled66 -> { + val size = info.size + decoder.setTargetSize((size.width * .66).toInt(), (size.height * .66).toInt()) + } + DecodeMode.CropedSquared -> { + val dimen = minOf(info.size.width, info.size.height) + decoder.crop = Rect(50, 50, dimen - 100, dimen - 100) + } + DecodeMode.CropedSquaredScaled33 -> { + val size = info.size + val targetWidth = (size.width * .33).toInt() + val targetHeight = (size.height * .33).toInt() + decoder.setTargetSize(targetWidth, targetHeight) + val dimen = minOf(targetWidth, targetHeight) + decoder.crop = Rect(50, 50, dimen - 100, dimen - 100) + } + } + } + + val gainmapContents = gainmapImage.gainmap!!.gainmapContents!! + val sdrBitmap = gainmapImage.also { it.gainmap = null } + + findViewById<ImageView>(R.id.sdr_source)!!.setImageBitmap(sdrBitmap) + findViewById<TextView>(R.id.sdr_label)!!.text = + "SDR Size: ${sdrBitmap.width}x${sdrBitmap.height}" + + findViewById<ImageView>(R.id.gainmap)!!.setImageBitmap(gainmapContents) + findViewById<TextView>(R.id.gainmap_label)!!.text = + "Gainmap Size: ${gainmapContents.width}x${gainmapContents.height}" + } + + override fun onFinishInflate() { + super.onFinishInflate() + decode(DecodeMode.Full) + + findViewById<Button>(R.id.decode_full)!!.setOnClickListener { + decode(DecodeMode.Full) + } + findViewById<Button>(R.id.decode_subsampled4)!!.setOnClickListener { + decode(DecodeMode.Subsampled4) + } + findViewById<Button>(R.id.decode_scaled66)!!.setOnClickListener { + decode(DecodeMode.Scaled66) + } + findViewById<Button>(R.id.decode_crop)!!.setOnClickListener { + decode(DecodeMode.CropedSquared) + } + findViewById<Button>(R.id.decode_cropScaled33)!!.setOnClickListener { + decode(DecodeMode.CropedSquaredScaled33) + } + } +}
\ No newline at end of file diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt new file mode 100644 index 000000000000..387564437b5f --- /dev/null +++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/GainmapImage.kt @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.silkfx.hdr + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.ColorMatrixColorFilter +import android.graphics.Gainmap +import android.graphics.ImageDecoder +import android.graphics.Paint +import android.util.AttributeSet +import android.view.View +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.FrameLayout +import android.widget.RadioGroup +import android.widget.Spinner +import android.widget.TextView +import com.android.test.silkfx.R +import com.davemorrissey.labs.subscaleview.ImageSource +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView + +class GainmapImage(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) { + + private val gainmapImages: Array<String> + private var selectedImage = -1 + private var outputMode = R.id.output_hdr + private var bitmap: Bitmap? = null + private var gainmap: Gainmap? = null + private var gainmapVisualizer: Bitmap? = null + private lateinit var imageView: SubsamplingScaleImageView + + init { + gainmapImages = context.assets.list("gainmaps")!! + } + + fun setImageSource(source: ImageDecoder.Source) { + findViewById<Spinner>(R.id.image_selection)!!.visibility = View.GONE + doDecode(source) + } + + override fun onFinishInflate() { + super.onFinishInflate() + + imageView = findViewById(R.id.image)!! + + findViewById<RadioGroup>(R.id.output_mode)!!.also { + it.check(outputMode) + it.setOnCheckedChangeListener { _, checkedId -> + val previousMode = outputMode + outputMode = checkedId + if (previousMode == R.id.output_sdr && checkedId == R.id.output_hdr) { + animateToHdr() + } else if (previousMode == R.id.output_hdr && checkedId == R.id.output_sdr) { + animateToSdr() + } else { + updateDisplay() + } + } + } + + val spinner = findViewById<Spinner>(R.id.image_selection)!! + val adapter = ArrayAdapter(context, android.R.layout.simple_spinner_item, gainmapImages) + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + spinner.adapter = adapter + spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected( + parent: AdapterView<*>?, + view: View?, + position: Int, + id: Long + ) { + setImage(position) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + } + } + + setImage(gainmapImages.indexOf("cave.jpg")) + + imageView.apply { + isClickable = true + setOnClickListener { + animate().alpha(.5f).withEndAction { + animate().alpha(1f).start() + }.start() + } + } + } + + private fun setImage(position: Int) { + if (selectedImage == position) return + selectedImage = position + val source = ImageDecoder.createSource(resources.assets, + "gainmaps/${gainmapImages[position]}") + doDecode(source) + } + + private fun doDecode(source: ImageDecoder.Source) { + gainmap = null + bitmap = ImageDecoder.decodeBitmap(source) { decoder, info, source -> + decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE + } + if (!bitmap!!.hasGainmap()) { + outputMode = R.id.output_sdr + findViewById<TextView>(R.id.error_msg)!!.also { + it.visibility = View.VISIBLE + it.text = "Image doesn't have a gainmap, only showing in SDR" + } + findViewById<RadioGroup>(R.id.output_mode)!!.also { + it.check(R.id.output_sdr) + it.visibility = View.GONE + } + } else { + findViewById<TextView>(R.id.error_msg)!!.visibility = View.GONE + findViewById<RadioGroup>(R.id.output_mode)!!.visibility = View.VISIBLE + + gainmap = bitmap!!.gainmap + val map = gainmap!!.gainmapContents + if (map.config != Bitmap.Config.ALPHA_8) { + gainmapVisualizer = map + } else { + gainmapVisualizer = Bitmap.createBitmap(map.width, map.height, + Bitmap.Config.ARGB_8888) + val canvas = Canvas(gainmapVisualizer!!) + val paint = Paint() + paint.colorFilter = ColorMatrixColorFilter( + floatArrayOf( + 0f, 0f, 0f, 1f, 0f, + 0f, 0f, 0f, 1f, 0f, + 0f, 0f, 0f, 1f, 0f, + 0f, 0f, 0f, 0f, 255f + ) + ) + canvas.drawBitmap(map, 0f, 0f, paint) + canvas.setBitmap(null) + } + } + + updateDisplay() + } + + private fun animateToHdr() { + if (bitmap == null || gainmap == null) return + + // TODO: Trigger an animation + updateDisplay() + } + + private fun animateToSdr() { + if (bitmap == null) return + + // TODO: Trigger an animation + updateDisplay() + } + + private fun updateDisplay() { + if (bitmap == null) return + + imageView.setImage(ImageSource.cachedBitmap(when (outputMode) { + R.id.output_hdr -> { bitmap!!.gainmap = gainmap; bitmap!! } + R.id.output_sdr -> { bitmap!!.gainmap = null; bitmap!! } + R.id.output_gainmap -> gainmapVisualizer!! + else -> throw IllegalStateException() + })) + } +}
\ No newline at end of file diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/RadialGlow.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/RadialGlow.kt index 599585e9d125..20acb4919c78 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/hdr/RadialGlow.kt +++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/RadialGlow.kt @@ -26,9 +26,7 @@ import android.util.AttributeSet import com.android.test.silkfx.common.BaseDrawingView import kotlin.math.min -class RadialGlow : BaseDrawingView { - - constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) +class RadialGlow(context: Context, attrs: AttributeSet?) : BaseDrawingView(context, attrs) { var glowToggle = false |