فهرست منبع

Progress on GTK4 port

Benjamin Schaaf 3 سال پیش
والد
کامیت
d42ee3e1c0
4فایلهای تغییر یافته به همراه184 افزوده شده و 268 حذف شده
  1. 73 146
      data/camera.ui
  2. 101 120
      src/main.c
  3. 3 0
      src/main.h
  4. 7 2
      src/process_pipeline.c

+ 73 - 146
data/camera.ui

@@ -18,9 +18,8 @@
           <object class="GtkStackPage">
             <property name="name">main</property>
             <property name="child">
-              <object class="GtkBox" id="page_main">
+              <object class="GtkOverlay" id="page_main">
                 <property name="can-focus">0</property>
-                <property name="orientation">vertical</property>
                 <child>
                   <object class="GtkGLArea" id="preview">
                     <property name="vexpand">1</property>
@@ -28,7 +27,7 @@
                     <property name="use-es">1</property>
                   </object>
                 </child>
-                <child>
+                <child type="overlay">
                   <object class="GtkBox" id="control_box">
                     <property name="visible">0</property>
                     <property name="can-focus">0</property>
@@ -68,38 +67,53 @@
                     </style>
                   </object>
                 </child>
-                <child>
-                  <object class="GtkActionBar" id="controls_box">
+                <child type="overlay">
+                  <object class="GtkBox" id="controls_box">
+                    <property name="orientation">horizontal</property>
+                    <property name="hexpand">1</property>
+                    <property name="valign">end</property>
+                    <property name="homogeneous">0</property>
                     <property name="can-focus">0</property>
-                    <child type="start">
-                      <object class="GtkButton" id="settings">
-                        <property name="receives-default">1</property>
+                    <property name="margin-bottom">5</property>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="orientation">horizontal</property>
+                        <property name="hexpand">1</property>
+                        <property name="valign">end</property>
+                        <property name="can-focus">0</property>
+                        <property name="margin-start">5</property>
+                        <property name="spacing">5</property>
                         <child>
-                          <object class="GtkImage">
-                            <property name="can-focus">0</property>
-                            <property name="resource">/org/postmarketos/Megapixels/settings-symbolic.svg</property>
+                          <object class="GtkButton" id="settings">
+                            <property name="receives-default">1</property>
+                            <child>
+                              <object class="GtkImage">
+                                <property name="can-focus">0</property>
+                                <property name="resource">/org/postmarketos/Megapixels/settings-symbolic.svg</property>
+                              </object>
+                            </child>
                           </object>
                         </child>
-                      </object>
-                    </child>
-                    <child type="start">
-                      <object class="GtkButton" id="switch_camera">
-                        <property name="receives-default">1</property>
                         <child>
-                          <object class="GtkImage">
-                            <property name="can-focus">0</property>
-                            <property name="resource">/org/postmarketos/Megapixels/switch-camera.svg</property>
+                          <object class="GtkButton" id="switch_camera">
+                            <property name="receives-default">1</property>
+                            <child>
+                              <object class="GtkImage">
+                                <property name="can-focus">0</property>
+                                <property name="resource">/org/postmarketos/Megapixels/switch-camera.svg</property>
+                              </object>
+                            </child>
                           </object>
                         </child>
                       </object>
                     </child>
-                    <child type="center">
-                      <object class="GtkButton" id="shutter">
-                        <property name="width-request">48</property>
-                        <property name="height-request">48</property>
+                    <child>
+                      <object class="GtkButton">
+                        <property name="action-name">app.capture</property>
                         <property name="receives-default">1</property>
                         <child>
                           <object class="GtkImage">
+                            <property name="pixel-size">60</property>
                             <property name="can-focus">0</property>
                             <property name="resource">/org/postmarketos/Megapixels/shutter-button.svg</property>
                           </object>
@@ -109,35 +123,46 @@
                         </style>
                       </object>
                     </child>
