CBI - Häviötöntä kuvanpakkausta

Jaa meneillään olevat projektisi tai valmiit pelit muun yhteisön kanssa täällä.
Post Reply
User avatar
Ruuttu
Devoted Member
Posts: 688
Joined: Thu Aug 30, 2007 5:11 pm
Location: Finland, Sipoo

CBI - Häviötöntä kuvanpakkausta

Post by Ruuttu »

CBI on yksinkertainen kuvaformaatti, jolla kuvia voidaan pakata pienempään tilaan - täysin häviöttömästi. CBI kuvat siis säästyvät pakattaessa siltä kauhealta kohtalolta, jonka JPEG kuvat joutuvat kohtaamaan: pikselimössöltä! Kuvien lataus on suhteellisen nopeaa kun otetaan huomioon että alustana on CoolBasic; 800x600 kokoisen kuvan lataaminen kestää noin sekunnin, mutta latausaika riippuu erittäin paljon sisällöstä. (Ja tietysti tätä koodia voi vielä optimoida...)
Noh, paljonko tämä systeemi sitten pakkaa niitä kuvia? Viisi prosenttia? Kymmenen prosenttia? Noh, sekin riippuu tietysti sisällöstä, mutta jos kuvassa on about 50% tasaisia alueita (esimerkiksi puhdasta mustaa), niin tiedoston koostakin säästyy noin 50%. Jos kuvan joka ikinen pikseli on erivärinen, kuva vain suurenee pakattaessa, joten tätä kuvaformaattia kannattaakin käyttää esimerkiksi kuvamuotoisten pelikenttien pakkaamiseen, jolloin tilaa säästyy eniten pelikenttien sisältämien tyhjien kohtien ansiosta.

Mutta hetkinen? Eikös PNG:kin ole häviötön, ja paljon tiheämpään pakkautuva kuvamuoto? Miksi hemmetissä kannattaisi käyttää CBI:tä? Jaa'a, ainoa syy jonka olen keksinyt on, ettei ihan kuka tahansa tavallinen pulliainen voi mennä sorkkimaan pelisi mediaa (CBI kuvia kun ei MS paint osaa avata), mutta siihen se sitten jääkin. Toiveeni olisikin, että te koodaustaitoiset ja/tai mielikuvitukselliset foorumilaiset voisitte hieman auttaa tämän formaatin kehittämisessä, jotta siitä saataisiin nopeampi ja tehokkaampi.

CBImage.cb - Liitä tämä tiedosto Includella projektisi koodiin, jos haluat käyttää CBI -kuvia.

Code: Select all

