Aktualności

Powitaj nowego opiekuna Ansela

Jiyoné (Guillaume Stutin) przejął opiekę nad Anselem od października 2025. Obecnym celem jest przekształcenie Ansela w spółdzielnię , w której użytkownicy mogą stawać się członkami i demokratycznie kontrolować kierunki i priorytety projektu, a także zagwarantować sprawiedliwe wynagrodzenie oraz bezpieczne środowisko pracy tym, którzy angażują swoją siłę roboczą w projekt. Opisałem problem i proponowane rozwiązanie na stronie demokracja.

W oczekiwaniu na prawdziwą strukturę Guillaume potrzebuje darowizn, aby opłacać swoje rachunki, i możesz wesprzeć go na Liberapay .

Zmiany w dystrybucji pakietów Ansel

Development

Klony docelowe (target clones)

Kompilowanie oprogramowania natywnie na komputerze poprawiało czasy działania na CPU o około 30 % w porównaniu z gotowymi pakietami. Powodem jest to, że kompilator dokonuje specyficznych optymalizacji dla docelowego sprzętu, na którym jest kompilowany, podczas gdy gotowe pakiety muszą pozostać uniwersalne i uruchamiają bardziej zachowawcze optymalizacje ze względu na szerokie wsparcie. Zwróć uwagę, że jądra OpenCL i tak są kompilowane dla Twojego konkretnego GPU przy użyciu Twojego sterownika OpenCL, więc tam sytuacja wygląda inaczej.

Elementy sterujące kolorem wreszcie poprawne

Development Design

Wprowadzenie

Narzędzia kontra maszyny, rzemiosło kontra przemysł

W swojej książce Społeczeństwo technologiczne (1954) Jacques Ellul przedstawia różnicę między okresem przed- i porewolucji przemysłowej w następujący sposób:

Epoka przedindustrialna to panowanie narzędzia i rzemiosła. Najważniejszą cechą narzędzi jest to, że są ogólne, wszechstronne i łatwe do przystosowania. To rzemieślnik musi rozwijać swoje umiejętności, aby narzędzia podążały za jego intencją, tak by ręka nadrabiała ograniczenia instrumentu. Koncepcja ta jest wciąż dobrze znana dzisiejszym muzykom: musisz ćwiczyć, uczyć się, próbować, ponosić porażki, próbować ponownie… nie ma dróg na skróty. Ellul podkreśla ideę oszczędności, która towarzyszy narzędziom: zasoby są ograniczone, więc Twój zestaw narzędzi jest w zasadzie określony przez to, na co Cię stać, co możesz nosić, opanować i zbudować lokalnie. Trendy zmieniają się powoli i są lokalne, ponieważ wykorzystują lokalne zasoby i dostosowują się do lokalnych potrzeb, a narzędzia podążają za tym samym wzorcem. Narzędzia to dziedzictwo przekazywane od mistrza do ucznia, od rodzica do dziecka. Nie stają się niekompatybilne ani przestarzałe.

Przeprojektowanie stołu podświetlanego i pamięci podręcznej mipmap

Development Redesign Wydajność

Między styczniem 2022 a marcem 2026 do Ansela trafiło 297 commitów (nie licząc merge’y) dotyczących siatki stołu podświetlanego, jej miniatur oraz potoku (pipeline) ich renderowania i buforowania. Tak długo, jak się dało, próbowałem radzić sobie z niechlujnym kodem stołu podświetlanego z Darktable, jedynie odtłuszczonym, ale niestety był to czysty dług techniczny i działał boleśnie wolno.

Rzeczywiście, Darktable „radzi sobie" z kiepską jakością swojego stołu podświetlanego, zmniejszając jego rozmiar: lewy i prawy panel boczny zajmują dużą część powierzchni wyświetlania, przez co stołowi podświetlanemu zostaje jeszcze mniej obszaru do przemalowania. Ponieważ Ansel usunął prawy panel boczny, scalając jego zawartość z lewym panelem i menu globalnym, powierzchni do malowania było więcej, pracy dla procesora więcej, a fatalny projekt stołu podświetlanego stał się tym bardziej szkodliwy.

Całkowita przebudowa potoku (pipeline)

Development

