///////////////////////////////////////////////////////
| 586 | |
| 587 | //////////////////////////////////////////////////////////// |
| 588 | bool Image::copy(const Image& source, Vector2u dest, const IntRect& sourceRect, bool applyAlpha) |
| 589 | { |
| 590 | // Make sure that both images are valid |
| 591 | if (source.m_size.x == 0 || source.m_size.y == 0 || m_size.x == 0 || m_size.y == 0) |
| 592 | return false; |
| 593 | |
| 594 | // Make sure the sourceRect components are non-negative before casting them to unsigned values |
| 595 | if (sourceRect.position.x < 0 || sourceRect.position.y < 0 || sourceRect.size.x < 0 || sourceRect.size.y < 0) |
| 596 | return false; |
| 597 | |
| 598 | Rect<unsigned int> srcRect(sourceRect); |
| 599 | |
| 600 | // Use the whole source image as srcRect if the provided source rectangle is empty |
| 601 | if (srcRect.size.x == 0 || srcRect.size.y == 0) |
| 602 | { |
| 603 | srcRect = Rect<unsigned int>({0, 0}, source.m_size); |
| 604 | } |
| 605 | // Otherwise make sure the provided source rectangle fits into the source image |
| 606 | else |
| 607 | { |
| 608 | // Checking the bottom right corner is enough because |
| 609 | // left and top are non-negative and width and height are positive. |
| 610 | if (source.m_size.x < srcRect.position.x + srcRect.size.x || source.m_size.y < srcRect.position.y + srcRect.size.y) |
| 611 | return false; |
| 612 | } |
| 613 | |
| 614 | // Make sure the destination position is within this image bounds |
| 615 | if (m_size.x <= dest.x || m_size.y <= dest.y) |
| 616 | return false; |
| 617 | |
| 618 | // Then find the valid size of the destination rectangle |
| 619 | const Vector2u dstSize(std::min(m_size.x - dest.x, srcRect.size.x), std::min(m_size.y - dest.y, srcRect.size.y)); |
| 620 | |
| 621 | // Precompute as much as possible |
| 622 | const std::size_t pitch = static_cast<std::size_t>(dstSize.x) * 4; |
| 623 | const unsigned int srcStride = source.m_size.x * 4; |
| 624 | const unsigned int dstStride = m_size.x * 4; |
| 625 | |
| 626 | const std::uint8_t* srcPixels = source.m_pixels.data() + (srcRect.position.x + srcRect.position.y * source.m_size.x) * 4; |
| 627 | std::uint8_t* dstPixels = m_pixels.data() + (dest.x + dest.y * m_size.x) * 4; |
| 628 | |
| 629 | // Copy the pixels |
| 630 | if (applyAlpha) |
| 631 | { |
| 632 | // Interpolation using alpha values, pixel by pixel (slower) |
| 633 | for (unsigned int i = 0; i < dstSize.y; ++i) |
| 634 | { |
| 635 | for (unsigned int j = 0; j < dstSize.x; ++j) |
| 636 | { |
| 637 | // Get a direct pointer to the components of the current pixel |
| 638 | const std::uint8_t* src = srcPixels + j * 4; |
| 639 | std::uint8_t* dst = dstPixels + j * 4; |
| 640 | |
| 641 | // Interpolate RGBA components using the alpha values of the destination and source pixels |
| 642 | const std::uint8_t srcAlpha = src[3]; |
| 643 | const std::uint8_t dstAlpha = dst[3]; |
| 644 | const auto outAlpha = static_cast<std::uint8_t>(srcAlpha + dstAlpha - srcAlpha * dstAlpha / 255); |
| 645 |
nothing calls this directly
no outgoing calls
no test coverage detected