Skip to content

[Sample] [Graphic] - Implementation of "Displaying UltraHDR" Sample #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jul 10, 2023
Merged
4 changes: 3 additions & 1 deletion samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Demonstrates how to implement the incremental search feature for non-alphabet la
Shows how to create a GATT server and communicate with the GATT client
- [Data Access](privacy/transparency/src/main/java/com/example/platform/privacy/transparency/DataAccess.kt):
Demonstrates how to implement data access auditing for your app to identify
- [Displaying UltraHDR](graphics/ultrahdr/src/main/java/com/example/platform/graphics/ultrahdr/display/DisplayingUltraHDR.kt):
This sample demonstrates displaying an UltraHDR image
- [Downloadable Fonts](user-interface/text/src/main/java/com/example/platform/ui/text/DownloadableFonts.kt):
Download fonts instead of bundling them in the app resources.
- [Drag and Drop](user-interface/draganddrop/src/main/java/com/example/platform/ui/draganddrop/DragAndDrop.kt):
Expand Down Expand Up @@ -58,7 +60,7 @@ Basic motion example using referenced ConstraintLayout files
Shows the recommended flow to request multiple RELATED runtime permissions
- [Package Visibility](privacy/data/src/main/java/com/example/platform/privacy/data/PackageVisibility.kt):
A sample that showcase how the package visibility queries affects the available packages
- [PdfRenderer](graphics/src/main/java/com/example/platform/graphics/PdfRenderer.kt):
- [PdfRenderer](graphics/pdf/src/main/java/com/example/platform/graphics/pdf/PdfRenderer.kt):
Demonstrates how to use PdfRenderer to display PDF documents on the screen.
- [Permissionless](privacy/permissions/src/main/java/com/example/platform/privacy/permissions/Permissionless.kt):
This sample demonstrate how you can avoid requesting permission for certain actions by leveraging System APIs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Graphics samples
# PDF Samples

## [PdfRenderer](/src/main/java/com/example/platform/graphics/PdfRenderer.kt)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ plugins {
}