Function SaveCBImage(img,path$,grid=10)

    If grid = 0 Then MakeError "CBI: The grid size has been set to automatic."+Chr(10)+Chr(13)+"This feature doesn't work yet!"

    F = OpenToWrite(path$)
        If F = 0 Then MakeError "CBI: File access error!"
        WriteByte f,67 // C
        WriteByte f,66 // B
        WriteByte f,73 // I
        
        WriteByte f,1 // CBI -kuvaformaatin versionumero. Tämän avulla formaattiin
                      // voidaan teoriassa tehdä muutoksia, mutta säilyttää vanhojenkin
                      // kuvien toimivuus.
        
        WriteInt f,ImageWidth(img) // Kuvan leveys
        WriteInt f,ImageHeight(img) // Kuvan korkeus
        
        WriteInt f,grid // Ruudukon koko
        
        WriteByte f, 0 // Tarpeeton numero, tulevaisuudessa esim. kuvan väritila (RGB, BW)
        WriteInt f, 0 // Tarpeeton numero, tulevaisuudessa esim. kuvan bittisyys
        
        WriteString f, "X" // Tarpeeton merkkijono, tulevaisuudessa esim. kuvan tekijänoikeustiedot
        WriteString f, "Y" // Tarpeeton merkkijono, tulevaisuudessa esim. kuvan "otsikko"

        // Luodaan taulukko kuvan väriarvojen säilömistä varten.
        Dim BaseGrid(ImageWidth(img)/grid+1,ImageHeight(img)/grid+1,2) As Byte

                // VAIHE 1:
                //    TALLENNETAAN KUVASTA PALIKKAMAINEN POHJARUUDUKKO.

                Lock Image(img)
                
                // Seuraavalta riviltä alkavan loopin voisi korvata
                // For .. next -loopilla, mutta ikävä kyllä silloin
                // ruudukon kokoa ei voisi muuttaa (step arvon on
                // oltava vakio.
                Repeat
                    If X > ImageWidth(img)-1 Then X = 0 : Y + grid
                    
                    If X > ImageWidth(img)-1 Then X = ImageWidth(img)-1
                    If Y > ImageHeight(img)-1 Then Exit
                    PickImageColor2 img, X,Y
                    
                    R = getRGB(1)
                    G = getRGB(2)
                    B = getRGB(3)

                    BaseGrid(X/grid,Y/grid,0)=R
                    BaseGrid(X/grid,Y/grid,1)=G
                    BaseGrid(X/grid,Y/grid,2)=B
                    
                    // Tallennetaan tiedostoon yhden ruudun väriarvot.
                    // Jos arvot on samat kuin edellisessä ruudussa,
                    // säästetään tiedoston koosta kaksi tavua.
                    
                    If EXR = R And EXG = G And EXB = B Then
                        WriteByte f,1
                    Else
                        R2 = R 'purkkaa
                        If R2 = 1 Then R2 = 2 'tikkaria
                        WriteByte f,R2
                        WriteByte f,G
                        WriteByte f,B
                    End If
                    
                    // Pistetään tämän ruudun väriarvot muistiin,
                    // jotta niitä voidaan vertailla seuraavan ruudun
                    // väriarvoihin.
                    EXR = R
                    EXG = G
                    EXB = B

                    X + grid
                
                Forever
                Unlock
                
                // Tallennetaan maagiset arvot, joista voidaan varmistaa,
                // onko kaikki OK tähän asti...
                WriteByte f,79
                WriteByte f,75
                WriteByte f,33

                
                Dim DetGrid(ImageWidth(img),ImageHeight(img),2) As Byte
                
                // VAIHE 2:
                //    VERRATAAN LUOTUA POHJARUUDUKKOA ALKUPERÄISEEN
                //    KUVAAN. POHJARUUDUKON PÄÄLLE LISÄTÄÄN YKSITTÄISIÄ,
                //    ERIVÄRISIÄ PIKSELEITÄ, JOISTA YKSITYISKOHDAT
                //    RAKENNETAAN.
                
                Lock Image(img)
                
                // Seuraavalta riviltä alkavan loopin voisi korvata
                // For .. next -loopilla, mutta ikävä kyllä silloin
                // ruudukon kokoa ei voisi muuttaa (step arvon on
                // oltava vakio.
                X = 0 : Y = 0
                Repeat
                    If X > ImageWidth(img)-1 Then X = 0 : Y + 1
                    If Y > ImageHeight(img)-1 Then Exit
                    
                    PickImageColor2 img, X,Y
                        // Jos pikseli poikkeaa pohjaruudukon väriarvoista, tallennetaan ko. pikselin arvot...
                        If getRGB(1) <> BaseGrid(X/grid,Y/grid,0) Or getRGB(2) <> BaseGrid(X/grid,Y/grid,1) Or getRGB(3) <> BaseGrid(X/grid,Y/grid,2) Then
                            R = getRGB(1)
                            If R = 1 Then R = 2
                            WriteByte f,R
                            WriteByte f,getRGB(2)
                            WriteByte f,getRGB(3)
                        Else
                            WriteByte f,1 
                            // Tämä pikseli on samanvärinen kuin pohjaruudukko. Tallennetaan tähän "TYHJÄ"
                            // pikseli ja siirrytään seuraavaan. Tiedoston koossa säästetään kaksi tavua.  
                        End If

                    X + 1
                
                Forever
                Unlock

    CloseFile f

    Return 1