Odkąd zacząłem używać Darktable, mniej więcej w 2012 roku, zawsze zaskakiwało mnie, jak mało pamięci RAM zużywa. Ludzie sądzą, że to dobrze, gdy aplikacja oszczędnie gospodaruje pamięcią — i to z pewnością prawda, gdy mowa o Twoim środowisku graficznym. Ale gdy mówimy o oprogramowaniu produkcyjnym, które wykonuje ciężkie renderowanie pikseli na obrazach od 12 do 54 Mpikseli, oznacza to, że te same ciężkie obliczenia wykonywane są w kółko, zamiast być zapisane do ponownego wykorzystania później. Właśnie od tego jest pamięć podręczna (cache): od unikania kosztownych obliczeń. I powinna używać do tego całej dostępnej pamięci RAM, ponieważ obliczanie to marnowanie energii, a to ma konkretny wpływ, jeśli pracujesz na baterii. Poza tym zapłaciłeś za tę pamięć RAM, a jej używanie nie rozładowuje baterii. Z kolei CPU/GPU…

Scalanie historii uczynione solidnym i przewidywalnym

Development

Wspomnienia gościa, który spędził zbyt wiele czasu na sprzątaniu cudzego gówna i płaceniu za cudze złe decyzje, odcinek #zbyt wiele.

Kopiowanie/wklejanie historii i stylów to kluczowe funkcje w Anselu i te, które sprawiają, że zasługuje on (lub nie) na miano „aplikacji do pracy”. Są to jednak zarazem jedne z najtrudniejszych do poprawnego zaimplementowania wewnętrznie. Użytkownicy widzą listę edycji, ale pod maską edycje te zależą od kolejności w potoku, instancji modułów i masek. Jeśli dwa zdjęcia mają różne topologie potoku, naiwne kopiowanie edycji może wywołać niespójności.

Przepisywanie skrótów klawiszowych (akceleratorów) od zera

GUI Użyteczność

W moim przełomowym wpisie, Darktable: crashing into the wall in slow-motion, przedstawiłem katastrofę, jaką był nowy „Wielki turducken MIDI". Celem tego turduckena1 było przepisanie systemu skrótów klawiszowych, aby rozszerzyć go o urządzenia MIDI.

Do dziś jestem wściekły na to przedsięwzięcie masowego niszczenia, oto podsumowanie powodów:

  1. w 2021 roku zastąpił system skrótów klawiszowych, który był całkiem dobry, kompletny funkcjonalnie, dobrze przetestowany, stabilny i zakodowany w mniej niż 1500 liniach (łącznie z komentarzami),
  2. …aby dodać obsługę urządzeń MIDI i gamepadów PlayStation (!?!)…
  3. …ale w moim ankiecie Darktable z 2022 roku, rok po tej nowej funkcji, spośród ponad 1251 użytkowników, którzy wzięli udział:
    • 81% użytkowników nie miało urządzenia MIDI i nie planowało go kupić,
    • 2% nawet nie wiedziało, czym jest urządzenie MIDI.
    • 8% użytkowników miało urządzenie MIDI, ale nie używało go z Darktable,
    • 6% rozważało może kupno urządzenia MIDI w przyszłości,
    • 2% użytkowników miało urządzenie MIDI, którego faktycznie używało w Darktable,
  4. kod był absolutnie okropny pod względem:
    • jakości kodu: nieczytelne instrukcje if/switch-case zagnieżdżone na 4 poziomach, w środku funkcji liczących 1000 linii (przykładowe fragmenty zamieściłem w moim artykule),
    • objętości kodu:
      • 3546 linii kodu dla Darktable 4.0,
      • 4397 linii kodu dla Darktable 5.0,
      • wzrost objętości jest bezpośrednim skutkiem prób naprawiania błędów w architekturze, której nie da się naprawić, ponieważ jej złożoność sprzyja jeszcze większej złożoności. Wszystko to wynika z projektu, ale rozwiązywanie problemów stworzonych przez złożoność poprzez dodawanie kolejnej złożoności nie jest rozwiązaniem.
    • złożoności kodu:
      • złożoność cyklomatyczna :
      • złożoność poznawcza :
      • jest to zdecydowanie najbardziej złożona funkcja oprogramowania, mimo że nie operuje na obrazach. Dla porównania, drugą najbardziej złożoną funkcją jest dekodowanie metadanych EXIF, którego złożoność poznawcza wynosi 1348.
  5. z założenia nie dekoduje modyfikatorów klawiszy, lecz zajmuje się wyłącznie sprzętowymi naciśnięciami klawiszy, co oznacza, że:
    • wejście „1" z klawiatury numerycznej jest dekodowane jako Keypad End,
    • wejście „1" z francuskiej klawiatury AZERTY jest dekodowane jako Shift+& lub Shift+" na BÉPO,
    • musisz zatem zduplikować wszystkie swoje skróty oparte na cyfrach dla każdego sposobu wprowadzania cyfry i przygotować się na to, że okno ustawień skrótów nie będzie zawierać żadnej faktycznej cyfry w kombinacjach klawiszy.
  6. projekt od strony użytkownika jest absolutnie okropny, ze zdecydowanie zbyt wieloma akcjami i emulacjami do skonfigurowania („efektami"), które nawet 4 lata później nie są w pełni udokumentowane (czym jest „ctrl-toggle"? „right-activate"?), a konfiguracja skrótów używa dziwnego podzielonego okna, które nie ma żadnego sensu,
  7. implementacja jest równie okropna: funkcja jest świadoma całego GUI oprogramowania, a GUI oprogramowania jest świadome kodu skrótów. Nie ma tu żadnej modularności, a zmiana czegokolwiek w kodzie skrótów może mieć nieoczekiwane i niepożądane skutki gdziekolwiek w oprogramowaniu.2 Spójrz tylko na graf zależności poniżej,
  8. kilka „skrótów" (lub powiązań MIDI) może być przypisanych do tej samej akcji, co oznacza, że każda interakcja użytkownika musi przeszukać całą listę dostępnych akcji, powodując bardzo nieefektywną obsługę skrótów, w niektórych przypadkach opóźnienia GUI oraz fałszywe alarmy „nieznana kombinacja klawiszy" w szczególnych przypadkach.
image
Niezdekodowane klawisze cyfr i dziwny podział okna między „akcją" a „skrótem".
image

Graf zależności src/gui/accelerators.c (Wielki turducken MIDI) przed przepisaniem. Zgadnij, dlaczego nazywamy to „kodem spaghetti "… Widać wyraźnie, że istnieje dwustronna zależność między kodem akceleratorów a resztą kodu GUI. Utrzymanie tego to koszmar.

Witaj, Ansel GPT!

Ogłoszenie

Po tym, jak w końcu połączyłem całą stronę i dokumentację w szczelny przepływ pracy tłumaczeniowej (używając po4a na bazie Hugo), który akurat wykorzystuje dokładnie ten sam zestaw narzędzi i logikę co aplikacja Ansel, wpadłem na pomysł automatyzacji pustych tłumaczeń, najpierw z plików tłumaczeń oprogramowania, a potem poprzez API ChatGPT, które całkiem nieźle radzi sobie z tłumaczeniem składni Markdown.

Pracując w pojedynkę, nie możesz liczyć na próżniactwo społeczne , więc musisz być sprytny. Możesz zobaczyć listę rzeczy, które już zautomatyzowałem w tle dla Ansela.

Witaj, dokumentacjo dla programistów !

Development

W grudniu 2019 roku poprosiłem, aby ktoś zajął się dostarczaniem pakietów AppImage  dla Darktable. Oczywistą korzyścią byłoby umożliwienie wczesnego testowania, przed wydaniem, przez osoby, które nie potrafią samodzielnie zbudować kodu źródłowego, tak by z nadzieją uzyskać wczesne opinie i pomóc w usuwaniu błędów przed wydaniem. Nigdy nie było to priorytetem, co oznacza, że można było mieć pośpiech z naprawą błędów zarówno przed wydaniem, jak i po nim.

Naprawianie pamięci podręcznej potoku i 10-letnich błędów

Development

Podsumowanie poprzednich odcinków

  1. W latach 2020–2022 Darktable przeszedł przez przedsięwzięcie masowej destrukcji, za sprawą garstki gości mających więcej wolnego czasu i dobrej woli niż faktycznych umiejętności,
  2. W 2022 roku zacząłem zauważać irytujące opóźnienie  między interakcjami w interfejsie z suwakami a informacją zwrotną/aktualizacją owych suwaków. Z braku informacji zwrotnej stwierdzającej, że zmiana wartości została zapisana, użytkownicy mogli zmienić ją ponownie, tym samym uruchamiając dodatkowe przeliczenia potoku i skutecznie zawieszając swój komputer, ponieważ głupi interfejs nigdy nie powiedział „mam cię, teraz chwilę poczekaj".
  3. Odkryłem, że rozkazy przeliczenia potoku były wydawane dwukrotnie na kliknięcie (raz przy zdarzeniu „przycisk wciśnięty", raz przy „przycisk zwolniony") oraz jeszcze raz przy każdym ruchu myszy, ale również, że stany interfejsu były pozornie aktualizowane po przeliczeniu potoku.
  4. Naprawiłem to, niemal przepisując od nowa niestandardowe kontrolki interfejsu (biblioteka Bauhaus). Sądziłem, że powstrzymanie lekkomyślnych rozkazów przeliczenia rozwiąże problem opóźnienia: tak się nie stało. Następnie odkryłem, że żądanie nowego przeliczenia potoku przed zakończeniem poprzedniego czekało na zakończenie poprzedniego, mimo mechanizmu wyłączania zaimplementowanego wiele lat temu, który powinien był działać.
  5. Naprawiłem to, implementując mechanizm wyłącznika awaryjnego (kill-switch) na potokach, kierując się komentarzami w kodzie z lat 2010. i wewnętrznymi narzędziami, które równie dobrze mogły nigdy nie działać. Nie zawsze to działało, ponieważ rozkaz zabicia przychodził często z zauważalnym opóźnieniem. Po raz kolejny opóźnienie interfejsu nie zostało naprawione.

Przepisywanie narzędzia importu

Development Redesign

Ansel dziedziczy po Darktable jego bazodanowy kręgosłup: nieniszczące historie edycji zapisywane są dla każdego zdjęcia w bazie danych SQLite, wraz z metadanymi i innymi danymi zdefiniowanymi przez użytkownika. Uświadomienie bazie danych istnienia nowych zdjęć odbywa się poprzez „importowanie" zdjęć z dysku lub karty pamięci. I tu pojawia się narzędzie importu.

Niestety, importer Darktable to kolejna rzecz, którą sknocono około 2020 roku i zamieniono w coś głęboko niepokojącego, ponieważ jest to przeglądarka plików, która nie przypomina żadnej wcześniej znanej przeglądarki plików, a przy tym udaje jej się nie mieć podstawowych funkcji (jak Ctrl+F czy podgląd EXIF), będąc jednocześnie napchaną bezużytecznymi (patrz niżej). To tutaj tracimy niejednego przyszłego użytkownika, a jest to dopiero krok 0 procesu pracy. Cóż za wspaniała wizytówka tego, co potrafi „aplikacja do pracy z procesem" (workflow app)!

Implementacja wyłącznika awaryjnego w potoku

Development

Przez bardzo długi czas myślałem, że w potoku pikseli istnieje jakiś mechanizm wyłącznika awaryjnego. Przypadek użycia jest następujący:

  1. zmieniasz parametr modułu,
  2. podglądy (centralny podgląd w ciemni oraz miniatura w lewym panelu, używana także dla histogramu i próbników koloru) przeliczają swój potok, aby uwzględnić tę zmianę,
  3. jeden z podglądów kończy renderowanie przed drugim, a wynik jest oczywiście nie tym, czego chciałeś,
  4. zmieniasz ponownie parametr modułu, nie czekając na zakończenie przeliczania.

W takim przypadku chcesz zabić wszystkie aktywne potoki, ponieważ ich wynik nie zostanie użyty, i natychmiast rozpocząć przeliczanie wszystkiego z nowymi parametrami. Tyle że Darktable tego nie robi — pozwala potokowi zakończyć się przed jego ponownym uruchomieniem, a patrząc na komentarze w kodzie źródłowym, wygląda na to, że jest to dość niedawna regresja, a nie pierwotnie zamierzone zachowanie.

Od-darktable-owienie kontrolek GUI

Development

Darktable ma własną bibliotekę widżetów GUI, dla suwaków i list rozwijanych (znanych też jako menu rozwijane lub pola wyboru), nazwaną Bauhaus (w kodzie źródłowym znajduje się ona w src/bauhaus/bauhaus.c). Choć jako backendu używają Gtk, obiekty Bauhaus są niestandardowe. A jak wiele rzeczy w Darktable, niestandardowe znaczy zepsute.

W 2022 roku ‍zauważyłem pasożytnicze przerysowania i opóźnienia  podczas ich używania, prowadzące do frustrującego doświadczenia użytkownika: przerysowanie widżetu zdawało się czekać na zakończenie ponownych obliczeń potoku (pipeline), co oznaczało, że użytkownicy nie byli do końca pewni, czy zmiana ich wartości została zapisana, co mogło skłaniać ich do ponawiania próby, uruchamiając kolejny cykl kosztownych ponownych obliczeń i skutecznie zawieszając ich komputer na kilka bardzo frustrujących minut bezużytecznych, pośrednich ponownych obliczeń potoku.

Zmiany w obsłudze dystrybucji pakietu AppImage dla systemu Linux

Ogłoszenie

Rawspeed (biblioteka dostarczająca dekodery dla plików raw z aparatów) porzuciła obsługę GCC < 12. W związku z tym nie mogę już budować AppImage na Ubuntu 20.04 (za pomocą runnerów Github), lecz muszę budować go na 22.04.

Oznacza to, że żadna dystrybucja Linuksa mająca libc starsze niż 2.35 nie będzie w stanie uruchomić nowych AppImage, począwszy od dzisiaj. Nie powinno to dotyczyć większości użytkowników korzystających z dystrybucji zaktualizowanych w 2021 roku lub później. Ubuntu 20.04 oraz inne dystrybucje LTS/stare stabilne (Debian stable) mogą być tym dotknięte.

Nowe opcje kompilacji dla Linuksa

Development

Przypadkiem odkryłem, że skrypt kompilacji dla Linuksa używał kompilacji „pakietowej", co oznacza, że optymalizacje CPU są ograniczone do ogólnych, aby wytwarzać przenośne pliki binarne, które można zainstalować na dowolnej platformie x86-64. Przez „używał" mam na myśli, że kompilacja pakietowa nie była jawnie wyłączona, więc była domyślnie włączona.

W każdym razie jest to teraz domyślnie wyłączone, ponieważ właściwe pakiety (.exe i .appimage) nie są budowane przez ten skrypt, który jest przede wszystkim przeznaczony do pomocy użytkownikom końcowym. Aby przywrócić poprzednie zachowanie, musisz uruchomić:

Dziennik dewelopera #2: przedstawiamy Chantal

Development

Rok 2022 był tak fatalny pod względem śmieciowych e-maili i szumu, że rozpocząłem projekt Virtual Secretary , framework w Pythonie do pisania inteligentnych filtrów poczty, które krzyżują informacje z kilku źródeł, aby odgadnąć, czym są przychodzące e-maile i czy są ważne/pilne, czy nie. Kiedy mówię o śmieciowych e-mailach, chodzi też o powiadomienia z Githuba, pingi na pixls.us (dzięki Bogu zamknąłem konto na tym głupim forum), YouTube oraz bezpośrednie e-maile od ludzi liczących na uzyskanie prywatnej pomocy.

Dziennik dewelopera

Development

Minęły mniej więcej 3 miesiące, odkąd zmieniłem nazwę „R&Darktable" (której nikt zdawał się nie rozumieć poprawnie) na „Ansel", a następnie kupiłem domenę i stworzyłem stronę internetową od zera przy użyciu Hugo (nigdy wcześniej nie programowałem w Golangu, ale to głównie kod szablonów).

Potem spędziłem łącznie 70 h na tym, żeby nocne kompilacje pakietów dla Windowsa i Linuksa działały w ramach ciągłego dostarczania — coś, czego Darktable nigdy nie zrobił porządnie („możesz skompilować samodzielnie, to nietrudne") — tylko po to, by po wydaniu zobaczyć eksplozję w systemie zgłaszania błędów (nic tak nie skraca oczekiwanej długości życia jak połączenie sprintu przedwydaniowego ze sprintem powydaniowym).

Darktable: wjeżdżanie w ścianę w zwolnionym tempie

Co się dzieje, gdy grupka fotografów amatorów, przekwalifikowanych na programistów amatorów, w towarzystwie zgrai programistów back-endu, którzy piszą biblioteki dla programistów, postanawia pracować bez metody ani struktury nad przemysłowym oprogramowaniem dla użytkowników końcowych, którego kluczowa kompetencja (kolorymetria i psychofizyka) leży gdzieś pomiędzy licencjatem z fotografii a magisterium z nauk stosowanych, obiecując jednocześnie dostarczać 2 wersje rocznie bez zarządzania projektem? A wszystko to, rzecz jasna, w projekcie, w którym założyciele i pierwsze pokolenie programistów poszli dalej i uciekli?

Search

You can also ask Chantal, the AI search engine.