package com.example.smtias_capture
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CaptureResult
import android.hardware.camera2.TotalCaptureResult
import android.media.Image
import android.os.Build
import java.time.Instant
/**
* 定量モード撮影のメタデータ Map(meta.json の元データ)を構築するユーティリティ.
*
* 撮影設定([exposureTimeNs] 等は呼び出し元が適用した値)・実適用値(CaptureResult)・
* センサ特性(CameraCharacteristics)・画素統計・Hot pixel map をまとめる.
*/
internal object CaptureMetadata {
/** メタデータ Map を構築する. */
fun build(
cameraId: String,
characteristics: CameraCharacteristics,
captureResult: TotalCaptureResult,
image: Image,
exposureTimeNs: Long,
sensitivity: Int,
frameDurationNs: Long,
imageStatistics: Map<String, Any?>? = null,
hotPixelMap: Map<String, Any?>? = null,
): Map<String, Any?> {
val settingsMap = mapOf<String, Any?>(
"control_mode" to "OFF",
"ae_mode" to "OFF",
"exposure_time_ns" to exposureTimeNs,
"sensor_sensitivity_iso" to sensitivity,
"frame_duration_ns" to frameDurationNs,
"awb_mode" to "OFF",
"color_correction_gains" to listOf(1.0, 1.0, 1.0, 1.0),
"color_correction_transform" to "identity",
"noise_reduction_mode" to "OFF",
"edge_mode" to "OFF",
"tonemap_mode" to "CONTRAST_CURVE_LINEAR",
"shading_mode" to "HIGH_QUALITY",
"statistics_lens_shading_map_mode" to "ON",
"statistics_hot_pixel_map_mode" to "ON",
"af_mode" to "OFF",
"black_level_lock" to true,
)
val actualMap = mapOf<String, Any?>(
"exposure_time_ns" to captureResult.get(CaptureResult.SENSOR_EXPOSURE_TIME),
"sensor_sensitivity" to captureResult.get(CaptureResult.SENSOR_SENSITIVITY),
"frame_duration_ns" to captureResult.get(CaptureResult.SENSOR_FRAME_DURATION),
"sensor_timestamp" to captureResult.get(CaptureResult.SENSOR_TIMESTAMP),
"dynamic_black_level" to
captureResult.get(CaptureResult.SENSOR_DYNAMIC_BLACK_LEVEL)?.toList(),
"dynamic_white_level" to
captureResult.get(CaptureResult.SENSOR_DYNAMIC_WHITE_LEVEL),
"neutral_color_point" to
captureResult.get(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT)?.map {
"${it.numerator}/${it.denominator}"
},
"color_gains" to captureResult.get(CaptureResult.COLOR_CORRECTION_GAINS)?.let {
listOf(
it.red.toDouble(),
it.greenEven.toDouble(),
it.greenOdd.toDouble(),
it.blue.toDouble()
)
},
"color_transform" to
captureResult.get(CaptureResult.COLOR_CORRECTION_TRANSFORM)?.let { transform ->
(0 until 3).map { row ->
(0 until 3).map { col ->
val r = transform.getElement(col, row)
"${r.numerator}/${r.denominator}"
}
}
},
)
val sensorCharacteristicsMap = mapOf<String, Any?>(
"color_filter_arrangement" to
characteristics.get(
CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
),
"black_level_pattern" to
characteristics.get(
CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN
)?.toString(),
"white_level" to characteristics.get(CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL),
"physical_size" to
characteristics.get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE)?.let {
listOf(it.width, it.height)
},
"pixel_array_size" to
characteristics.get(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE)?.let {
listOf(it.width, it.height)
},
"active_array_size" to
characteristics.get(
CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE
)?.toString(),
)
return mapOf(
"captureTimestampUtc" to Instant.now().toString(),
"deviceModel" to Build.MODEL,
"androidVersion" to Build.VERSION.RELEASE,
"cameraId" to cameraId,
"hardwareLevel" to
characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL),
"captureMode" to "quantitative",
"imageFormat" to "RAW_SENSOR",
"imageSize" to listOf(image.width, image.height),
"settings" to settingsMap,
"actual" to actualMap,
"sensorCharacteristics" to sensorCharacteristicsMap,
"image_statistics" to imageStatistics,
"hot_pixel_map" to hotPixelMap,
)
}
}