mirror of
https://github.com/SFML/SFML.git
synced 2024-12-01 15:51:04 +08:00
Clarify Image::copy implementation
This commit is contained in:
parent
6cd07a043f
commit
c4790bcb14
@ -199,7 +199,7 @@ public:
|
|||||||
/// Note that this function can fail if either image is invalid
|
/// Note that this function can fail if either image is invalid
|
||||||
/// (i.e. zero-sized width or height), or if \a sourceRect is
|
/// (i.e. zero-sized width or height), or if \a sourceRect is
|
||||||
/// not within the boundaries of the \a source parameter, or
|
/// not within the boundaries of the \a source parameter, or
|
||||||
/// if the destination area is invalid (i.e. negative coordinates).
|
/// if the destination area is out of the boundaries of this image.
|
||||||
///
|
///
|
||||||
/// On failure, the destination image is left unchanged.
|
/// On failure, the destination image is left unchanged.
|
||||||
///
|
///
|
||||||
|
@ -174,56 +174,53 @@ void Image::createMaskFromColor(const Color& color, Uint8 alpha)
|
|||||||
[[nodiscard]] bool Image::copy(const Image& source, const Vector2u& dest, const IntRect& sourceRect, bool applyAlpha)
|
[[nodiscard]] bool Image::copy(const Image& source, const Vector2u& dest, const IntRect& sourceRect, bool applyAlpha)
|
||||||
{
|
{
|
||||||
// Make sure that both images are valid
|
// Make sure that both images are valid
|
||||||
if ((source.m_size.x == 0) || (source.m_size.y == 0) || (m_size.x == 0) || (m_size.y == 0))
|
if (source.m_size.x == 0 || source.m_size.y == 0 || m_size.x == 0 || m_size.y == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Make sure the sourceRect left & top and the {left, top} + {width, height} within bounds
|
// Make sure the sourceRect components are non-negative before casting them to unsigned values
|
||||||
if (static_cast<unsigned int>(sourceRect.left) >= source.m_size.x || static_cast<unsigned int>(sourceRect.left + sourceRect.width) > source.m_size.x ||
|
if (sourceRect.left < 0 || sourceRect.top < 0 || sourceRect.width < 0 || sourceRect.height < 0)
|
||||||
static_cast<unsigned int>(sourceRect.top) >= source.m_size.y || static_cast<unsigned int>(sourceRect.top + sourceRect.height) > source.m_size.y)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Adjust the source rectangle
|
Rect<unsigned int> srcRect(sourceRect);
|
||||||
IntRect srcRect = sourceRect;
|
|
||||||
if (srcRect.width == 0 || (srcRect.height == 0))
|
// Use the whole source image as srcRect if the provided source rectangle is empty
|
||||||
|
if (srcRect.width == 0 || srcRect.height == 0)
|
||||||
{
|
{
|
||||||
srcRect.left = 0;
|
srcRect = Rect<unsigned int>({0, 0}, source.m_size);
|
||||||
srcRect.top = 0;
|
|
||||||
srcRect.width = static_cast<int>(source.m_size.x);
|
|
||||||
srcRect.height = static_cast<int>(source.m_size.y);
|
|
||||||
}
|
}
|
||||||
|
// Otherwise make sure the provided source rectangle fits into the source image
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (srcRect.left < 0) srcRect.left = 0;
|
// Checking the bottom right corner is enough because
|
||||||
if (srcRect.top < 0) srcRect.top = 0;
|
// left and top are non-negative and width and height are positive.
|
||||||
if (srcRect.width > static_cast<int>(source.m_size.x)) srcRect.width = static_cast<int>(source.m_size.x);
|
if (source.m_size.x < srcRect.left + srcRect.width ||
|
||||||
if (srcRect.height > static_cast<int>(source.m_size.y)) srcRect.height = static_cast<int>(source.m_size.y);
|
source.m_size.y < srcRect.top + srcRect.height)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then find the valid bounds of the destination rectangle
|
// Make sure the destination position is within this image bounds
|
||||||
auto width = static_cast<unsigned int>(srcRect.width);
|
if (m_size.x <= dest.x || m_size.y <= dest.y)
|
||||||
auto height = static_cast<unsigned int>(srcRect.height);
|
|
||||||
if (dest.x + width > m_size.x) width = m_size.x - dest.x;
|
|
||||||
if (dest.y + height > m_size.y) height = m_size.y - dest.y;
|
|
||||||
|
|
||||||
// Make sure the destination area is valid
|
|
||||||
if ((width <= 0) || (height <= 0))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Then find the valid size of the destination rectangle
|
||||||
|
const Vector2u dstSize(std::min(m_size.x - dest.x, srcRect.width),
|
||||||
|
std::min(m_size.y - dest.y, srcRect.height));
|
||||||
|
|
||||||
// Precompute as much as possible
|
// Precompute as much as possible
|
||||||
std::size_t pitch = static_cast<std::size_t>(width) * 4;
|
const std::size_t pitch = static_cast<std::size_t>(dstSize.x) * 4;
|
||||||
unsigned int rows = height;
|
const unsigned int srcStride = source.m_size.x * 4;
|
||||||
int srcStride = static_cast<int>(source.m_size.x) * 4;
|
const unsigned int dstStride = m_size.x * 4;
|
||||||
int dstStride = static_cast<int>(m_size.x) * 4;
|
|
||||||
const Uint8* srcPixels = source.m_pixels.data() + (static_cast<unsigned int>(srcRect.left) + static_cast<unsigned int>(srcRect.top) * source.m_size.x) * 4;
|
const Uint8* srcPixels = source.m_pixels.data() + (srcRect.left + srcRect.top * source.m_size.x) * 4;
|
||||||
Uint8* dstPixels = m_pixels.data() + (dest.x + dest.y * m_size.x) * 4;
|
Uint8* dstPixels = m_pixels.data() + (dest.x + dest.y * m_size.x) * 4;
|
||||||
|
|
||||||
// Copy the pixels
|
// Copy the pixels
|
||||||
if (applyAlpha)
|
if (applyAlpha)
|
||||||
{
|
{
|
||||||
// Interpolation using alpha values, pixel by pixel (slower)
|
// Interpolation using alpha values, pixel by pixel (slower)
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
for (unsigned int i = 0; i < dstSize.y; ++i)
|
||||||
{
|
{
|
||||||
for (unsigned int j = 0; j < width; ++j)
|
for (unsigned int j = 0; j < dstSize.x; ++j)
|
||||||
{
|
{
|
||||||
// Get a direct pointer to the components of the current pixel
|
// Get a direct pointer to the components of the current pixel
|
||||||
const Uint8* src = srcPixels + j * 4;
|
const Uint8* src = srcPixels + j * 4;
|
||||||
@ -251,7 +248,7 @@ void Image::createMaskFromColor(const Color& color, Uint8 alpha)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Optimized copy ignoring alpha values, row by row (faster)
|
// Optimized copy ignoring alpha values, row by row (faster)
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
for (unsigned int i = 0; i < dstSize.y; ++i)
|
||||||
{
|
{
|
||||||
std::memcpy(dstPixels, srcPixels, pitch);
|
std::memcpy(dstPixels, srcPixels, pitch);
|
||||||
srcPixels += srcStride;
|
srcPixels += srcStride;
|
||||||
|
Loading…
Reference in New Issue
Block a user