diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h
index b8b24bb1..1e54a4fe 100644
--- a/include/libcamera/internal/software_isp/software_isp.h
+++ b/include/libcamera/internal/software_isp/software_isp.h
@@ -67,6 +67,7 @@ public:
 		      const std::vector<std::reference_wrapper<const StreamConfiguration>> &outputCfgs,
 		      const ipa::softisp::IPAConfigInfo &configInfo,
 		      ControlInfoMap *ipaControls);
+	Rectangle inputCrop() const;
 
 	int exportBuffers(const Stream *stream, unsigned int count,
 			  std::vector<std::unique_ptr<FrameBuffer>> *buffers);
diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp
index a4854e51..14b09937 100644
--- a/src/libcamera/software_isp/debayer.cpp
+++ b/src/libcamera/software_isp/debayer.cpp
@@ -66,6 +66,17 @@ Debayer::~Debayer()
 }
 
 /**
+ * \fn Rectangle Debayer::inputCrop() const
+ * \brief Retrieve the input region visible in the configured output
+ *
+ * The rectangle is in input-buffer coordinates and excludes any additional
+ * alignment performed for statistics sampling. It is valid after a successful
+ * configure() call.
+ *
+ * \return The configured image crop
+ */
+
+/**
  * \fn int Debayer::configure()
  * \brief Configure the debayer object according to the passed in parameters
  * \param[in] inputCfg The input configuration
diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h
index 55685226..7ffdaea1 100644
--- a/src/libcamera/software_isp/debayer.h
+++ b/src/libcamera/software_isp/debayer.h
@@ -53,6 +53,7 @@ public:
 	virtual void stop() {}
 
 	virtual SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) = 0;
+	virtual Rectangle inputCrop() const = 0;
 
 	virtual const SharedFD &getStatsFD() = 0;
 
diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h
index 2c88c9e1..1e037a79 100644
--- a/src/libcamera/software_isp/debayer_cpu.h
+++ b/src/libcamera/software_isp/debayer_cpu.h
@@ -46,6 +46,10 @@ public:
 	int start() override;
 	void stop() override;
 	SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override;
+	Rectangle inputCrop() const override
+	{
+		return window_.translatedBy({ static_cast<int>(xShift_), 0 });
+	}
 	const SharedFD &getStatsFD() override { return stats_->getStatsFD(); }
 
 private:
diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
index 9f3dc752..cd9ad888 100644
--- a/src/libcamera/software_isp/debayer_egl.cpp
+++ b/src/libcamera/software_isp/debayer_egl.cpp
@@ -327,7 +327,8 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,
 	 * The GPU scales the visible sensor crop to outputSize_. Statistics
 	 * consume the original input buffer, so use sensor coordinates here.
 	 */
-	stats_->setWindow(debayerCrop(inputCfg.size, nativeOutputSize_, outputSize_));
+	inputCrop_ = debayerCrop(inputCfg.size, nativeOutputSize_, outputSize_);
+	stats_->setWindow(inputCrop_);
 
 	inputBufferCount_ = inputCfg.bufferCount;
 	outputBufferCount_ = outputCfg.bufferCount;
diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
index 52b8aa07..5a4cd2d8 100644
--- a/src/libcamera/software_isp/debayer_egl.h
+++ b/src/libcamera/software_isp/debayer_egl.h
@@ -60,6 +60,7 @@ public:
 	const SharedFD &getStatsFD() override { return stats_->getStatsFD(); }
 
 	SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override;
+	Rectangle inputCrop() const override { return inputCrop_; }
 
 private:
 	static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);
@@ -111,6 +112,7 @@ private:
 	GLint contrastExpUniformDataIn_;
 
 	Size nativeOutputSize_;
+	Rectangle inputCrop_;
 	std::unique_ptr<SwStatsCpu> stats_;
 	eGL egl_;
 	uint32_t width_;
diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
index a4097605..c0c55fbf 100644
--- a/src/libcamera/software_isp/software_isp.cpp
+++ b/src/libcamera/software_isp/software_isp.cpp
@@ -306,6 +306,20 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg,
 }
 
 /**
+ * \brief Retrieve the input region used to produce the configured output
+ *
+ * The rectangle is expressed in input-buffer pixels, before any Bayer
+ * alignment applied by the statistics engine. It is valid after configure()
+ * succeeds and describes the selected CPU or EGL debayer backend.
+ *
+ * \return The configured input crop
+ */
+Rectangle SoftwareIsp::inputCrop() const
+{
+	return debayer_->inputCrop();
+}
+
+/**
  * \brief Export the buffers from the Software ISP
  * \param[in] stream Output stream exporting the buffers
  * \param[in] count Number of buffers to allocate
