Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[SFML 3.0.2] Kopiowanie sf::Image wraz z kanałem alfa do schowka

Ostatnio zmodyfikowano 2025-11-07 21:05
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
[SFML 3.0.2] Kopiowanie sf::Image wraz z kanałem alfa do schowka
» 2025-11-07 12:29:17
Witam. Jak skopiować sf::Image wraz z kanałem alfa (przezroczystością) do schowka systemowego? Mam kod ale nie obsługuje kanału alfa :-/

Kopioweanie bez kanału alfa
C/C++
bool copyImageToClipboard( sf::Image & image, sf::IntRect rect ) {
   
   
if( image.getSize().x == 0 || image.getSize().y == 0 ) {
       
return false;
   
}
   
   
int x0 = std::clamp( rect.position.x, 0, int( image.getSize().x ) );
   
int y0 = std::clamp( rect.position.y, 0, int( image.getSize().y ) );
   
int x1 = std::clamp( rect.position.x + rect.size.x, 0, int( image.getSize().x ) );
   
int y1 = std::clamp( rect.position.y + rect.size.y, 0, int( image.getSize().y ) );
   
   
std::wcout << x0 << "\n";
   
std::wcout << y0 << "\n";
   
std::wcout << x1 << "\n";
   
std::wcout << y1 << "\n";
   
   
const unsigned int w =( x1 > x0 ) ? unsigned( x1 - x0 )
        :
0u;
   
const unsigned int h =( y1 > y0 ) ? unsigned( y1 - y0 )
        :
0u;
   
sf::IntRect r( { 0, 0 }, { int( image.getSize().x ), int( image.getSize().y ) } );
   
   
   
if( !rect.findIntersection( r ).has_value() || w == 0 || h == 0 ) {
       
if( w == 0 ) std::cout << " w is 0\n"; // tu  sie włącza
       
       
if( h == 0 ) std::cout << " h is 0\n"; // tu  sie włącza
       
       
return false;
   
}
   
   
const uint8_t * pixels = image.getPixelsPtr();
   
   
BITMAPINFOHEADER bi { };
   
bi.biSize = sizeof( BITMAPINFOHEADER );
   
bi.biWidth = LONG( w );
   
bi.biHeight = - LONG( h );
   
bi.biPlanes = 1;
   
bi.biBitCount = 32;
   
bi.biCompression = BI_RGB;
   
   
const SIZE_T pixelBytes = SIZE_T( w ) * SIZE_T( h ) * 4;
   
HGLOBAL hMem = GlobalAlloc( GHND, sizeof( BITMAPINFOHEADER ) + pixelBytes );
   
if( !hMem ) return false;
   
   
void * pMem = GlobalLock( hMem );
   
auto * pHeader = static_cast < BYTE * >( pMem );
   
auto * dstPixels = pHeader + sizeof( BITMAPINFOHEADER );
   
   
std::memcpy( pHeader, & bi, sizeof( BITMAPINFOHEADER ) );
   
   
for( unsigned int y = 0; y < h; ++y ) {
       
const uint8_t * srcRow = pixels +(( y0 + y ) * image.getSize().x + x0 ) * 4;
       
uint8_t * dstRow = dstPixels +( y * w ) * 4;
       
       
for( unsigned int x = 0; x < w; ++x ) {
           
const uint8_t r = srcRow[ 4 * x + 0 ];
           
const uint8_t g = srcRow[ 4 * x + 1 ];
           
const uint8_t b = srcRow[ 4 * x + 2 ];
           
const uint8_t a = srcRow[ 4 * x + 3 ];
           
           
dstRow[ 4 * x + 0 ] = b; // B
           
dstRow[ 4 * x + 1 ] = g; // G
           
dstRow[ 4 * x + 2 ] = r; // R
           
dstRow[ 4 * x + 3 ] = a; // A
       
}
    }
   
   
GlobalUnlock( hMem );
   
   
if( !OpenClipboard( nullptr ) ) {
       
GlobalFree( hMem );
       
return false;
   
}
   
EmptyClipboard();
   
   
if( !SetClipboardData( CF_DIB, hMem ) ) {
       
CloseClipboard();
       
GlobalFree( hMem );
       
return false;
   
}
   
CloseClipboard();
   
   
   
return true;
}
P-183408
tBane
Temat założony przez niniejszego użytkownika
» 2025-11-07 21:05:02
C/C++
bool copyImageToClipboard( sf::Image & image, sf::IntRect rect )
{
   
const auto imgW = static_cast < int >( image.getSize().x );
   
const auto imgH = static_cast < int >( image.getSize().y );
   
if( imgW == 0 || imgH == 0 ) return false;
   
   
// Granice obrazu i bezpieczne przecięcie z rect
   
const sf::IntRect imgRect( { 0, 0 }, { imgW, imgH } );
   
std::optional < sf::IntRect > interOpt = rect.findIntersection( imgRect );
   
if( !interOpt.has_value() ) {
       
std::cout << "Brak przeciecia z obrazem.\n";
       
return false;
   
}
   
const sf::IntRect inter = * interOpt;
   
   
// Wymiary i start
   
const int x0 = inter.position.x;
   
const int y0 = inter.position.y;
   
const unsigned w = static_cast < unsigned >( inter.size.x > 0 ? inter.size.x: 0 );
   
const unsigned h = static_cast < unsigned >( inter.size.y > 0 ? inter.size.y: 0 );
   
if( w == 0 || h == 0 ) {
       
if( w == 0 ) std::cout << "w == 0\n";
       
       
if( h == 0 ) std::cout << "h == 0\n";
       
       
return false;
   
}
   
   
std::wcout << x0 << L"\n" << y0 << L"\n"
   
<<( x0 + static_cast < int >( w ) ) << L"\n"
   
<<( y0 + static_cast < int >( h ) ) << L"\n";
   
   
const uint8_t * src = image.getPixelsPtr(); // RGBA (R,G, B, A)
   
    // Przygotuj nagłówek DIB 32bpp (BGRA), top-down
   
BITMAPINFOHEADER bi { };
   
bi.biSize = sizeof( BITMAPINFOHEADER );
   
bi.biWidth = static_cast < LONG >( w );
   
bi.biHeight = - static_cast < LONG >( h ); // top-down
   
bi.biPlanes = 1;
   
bi.biBitCount = 32; // 32 bpp
   
bi.biCompression = BI_RGB;
   
bi.biSizeImage = w * h * 4; // nieobowiązkowe przy BI_RGB, ale pomocne
   
   
const SIZE_T headerSize = sizeof( BITMAPINFOHEADER );
   
const SIZE_T pixelBytes = static_cast < SIZE_T >( w ) * static_cast < SIZE_T >( h ) * 4;
   
   
HGLOBAL hMem = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, headerSize + pixelBytes );
   
