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

[SFML 2.X] Narzędzie Fill - czyli wypełnianie danego obszaru kolorem

Ostatnio zmodyfikowano 2025-09-11 23:48
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
[SFML 2.X] Narzędzie Fill - czyli wypełnianie danego obszaru kolorem
» 2025-09-11 19:41:00
Cześć Wszystkim!
Próbuję napisać poprawnie narzędzie Fill w moim programie do edycji grafiki. Narzędzie to ma działać w ten sposób, że klikamy w dane miejsce na canvasie i wypełnia cały możliwy obszar zadanym kolorem. Napisałem pod to funkcje jedną główną i drugą rekurencyjną. Narzędzie czasem działa a czasem wyrzuca błąd mallock.

Log z błędem

_NODISCARD _Ret_notnull_ _Post_writable_byte_size_(size) _VCRT_ALLOCATOR
_CRT_SECURITYCRITICAL_ATTRIBUTE
void* __CRTDECL operator new(size_t const size)
{
    for (;;)
    {
        if (void* const block = malloc(size))
        {
            return block;
        }

        if (_callnewh(size) == 0)
        {
            if (size == SIZE_MAX)
            {
                __scrt_throw_std_bad_array_new_length();
            }
            else
            {
                __scrt_throw_std_bad_alloc();
            }
        }

        // The new handler was successful; try to allocate again...
    }

Kod narzędzia
C/C++
void fill( sf::Color colorToEdit, sf::Color newColor, sf::Vector2i tile ) {
   
   
sf::IntRect tileRect = sf::IntRect( 0, 0, animation->getCurrentLayer()->image.getSize().x, animation->getCurrentLayer()->image.getSize().y );
   
if( !tileRect.contains( tile ) )
       
 return;
   
   
if( colorToEdit == newColor )
       
 return;
   
   
   
if( animation->getCurrentLayer()->image.getPixel( tile.x, tile.y ) == colorToEdit ) {
       
animation->getCurrentLayer()->image.setPixel( tile.x, tile.y, newColor );
       
       
fill( colorToEdit, newColor, sf::Vector2i( tile.x - 1, tile.y ) );
       
fill( colorToEdit, newColor, sf::Vector2i( tile.x + 1, tile.y ) );
       
fill( colorToEdit, newColor, sf::Vector2i( tile.x, tile.y - 1 ) );
       
fill( colorToEdit, newColor, sf::Vector2i( tile.x, tile.y + 1 ) );
   
}
   
}

void fillPixels( sf::Color color ) {
   
sf::Vector2i tile = worldToTile( worldMousePosition, position, zoom, zoom_delta );
   
sf::Color colorToEdit = animation->getCurrentLayer()->image.getPixel( tile.x, tile.y );
   
fill( colorToEdit, color, tile );
}
P-182990
tBane
Temat założony przez niniejszego użytkownika
» 2025-09-11 19:50:39
Chyba znalazłem rozwiązanie. Zamiast stosować rekurencję użyłem std::vector do przechowywania współrzędnych pikseli i tym sposobem omijam przepełnienie .. stosu ? w każdym bądź razie pamięć wystarcza :-)

C/C++
void fill( sf::Color colorToEdit, sf::Color newColor, sf::Vector2i pixelCoords ) {
   
   
if( colorToEdit == newColor )
       
 return;
   
   
sf::IntRect imageRect = sf::IntRect( 0, 0, animation->getCurrentLayer()->image.getSize().x, animation->getCurrentLayer()->image.getSize().y );
   
   
std::vector < sf::Vector2i > pixels;
   
pixels.push_back( pixelCoords );
   
while( !pixels.empty() ) {
       
       
sf::Vector2i t = pixels.back();
       
pixels.pop_back();
       
       
if( !imageRect.contains( t ) )
           
 continue;
       
       
if( animation->getCurrentLayer()->image.getPixel( t.x, t.y ) == colorToEdit ) {
           
animation->getCurrentLayer()->image.setPixel( t.x, t.y, newColor );
           
           
pixels.push_back( sf::Vector2i( t.x - 1, t.y ) );
           
pixels.push_back( sf::Vector2i( t.x + 1, t.y ) );;
           
pixels.push_back( sf::Vector2i( t.x, t.y - 1 ) );;
           
pixels.push_back( sf::Vector2i( t.x, t.y + 1 ) );;
       
}
       
    }
   
}

void fillPixels( sf::Color color ) {
   
sf::Vector2i tile = worldToTile( worldMousePosition, position, zoom, zoom_delta );
   
sf::Color colorToEdit = animation->getCurrentLayer()->image.getPixel( tile.x, tile.y );
   
fill( colorToEdit, color, tile );
}
P-182991
pekfos
» 2025-09-11 22:18:53
Co to za log z błędem? W tym kodzie nie widać dynamicznej alokacji pamięci, a przepełnienie stosu nie daje takiego objawu.
P-182992
tBane
Temat założony przez niniejszego użytkownika
» 2025-09-11 22:34:22
IDE nie pokazywało logu z błędem kompilacji tylko przekierowało do tego kodu, który wstawiłem. ChatGPT zasugerował, że to przez przepełnienie pamięci więc napisałem kod z std::Vector. Dobry jest ten kod?
P-182993
pekfos
» 2025-09-11 22:43:50
W sensie że uruchomiłeś program pod debuggerem i wywaliło błąd w tym fragmencie? Masz na repo tą wersję do uruchomienia?
P-182994
tBane
Temat założony przez niniejszego użytkownika
» 2025-09-11 22:46:51
P-182995
pekfos
» 2025-09-11 23:03:15
Dobra, to jest przepełnienie stosu tylko jako "log" wziąłeś kod źródłowy, zamiast faktyczny komunikat błędu który wyskakuje.
Unhandled exception at 0x00007FFA9FC1B3C2 (ntdll.dll) in xxxxx.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x0000003BB34F3FD8).
P-182996
tBane
Temat założony przez niniejszego użytkownika
» 2025-09-11 23:05:23
Mi takiego błędu nie pokazuje, tylko wyświetla nową zakładkę z kodem, więc zgadywałem trochę. Czy mój drugi kod rozwiązuje ten problem? To znaczy czy to rozwiazanie jest optymalne ?
P-182997
« 1 » 2
  Strona 1 z 2 Następna strona