-                    <child type="end">
-                      <object class="GtkButton" id="open_directory">
-                        <property name="receives-default">1</property>
-                        <child>
-                          <object class="GtkImage">
-                            <property name="can-focus">0</property>
-                            <property name="resource">/org/postmarketos/Megapixels/folder-symbolic.svg</property>
-                          </object>
-                        </child>
-                      </object>
-                    </child>
-                    <child type="end">
-                      <object class="GtkButton" id="open_last">
-                        <property name="receives-default">1</property>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="orientation">horizontal</property>
+                        <property name="hexpand">1</property>
+                        <property name="halign">end</property>
+                        <property name="valign">end</property>
+                        <property name="can-focus">0</property>
+                        <property name="margin-end">5</property>
+                        <property name="spacing">5</property>
                         <child>
-                          <object class="GtkStack" id="open_last_stack">
-                            <property name="can-focus">0</property>
+                          <object class="GtkButton" id="open_directory">
+                            <property name="receives-default">1</property>
                             <child>
-                              <object class="GtkImage" id="thumb_last">
-                                <property name="width-request">24</property>
-                                <property name="height-request">24</property>
+                              <object class="GtkImage">
                                 <property name="can-focus">0</property>
+                                <property name="resource">/org/postmarketos/Megapixels/folder-symbolic.svg</property>
                               </object>
                             </child>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="open_last">
+                            <property name="receives-default">1</property>
                             <child>
-                              <object class="GtkSpinner" id="process_spinner">
-                                <property name="width-request">24</property>
-                                <property name="height-request">24</property>
+                              <object class="GtkStack" id="open_last_stack">
                                 <property name="can-focus">0</property>
+                                <child>
+                                  <object class="GtkImage" id="thumb_last">
+                                    <property name="width-request">24</property>
+                                    <property name="height-request">24</property>
+                                    <property name="can-focus">0</property>
+                                  </object>
+                                </child>
+                                <child>
+                                  <object class="GtkSpinner" id="process_spinner">
+                                    <property name="width-request">24</property>
+                                    <property name="height-request">24</property>
+                                    <property name="can-focus">0</property>
+                                  </object>
+                                </child>
                               </object>
                             </child>
                           </object>
@@ -146,7 +171,7 @@
                     </child>
                   </object>
                 </child>
-                <child>
+                <child type="overlay">
                   <object class="GtkBox" id="error_box">
                     <property name="visible">0</property>
                     <property name="can-focus">0</property>
@@ -184,18 +209,15 @@
             </property>
           </object>
         </child>
-        <!-- <child>
+        <child>
           <object class="GtkStackPage">
             <property name="name">settings</property>
             <property name="title" translatable="yes">page1</property>
-            <property name="position">1</property>
             <property name="child">
               <object class="GtkScrolledWindow" id="page_settings">
-                <property name="shadow-type">in</property>
                 <property name="child">
                   <object class="GtkViewport">
                     <property name="can-focus">0</property>
-                    <property name="shadow-type">none</property>
                     <property name="child">
                       <object class="GtkBox">
                         <property name="can-focus">0</property>
@@ -227,101 +249,6 @@
                             </child>
                           </object>
                         </child>
