• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.test.silkfx.hdr
18 
19 import android.content.Context
20 import android.graphics.Bitmap
21 import android.graphics.Canvas
22 import android.graphics.ColorMatrixColorFilter
23 import android.graphics.Gainmap
24 import android.graphics.ImageDecoder
25 import android.graphics.Paint
26 import android.util.AttributeSet
27 import android.view.View
28 import android.widget.AdapterView
29 import android.widget.ArrayAdapter
30 import android.widget.Button
31 import android.widget.FrameLayout
32 import android.widget.RadioGroup
33 import android.widget.Spinner
34 import android.widget.TextView
35 import com.android.test.silkfx.R
36 import com.davemorrissey.labs.subscaleview.ImageSource
37 import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
38 
39 class GainmapImage(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {
40 
41     private val gainmapImages: Array<String>
42     private var selectedImage = -1
43     private var outputMode = R.id.output_hdr
44     private var bitmap: Bitmap? = null
45     private var originalGainmap: Gainmap? = null
46     private var gainmapVisualizer: Bitmap? = null
47     private lateinit var imageView: SubsamplingScaleImageView
48     private lateinit var gainmapMetadataEditor: GainmapMetadataEditor
49 
50     init {
51         gainmapImages = context.assets.list("gainmaps")!!
52     }
53 
54     fun setImageSource(source: ImageDecoder.Source) {
55         findViewById<Spinner>(R.id.image_selection)!!.visibility = View.GONE
56         doDecode(source)
57     }
58 
59     override fun onFinishInflate() {
60         super.onFinishInflate()
61 
62         imageView = findViewById(R.id.image)!!
63         gainmapMetadataEditor = GainmapMetadataEditor(this, imageView)
64 
65         findViewById<RadioGroup>(R.id.output_mode)!!.also {
66             it.check(outputMode)
67             it.setOnCheckedChangeListener { _, checkedId ->
68                 outputMode = checkedId
69                 updateDisplay()
70             }
71         }
72 
73         val spinner = findViewById<Spinner>(R.id.image_selection)!!
74         val adapter = ArrayAdapter(context, android.R.layout.simple_spinner_item, gainmapImages)
75         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
76         spinner.adapter = adapter
77         spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
78             override fun onItemSelected(
79                     parent: AdapterView<*>?,
80                     view: View?,
81                     position: Int,
82                     id: Long
83             ) {
84                 setImage(position)
85             }
86 
87             override fun onNothingSelected(parent: AdapterView<*>?) {
88             }
89         }
90 
91         findViewById<Button>(R.id.gainmap_metadata)!!.setOnClickListener {
92             gainmapMetadataEditor.openEditor()
93         }
94 
95         setImage(0)
96 
97         imageView.apply {
98             isClickable = true
99             setOnClickListener {
100                 animate().alpha(.5f).withEndAction {
101                     animate().alpha(1f).start()
102                 }.start()
103             }
104         }
105     }
106 
107     private fun setImage(position: Int) {
108         if (selectedImage == position) return
109         selectedImage = position
110         val source = ImageDecoder.createSource(resources.assets,
111                 "gainmaps/${gainmapImages[position]}")
112         doDecode(source)
113     }
114 
115     private fun doDecode(source: ImageDecoder.Source) {
116         originalGainmap = null
117         bitmap = ImageDecoder.decodeBitmap(source) { decoder, info, source ->
118             decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
119         }
120         if (!bitmap!!.hasGainmap()) {
121             outputMode = R.id.output_sdr
122             findViewById<TextView>(R.id.error_msg)!!.also {
123                 it.visibility = View.VISIBLE
124                 it.text = "Image doesn't have a gainmap, only showing in SDR"
125             }
126             findViewById<RadioGroup>(R.id.output_mode)!!.also {
127                 it.check(R.id.output_sdr)
128                 it.visibility = View.GONE
129             }
130         } else {
131             findViewById<TextView>(R.id.error_msg)!!.visibility = View.GONE
132             findViewById<RadioGroup>(R.id.output_mode)!!.visibility = View.VISIBLE
133 
134             val gainmap = bitmap!!.gainmap!!
135             originalGainmap = gainmap
136             gainmapMetadataEditor.setGainmap(Gainmap(gainmap, gainmap.gainmapContents))
137             val map = gainmap.gainmapContents
138             if (map.config != Bitmap.Config.ALPHA_8) {
139                 gainmapVisualizer = map
140             } else {
141                 gainmapVisualizer = Bitmap.createBitmap(map.width, map.height,
142                         Bitmap.Config.ARGB_8888)
143                 val canvas = Canvas(gainmapVisualizer!!)
144                 val paint = Paint()
145                 paint.colorFilter = ColorMatrixColorFilter(
146                         floatArrayOf(
147                                 0f, 0f, 0f, 1f, 0f,
148                                 0f, 0f, 0f, 1f, 0f,
149                                 0f, 0f, 0f, 1f, 0f,
150                                 0f, 0f, 0f, 0f, 255f
151                         )
152                 )
153                 canvas.drawBitmap(map, 0f, 0f, paint)
154                 canvas.setBitmap(null)
155             }
156         }
157 
158         updateDisplay()
159     }
160 
161     private fun updateDisplay() {
162         if (bitmap == null) return
163 
164         imageView.setImage(ImageSource.cachedBitmap(when (outputMode) {
165             R.id.output_hdr -> {
166                 bitmap!!.gainmap = originalGainmap
167                 bitmap!!
168             }
169 
170             R.id.output_hdr_test -> {
171                 bitmap!!.gainmap = gainmapMetadataEditor.editedGainmap()
172                 bitmap!!
173             }
174 
175             R.id.output_sdr -> {
176                 bitmap!!.gainmap = null; bitmap!!
177             }
178 
179             R.id.output_gainmap -> gainmapVisualizer!!
180             else -> throw IllegalStateException()
181         }))
182     }
183 }
184