SilkFX HDR demos
Test: this
Bug: 266628247
Change-Id: Ib41de2de8634e03dd6f7f6b3909e4e109793fa31
diff --git a/libs/hwui/effects/GainmapRenderer.cpp b/libs/hwui/effects/GainmapRenderer.cpp
index a544ae8..8977d3c 100644
--- a/libs/hwui/effects/GainmapRenderer.cpp
+++ b/libs/hwui/effects/GainmapRenderer.cpp
@@ -48,10 +48,7 @@
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 088d9a2..1e467db 100644
--- a/tests/SilkFX/Android.bp
+++ b/tests/SilkFX/Android.bp
@@ -25,13 +25,17 @@
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 21256d8..1b8e08b 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
new file mode 100644
index 0000000..fa7d3fc3
--- /dev/null
+++ b/tests/SilkFX/assets/gainmaps/cave.jpg
Binary files differ
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 0000000..c183c5d
--- /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 0000000..d2653d0
--- /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 0000000..c600d0f
--- /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 0000000..d0c17fa
--- /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 0000000..c75f925
--- /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 0000000..e3b834a
--- /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 0000000..37242ee
--- /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 944c684..c0eaf9b 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 0000000..e7ef61f8
--- /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 0000000..89bbb70
--- /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 0000000..261022a
--- /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 0000000..9816430
--- /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 7132ae8..a6cdbb9 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.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 @@
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 @@
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 e0a0a20..e56ce40 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 @@
const val EXTRA_LAYOUT = "layout"
const val EXTRA_TITLE = "title"
+const val EXTRA_COMMON_CONTROLS = "common_controls"
class CommonDemoActivity : BaseDemoActivity() {
@@ -38,8 +39,13 @@
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 0000000..f16f0e4
--- /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 4b85953..f88e6b0 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.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 0000000..6920f83
--- /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 0000000..db812ac
--- /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 0000000..3875644
--- /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 599585e..20acb49 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 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