EndFunction

Function LoadCBImage(path$)

    F = OpenToRead(path$)
        If F = 0 Then MakeError "CBI: File access error!"
        If ReadByte(f)<> 67 Then MakeError "CBI: Not a proper CBimage file!"
        If ReadByte(f)<> 66 Then MakeError "CBI: Not a proper CBimage file!"
        If ReadByte(f)<> 73 Then MakeError "CBI: Not a proper CBimage file!"

        If ReadByte(f) <> 1 Then MakeError "CBI: The version number was incorrect."

        ImageW = ReadInt(f)
        ImageH = ReadInt(f)
        
        grid = ReadInt(f)
        
        TempImg = MakeImage(ImageW,ImageH)

        PointlessByte = ReadByte(f)
        PointlessInt = ReadInt(f)

        PointlessString = ReadString(f)
        PointlessString2 = ReadString(f)

        // VAIHE 1:
        //    LUETAAN JA LUODAAN KUVAN POHJARUUDUKKO

                DrawToImage TempImg
                Repeat
                    If X > ImageW-1 Then X = 0 : Y + grid
                    If Y > ImageH-1 Then Exit
                    
                    R = ReadByte(f)
                    
                    If R = 1 Then
                        R = EXR
                        G = EXG
                        B = EXB
                    Else
                        G = ReadByte(f)
                        B = ReadByte(f)
                    End If
                    
                    Color R,G,B
                    Box X,Y,grid,grid

                    // Pistetään tämän ruudun väriarvot muistiin,
                    // jotta niitä voidaan vertailla seuraavan ruudun
                    // väriarvoihin.
                    EXR = R
                    EXG = G
                    EXB = B

                    X + grid
                
                Forever

                Unlock
                DrawToScreen

                // Tallennetaan maagiset arvot, joista voidaan varmistaa,
                // onko kaikki OK tähän asti...
                If ReadByte(f)<>79 Then MakeError "CBI: The file is corrupted."+Chr(10)+Chr(13)+"(Or we've screwed up at some point...)"
                If ReadByte(f)<>75 Then MakeError "CBI: The file is corrupted."
                If ReadByte(f)<>33 Then MakeError "CBI: The file is corrupted."

                // VAIHE 2:
                //    LISÄTÄÄN POHJARUUDUKON PÄÄLLE YKSITTÄISIÄ PIKSELEITÄ,
                //    ELI RAKENNETAAN KUVAN YKSITYISKOHDAT

                // Seuraavalta riviltä alkavan loopin voisi korvata
                // For .. next -loopilla, mutta ikävä kyllä silloin
                // ruudukon kokoa ei voisi muuttaa (step arvon on
                // oltava vakio.
                X = 0 : Y = 0
                Lock Image(TempImg)
                Repeat
                    If X > ImageW-1 Then X = 0 : Y + 1
                    If Y > ImageH-1 Then Exit
                    
                    R = ReadByte(f)
                    If R = 1 Then
                        // Tämä pikseli on "TYHJÄ", ei tehdä mitään
                    Else
                        G = ReadByte(f)
                        B = ReadByte(f)
                        'SetWindow X+" "+Y
                        PutPixel X,Y,2,Image(TempImg)
                    End If

                    X + 1
                
                Forever
                Unlock

    CloseFile f

    Return TempImg
EndFunction

Function RGBToPixel(r,g,b)
    Return b + (g Shl 8) + (r Shl 16) + (255 Shl 24)
EndFunction
Voit tallentaa minkä tahansa ladatun kuvan CBI -tiedostoksi seuraavalla komennolla:
SaveCBImage(Kuva, "Target.cbi", 10)
... jossa "kuva" on kuvamuuttuja, "Target.cbi" kohdetiedosto, ja 10 on pohjaruudukon koko. Anna sen olla se 10.

