mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-12 14:59:44 +03:00
libcamera: geometry: Add Rectangle::transformedBetween()
Handling cropping and scaling within a complicated pipeline involves transformations of rectangles between different coordinate systems. For example the full input of the dewarper (0,0)/1920x1080 might correspond to the rectangle (0, 243)/2592x1458 in sensor coordinates (of a 2592x1944 sensor). Add a function that allows the transformation of a rectangle defined in one reference frame (dewarper) into the coordinates of a second reference frame (sensor). Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
This commit is contained in:
parent
db9b6f8e23
commit
ec097d63ef
3 changed files with 63 additions and 0 deletions
|
@ -299,6 +299,9 @@ public:
|
|||
__nodiscard Rectangle scaledBy(const Size &numerator,
|
||||
const Size &denominator) const;
|
||||
__nodiscard Rectangle translatedBy(const Point &point) const;
|
||||
|
||||
Rectangle transformedBetween(const Rectangle &source,
|
||||
const Rectangle &target) const;
|
||||
};
|
||||
|
||||
bool operator==(const Rectangle &lhs, const Rectangle &rhs);
|
||||
|
|
|
@ -837,6 +837,55 @@ Rectangle Rectangle::translatedBy(const Point &point) const
|
|||
return { x + point.x, y + point.y, width, height };
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Transform a Rectangle from one reference rectangle to another
|
||||
* \param[in] source The \a source reference rectangle
|
||||
* \param[in] destination The \a destination reference rectangle
|
||||
*
|
||||
* The \a source and \a destination parameters describe two rectangles defined
|
||||
* in different reference systems. The Rectangle is translated from the source
|
||||
* reference system into the destination reference system.
|
||||
*
|
||||
* The typical use case for this function is to translate a selection rectangle
|
||||
* specified in a reference system, in example the sensor's pixel array, into
|
||||
* the same rectangle re-scaled and translated into a different reference
|
||||
* system, in example the output frame on which the selection rectangle is
|
||||
* applied to.
|
||||
*
|
||||
* For example, consider a sensor with a resolution of 4040x2360 pixels and a
|
||||
* assume a rectangle of (100, 100)/3840x2160 (sensorFrame) in sensor
|
||||
* coordinates is mapped to a rectangle (0,0)/(1920,1080) (displayFrame) in
|
||||
* display coordinates. This function can be used to transform an arbitrary
|
||||
* rectangle from display coordinates to sensor coordinates or vice versa:
|
||||
*
|
||||
* \code{.cpp}
|
||||
* Rectangle sensorReference(100, 100, 3840, 2160);
|
||||
* Rectangle displayReference(0, 0, 1920, 1080);
|
||||
*
|
||||
* // Bottom right quarter in sensor coordinates
|
||||
* Rectangle sensorRect(2020, 100, 1920, 1080);
|
||||
* displayRect = sensorRect.transformedBetween(sensorReference, displayReference);
|
||||
* // displayRect is now (960, 540)/960x540
|
||||
*
|
||||
* // Transformation back to sensor coordinates
|
||||
* sensorRect = displayRect.transformedBetween(displayReference, sensorReference);
|
||||
* \endcode
|
||||
*/
|
||||
Rectangle Rectangle::transformedBetween(const Rectangle &source,
|
||||
const Rectangle &destination) const
|
||||
{
|
||||
Rectangle r;
|
||||
double sx = static_cast<double>(destination.width) / source.width;
|
||||
double sy = static_cast<double>(destination.height) / source.height;
|
||||
|
||||
r.x = static_cast<int>((x - source.x) * sx) + destination.x;
|
||||
r.y = static_cast<int>((y - source.y) * sy) + destination.y;
|
||||
r.width = static_cast<int>(width * sx);
|
||||
r.height = static_cast<int>(height * sy);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compare rectangles for equality
|
||||
* \return True if the two rectangles are equal, false otherwise
|
||||
|
|
|
@ -495,6 +495,17 @@ protected:
|
|||
return TestFail;
|
||||
}
|
||||
|
||||
Rectangle f1 = Rectangle(100, 200, 3000, 2000);
|
||||
Rectangle f2 = Rectangle(200, 300, 1500, 1000);
|
||||
/* Bottom right quarter of the corresponding frames. */
|
||||
Rectangle r1 = Rectangle(100 + 1500, 200 + 1000, 1500, 1000);
|
||||
Rectangle r2 = Rectangle(200 + 750, 300 + 500, 750, 500);
|
||||
if (r1.transformedBetween(f1, f2) != r2 ||
|
||||
r2.transformedBetween(f2, f1) != r1) {
|
||||
cout << "Rectangle::transformedBetween() test failed" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue