2017-01-22 46 views
7

Pracuję nad programem, który pobiera ciąg znaków, przekształca każdy znak ciągu w kolor, a następnie rysuje kolory od lewej do prawej, od góry do dołu w poprzek obrazu. Obraz można następnie zdekodować, używając tego samego programu, aby odzyskać oryginalną wiadomość. Jako przykład, oto clojure.core, zakodowany jako obraz:Kodowanie ciągu znaków jako obrazu powoduje kompresję

Clojure.core encoded as an image

napisałem to tylko jako zabawka, ale zauważyłem ciekawą właściwość obrazów produkuje: są one mniejsze niż oryginalne komunikaty były jako tekst. Dla clojure.core jest to 259 kB jako tekst, ale tylko 88,9 kB jako obraz (powyżej) (obie wartości to "rozmiar na dysku"). Aby upewnić się, że dane nie zostały utracone, dekodowałem obraz i odzyskałem oryginalną wiadomość.

Jak to jest możliwe? Myślę, że obraz (format png) miałby nagłówki i inne dodatkowe informacje, które mogłyby zawyżać rozmiar.

Cały kod clojure.core zawiera 265486 znaków (zgodnie z Notepad ++), co oznacza, że ​​każda postać zajmuje po prostu bajt.

Po pracy z klasą BufferedImage (Java) wygląda na to, że kolory są zapisywane jako 4-bajtowe liczby całkowite, więc czy nie każdy piksel wymaga ~ 4x pamięci?

Oto jak to zakodowane:

  1. Pierwszy znak ciąg jest zdejmowana

  2. To przekłada się na kolor przez coraz to wartość ASCII, mnożąc ją przez dużą liczbę (tak go lepiej pasuje do zakresu możliwych kolorów), następnie liczba ta jest konwertowana na 3-cyfrowy numer bazowy 256 ([123 100 200]).

  3. Każda cyfra jest traktowana jako kanały czerwony, zielony i niebieski, które są podawane w metodzie BufferedImage 's za pomocą metody .

  4. Wskaźnik position jest zaawansowany, następny znak jest wstawiany, a proces powtarza się, aż cały komunikat zostanie zakodowany.

Algorytm jest teraz trochę zawiłowany. @Thumbnail zasugerował znacznie lepszy sposób przeglądania kodu, ale jeszcze go nie wdrożyłem. Ponieważ wyniki są takie same, nie powinno to mieć znaczenia dla pytania.

+2

Mimo że odpowiedź była dość oczywista, nadal lubiłem czytać o twoich odkryciach. Zawsze fajnie jest spotkać takie rzeczy. –

Odpowiedz

7

Portable Network Graphics (PNG) to format pliku grafiki rastrowej, który obsługuje bezstratną kompresję danych (od https://en.wikipedia.org/wiki/Portable_Network_Graphics), iow. dane obrazu są kompresowane, gdy są przechowywane jako plik .png.

+0

Doh. Cóż, to oczywiste z perspektywy czasu. Dzięki. – Carcigenicate

+0

Warto chyba wspomnieć, że PNG używa kompresji Zlib/Deflate (i że prawdopodobnie uzyskasz lepsze wyniki przy użyciu Deflate bezpośrednio w pliku tekstowym). – haraldK

+0

@haraldK, który również byłby moim oczekiwaniem. Oprócz deflacji, png wykonuje wstępne przejście, które pomaga w kompresji "prawdziwych" obrazów (gdzie piksel, statystycznie, przypomina bardzo sąsiadujące piksele). Prawdopodobnie możesz skorzystać z tego, dobierając kolory, które są blisko siebie (uzyskując w ten sposób lepszą kompresję png).Nie ma związku z tym, że prawdopodobnie możliwe jest tworzenie mniejszych obrazów wymiarowych poprzez kodowanie więcej niż jednego znaku na piksel (obrazy TrueColor + Alpha png używają 64 bitów na piksel) - najprawdopodobniej nie będzie to jednak kompresja. – thebjorn