Voit ladata CBI muotoisen kuvan komennolla:
Kuva = LoadCBImage("TheImage.cbi")
... jossa ainoa parametri on kuvan polku. Kun CBI kuva on ladattu, sitä voidaan käsitellä samoilla komennoilla kuin LoadImagella ladattuja kuvia.

Muutama sana kuvaformaatin toimintaperiaatteesta (älä lue ellei sinua oikeasti kiinnosta :)):
Idea on, että kuva jaetaan pieniin, esim. 10x10px kokoisiin ruutuihin. CBI tiedostoon tallennetaan jokaisen pienen ruudun RGB arvot. Nyt meillä on siis kasassa kuva, joka näyttää erittäin palikkamaiselta, mutta sen tallennus on vienyt vasta 1% alkuperäisen tiedoston koosta. Noh, nyt tuon ruman palikkakuvan päälle lisätään yksittäisiä pikseleitä sinne tänne, jotta kuvasta saadaan katselukelpoinen. Jos esimerkiksi kuvan vasemmassa yläreunassa oli 10x10 kokoinen musta laatikko, jonka sisällä yksi valkoinen pikseli, tallennetaan nyt tiedostoon kaikki tuon 10x10 kokoisen laatikon sisällä olleet pikselit... Mutta koska ne ovat suurin osa mustia kuten pohjaruudukossakin, kolmen tavun sijaan (RGB) tallennetaan vain ensimmäinen (R), ja näin ollen säästetään 2/3 tilaa. Kun tiedosto jälkeenpäin avataan, huomataan että "Jaahas, tuo tavun arvo on 1, se tarkoittaa että en lue enää kahta seuraavaa tavua saadakseni kasaan RGB arvon, vaan tähän kohtaan kuvaa ei tule pikseliä. Hyppäänpä tästä nyt seuraavaan pikseliin". Seuraavana tavoitteena olisi virittää systeemiä niin, että jos esim. ensimmäisen 10x10 kokoisen ruudukon sisällä kaikki pikselit ovat samanvärisiä, tallennetaan vain jokin tietty luku, esim. 0, ja sitten se RGB arvo, ja sen jälkeen hypättäisiin suoraan seuraavaan ruutuun, ja säästettäisiin hemmetisti enemmän tilaa.
Ohhoh, siitä tulikin vähän enemmän kuin "muutama" sanaa. Ja kukaan ei todennäköisesti edes lue koko tekstiä... No jaa.

Liitetiedosto sisältää yltälöytyvän koodin .cb tiedostona, esimerkit, sekä yhden esimerkkikuvan, jolla pakkaustehoa voi testata.
PS: Jos kokeilet funktioiden pakkauskykyä CB:n media -kansion tiedostoilla, pakatusta kuvasta tulee todennäköisesti pari kertaa isompi kuin alkuperäisestä, sillä suurin osa CoolBasicin kuvista on 8 bittisessä muodossa, mutta CBI kuvat tallennetaan aina 32 bittisinä, jolloin tilaa menee enemmän. Systeemillä kannattaakin siis pakata vain 32 bittisiä kuvia.
PSS: Koodissa on pieni puute: Looppi, joka alkaa riviltä 205 joutuu piirtämään kaikki pikselit PutPixelillä, sillä PutPixel2 aiheutti MAVin. Voisiko joku korjata tämän?

EDIT: Julistan projektin virallisesti jäätyneeksi. Sulattaminen aloitetaan, kun CoolBasicin kolmosversion myötä saadaan lisätehoa kuvien tarkempaan analysointiin.
Attachments
CBImage.rar
(127.5 KiB) Downloaded 254 times
Last edited by Ruuttu on Fri May 22, 2009 4:39 pm, edited 1 time in total.
Aavesoturi
Active Member
Posts: 163
Joined: Fri Aug 31, 2007 7:07 pm
Location: Helsinki
Contact:

Re: CBI - Häviötöntä kuvanpakkausta

Post by Aavesoturi »

