Autor Wątek: zmiejszanie rozmiaru pliku  (Przeczytany 5434 razy)

Offline kafor7

  • Użytkownik

# Wrzesień 14, 2008, 19:37:20
jakieś inne pomysły ?

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Moriturius

  • Użytkownik

# Wrzesień 14, 2008, 19:58:09
jakieś inne pomysły ?
Nie sądzę aby dało się wymyślić coś lepszego od zapisu binarnego w tym wypadku. Zwróć uwagę, że zapisujesz liczby float, które w pamięci mają wielkość 4 bajtów, a po zapisie tekstowym zależnie od dokładności 5-8 bajtów. Mógłbyś na samym zapisie binarnym zyskać z 2 razy mniejszy plik. Widzę, że do każdego wierzchołka zapisujesz jeszcze jakieś 2 liczby. Jeśli są one zawsze mniejsze niż 255 to możesz je zapisać w jednym bacjie (char). Jeśli są większe to myślę, że short powinno wystarczyć.

Nie wspomnę już o tym, że w ten sposób pozbędziesz się też wielu spacji, kropek i minusów które też zajmują każda po 1 bajcie w pliku, a jest ich dużo.

Na koniec - 0 problemu z pafsowaniem chociaż można użyć zwykłego fscanf więc to nie jest takie problematyczne ^^

Offline kafor7

  • Użytkownik

# Wrzesień 14, 2008, 20:50:13
no tylko że jak zapisuje binarnie (robie to tak :

               plik.open(nazwa_pliku,std::ios::binary|std::ios::out);
                                   plik.write(data.str().c_str(),data.str().length());
               plik.close();

data to zmienna std::stringstream

to otrzymuje praktycznie to samo co w zwykłej postaci. Jedyna zmiana to w tym że nie ma enterów a zamiast tego jest taki prostokątny znaczek.

praktycznie tak samo jak w normalnej postaci a zajmuje troszeczkę mniej ( z jakiś 1mb )

może coś źle zapisuje ?

P.S a te 2 liczby to koordynaty textury
« Ostatnia zmiana: Wrzesień 14, 2008, 20:54:37 wysłana przez kafor7 »

Offline Fiołek

  • Użytkownik
    • Blog

# Wrzesień 14, 2008, 21:07:59
Zapisujesz TEKST więc na jedno wychodzi. Musisz zapisać floata jako floata a nie jako tekst.
Np.:
Kod: (cpp) [Zaznacz]
float liczba = 1.2f;
plik.write((char*)&liczba, sizeof(float));
(kod pisany z pamięci, możliwe błędy).

Offline Mrowa

  • Użytkownik

# Wrzesień 14, 2008, 21:14:37
Z kompresją akurat sam miałem problemy, znaczy się nie chciało mi się myśleć nad tym, jak wyciągnąć skompresowane dane i poustawiać jak należy. Też tworzyłem własny format danych, ale to nie do gier, tylko do projektu antycheata do CSa, który zresztą upadł :P

I nie rezygnuj z kompresji, bo moim zdaniem nie ma lepszego sposobu na zmniejszenie rozmiaru pliku. Między zapisem liczbowym a binarnym są różnice, ale nie takie jak przy kompresji, to wiadomo :)

Mogę się podzielić tym co wydedukowałem tworząc swój format, który jednak nie został stworzony, więc nie wiem czy to dobre rozwiązanie itp i czy w ogóle możliwe.

Czyli:
- najprościej wszystko umieścić w strukturze, zastanówmy się. Jak wczytujesz/zapisujesz strukturę bitmap (np. BITMAPINFOHEADER) to rozmiar pamięci jaki wczytać to po prostu rozmiar struktury.

No to tak, ale jeśli mamy kompresję to nie wiemy ile to po kompresji zajmować będzie. Ale tam w tym zlib funkcja zwraca, albo wpisuje do parametru rozmiar skompresowanych danych. No to tak, plik organizujesz mniej wiecej tak:

NAGŁÓWEK -> nie podlega kompresji
 - typ
 - rozmiar skompresowanych danych
 - ilość wierzchołków i co tam trzeba
DANE -> skompresowane
 - te wszystkie wierzchołki itp

Potem to tak, zapisujesz nagłówek, potem skompresowane dane. Przy odczycie odczytujesz nagłówek i potem odczytujesz skompresowane dane(bo wiesz ile odczytać). Dekompresujesz, bo inaczej to to jest upchane i pozmieniane trochę (jak chcesz wiedzieć więcej to sobie poczytaj o algorytmach kompresji, ja się na to natknąłem przy czytaniu o png) i ciężko chyba wydobyć dane. No i potem to też jakoś lecisz i odczytujesz. W sumie możesz potem normalnie też zmienne odczytywać, to że to jest zapisane jako char, to nie ważne, bo zapis binarny ma gdzieś typy, on po prostu umieszcza wsio w pamięci bajt po bajcie.

