wtorek, 11 lutego 2014

Pygame atakuje - "File is not a Windows BMP file"

Widziałem wielu użytkowników którzy napotkali problem przy ładowaniu obrazów png jak i jpeg.

"File is not a Windows BMP file" - nie jest to zbyt prydatna informacja w tym przypadku :)

Zgodnie z dokumentacją pygame, by sprawdzić czy wsparcie dla obrazów jest włączone należy:

>>> print(pygame.image.get_extended())
0

Zero oznacza brak wsparcia, lecz w moim przypadku wiedziałem że zostało ono dodane, a jeśli sam nie jesteś tego pewien - prawdopodobnie jest.

Droga do oświecenia

Otworzyłem katalog site-packages mojej instalacji Python3.3 (Twoja ścieżka może sie różnić): /usr/lib/python3.3/site-packages/pygame/

Znajdował się tam plik image.so który w interpreterze python'a jest modułem pygame.image, ale co z drugim podobnie nazwanym plikiem - imageext.so? Oba posiadają korzystają z libpng a image.so importuje się poprawnie.

Więc co sie stanie gdy zaimportuję imageext?

Dobre pytanie - to:

>>> import pygame.imageext
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: libpng15.so.15: cannot open shared object file: No such file or directory

To jest główna przyczyna całego problemu - zmieniła się wersja libpng a pygame chce korzystać ze starszej.

Naprawiamy

Potrafię wymyśleć 3 sposoby:

Na szybko - Możesz użyć linkowania symbolicznego do podpięcia ścieżki wymaganej przez pygame do aktualnego libpng, lecz jest to brzydkie rozwiązanie i dodatkowo może prowadzić do niepoprawnego działania ™.

Tak sobie - Możesz przywrócić w systemie starą wersję libpng by zgadzała sie z wymaganą.

Najlepiej - Napraw wszystko! Jeśli system na to pozwala - skompiluj na nowo pakiety - używam Gentoo więc wybrałem tą drogę ;)

Więc, najlepsza droga to:

By wylistować biblioteki zależne od nieistniejącego pliku, obojętnie w jakiej dystrybucji, uruchom:

grep -R libpng15.so.15 /usr/lib/*

Komenda może zwrócić coś takiego:

Plik binarny /usr/lib/libSDL_image-1.2.so.0 pasuje do wzorca
Plik binarny /usr/lib/libSDL_image-1.2.so.0.8.4 pasuje do wzorca
Plik binarny /usr/lib/libSDL_image.so pasuje do wzorca

Zepsuła się paczka sdl-image, na której z kolei polega pygame.

Teraz musimy tylko zainstalować ponownie/zaktualizować paczkę sdl-image i wszystko powinno zacząć działać. Do następnej aktualizacji libpng :)