Pakkausta voisi tehostaa valitsemalla pohjalaatikoiden väriarvoiksi sen, mitä väriä siellä on eniten. Tämä tietysti lisää pakkausaikaa, mutta sehän on harvoin olennaisin asia. Lisäksi kannattanee tutustua RLE eli run length encoding tekniikkaan jossa samanlaiset peräkkäiset värit korvataan numerolla, esim. ABCCCCCCCA --> AB7CA. (Käytäntö on hieman monimutkaisempi kuin tuo esimerkki). Pohja gridin voisi esim. pakata RLE:lla sen muodostamisen jälkeen tai jotain.

Lisää pakkaustehoa saa tekemällä paletin, eli katsotaan ensin kuinka monta eri väriä kuvassa on jolloin tiedätään kuinka monta bittiä tarvitaan yhden värin kertomiseen. Sitten annetaan jokaiselle RGB arvolle juokseva numero joita sitten käytetään kuvan tallentamiseen rgb arvojen sijasta. Esim. jos jossain spritessä voisi olla vaikka 32 eri väriä, jolloin niiden kertomiseen tarvitaan 5 bittiä eli yksi tavu riittää. Tämän tehoa huonontaa hieman se, että itse paletti pitää tallentaa myös, mutta loppupeleissä hyöty on usein huomattavasti suurempi.

Tosi advancedia olisi sitten käyttää vaihtelevan mittaisia palettikoodeja, jotka eivät edes noudata 8 bitin tavu rajoja. Tämä vaatii bittitason operaatioita, joihin löytyy funkkarit cbkk:sta. Silloin voidaankin ryhtyä entropiakoodaamaan, eli järjestetään paletin värit niiden esiintymistiheyden perusteella ja annetaan kaikista todennäköisimmälle värille lyhyin koodi mahdollinen koodi, esim. 01. Silloin saadaan puristettua taas jonkun verran tilaa pois.

Lisätietoja pakkauksesta löytää vaikka wikipediasta.

EDIT: Tossa kun mietin, niin aika hyvään pakkaukseen pääsis varmaan jo pelkästään tekemällä paletin ja sitten RLE pakkaamalla kuvadatan (jossa siis palettikoodit RGB arvojen sijaan). Paletin kanssa RLE olis vieläpä sangen helppo toteuttaa; varaa yhden palettikoodin merkiksi, joka kertoo että seuraava tavu onkin lukumäärätavu. Jos lukumäärätavua käytetään ainoastaan silloin kun peräkkäisiä samoja värejä on kolme tai enemmän, RLE ei koskaan kasvata tiedoston kokoa, vaikka se olisikin joku valokuva, jossa ei ole yhtään samanlaisia värejä vierekkäin.
User avatar
Ruuttu
Devoted Member
Posts: 688
Joined: Thu Aug 30, 2007 5:11 pm
Location: Finland, Sipoo

Re: CBI - Häviötöntä kuvanpakkausta

Post by Ruuttu »

Aavesoturi wrote:(Asiatekstiä ja hyviä pointteja)
Ohhoh, siinäpä oli paljon asiaa. Hyvä juttu on että jopa ymmärsin osan siitä. :D Seuraavaksi ajattelin tosiaan ruveta virittämään tuota palettisysteemiä, sillä peligrafiikassa (jolle tämä kuvamuoto onkin tarkoitettu) hyödynnetään useinkin vain muutamaa eri väriä, joten 32 bittisten väriarvojen tallentaminen joka pikselissä on aikamoista tuhlailua. Myöskin tietojen tallennusjärjestys vaatii viilausta: nyt tiedostoon tallennetaan koko ruudukko kerrallaan, ja sitten pikselit. Käytännössä olisi kuitenkin helpompaa tallentaa ensin yksi ruutu, sitten sen pikselit, sitten taas yksi ruutu ja sitten pikselit. Seuraavassa versiossa voidaan myös määrittää kuvan tarkkuus, joten kuvat voidaan pakata entistäkin pienempään tilaan muutamien yksityiskohtien hinnalla. Koska CoolBasicilla ei pysty tallentamaan tiedostoon bittiä kerrallaan (voisiko sen muuten tehdä esim. dll:llä?) enkä ainakaan toistaiseksi osaisi tunkea vaikkapa kahdeksaa "irtobittiä" yhteen tavuun, en vielä pysty virittämään pakkaustehoa ihan huippuunsa, mutta katotaan nyt...
EDIT:

Tämä palettisysteemi muuttaa tiedostomuotoa niin rajusti, että taidan kirjoittaa koko systeemin uudelleen. Kestänee siis hetken ennen kuin seuraavaa versiota tulee, mutta onneksi sitä ei kukaan odotakaan, niin ei ole turhia paineita. ;)

User avatar
Ruuttu
Devoted Member
Posts: 688
Joined: Thu Aug 30, 2007 5:11 pm
Location: Finland, Sipoo

Re: CBI - Häviötöntä kuvanpakkausta

Post by Ruuttu »

Olen tässä huomannut että tuon palettisysteemin optimointi on ihan mielettömän vaikeaa. Tällä hetkellä systeemi toimii näin:

Luodaan taulukko, jossa tilaa 255 RGB arvolle.
Käydään For .. next loopilla koko hemmetin kuva läpi pikseli kerrallaan. Tarkistetaan, löytyykö pikselin RGB -arvoa taulukosta, jos ei, lisätään se sinne. Kun taulukossa on 255 väriä tai kuva on käyty kokonaan läpi, homma on valmis. Tämä on erittäin hidasta, sillä jokaisen pikselin kohdalla joudutaan tarkistamaan koko taulukko läpi, jottei palettiin tulisi samoja värejä useaan kertaan. Niinpä esim. 800x600 kokoisen kuvan kohdalla taulukkoa joudutaan lukemaan pahimmillaan 800x600x255 kertaa, ja se kestää niin hemmetin kauan. Miten se paletin luonti olisi järkevintä / nopeinta toteuttaa?
EDIT:

Aavesoturi wrote:Ratkaisu
Höh, miten en itse tuota keksinyt?! No jaa... Tuo on tosiaan hyvä systeemi, about 40 kertaa nopeampi kuin alkuperäinen taulukkohässäkkä. Muistia kuluu tosiaan aika huolestuttavasti (olikos se nyt abt. 15 megaa?), mutta parempaa ratkaisua tuskin on. Kiitos.[/edit]
Last edited by Ruuttu on Tue Dec 30, 2008 10:11 am, edited 2 times in total.
Aavesoturi
Active Member
Posts: 163
Joined: Fri Aug 31, 2007 7:07 pm
Location: Helsinki
Contact:

Re: CBI - Häviötöntä kuvanpakkausta

Post by Aavesoturi »

Ruuttu wrote:Miten se paletin luonti olisi järkevintä / nopeinta toteuttaa?
Yksi tapa olisi tehdä väliaikainen kolmiulotteinen byte taulukko, Dim colorflags(255,255,255) As Byte
ja sitten aina jokaisen pikselin kohdalla tarkistaa onko tuossa taulukossa väriä vastaavassa kohdassa jo numero; jos ei, luodaan uusi palettinumero ja asetetaan se taulukkoon. Toisin sanoen taulukko kertoo mikä palettikoodi, jos mikään, vastaa tiettyjä värikoordinaatteja.
Tämä olis nopeaa, mutta en oo varma tykkääkö cb taulukoista, joissa on noin paljon alkoita (enkä nyt pysty testaa ku oon ubuntun puolella), muistiakin kuluu aikas paljon.
Cérebro
Newcomer
Posts: 35
Joined: Wed Jul 16, 2008 8:56 pm

Re: CBI - Häviötöntä kuvanpakkausta

Post by Cérebro »