Kolejne artykuły na ten temat na warsztacie(Struktury danych i formaty plików - Adam Sawicki)
http://www.warsztat.gd/articles.php?x=view&id=6

Ufff ale się opisałem :P Ale mam nadzieję, że te wyższe wypociny pomogły jakoś i nie są za bardzo chaotyczne.
Pozdrawiam
Mrowa

Edit:
A ja się zatrzymałem na tym, bo nie wiedziałem jak odczytywać dane z pamięci. Bo po dekompresji z pliku dane wchodzą do pamięci do buffora. I nie ma czegoś takiego chyba jak wskaźniki plików (jak fseek w tym nie strumieniowym sposobie). Aczkolwiek projekt upadł i już się nie bawiłem. A może normalne wskaźniki się nadadzą, albo buffor w pamięci można jakoś traktować jak plik. Nie wiem, bo ja początkujący programista jestem :P Tutaj już musisz radzić sobie sam.


Edit 2: Do wypowiedzi niżej.

Hmmm... ja też :P. Ogólnie wczytujesz dane do pamięci z pliku, to jest w artykule, który Ci podesłałem wyżej o strukturach danych. I to spokojnie wczytasz po tamtym artykule. Tutaj jest to przesuwanie wskaźnika pliku (a przy strukturach chyba samo się przesuwa, nie wiem, bo np. przy bitmapach nie trzeba przesuwać jak zapisujesz BITMAPFILEHEADER i BITMAPINFOHEADER, przesuwasz dopiero na dane obrazu o rozmiar dwóch poprzednich struktur).

Czyli zadanie dla Ciebie: Jak odczytywać te dane które już masz w pamięci, a nie w pliku. Bo ogólnie robisz tak:
1. Kompresujesz dane.
2. Zapisujesz nagłówek.
3. Zapisujesz buffor z skompresowanymi danymi.

4. Odczytujesz nagłówek.
5. Odczytujesz skompresowane dane.
6. Teraz masz je w bufforze.
I tutaj kończy się moja wiedza. Może ktoś inny Ci pomoże z tym, jak te dane z buffora pozapisywać do zmiennych.

« Ostatnia zmiana: Wrzesień 14, 2008, 21:29:59 wysłana przez Mrowa »

Offline kafor7

  • Użytkownik

# Wrzesień 14, 2008, 21:15:29
ale chyba ten pomysł z tą kompresją jest lepszy tzn sporo mniej miejsca zajmuje więc może ktoś wpadł na jakiś szybki sposób zamiany tego char* buffer na te liczby float?

Dekompresujesz, bo inaczej to to jest upchane i pozmieniane trochę (jak chcesz wiedzieć więcej to sobie poczytaj o algorytmach kompresji, ja się na to natknąłem przy czytaniu o png) i ciężko chyba wydobyć dane. No i potem to też jakoś lecisz i odczytujesz

no właśnie nie wiem jak lecieć i odczytywać tu właśnie tkwi mój problem...
« Ostatnia zmiana: Wrzesień 14, 2008, 21:22:04 wysłana przez kafor7 »

Offline voytech

  • Użytkownik

# Wrzesień 15, 2008, 00:04:26
Jeżeli chodzi o wczytywanie danych binarnych to podaje przykładowy kod, który wczytuje na początku 4 bajty czyli zmienną typu unsigned int informującą ile wierzchołków jest zapisanych w pliku. Następnie rezerwuje się bufor o odpowiedniej wielkości i wczytuje od razu wszystkie potrzebne wierzchołki:
Kod: (cpp) [Zaznacz]
unsigned int num_verts;
float *vector_buf;

ifstream in("model.bin", ios::binary);
in.read(reinterpret_cast<char*>(&num_verts), sizeof(num_verts)); //wczytaj zmienna unsigned int
vector_buf = new float[num_verts * 3 ]; // przydziel pamiec na bufor
in.read(reinterpret_cast<char*>(vector_buf), num_verts * 3 * sizeof(float)); //wczytaj dane
in.close()

Zapisywanie też jest proste:
Kod: (cpp) [Zaznacz]
ofstream out("plik.bin", ios::binary);

float x = 2.5f;

out.write(reinterpret_cast<const char*>(&x), sizeof(float));
out.close();