-                        <child>
-                          <object class="GtkBox">
-                            <property name="can-focus">0</property>
-                            <property name="orientation">vertical</property>
-                            <property name="spacing">4</property>
-                            <child>
-                              <object class="GtkLabel">
-                                <property name="can-focus">0</property>
-                                <property name="halign">start</property>
-                                <property name="label" translatable="yes">Photos</property>
-                                <style>
-                                  <class name="heading"/>
-                                </style>
-                              </object>
-                            </child>
-                            <child>
-                              <object class="GtkFrame">
-                                <property name="can-focus">0</property>
-                                <property name="shadow-type">in</property>
-                                <child>
-                                  <object class="GtkAlignment">
-                                    <property name="visible">True</property>
-                                    <property name="can-focus">False</property>
-                                    <property name="left-padding">12</property>
-                                    <child>
-                                      <object class="GtkBox">
-                                        <property name="can-focus">0</property>
-                                        <property name="orientation">vertical</property>
-                                        <property name="spacing">6</property>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="can-focus">0</property>
-                                            <property name="halign">start</property>
-                                            <property name="label" translatable="yes">Resolution</property>
-                                          </object>
-                                        </child>
-                                        <child>
-                                          <object class="GtkComboBox">
-                                            <property name="can-focus">0</property>
-                                          </object>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel">
-                                            <property name="can-focus">0</property>
-                                            <property name="halign">start</property>
-                                            <property name="label" translatable="yes">Storage mode</property>
-                                          </object>
-                                        </child>
-                                        <child>
-                                          <object class="GtkBox">
-                                            <property name="can-focus">0</property>
-                                            <property name="orientation">vertical</property>
-                                            <child>
-                                              <object class="GtkCheckButton" id="store_vng">
-                                                <property name="label" translatable="yes">Debayer with VNG (slowest)</property>
-                                                <property name="active">1</property>
-                                              </object>
-                                            </child>
-                                            <child>
-                                              <object class="GtkCheckButton" id="store_simple">
-                                                <property name="label" translatable="yes">Debayer with linear interpolation</property>
-                                                <property name="group">store_vng</property>
-                                              </object>
-                                            </child>
-                                            <child>
-                                              <object class="GtkCheckButton" id="store_raw">
-                                                <property name="label" translatable="yes">Raw</property>
-                                                <property name="group">store_vng</property>
-                                              </object>
-                                            </child>
-                                          </object>
-                                        </child>
-                                      </object>
-                                    </child>
-                                  </object>
-                                </child>
-                                <child type="label_item">
-                                  <placeholder/>
-                                </child>
-                                <style>
-                                  <class name="view"/>
-                                </style>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
                       </object>
                     </property>
                   </object>
@@ -329,7 +256,7 @@
               </object>
             </property>
           </object>
-        </child> -->
+        </child>
       </object>
     </property>
   </object>

+ 101 - 120
src/main.c

@@ -51,6 +51,8 @@ static bool has_auto_focus_continuous;
 static bool has_auto_focus_start;
 
 static MPProcessPipelineBuffer *current_preview_buffer = NULL;
+static int preview_buffer_width = -1;
+static int preview_buffer_height = -1;
 
 static cairo_surface_t *status_surface = NULL;
 static char last_path[260] = "";
@@ -130,6 +132,9 @@ update_state(const struct mp_main_state *state)
 		has_auto_focus_start = state->has_auto_focus_start;
 	}
 
+	preview_buffer_width = state->image_width;
+	preview_buffer_height = state->image_height;
+
 	return false;
 }
 
@@ -381,6 +386,12 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
 	glClearColor(0, 0, 0, 1);
 	glClear(GL_COLOR_BUFFER_BIT);
 
+	double ratio = preview_buffer_height / (double)preview_buffer_width;
+	glViewport(0,
+		   preview_height - preview_width * ratio,
+		   preview_width,
+		   preview_width * ratio);
+
 	if (current_preview_buffer) {
 		glUseProgram(blit_program);
 
@@ -488,18 +499,18 @@ on_open_directory_clicked(GtkWidget *widget, gpointer user_data)
 }
 
 void
-on_shutter_clicked(GtkWidget *widget, gpointer user_data)
+run_capture_action(GSimpleAction *action, GVariant *param, gpointer user_data)
 {
 	gtk_spinner_start(GTK_SPINNER(process_spinner));
 	gtk_stack_set_visible_child(GTK_STACK(open_last_stack), process_spinner);
 	mp_io_pipeline_capture();
 }
 
-// void
-// on_capture_shortcut(void)
-// {
-// 	on_shutter_clicked(NULL, NULL);
-// }
+void
+run_quit_action(GSimpleAction *action, GVariant *param, GApplication *app)
+{
+	g_application_quit(app);
+}
 
 // static bool
 // check_point_inside_bounds(int x, int y, int *bounds_x, int *bounds_y)
@@ -584,69 +595,66 @@ on_shutter_clicked(GtkWidget *widget, gpointer user_data)
 // 	gtk_widget_destroy(dialog);
 // }
 
-// void
-// on_preview_tap(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
-// {
-// 	if (event->type != GDK_BUTTON_PRESS)
-// 		return;
-
-// 	// Handle taps on the controls
-// 	if (event->y < 32) {
-// 		if (gtk_widget_is_visible(control_box)) {
-// 			gtk_widget_hide(control_box);
-// 			return;
-// 		} else {
-// 			gtk_widget_show(control_box);
-// 		}
-
-// 		if (event->x < 60) {
-// 			// ISO
-// 			current_control = USER_CONTROL_ISO;
-// 			gtk_label_set_text(GTK_LABEL(control_name), "ISO");
-// 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(control_auto),
-// 						     !gain_is_manual);
-// 			gtk_adjustment_set_lower(control_slider, 0.0);
-// 			gtk_adjustment_set_upper(control_slider, (float)gain_max);
-// 			gtk_adjustment_set_value(control_slider, (double)gain);
-
-// 		} else if (event->x > 60 && event->x < 120) {
-// 			// Shutter angle
-// 			current_control = USER_CONTROL_SHUTTER;
-// 			gtk_label_set_text(GTK_LABEL(control_name), "Shutter");
-// 			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(control_auto),
-// 						     !exposure_is_manual);
-// 			gtk_adjustment_set_lower(control_slider, 1.0);
-// 			gtk_adjustment_set_upper(control_slider, 360.0);
-// 			gtk_adjustment_set_value(control_slider, (double)exposure);
-// 		}
-
-// 		return;
-// 	}
+void
+preview_pressed(GtkGestureClick *gesture, int n_press, double x, double y)
+{
+	// Handle taps on the controls
+	// if (event->y < 32) {
+	// 	if (gtk_widget_is_visible(control_box)) {
+	// 		gtk_widget_hide(control_box);
+	// 		return;
+	// 	} else {
+	// 		gtk_widget_show(control_box);
+	// 	}
+
+	// 	if (event->x < 60) {
+	// 		// ISO
+	// 		current_control = USER_CONTROL_ISO;
+	// 		gtk_label_set_text(GTK_LABEL(control_name), "ISO");
+	// 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(control_auto),
+	// 					     !gain_is_manual);
+	// 		gtk_adjustment_set_lower(control_slider, 0.0);
+	// 		gtk_adjustment_set_upper(control_slider, (float)gain_max);
+	// 		gtk_adjustment_set_value(control_slider, (double)gain);
+
+	// 	} else if (event->x > 60 && event->x < 120) {
+	// 		// Shutter angle
+	// 		current_control = USER_CONTROL_SHUTTER;
+	// 		gtk_label_set_text(GTK_LABEL(control_name), "Shutter");
+	// 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(control_auto),
+	// 					     !exposure_is_manual);
+	// 		gtk_adjustment_set_lower(control_slider, 1.0);
+	// 		gtk_adjustment_set_upper(control_slider, 360.0);
+	// 		gtk_adjustment_set_value(control_slider, (double)exposure);
+	// 	}
 
-// 	// Tapped zbar result
-// 	if (zbar_result) {
-// 		// Transform the event coordinates to the image
-// 		int width = cairo_image_surface_get_width(surface);
-// 		int height = cairo_image_surface_get_height(surface);
-// 		double scale = MIN(preview_width / (double)width, preview_height / (double)height);
-// 		int x = (event->x - preview_width / 2) / scale + width / 2;
-// 		int y = (event->y - preview_height / 2) / scale + height / 2;
-
-// 		for (uint8_t i = 0; i < zbar_result->size; ++i) {
-// 			MPZBarCode *code = &zbar_result->codes[i];
-
-// 			if (check_point_inside_bounds(x, y, code->bounds_x, code->bounds_y)) {
-// 				on_zbar_code_tapped(widget, code);
-// 				return;
-// 			}
-// 		}
-// 	}
+	// 	return;
+	// }
 
-// 	// Tapped preview image itself, try focussing
-// 	if (has_auto_focus_start) {
-// 		mp_io_pipeline_focus();
-// 	}
-// }
+	// Tapped zbar result
+	// if (zbar_result) {
+	// 	// Transform the event coordinates to the image
+	// 	int width = cairo_image_surface_get_width(surface);
+	// 	int height = cairo_image_surface_get_height(surface);
+	// 	double scale = MIN(preview_width / (double)width, preview_height / (double)height);
+	// 	int x = (event->x - preview_width / 2) / scale + width / 2;
+	// 	int y = (event->y - preview_height / 2) / scale + height / 2;
+
+	// 	for (uint8_t i = 0; i < zbar_result->size; ++i) {
+	// 		MPZBarCode *code = &zbar_result->codes[i];
+
+	// 		if (check_point_inside_bounds(x, y, code->bounds_x, code->bounds_y)) {
+	// 			on_zbar_code_tapped(widget, code);
+	// 			return;
+	// 		}
+	// 	}
+	// }
+
+	// Tapped preview image itself, try focussing
+	if (has_auto_focus_start) {
+		mp_io_pipeline_focus();
+	}
+}
 
 void
 on_error_close_clicked(GtkWidget *widget, gpointer user_data)
