diff --git a/src/io_pipeline.c b/src/io_pipeline.c index f9bb1dc..73f0987 100644 --- a/src/io_pipeline.c +++ b/src/io_pipeline.c @@ -34,7 +34,9 @@ struct camera_info { bool has_auto_focus_continuous; bool has_auto_focus_start; - + + bool has_whitebalance; + bool has_redbluebalance; // unsigned int entity_id; // enum v4l2_buf_type type; @@ -85,6 +87,10 @@ struct control_state { bool exposure_is_manual; int exposure; + + bool wb_is_manual; + int red_balance; + int blue_balance; }; static struct control_state desired_controls = {}; @@ -216,6 +222,13 @@ setup_camera(MPDeviceList **device_list, const struct mp_camera_config *config) info->gain_ctrl = V4L2_CID_ANALOGUE_GAIN; info->gain_max = control.max; } + + if (mp_camera_query_control(info->camera, V4L2_CID_AUTO_WHITE_BALANCE, NULL)) { + info->has_whitebalance = true; + } + if (mp_camera_query_control(info->camera, V4L2_CID_RED_BALANCE, NULL)) { + info->has_redbluebalance = true; + } } } @@ -272,6 +285,12 @@ update_process_pipeline() current_controls.exposure = mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE); } + if (!current_controls.wb_is_manual) { + current_controls.red_balance = + mp_camera_control_get_int32(info->camera, V4L2_CID_RED_BALANCE); + current_controls.blue_balance = + mp_camera_control_get_int32(info->camera, V4L2_CID_BLUE_BALANCE); + } struct mp_process_pipeline_state pipeline_state = { .camera = camera, @@ -286,6 +305,9 @@ update_process_pipeline() .gain_max = info->gain_max, .exposure_is_manual = current_controls.exposure_is_manual, .exposure = current_controls.exposure, + .wb_is_manual = current_controls.wb_is_manual, + .red_balance = current_controls.red_balance, + .blue_balance = current_controls.blue_balance, .has_auto_focus_continuous = info->has_auto_focus_continuous, .has_auto_focus_start = info->has_auto_focus_start, }; @@ -311,10 +333,13 @@ capture(MPPipeline *pipeline, const void *data) captures_remaining = burst_length; - // Disable the autogain/exposure while taking the burst + // Disable the autogain/exposure/wb while taking the burst mp_camera_control_set_int32(info->camera, V4L2_CID_AUTOGAIN, 0); mp_camera_control_set_int32(info->camera, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL); + if (info->has_whitebalance) { + mp_camera_control_set_int32(info->camera, V4L2_CID_AUTO_WHITE_BALANCE, 0); + } // Change camera mode for capturing mp_process_pipeline_sync(); @@ -454,6 +479,11 @@ on_frame(MPBuffer buffer, void * _data) V4L2_CID_AUTOGAIN, true); } + if (!current_controls.wb_is_manual) { + mp_camera_control_set_bool(info->camera, + V4L2_CID_AUTO_WHITE_BALANCE, true); + } + // Go back to preview mode mp_process_pipeline_sync(); mp_camera_stop_capture(info->camera); @@ -522,6 +552,9 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state) V4L2_EXPOSURE_MANUAL; current_controls.exposure = mp_camera_control_get_int32( info->camera, V4L2_CID_EXPOSURE); + current_controls.wb_is_manual = + mp_camera_control_get_bool(info->camera, + V4L2_CID_AUTO_WHITE_BALANCE) == 0; } } @@ -543,6 +576,7 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state) desired_controls.gain = state->gain; desired_controls.exposure_is_manual = state->exposure_is_manual; desired_controls.exposure = state->exposure; + desired_controls.wb_is_manual = state->wb_is_manual; has_changed = has_changed || memcmp(&previous_desired, &desired_controls, diff --git a/src/io_pipeline.h b/src/io_pipeline.h index a8a0f2c..5d5f24d 100644 --- a/src/io_pipeline.h +++ b/src/io_pipeline.h @@ -18,6 +18,8 @@ struct mp_io_pipeline_state { bool exposure_is_manual; int exposure; + bool wb_is_manual; + bool save_dng; }; diff --git a/src/main.c b/src/main.c index 97b048c..433f207 100644 --- a/src/main.c +++ b/src/main.c @@ -46,6 +46,8 @@ static bool gain_is_manual = false; static int gain; static int gain_max; +static bool wb_is_manual = false; + static bool exposure_is_manual = false; static int exposure; @@ -105,6 +107,7 @@ update_io_pipeline() .gain = gain, .exposure_is_manual = exposure_is_manual, .exposure = exposure, + .wb_is_manual = wb_is_manual, .save_dng = gtk_check_button_get_active(GTK_CHECK_BUTTON(setting_dng)), }; mp_io_pipeline_update_state(&io_state); diff --git a/src/process_pipeline.c b/src/process_pipeline.c index 606b714..8234f8b 100644 --- a/src/process_pipeline.c +++ b/src/process_pipeline.c @@ -51,6 +51,10 @@ static int gain_max; static bool exposure_is_manual; static int exposure; +static bool wb_is_manual; +static int red_balance; +static int blue_balance; + static bool save_dng; static char capture_fname[255]; @@ -397,9 +401,13 @@ process_image_for_capture(const uint8_t *image, int count) if (camera->forwardmatrix[0]) { TIFFSetField(tif, TIFFTAG_FORWARDMATRIX1, 9, camera->forwardmatrix); } - static const float neutral[] = { 1.0, 1.0, 1.0 }; - TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral); + //static const float neutral[] = { 1.0, 1.0, 1.0 }; + //TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral); TIFFSetField(tif, TIFFTAG_CALIBRATIONILLUMINANT1, 21); + + static const float ab[] = {red_balance/4096, 1.0, blue_balance/4096}; + TIFFSetField(tif, TIFFTAG_ANALOGBALANCE, 3, ab); + // Write black thumbnail, only windows uses this { unsigned char *buf = @@ -723,6 +731,10 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state exposure_is_manual = state->exposure_is_manual; exposure = state->exposure; + wb_is_manual = state->wb_is_manual; + red_balance = state->red_balance; + blue_balance = state->blue_balance; + if (output_changed) { camera_rotation = mod(camera->rotate - device_rotation, 360); diff --git a/src/process_pipeline.h b/src/process_pipeline.h index 6902409..0ca169f 100644 --- a/src/process_pipeline.h +++ b/src/process_pipeline.h @@ -25,6 +25,10 @@ struct mp_process_pipeline_state { bool has_auto_focus_continuous; bool has_auto_focus_start; + bool wb_is_manual; + int red_balance; + int blue_balance; + bool save_dng; };