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? = null, hotPixelMap: Map? = null, ): Map { val settingsMap = mapOf( "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( "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( "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, ) } }