@@ -770,21 +778,9 @@ on_realize(GtkWidget *window, gpointer *data)
 	update_io_pipeline();
 }
 
-typedef struct
-{
-	GtkApplication parent_instance;
-} MegapixelsApp;
-
-typedef GtkApplicationClass MegapixelsAppClass;
-
-GType megapixels_app_get_type (void);
-G_DEFINE_TYPE(MegapixelsApp, megapixels_app, GTK_TYPE_APPLICATION)
-
 static void
-startup(GApplication *app)
+activate(GtkApplication *app, gpointer data)
 {
-	G_APPLICATION_CLASS(megapixels_app_parent_class)->startup(app);
-
 	g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme",
 		     TRUE, NULL);
 
@@ -794,7 +790,6 @@ startup(GApplication *app)
 		"/org/postmarketos/Megapixels/camera.ui");
 
 	GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
-	GtkWidget *shutter = GTK_WIDGET(gtk_builder_get_object(builder, "shutter"));
 	GtkWidget *switch_btn =
 		GTK_WIDGET(gtk_builder_get_object(builder, "switch_camera"));
 	GtkWidget *settings_btn =
@@ -820,8 +815,6 @@ startup(GApplication *app)
 		GTK_ADJUSTMENT(gtk_builder_get_object(builder, "control_adj"));
 	control_auto = GTK_WIDGET(gtk_builder_get_object(builder, "control_auto"));
 	g_signal_connect(window, "realize", G_CALLBACK(on_realize), NULL);
-	// g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
-	g_signal_connect(shutter, "clicked", G_CALLBACK(on_shutter_clicked), NULL);
 	g_signal_connect(error_close, "clicked", G_CALLBACK(on_error_close_clicked),
 			 NULL);
 	g_signal_connect(switch_btn, "clicked", G_CALLBACK(on_camera_switch_clicked),
@@ -834,15 +827,14 @@ startup(GApplication *app)
 			 NULL);
 	g_signal_connect(open_directory, "clicked",
 			 G_CALLBACK(on_open_directory_clicked), NULL);
+
 	g_signal_connect(preview, "realize", G_CALLBACK(preview_realize), NULL);
 	g_signal_connect(preview, "render", G_CALLBACK(preview_draw), NULL);
-	g_signal_connect(preview, "resize", G_CALLBACK(preview_resize),
-			 NULL);
-	// gtk_widget_set_events(preview, gtk_widget_get_events(preview) |
-	// 				       GDK_BUTTON_PRESS_MASK |
-	// 				       GDK_POINTER_MOTION_MASK);
-	// g_signal_connect(preview, "button-press-event", G_CALLBACK(on_preview_tap),
-	// 		 NULL);
+	g_signal_connect(preview, "resize", G_CALLBACK(preview_resize), NULL);
+	GtkGesture *click = gtk_gesture_click_new();
+	g_signal_connect(click, "pressed", G_CALLBACK(preview_pressed), NULL);
+	gtk_widget_add_controller(preview, GTK_EVENT_CONTROLLER(click));
+
 	g_signal_connect(control_auto, "toggled",
 			 G_CALLBACK(on_control_auto_toggled), NULL);
 	g_signal_connect(control_slider, "value-changed",
@@ -858,46 +850,35 @@ startup(GApplication *app)
 	gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider),
 				       GTK_STYLE_PROVIDER_PRIORITY_USER);
 
