Tak, stary dobry GIF. Uwielbiany za swoją wszechstronność, nienawidzony za patenty i częściowo przestarzały ze względu na swoje ograniczenia (i patenty), GIF składa się zasadniczo z palety kolorów i obrazu indeksowanego paletą skompresowanego przy użyciu algorytmu LZW.
Twoim zadaniem jest napisanie programu, który odczytuje obraz w formacie ASCII PPM (magiczna liczba „P3”) ze standardowego wejścia i zapisuje ten sam obraz (identyczny piksel po pikselu) na standardowym wyjściu. Dane wyjściowe mogą mieć postać binarną lub tekst ASCII, przy czym każdy bajt jest reprezentowany przez liczbę od 0 do 255 (włącznie), oddzielone białymi spacjami.
Gwarantujemy, że obraz wejściowy nie będzie miał więcej niż 256 różnych kolorów.
Punktacja:
Twój program zostanie przetestowany na 3 przykładowych obrazach, a twój wynik zostanie obliczony jako:
rozmiar programu + suma (rozmiar wyjściowy - rozmiar odniesienia dla każdego przykładowego obrazu)
Wygrywa najniższy wynik.
Wymagania:
- Twój program musi działać z dowolnymi podobnymi obrazami o różnych rozmiarach i nie może być ograniczony do przykładowych obrazów. Można na przykład ograniczyć wymiary do wielokrotności 2 lub założyć, że maksymalny kolor na minutę to 255, ale nadal powinien działać z szeroką gamą obrazów wejściowych.
- Dane wyjściowe muszą być poprawnymi plikami GIF, które można załadować dowolnym zgodnym programem (po konwersji z powrotem na plik binarny, jeśli używana jest opcja wyjścia ASCII).
- Nie możesz używać żadnych funkcji przetwarzania obrazu (wbudowanych lub zewnętrznych), twój program musi zawierać cały odpowiedni kod.
- Twój program musi być uruchamialny w systemie Linux przy użyciu ogólnodostępnego oprogramowania.
- Kod źródłowy musi używać tylko znaków ASCII.
Przykładowe obrazy:
Oto 3 przykładowe obrazy, które zostaną wykorzystane do oceny. Możesz pobrać archiwum zip z plikami ppm (użyj przycisku pobierania na górze tej strony). Lub możesz przekonwertować je z poniższych obrazów png, używając ImageMagick za pomocą następującego polecenia:
convert file.png -compress none file.ppm
Podaję również sumy kontrolne MD5 plików ppm w celu potwierdzenia.
1. bursztyn
Rozmiar odniesienia: 38055
MD5 suma kontrolna ppm: d1ad863cb556869332074717eb278080
2. niebieskie oczy
Rozmiar odniesienia: 28638
MD5 suma kontrolna ppm: e9ad410057a5f6c25a22a534259dcf3a
3. papryka
Rozmiar odniesienia: 53586
MD5 suma kontrolna ppm: 74112dbdbb8b7de5216f9e24c2e1a627
źródło
Odpowiedzi:
Perl, 515 + -2922 + 0 + -2571 = -4978
Inne podejście. Tym razem próbuję zapisać obraz w kafelkach o rozmiarze 64xH. Jest to zgodne ze specyfikacjami, ale niektóre programy mogą wyświetlać tylko pierwszy kafelek lub animację. Płytki lepiej się kompresują ze względu na lepszą lokalizację przestrzenną. Nadal robię też normalną kompresję dla drugiego obrazu i wybieram to, co było krótsze. Ponieważ kompresuje to obraz dwukrotnie, jest dwa razy wolniejszy w porównaniu do mojego poprzedniego rozwiązania.
Perl, 354 + 12 + 0 + -1 = 365
418 9521 51168 56639W moim kodzie jest jakiś błąd lub drugi obraz jest zoptymalizowany dla konkretnego kodera, ponieważ pozornie nieznaczna zmiana dokładnie zmniejszyła rozmiar do odwołania. Trwa około 30s-60s na zdjęcie.
Wersja golfowa.
Jedyną decyzją, jaką może podjąć kompresor GIF, jest czas resetu słownika LZW. Zasadniczo ze względu na sposób wyboru obrazów dla tego zadania najlepszym momentem na wykonanie tego jest 4096 kodów, czyli moment, w którym słownik się przepełni. Przy takim limicie słownik nigdy się nie przepełnia, co oszczędza kilka bajtów w implementacji. Oto jak to działa szczegółowo:
Perl, 394 + -8 + 0 + -12 = 374
Dodanie heurystyki w celu odgadnięcia punktu resetowania poprawia nieco kompresję, ale nie wystarcza, aby uzasadnić dodatkowy kod:
źródło
CJam, wynik 155 + 35306 + 44723 + 21518 = 101702
Tylko głupia implementacja odniesienia. Jest powolny, nie kompresuje się i nie gra w golfa.
źródło