Offline kafor7

  • Użytkownik

# Wrzesień 15, 2008, 08:09:24
no ok dzięki ale ja bym wolał skorzystać z tej kompresji.. więc może jednak ktoś napisze o wczytywaniu danych z tej kompresji ??:)

Offline misioslaw

  • Użytkownik
    • www.asmforce.eu

# Wrzesień 15, 2008, 08:35:34
Dane binarne też można kompresować, to raz. Dwa, że po dekompresji masz cały blok danych w pamięci i wystarczy im tylko powiedzieć "od teraz jesteście floatami :D czy od razu podpiąć pod VBO lub coś podobnego

Także połączenie jednego z drugim przynosi same korzyści.

Offline Mrowa

  • Użytkownik

# Wrzesień 15, 2008, 16:50:31
@ misiosław wyżej
Dane binarne też można kompresować, to raz.

Czytałeś cały wątek, a dokładniej moje wypowiedzi ? Przecież cały czas piszę, żeby używał danych binarnych i je kompresował, tylko on ma problem w tym, że po dekompresji masz cały buffor pliku w pamięci. I teraz co, proponujesz po prostu te 5MB pamięci przerzutować na float?
Pseudokod.
char *buffer = UzyskajDaneOdkompresowaneZPliku();
float buf_zastepczy;
buf_zastepczy = (float) buffer;

Wydaje mi się, że to chyba za proste, ale jak już mówiłem, nie wiem, więc może i zadziała :PP ale nie wyciągnąłeś danych do np. tablic wierzchołków. Może zwykłymi wskaźnikami się da coś pokombinować, w końcu służą one na pokazywanie na miejsce w pamięci. Albo czymś innym :)


@Dab na dole
No dobra, nie czepiajmy się szczegółów typu (float*) a nie (float). Ale autor tutaj pisze, że to mu potrzebne bo robi własny format modeli. Czyli mówisz, żeby ten buffor z danymi potraktować jako tablicę jednowymiarową typu float? Czyli ustawić wskaźnik na początku bufora, a potem przesuwać go tak jak po tablicy(chyba to się robi inkrementując wskaźnik, wtedy się przesuwa o jeden element dalej). Jeśli dobrze mówię to pomóż bardziej autorowi wątku rozwijając czy poprawiając mnie.

No i myślę, że chyba już tu się tak nie udzielam, bo to co wiedziałem powiedziałem, to co wymyśliłem też i po tej burzy mózgów na pewno autor coś wymyśli.
« Ostatnia zmiana: Wrzesień 15, 2008, 18:07:08 wysłana przez Mrowa »

Offline Dab

  • Redaktor
    • blog

# Wrzesień 15, 2008, 17:07:37
float* a nie float -- i jest to tablica jak by nie patrzył

Offline RedHot

  • Użytkownik

# Wrzesień 15, 2008, 19:41:16
@Mrowa
Nie. Z tego co widziałem struktura jego pliku nie składa się z samych floatów. Autor wątku będzie sobie musiał przeskakiwać odpowiednią ilość miejsc w pamięci zanim dotrze do miejsca z floatami.

Offline soku11

  • Użytkownik

# Wrzesień 15, 2008, 21:58:31
Kod: (cpp) [Zaznacz]
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;


int main()
{
  char buf[]={"-12.45 123.543 54.123 -32.2"};
  char* ptr=buf;
  int i=strlen(buf);

  float val=0;
  bool newfloat=true;
  for(int j=0;j<i;++j,++ptr)
  {
    if(newfloat)
    {
      val=atof(ptr);
      cout<<val<<endl;
      newfloat=false;
    }

    if(*ptr==' ')
      newfloat=true;
  }

  return 0;
}


Masz kod, ktory przeszukuje ciag znakow char w ktorym sa liczby typu float oddzielone spacjami. Pozdrawiam.

Offline kafor7

  • Użytkownik

# Wrzesień 16, 2008, 21:44:07
dzięki soku chociaż jedyny napisał jakiś kod :) sprobuję tym kodem to wszystko wczytać troche pozmieniam może pójdzie jakoś.. Jeszcze jakby ktoś wpadł na jakiś kod to proszę oczywiście pisać:)

Vipa

  • Gość
# Wrzesień 16, 2008, 22:05:40
Nie zrozumiałeś zasad. Nikt nie napisze ci gotowego rozwiązania. Jak nie zrozumiesz zasad to nie napiszesz kodu, jak zrozumiesz zasadę to napiszesz kod sam i to w zeszycie na klasówce z matmy.