-	// GClosure* capture_shortcut = g_cclosure_new(on_capture_shortcut, 0, 0);
+	// Setup capture action
+	GSimpleAction *capture_action = g_simple_action_new("capture", NULL);
+	g_signal_connect(capture_action, "activate", G_CALLBACK(run_capture_action), NULL);
+	g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(capture_action));
 
-	// GtkAccelGroup* accel_group = gtk_accel_group_new();
-	// gtk_accel_group_connect(accel_group,
-	// 		GDK_KEY_space,
-	// 		0,
-	// 		0,
-	// 		capture_shortcut);
+	const char *capture_accels[] = { "space", NULL };
+	gtk_application_set_accels_for_action(app, "app.capture", capture_accels);
 
-	// gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
+	// Setup quit action
+	GSimpleAction *quit_action = g_simple_action_new("quit", NULL);
+	g_signal_connect(quit_action, "activate", G_CALLBACK(run_quit_action), app);
+	g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(quit_action));
+
+	const char *quit_accels[] = { "<Ctrl>q", "<Ctrl>w", NULL };
+	gtk_application_set_accels_for_action(app, "app.quit", quit_accels);
 
 	mp_io_pipeline_start();
 
-	gtk_application_add_window(GTK_APPLICATION(app), GTK_WINDOW(window));
+	gtk_application_add_window(app, GTK_WINDOW(window));
 	gtk_widget_show(window);
 }
 
 static void
-shutdown(GApplication *app)
+shutdown(GApplication *app, gpointer data)
 {
 	// Only do cleanup in development, let the OS clean up otherwise
 #ifdef DEBUG
 	mp_io_pipeline_stop();
 #endif
-
-	G_APPLICATION_CLASS(megapixels_app_parent_class)->shutdown(app);
-}
-
-static void
-megapixels_app_init(MegapixelsApp *app)
-{
-}
-
-static void
-megapixels_app_class_init(MegapixelsAppClass *class)
-{
-	GApplicationClass *application_class = G_APPLICATION_CLASS(class);
-
-	application_class->startup = startup;
-	application_class->shutdown = shutdown;
 }
 
 int
@@ -924,10 +905,10 @@ main(int argc, char *argv[])
 
 	setenv("LC_NUMERIC", "C", 1);
 
-	MegapixelsApp *app = g_object_new(
-		megapixels_app_get_type(),
-		"application-id", "org.postmarketos.Megapixels",
-		NULL);
+	GtkApplication *app = gtk_application_new("org.postmarketos.Megapixels", 0);
+
+	g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
+	g_signal_connect(app, "shutdown", G_CALLBACK(shutdown), NULL);
 
 	g_application_run(G_APPLICATION(app), argc, argv);
 

+ 3 - 0
src/main.h

@@ -11,6 +11,9 @@ struct mp_main_state {
 	const struct mp_camera_config *camera;
 	MPCameraMode mode;
 
+	int image_width;
+	int image_height;
+
 	bool gain_is_manual;
 	int gain;
 	int gain_max;

+ 7 - 2
src/process_pipeline.c

@@ -675,11 +675,14 @@ mp_process_pipeline_capture()
 	mp_pipeline_invoke(pipeline, capture, NULL, 0);
 }
 
+static int output_buffer_width = -1;
+static int output_buffer_height = -1;
+
 static void
 on_output_changed()
 {
-	int output_buffer_width = mode.width / 2;
-	int output_buffer_height = mode.height / 2;
+	output_buffer_width = mode.width / 2;
+	output_buffer_height = mode.height / 2;
 
 	if (camera->rotate != 0 || camera->rotate != 180) {
 		int tmp = output_buffer_width;
@@ -730,6 +733,8 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state
 	struct mp_main_state main_state = {
 		.camera = camera,
 		.mode = mode,
+		.image_width = output_buffer_width,
+		.image_height = output_buffer_height,
 		.gain_is_manual = state->gain_is_manual,
 		.gain = gain,
 		.gain_max = gain_max,