if( !hMem ) return false;
   
   
void * pMem = GlobalLock( hMem );
   
if( !pMem ) {
       
GlobalFree( hMem );
       
return false;
   
}
   
   
auto * pHeader = static_cast < uint8_t * >( pMem );
   
auto * dstPixels = pHeader + headerSize;
   
   
std::memcpy( pHeader, & bi, headerSize );
   
   
// Kopiowanie pikseli: RGBA (SFML) -> BGRA (DIB)
    // Dzięki top-down (ujemny height) kopiujemy od y=0 w dół bez odwracania.
   
const unsigned srcStride = static_cast < unsigned >( image.getSize().x ) * 4;
   
const unsigned dstStride = w * 4;
   
   
for( unsigned y = 0; y < h; ++y ) {
       
const uint8_t * srcRow = src +( static_cast < unsigned >( y0 ) + y ) * srcStride + static_cast < unsigned >( x0 ) * 4;
       
uint8_t * dstRow = dstPixels + y * dstStride;
       
       
for( unsigned x = 0; x < w; ++x ) {
           
const uint8_t r = srcRow[ 4 * x + 0 ];
           
const uint8_t g = srcRow[ 4 * x + 1 ];
           
const uint8_t b = srcRow[ 4 * x + 2 ];
           
const uint8_t a = srcRow[ 4 * x + 3 ];
           
           
// DIB (CF_DIB, BI_RGB, 32bpp) oczekuje BGRA
           
dstRow[ 4 * x + 0 ] = b; // B
           
dstRow[ 4 * x + 1 ] = g; // G
           
dstRow[ 4 * x + 2 ] = r; // R
           
dstRow[ 4 * x + 3 ] = a; // A (Windows może pominąć, ale zachowujemy)
       
}
    }
   
   
GlobalUnlock( hMem );
   
   
if( !OpenClipboard( nullptr ) ) {
       
GlobalFree( hMem );
       
return false;
   
}
   
// Ważne: po ustawieniu danych NIE wolno już wywoływać GlobalFree – własność przejmuje schowek.
   
EmptyClipboard();
   
if( !SetClipboardData( CF_DIB, hMem ) ) {
       
CloseClipboard();
       
GlobalFree( hMem );
       
return false;
   
}
   
CloseClipboard();
   
   
return true;
}
P-183410
« 1 »
  Strona 1 z 1