android {
namespace = "com.example.platform.graphics"
namespace = "com.example.platform.graphics.pdf"
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/


package com.example.platform.graphics
package com.example.platform.graphics.pdf

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
Expand All @@ -29,9 +29,7 @@ import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.unit.dp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.example.platform.graphics
package com.example.platform.graphics.pdf

import android.app.Application
import android.graphics.Bitmap
Expand Down
24 changes: 24 additions & 0 deletions samples/graphics/ultrahdr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# UltraHDR Samples

This is a catalog of graphics related UltraHDR samples that demonstrate the usage and capabilities of UltraHDR images on the Android Platform

> 🚧 **Work-in-Progress:** We are activtly working on bringing more UltraHDR samples

Check out the UltraHDR HDR specifications at https://developer.android.com/guide/topics/media/hdr-image-format

## License
```
Copyright 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

https://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.
```
30 changes: 30 additions & 0 deletions samples/graphics/ultrahdr/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

/*
* Copyright 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
*
* https://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.
*/


plugins {
id("com.example.platform.sample")
}

android {
namespace = "com.example.platform.graphics.ultrahdr"
viewBinding.isEnabled = true
}

dependencies {
// Add samples specific dependencies
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* Copyright 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
*
* https://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.example.platform.graphics.ultrahdr.common

import android.content.Context
import android.content.pm.ActivityInfo
import android.os.Build
import android.util.AttributeSet
import android.util.Log
import android.view.Display
import android.view.LayoutInflater
import android.view.Window
import android.widget.LinearLayout
import androidx.annotation.RequiresApi
import com.example.platform.graphics.ultrahdr.R
import com.example.platform.graphics.ultrahdr.databinding.ColorModeControlsBinding
import java.util.function.Consumer

/**
* This class creates a custom view that is able to change the Activity's Color Mode to HDR, which
* enable UltraHDR Viewing. The [setWindow] method must be called in order for the UltraHDR viewing
* to happen.
*/
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
class ColorModeControls : LinearLayout, WindowObserver {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

/**
* Android ViewBinding.
*/
private var _binding: ColorModeControlsBinding? = null
private val binding get() = _binding!!

/**
* Reference to [Window]. This should come from the currently active activity.
*/
private var window: Window? = null

init { // Inflate binding
_binding = ColorModeControlsBinding.inflate(LayoutInflater.from(context), this, true)
}

private val hdrSdrRatioListener = Consumer<Display> { display ->
Log.d(TAG, "HDR/SDR Ratio Changed ${display.hdrSdrRatio}")
post { updateModeInfoDisplay() }
}

override fun onAttachedToWindow() {
super.onAttachedToWindow()
display?.run {
registerHdrSdrRatioChangedListener(
{ executable ->
executable.run()
},
hdrSdrRatioListener,
)
}
}

override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
detach()
}

override fun setWindow(window: Window?) {
this.window = window
this.window?.let {
setColorMode(it.colorMode)

binding.ultrahdrColorModeSdr.setOnClickListener {
// Changed the activities color mode to SDR
setColorMode(ActivityInfo.COLOR_MODE_DEFAULT)
}

binding.ultrahdrColorModeHdr.setOnClickListener {
// Changed the activities color mode to HDR
setColorMode(ActivityInfo.COLOR_MODE_HDR)
}
}
}

private fun updateModeInfoDisplay() {
window?.let {
// The current hdr/sdr ratio expressed as the ratio of
// targetHdrPeakBrightnessInNits / targetSdrWhitePointInNits.
val sdrHdrRatio = when (display.isHdrSdrRatioAvailable) {
true -> display.hdrSdrRatio
false -> 1.0f
}

binding.ultrahdrColorModeCurrentMode.run {
val mode = when (it.colorMode) {
ActivityInfo.COLOR_MODE_DEFAULT -> resources.getString(R.string.color_mode_sdr)
ActivityInfo.COLOR_MODE_HDR -> String.format(
resources.getString(R.string.color_mode_hdr_with_ratio),
sdrHdrRatio,
)

else -> resources.getString(R.string.color_mode_unknown)
}
text = "Activity Color Mode: " + mode
}
}
}

/**
* Set the [ActivityInfo] Color Mode to the Window. Setting this to [ActivityInfo.COLOR_MODE_HDR]
* on a supported device will turn on the high brightness mode that is required to view and
* UltraHDR image properly.
*/
private fun setColorMode(newMode: Int) = window?.let {
it.colorMode = newMode
updateModeInfoDisplay()
}

fun detach() {
setColorMode(ActivityInfo.COLOR_MODE_DEFAULT)
display?.run {
unregisterHdrSdrRatioChangedListener(hdrSdrRatioListener)
}
}

companion object {
private val TAG = ColorModeControls::class.java.simpleName
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 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
*
* https://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.example.platform.graphics.ultrahdr.common

import android.view.Window

interface WindowObserver {
fun setWindow(window: Window?)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 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
*
* https://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.example.platform.graphics.ultrahdr.display

import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RadioButton
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import com.example.platform.graphics.ultrahdr.databinding.DisplayingUltrahdrBinding
import com.google.android.catalog.framework.annotations.Sample

@Sample(
name = "Displaying UltraHDR",
description = "This sample demonstrates displaying an UltraHDR image",
documentation = "https://developer.android.com/guide/topics/media/hdr-image-format",
tags = ["ultrahdr"],
)
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
class DisplayingUltraHDR : Fragment() {
/**
* Android ViewBinding.
*/
private var _binding: DisplayingUltrahdrBinding? = null
private val binding get() = _binding!!

/**
* List for UltraHDR Images
*/
private val ultraHDRImages = mapOf(
0 to ULTRA_HDR_IMAGE_LAMPS,
1 to ULTRA_HDR_IMAGE_CANYON,
2 to ULTRA_HDR_IMAGE_TRAIN_STATION,
)

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = DisplayingUltrahdrBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

// The ColorModeControls Class contain the necessary function to change the activities
// ColorMode to HDR, which allows and UltraHDRs images gain map to be used to enhance the
// image.
binding.colorModeControls.setWindow(requireActivity().window)
binding.imageOptionsSelectionGroup.setOnCheckedChangeListener { group, i ->
val selected = group.findViewById<RadioButton>(i)
val index = group.indexOfChild(selected)
updateDisplayedImage(index)
}
binding.optionLamps.isChecked = true
}

/**
* Updated the currently displayed UltraHDR image.
*/
private fun updateDisplayedImage(index: Int) {
ultraHDRImages[index]?.let {
binding.imageContainer.setImageResource(0)
val stream = context?.assets?.open(it)
val bitmap = BitmapFactory.decodeStream(stream)
binding.imageContainer.setImageBitmap(bitmap)
}
}

override fun onDetach() {
super.onDetach()
binding.colorModeControls.detach()
}

companion object {
/**
* Sample UltraHDR images paths
*/
private const val ULTRA_HDR_IMAGE_LAMPS = "gainmaps/lamps.jpg"
private const val ULTRA_HDR_IMAGE_CANYON = "gainmaps/grand_canyon.jpg"
private const val ULTRA_HDR_IMAGE_TRAIN_STATION = "gainmaps/train_station_night.jpg"
}
}
Loading