Ruuttu wrote:
Aavesoturi wrote:(Asiatekstiä ja hyviä pointteja)
Ohhoh, siinäpä oli paljon asiaa. Hyvä juttu on että jopa ymmärsin osan siitä. :D Seuraavaksi ajattelin tosiaan ruveta virittämään tuota palettisysteemiä, sillä peligrafiikassa (jolle tämä kuvamuoto onkin tarkoitettu) hyödynnetään useinkin vain muutamaa eri väriä, joten 32 bittisten väriarvojen tallentaminen joka pikselissä on aikamoista tuhlailua. Myöskin tietojen tallennusjärjestys vaatii viilausta: nyt tiedostoon tallennetaan koko ruudukko kerrallaan, ja sitten pikselit. Käytännössä olisi kuitenkin helpompaa tallentaa ensin yksi ruutu, sitten sen pikselit, sitten taas yksi ruutu ja sitten pikselit. Seuraavassa versiossa voidaan myös määrittää kuvan tarkkuus, joten kuvat voidaan pakata entistäkin pienempään tilaan muutamien yksityiskohtien hinnalla. Koska CoolBasicilla ei pysty tallentamaan tiedostoon bittiä kerrallaan (voisiko sen muuten tehdä esim. dll:llä?) enkä ainakaan toistaiseksi osaisi tunkea vaikkapa kahdeksaa "irtobittiä" yhteen tavuun, en vielä pysty virittämään pakkaustehoa ihan huippuunsa, mutta katotaan nyt...
EDIT:

Tämä palettisysteemi muuttaa tiedostomuotoa niin rajusti, että taidan kirjoittaa koko systeemin uudelleen. Kestänee siis hetken ennen kuin seuraavaa versiota tulee, mutta onneksi sitä ei kukaan odotakaan, niin ei ole turhia paineita. ;)

Näillä funktioilla voit luoda tavun 8 bitistä sekä hakea tavusta bitin.

Code: Select all

// Luo tavun 8 bitistä
Function MakeByte(_Bit1, _Bit2, _Bit3, _Bit4, _Bit5, _Bit6, _Bit7, _Bit8)
    Return (_Bit1 * 2 ^ 7) + (_Bit2 * 2 ^ 6) + (_Bit3 * 2 ^ 5) + (_Bit4 * 2 ^ 4) + (_Bit5 * 2 ^ 3) + (_Bit6 * 2 ^ 2) + (_Bit7 * 2 ^ 1) + _Bit8
End Function

// Hakee tavusta bitin
Function ExtractBit(_Byte, _BitNum)
    If _BitNum < 1 Or _BitNum > 8 Then MakeError("Bit number out of byte area")
    Return Int(Mid(Bin(_Byte), 24 + _BitNum, 1))
End Function
cbLib | XMap
In development: EasyBasic - Basic-tyylinen peliohjelmointikieli
User avatar
Ruuttu
Devoted Member
Posts: 688
Joined: Thu Aug 30, 2007 5:11 pm
Location: Finland, Sipoo

Re: CBI - Häviötöntä kuvanpakkausta

Post by Ruuttu »

Cérebro wrote: Näillä funktioilla voit luoda tavun 8 bitistä sekä hakea tavusta bitin.
Hmm... Nyt kun olen piilottanut kaiken "ylimääräisen" tiedon pikseleiden RGB -arvoihin en meinaa keksiä mitään hyötykäyttöä noille funktioille. Tosin jos oikein nerokkaasti koodin muotoilisi, säästäisi tasaisissa väripinnoissa kahden tavun sijasta 23 bittiä, eli melkein kokonaiset kolme tavua. Hmm, minun lienee parasta kirjoittaa koko höskä vielä kerran alusta, sillä tämä alkaa mennä jo suhteellisen monimutkaiseksi ja haluaisin kuitenkin pitää koodin niin optimoituna ja selkeänä kuin mahdollista. Joka tapauksessa, kiitos.
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Re: CBI - Häviötöntä kuvanpakkausta

Post by MaGetzUb »

Voisit pistää sitten vielä valinnaisen salauksen, sehän ei nyt kovin vaikeaa ole tehdä. Siis salasana vaan..
EDIT:

En saa itse aivan bittimappia kiinni pienuudessa, vaikka kuina olen kikkaillut.. Pieninpään, johonka pääsin media\map.bmp:llä oli 353kt kun taas itse alkuperäinen oli 351.. :) Hankalaa on kyllä keksiä itse kotikonstein pakkaus tapaa, joka olisi parempi, kuin bmp..

EDIT:

2. En oikein AaveSoturi, ymmärtänyt tuota 3ulotteista taulukkoa oikein, voisiko joku tehdä esimerkin?
Ja Ruuttu muuten ei kukkan tee yli 4triljoonan (kun ottaa huomioon, että kirjoitat aina pituuden ja leveyden 32bittiseen kokonaislukuun) pikselin kuvia se on varma

Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.
User avatar
Ruuttu
Devoted Member
Posts: 688
Joined: Thu Aug 30, 2007 5:11 pm
Location: Finland, Sipoo

Re: CBI - Häviötöntä kuvanpakkausta

Post by Ruuttu »

programmer of DSG wrote:Voisit pistää sitten vielä valinnaisen salauksen, sehän ei nyt kovin vaikeaa ole tehdä. Siis salasana vaan..
EDIT:

En saa itse aivan bittimappia kiinni pienuudessa, vaikka kuina olen kikkaillut.. Pieninpään, johonka pääsin media\map.bmp:llä oli 353kt kun taas itse alkuperäinen oli 351.. :) Hankalaa on kyllä keksiä itse kotikonstein pakkaus tapaa, joka olisi parempi, kuin bmp..

EDIT:

2. En oikein AaveSoturi, ymmärtänyt tuota 3ulotteista taulukkoa oikein, voisiko joku tehdä esimerkin?
Ja Ruuttu muuten ei kukkan tee yli 4triljoonan (kun ottaa huomioon, että kirjoitat aina pituuden ja leveyden 32bittiseen kokonaislukuun) pikselin kuvia se on varma

- Salaus oli itseasiassa alunperin mielessäni ensimmäisenä, kun mietin mitä hyötyä uudesta kuvaformaatista voisi olla. Tulossa.
- Bitmap kuvissa ei tietääkseni ole mitään muuta kuin perustiedot kuten kuvan leveus ja korkeus, ja sen jälkeen yksinkertaisesti mielettömät määrät tavuja (byte) järjestyksessä R,G,B,R,G,B... Jos tallennat yhtä pikseliä kohden enemmän kuin kolme tavua, kuvasta tulee varmasti suurempi kuin alkuperäisestä .bmp kuvasta. Toisekseen, jos olet testannut luomiasi kuvanpakkausmenetelmiä CoolBasicin omilla medioilla, olet varmasti saanut outoja tuloksia, sillä esim. Media\Level.bmp tiedosto on 8 bittinen, mutta luomasi kuvaformaatti tallentaa kuvan todennäköisesti 32 bittisenä, jolloin tilaa menee enemmän. Käytä siis aina 32 bittisiä kuvia formaattisi testaamiseen.
- Aavesoturin idea oli vissiin, että luodaan taulukko (255,255,255), jossa on siis tilaa joka ikiselle mahdolliselle RGB arvolle, esim. (0,128,255). Jos kuvasta poimitaan pikseli jonka väri oli 1,2,3, merkitään taulukkoon sijaintiin 1,2,3 numero 1 ja lisätään palettiin sama väri. Seuraavalla kerralla kun kuvasta poimitaan väri 1,2,3, ei sitä enään merkitä palettiin, sillä taulukosta 1,2,3 löytyvä arvo on jo 1. Näin palettiin tulee kaikki värit vain kerran.
- Jep, kukaan tuskin tarvitsee ihan niin suurta kuvakokoa kuin 32 bittinen arvo sallii (varsinkaan CB:llä... kyykkäis varmaan), mutta olisi aika typerä "rajoite" jos kuvien koosta ei saisi tehtyä haluamaansa. Se, tallennetaanko kuvan koko kokonaislukuna vai vaikka tavuna ei vaikuta lopullisen kuvatiedoston kokoon juuri lainkaan.
Post Reply