diff --git a/picamera2/configuration.py b/picamera2/configuration.py index 7c6a3f2d..9c01794b 100644 --- a/picamera2/configuration.py +++ b/picamera2/configuration.py @@ -83,7 +83,7 @@ def align(self, optimal=True): class StreamConfiguration(Configuration): - _ALLOWED_FIELDS = ("size", "format", "stride", "framesize") + _ALLOWED_FIELDS = ("size", "format", "stride", "framesize", "preserve_ar") _FIELD_CLASS_MAP = {} _FORWARD_FIELDS = {} diff --git a/picamera2/picamera2.py b/picamera2/picamera2.py index d3117d37..72f57e42 100644 --- a/picamera2/picamera2.py +++ b/picamera2/picamera2.py @@ -655,7 +655,7 @@ def _make_initial_stream_config(stream_config: dict, updates: dict, ignore_list= """ if updates is None: return None - valid = ("format", "size", "stride") + valid = ("format", "size", "stride", "preserve_ar") for key, value in updates.items(): if isinstance(value, SensorFormat): value = str(value) @@ -692,9 +692,9 @@ def create_preview_configuration(self, main={}, lores=None, raw={}, transform=li if not self._is_rpi_camera(): raw = None sensor = None - main = self._make_initial_stream_config({"format": "XBGR8888", "size": (640, 480)}, main) + main = self._make_initial_stream_config({"format": "XBGR8888", "size": (640, 480), "preserve_ar": True}, main) self.align_stream(main, optimal=False) - lores = self._make_initial_stream_config({"format": "YUV420", "size": main["size"]}, lores) + lores = self._make_initial_stream_config({"format": "YUV420", "size": main["size"], "preserve_ar": False}, lores) if lores is not None: self.align_stream(lores, optimal=False) raw = self._make_initial_stream_config({"format": self.sensor_format, "size": main["size"]}, @@ -726,9 +726,10 @@ def create_still_configuration(self, main={}, lores=None, raw={}, transform=libc if not self._is_rpi_camera(): raw = None sensor = None - main = self._make_initial_stream_config({"format": "BGR888", "size": self.sensor_resolution}, main) + main = self._make_initial_stream_config({"format": "BGR888", "size": self.sensor_resolution, "preserve_ar": True}, + main) self.align_stream(main, optimal=False) - lores = self._make_initial_stream_config({"format": "YUV420", "size": main["size"]}, lores) + lores = self._make_initial_stream_config({"format": "YUV420", "size": main["size"], "preserve_ar": False}, lores) if lores is not None: self.align_stream(lores, optimal=False) raw = self._make_initial_stream_config({"format": self.sensor_format, "size": main["size"]}, @@ -760,9 +761,9 @@ def create_video_configuration(self, main={}, lores=None, raw={}, transform=libc if not self._is_rpi_camera(): raw = None sensor = None - main = self._make_initial_stream_config({"format": "XBGR8888", "size": (1280, 720)}, main) + main = self._make_initial_stream_config({"format": "XBGR8888", "size": (1280, 720), "preserve_ar": True}, main) self.align_stream(main, optimal=False) - lores = self._make_initial_stream_config({"format": "YUV420", "size": main["size"]}, lores) + lores = self._make_initial_stream_config({"format": "YUV420", "size": main["size"], "preserve_ar": False}, lores) if lores is not None: self.align_stream(lores, optimal=False) raw = self._make_initial_stream_config({"format": self.sensor_format, "size": main["size"]}, @@ -1121,6 +1122,14 @@ def configure_(self, camera_config="preview") -> None: self.controls = Controls(self, controls=self.camera_config['controls']) self.configure_count += 1 + if "ScalerCrops" in self.camera_controls: + par_crop = self.camera_controls["ScalerCrops"] + full_fov = self.camera_controls["ScalerCrop"][1] + scaler_crops = [par_crop[0] if camera_config["main"]["preserve_ar"] else full_fov] + if self.lores_index >= 0: + scaler_crops.append(par_crop[1] if camera_config["lores"]["preserve_ar"] else scaler_crops[0]) + self.set_controls({"ScalerCrops": scaler_crops}) + def configure(self, camera_config="preview") -> None: """Configure the camera system with the given configuration.""" self.configure_(camera_config)