Autor Wątek: Wczytanie obrazka Freeimage, skompresowanie go libsquish do DXT i zapis do własn  (Przeczytany 2447 razy)

Offline bajos

  • Użytkownik

# Sierpień 03, 2015, 21:00:13
Witajcie,

W swoim silniku chcę zrobić tak jak napisałem w temacie. Mam problem z FreeImage. Załadowałem PNG do FIBITMAP i jak wywołałem na załadowanym obrazku (512x512 z alphą) GreeImage_GetBPP() to zwróciło mi 32 czyli ok, ale jak zrobiłem FreeImage_GetDIBSize() to zwróciło mi nie 1 048 576 (512*512*4), a 1 048 616 czyli o 40 więcej. Czy to poprawne? Nie działa mi funkcja FreeImage_GetMemorySize(), kompilator pisze, że taka nie istnieja mimo, że w dokumentacji nic nie pisze o żadnych wyjątkach na Linuxie (!). Czy FreeImage ładuje PNG do postaci RGBA czy BGRA? Jak będzie PNG wyeksportowane w GIMPIE bez alpha to kanału alpha nie będzie po prostu w pliku (nie wierzę, że to piszę), ale chodzi o to czy FreeImage będzie to trzymać bez Alphy czy doda sobie wszędzie pęłną widoczność (brak przezroczystości)?

PS. Jeśli kompresuje przez libsquish to w jakim formacie muszą być dane wejściowe(tj. RGBA | BGRA | RGB | BGR)(jeśli ktoś ma doświadczenie)? Niestety na stronie projektu nie ma żadnej dokumentacji tylko krótki example.
« Ostatnia zmiana: Sierpień 03, 2015, 22:29:08 wysłana przez bajos »

Offline Mr. Spam

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

Offline Kyroaku

  • Użytkownik

  • +2
# Sierpień 03, 2015, 23:55:58
Cytuj
ale jak zrobiłem FreeImage_GetDIBSize() to zwróciło mi nie 1 048 576 (512*512*4), a 1 048 616 czyli o 40 więcej. Czy to poprawne?
Funkcja pewnie uwzględnia jakiś nagłówek, czy coś. Zawsze możesz przemnożyć szerokość * wysokość * ilość_składowych (channels ?).

Cytuj
Czy FreeImage ładuje PNG do postaci RGBA czy BGRA?
BGRA.
Raczej łatwo to rozpoznać patrząc na wczytany obrazek ;)

Cytuj
Jak będzie PNG wyeksportowane w GIMPIE bez alpha to kanału alpha nie będzie po prostu w pliku (nie wierzę, że to piszę), ale chodzi o to czy FreeImage będzie to trzymać bez Alphy czy doda sobie wszędzie pęłną widoczność (brak przezroczystości)?
Jeśli zapiszesz plik .png z trzema składowymi, to FreeImage nie będzie nic dodawał.
Ilość składowych możesz łatwo wyliczyć pobierając ilość bitów na piksel i dzieląc przez 8.

Cytuj
PS. Jeśli kompresuje przez libsquish to w jakim formacie muszą być dane wejściowe(tj. RGBA | BGRA | RGB | BGR)(jeśli ktoś ma doświadczenie)? Niestety na stronie projektu nie ma żadnej dokumentacji tylko krótki example.
Zasada jest prosta:
Jeśli nie działa tak jak jest, to znaczy, że jest źle c(:

Offline bajos

  • Użytkownik

# Sierpień 05, 2015, 17:13:43
GLuint generateMipmaps(FIBITMAP* bitmap, GLubyte** & destination, GLuint width, GLuint height, GLubyte bpp)
{
// Obliczenie ilosci mipmap na podstawie wiekszego wymiaru
GLuint mipmapNum = std::log2(std::fmax(width, height));

// Jesli nie potrzeba mipmap
if(mipmapNum < 1)
return 0;

// Stworzenie tablicy wskaznikow na mipmapy
GLubyte** mipmap = new GLubyte*[mipmapNum];

// Wygenerowanie mipmap
GLuint mipWidth = width, mipHeight = height;
for(GLuint i=0;i<mipmapNum;++i)
{
// Zmniejszenie wymiarow o polowe
mipWidth /= 2;
mipHeight /= 2;

// Ochrona przed wyzerowaniem ktoregos wymiaru
if(mipWidth < 1) mipWidth = 1;
if(mipHeight < 1) mipHeight = 1;

// Obliczenie miejsca, stworzenie miejsca na mipmape
GLuint mipSize = mipWidth*mipHeight*bpp;
mipmap[i] = new GLubyte[mipSize];

// Przeskalowanie obrazka, przekopiowanie mipmapy, zwolnienie tymczasowego obrazka
FIBITMAP* tempImage = FreeImage_Rescale(bitmap, mipWidth, mipHeight, FILTER_BICUBIC);
std::memcpy(mipmap[i], FreeImage_GetBits(tempImage), mipSize);
FreeImage_Unload(tempImage);
}

Valgrind wywala w trzech ostatnich linijkach (tzn. po tym ostatnim komentarzu. Pewnie coś żle robie w FreeImage. Proszę o pomoc :)

PS. Na wejściu do funkcji wymiary oryginału wynoszą 512 i 512, a bpp wynosi 32, destination to referencja do wskaźnika na NULL bo to parametr out. Bitmap to załadowany obrazek PNG z alpha.
« Ostatnia zmiana: Sierpień 05, 2015, 17:17:16 wysłana przez bajos »

Offline Kyroaku

  • Użytkownik

# Sierpień 05, 2015, 20:46:07
Cytuj
GLuint generateMipmaps(FIBITMAP* bitmap, GLubyte** & destination, GLuint width, GLuint height, GLubyte bpp)
Po jakie licho przekazujesz width, height, bpp, skoro możesz je sobie pobrać za pomocą FreeImage'owskich funckcji ?

Nic nie widzę. Posprawdzaj rozmiary tablic i wartość mipSize, to przynajmniej będzie można coś wykluczyć.

Offline bajos

  • Użytkownik

# Sierpień 05, 2015, 22:30:26
Jeszcze sie zobaczy, kod przechodzi refactoring i dzielę go na klasy i osobne pliki. Jedną funkcję rozdzielam na mniejsze itp. Jak będą błędy to jeszcze coś napiszę bo tym razem w wektorach trzymam rozmiary wszystkich mipmap i inne dane więc więcej będzie można odczytać.

PS. Znalazłem. Przed std::memcpy obliczałem ilość bajtów tylko nie podziliłem BPP przez osiem :D
« Ostatnia zmiana: Sierpień 05, 2015, 23:07:17 wysłana przez bajos »

Offline bajos

  • Użytkownik

# Sierpień 12, 2015, 14:10:08
Błąd jest w kompresowaniu obrazka.
// Kompresuje bazowy obraz
GLubyte basicCompressedSize = squish::GetStorageRequirements(imageW, imageH, squishFlags);
GLubyte* basicCompressedImage = new GLubyte[basicCompressedSize];
squish::CompressImage(FreeImage_GetBits(image), imageW, imageH, basicCompressedImage, squishFlags);

Nie wiem w czym tutaj jest błąd.