Komprimieren, Packen, aus 4 mach 2 Byte??



  • @Jester
    Ja daran habe ich auch schon gedacht, sogar auf 4 Bits je Farbwert zu gehen (12 gesamt) somit ereiche ich 2 Farbwerte mit 3 Byte, ABER...
    Ich muß auch einen Farbverlauf vom einen Punkt zum anderen machen und ohne LoBits, oder halt nur einen, wird es nicht so dolle.

    Ich mein ich hatte sowas schon mal gesehen mit versch. Werten als Multiplikator, je nach höhe des Wertes.



  • ???

    Naja kommt drauf an wie du es abspeicherst ich meine 1 und 64000 belegt gleich viel speicher ( idr )

    aber wenn du 0xffffffff hast ( als string oder so ) kannst du ja auch 0x8f nehmen.

    ka so irgendwie kann man es auch machen



  • Rechne das ding in den YUV Farbraum um.



  • da sind viel zu viele fragen ungeklärt als dass man dir wirklich helfen könnte.

    1. sind es einzeln auftauchende farbwerte oder z.b. in einem bild oder einer textur.
    2. was für ne art von farben sind enthalten, z.b. nur regenbogenfarben, fotographiefarben oder normalmap colors?
    3. muss damit gerechnet werden oder ist es dann nur zum anschauen da oder wofür die farben?
    4. welche menge ist es den? wirklich nur 4byte die du auf 2byte runterrechnen muss (wat weiß ich für was für ein ultrakleines-altes-handy) oder sind die datenmengen extrem groß z.b. satelitenfotos?
    5. ist es wichtig dass es schnell zu encoden/decoden ist, dass es dabei wenig speicher verbraucht, dass jede wiederhollte kompression das bild nicht weiter verschlechtert... usw?

    vorschlagen würde ich abhängig davon:
    1. die umwandlung auf YCbCr und dann das abspeichern im 1:4:4
    2. dxt1 kompression mit 1:8 an kompressionsrate
    3. png
    4. VectorQuantitisierung
    5. umrechnung in ein anderes koordinatensystem z.b. aus r g b in alpha beta (reicht für z.b. normalmaps)
    6. einfach jpg?
    7. auf 256farben indiziert
    8. simples prediction encoding + huffman
    9. vielleicht nur runlenght?
    10. manchmal reicht simpelstes Wavelett udn quantitisieren
    .
    .
    .

    btw. ein beispiel würde auch was bringen 😉

    rapso->greets();



  • @rapso
    Du bist schuld das mein Hirn jetzt mit den Enten unterwegs ist.. 😃

    Also ich beabsichtige für Live-übertragung ein Videostream Format zu machen, welches mit 80 kbits/s (10kb) auskommen muß, bei 8 fps.
    Dabei werden alle 8Bilder in einem Packet gesendet, das erste Bild ist immer ein volles, die nachfolgenden, nur Blöcke mit änderungen (Motion erkennung)

    Wie erwähnt ist ein Bild in Blöcke und Subblöcke unterteilt,
    ein Alpha-Block beinhaltet 4x4 (16) Beta-Blöcke, das Alphablock giebt nur mit 2 Byte (16Bit kennung) an, in welchem Beta-Block eine änderung geschah.
    Ein Beta-Block umfasst 4x4 Pixel, in der nur eine Farbe drin steht, in der linken-oberen Ecke, von da aus werden die Restlichen Pixel horizontal, vertikal und diagonal zur Farbe des nächsten Beta-Blocks interpolariert.
    Nach ersten versuchen und berechnungen darf so ein Alphablock nicht mehr als 20-24 Byte betragen, da im ersten Bild alle Blöcke vorhanden sind.

    Ich versuche mal ein ASCII Schema:

    X O O O | X O O O | X O O O | X O O O O
      O O O O | O O O O | O O O O | O O O O O
      O O O O | O O O O | O O O O | O O O O O
      O O O O | O O O O | O O O O | O O O O O
      ---------------------------------------
      X O O O | X O O O | X O O O | X O O O O
      O O O O | O O O O | O O O O | O O O O O
      O O O O | O O O O | O O O O | O O O O O
      O O O O | O O O O | O O O O | O O O O O
      ---------------------------------------
      X O O O | X O O O | X O O O | X O O O O
      O O O O | O O O O | O O O O | O O O O O
      O O O O | O O O O | O O O O | O O O O O
      O O O O | O O O O | O O O O | O O O O O
      ---------------------------------------
      X O O O | X O O O | X O O O | X O O O O
      O O O O | O O O O | O O O O | O O O O O
      O O O O | O O O O | O O O O | O O O O O
      O O O O | O O O O | O O O O | O O O O O
    

    Also insgesamt 16 Farben, aber nur 20-24 Byte dafür.
    (daher 16 Farben x 3 Byte = 48 ... / 2 = 24)

    Mit 12 Bit je Farbe würde es gehen.
    Ein volles Bild umfast 108 A-Blöcke.



  • da empfehle ich dir Wavelet.

    wobei ich erstmal sagen muss, dass es ein wenig komisch ist das du ein bild mit 1/16 seiner auflösung verschickst.

    bei z.b. MPEG und JPG wandelt man die bilder erstmal in YCbCr um. bei JPG speichert man sich dann pro pixel je ein Y und für jeweils 4pixel ein CbCr wert, bei jpg sogar nur je pixel ein Y und für 4*4pixel ein CbCr wert.
    Y ist die helligkeit und die ist für menschliche augen relativ wichtig in einem Bild.
    CbCr sind Farbchrominanzen und die bemerkt man nicht so sehr mit menschlichen augen.

    bei 16Y+1CB+1CR hast du eine kompression von ca 1:2,67. der unterschied zu deinem ansatz ist, dass man den qualitätsverlust dabei so gut wie garnicht bemerkt (bei bewegten bildern). dabei ist die datenmenge natürlich um einiges höcher als bei dir, dafür fing die quantitisierung aber noch nicht wirklich an :), du kannst es ja mal qualitätsmässig vergleichen, das war jetzt aber mehr OT 🙂

    kommen wir zum Wavelet 🙂

    also, hier mal für 2d
    angenommen du hast die pixel

    1 3 5 7
    

    dann errechnest du für jeweils ein paar die mittelwerte und den resutlierende abweichung nach oben und unten

    (1+3)/2 = 2 mitte
    3-2     = 1 abweichung
    (5+7)/2 = 6 mitte
    7-6     = 1 abweichung
    

    dann

    (2+6)/2 = 4 mitte
    6-4     = 2 abweichung
    

    = 4 2 1 1

    die abweichungen merkst du dir pro iteration
    die mitten mittelst du pro iteration
    bis du am ende auf den durchschnittswert deines ganzen bildes gekommen ist (dabei solltest du abwechselnd in x udn y falten)

    du fragst dich was die umwandlung bringt. also du hast nun die grobfrequenzen und das rauschen darin. gerade bei bildern ist das rauschen oft sehr schwach, also vielleicht zwischen -32 udn 32 (natürlich gibt es manchmal ausreisser)
    du mußt dann also nicht mehr 8bit speichern für die werte, sondern vielleicht nur 6 (das hängt natürlich vom bild ab)

    weiter kannst du, falls zuviel daten aufkommen, einen teil des rauschens weglassen, dabei kannst du nach iterationen gehen. also erst das rauschen der ersten iteration weglassen, dann der zweiten... bis du die gewünschte datenmänge erreicht hast. in unserem beispiel würdest du also vielleicht 1 1 weglassen und nur 4 2 übertragen.

    naja, so wäre mein vorschlag. (bezogen auf deine farbewerte obenlinks in den blöcken)

    ich hab für meinen videochat die intel jpeg lib benutzt, mit der konnte ich über dsl ca 15fps erreichen und dabei hab ich den header sogar immer mitgeschickt *hehehe*

    rapso-<greets();



  • Danke für die ausfürliche erklärung, ich denke ich werde beides irgendwie verknüpfen um gute Qualität mit wenig Bytes zu ereichen, ich muß mich da aber noch mehr mit YCbCr beschäftigen.
    Ich tüftel auch gerade daran für einen 2x2 B-Block ein Byte als Grün zu nehmen (ähnlich Y als helligkeit) und je 1 Byte für 4Buit blau und 4Bit rot für jeden Punkt, so komme ich auf 20 je A-Block.

    PS:

    rapso schrieb:

    rapso-<greets();

    Ist das C-- 🙂



  • wenn du helligkeit + grün + rot hast, kannst du blau leicht errechnen.

    rapso->greets();

    btw ich war/bin in eile, deswegen sorry fürs falschpointen usw. 🙂



  • Ich bin auf JPEG2000 gestossen was mit Wavelet commprimiert, na da machen wir mal nen Videocodec raus, der DivX in den Schatten stellt.. 😉



  • DerPacker schrieb:

    Ich bin auf JPEG2000 gestossen was mit Wavelet commprimiert, na da machen wir mal nen Videocodec raus, der DivX in den Schatten stellt.. 😉

    Du bist zu spät... hat sich schon einer vor dir gedacht :p das ding nennt sich h.264 AVC, allgemein unter dem Namen MPEG4-Part 10 bekannt 🤡



  • naja und das meißte an moviecompression macht die motioncompensation aus, nicht die größe der KeyFrames soweit ich weiß und daran ändert sich wegen wavelets nicht wirklich was.

    rapso->greets();



  • Also für ne simple 8fps bild übertragung halte ich den aufwand für etwas übertrieben.
    Wenn du supper kompression und gubte bildquaität haben willst nimm nen fertigen codec, ist vieler besser als irgend welchen transformationen selbst zu implementieren.
    Wenn du dir selbst was bastelen willst würde ich das machen:
    - Wandle das bild ins YCbCr format um
    - Speicher nur die jeweiligen änderungswerte vom vorigen pixel
    - Mach ne RLE codierung
    - Mach ne Huffmann codierung

    Wenn du jetzt noch ne simple motioncompensation mit P frames (wenn du fleißarbeit machn willst produziere auch B farmes, bring noch mal was) dazu baust sollte doch das eingeltich reichen (achtung: schätzung, habs net nachgerechnet).



  • CMatt schrieb:

    - Speicher nur die jeweiligen änderungswerte vom vorigen pixel

    *hehe* diese diefinition klingt sehr lau, weil es eigentlich die definition von videokompressionen ist.

    äquivalent könnte man für bilder sagen: lass die unnötigen daten für die pixel weg und speicher nur das notwendige 😉

    und naja, im QCIF wären das noch 3KByte wenn man pro pixel 1bit als änderungsdaten speichert und das ließe sich dann auch noch schlecht komprimieren weil es zumeißt rauschdaten wären.

    rapso->greeets();



  • *hehe* diese diefinition klingt sehr lau, weil es eigentlich die definition von videokompressionen ist.

    äquivalent könnte man für bilder sagen: lass die unnötigen daten für die pixel weg und speicher nur das notwendige

    o_O
    mit weg lassen hat das nichts zu tun. Die Methoden in der liste sind alle verlustfrei (bis auf die RGB-YUV unwandlung).
    Der sinn von dem ist einfach: wenn ich nur die änderung speichere (zb: Y werte: 100,105,106,100 -> 100,5,6,-6), reduziere ich die anzahl der benötigen bits zum dastellen eines werte, was beteutet ich kann den RLE algo darauf trimmen und somit platz sparen.
    bsp:
    2bit count 8 bit data <- wird beim ersten wert zum einsatz kommen
    2bit count 4 bit dara <- wird bei sehr vielen (nicht 1.) wert werten zum einsatz kommen (2 bits gespart)
    4bit count 4 bit data <- kommt kleinen werten mit haufigem auftretem dran, gleiche länge wie 1. kann aber 14 sequenzielle werte mehr darstellen

    aber wie schon geschagt.. ich bevorzuge immer noch ein schönes, schon fertiges codec SDK 😃 🤡



  • CMatt schrieb:

    o_O
    mit weg lassen hat das nichts zu tun. Die Methoden in der liste sind alle verlustfrei (bis auf die RGB-YUV unwandlung).

    verlustfrei kommst du aber nur schwer auf die 2kb/bild von vorher, vielleicht QCIF,75kb/bild kommen.

    CMatt schrieb:

    Der sinn von dem ist einfach: wenn ich nur die änderung speichere (zb: Y werte: 100,105,106,100 -> 100,5,6,-6), reduziere ich die anzahl der benötigen bits zum dastellen eines werte, was beteutet ich kann den RLE algo darauf trimmen und somit platz sparen.

    aufgrund des rauschens, lässt die entrophie RLE so gut wie nicht zu.
    beim speichern der differenzwerte hat man zudem öfter mal das problem, dass werte von -256 bis +256 aus ursprünglich 256 werten auftauchen können, das vergrößert die datenmenge dann sogar. natürlich kannst du diese pixel gesondert verwalten, aber verwalten = mehr daten.

    CMatt schrieb:

    2bit count 8 bit data <- wird beim ersten wert zum einsatz kommen
    2bit count 4 bit dara <- wird bei sehr vielen (nicht 1.) wert werten zum einsatz kommen (2 bits gespart)
    4bit count 4 bit data <- kommt kleinen werten mit haufigem auftretem dran, gleiche länge wie 1. kann aber 14 sequenzielle werte mehr darstellen

    das problem von deinen ideen ist, dass er auf ca 0.6bit/pixel kommen muss. das ist nicht so einfach wenn man nur pixel für sich betrachtet.

    CMatt schrieb:

    aber wie schon geschagt.. ich bevorzuge immer noch ein schönes, schon fertiges codec SDK 😃 🤡

    man kann sehr vieles fertig nehmen, aber wieso dann nen fertigen codec und nicht gleich eines der unzähligen fertigen video-chat tools;)?

    rapso->greets();



  • verlustfrei kommst du aber nur schwer auf die 2kb/bild von vorher, vielleicht QCIF,75kb/bild kommen.

    Brauchst du nicht. So codiert sind nur die intra blocks, rest kommt doch nur alle x frames mal (mit jedem I frame).

    aufgrund des rauschens, lässt die entrophie RLE so gut wie nicht zu.
    beim speichern der differenzwerte hat man zudem öfter mal das problem, dass werte von -256 bis +256 aus ursprünglich 256 werten auftauchen können, das vergrößert die datenmenge dann sogar. natürlich kannst du diese pixel gesondert verwalten, aber verwalten = mehr daten.

    Ich glaube das überschätz du etwas. Habs eben getestet (war auch neugierig *g*): Bild mit 2 leuten auf ner wiese -> RGB24 nach YUV420 ->
    59% der pixel RLE comprimierbar.
    Diese goßen Unterschiede sind eher selten. Falls es auftritt muss damit leben das man ein bit oder zwei mehr für den wert braucht, aber der großteil der änderungen in nem normalen bild liegt im bereich den man in 4 bits packen kann.

    Wenn ich michts zu tun habe werde ich da zu dem ding mal ein test prog bauen, denn ausm bauch raus habe ich das gefühl das dürfte reichen.

    Ich will euch hier aber sicher nicht davon abhalten wavlet oder ne DCT einzusetzten. Mit frequenz-werten stehen natrülich nochmal x möglichkeiten mehr offen und vor allem kann man das ding quantisieren was euch von allen 'zu viele daten-ängsten' erlösen dürfte 😃 Ich glaube halt nur das sich der aufwand nicht lohnt 😉



  • CMatt schrieb:

    Brauchst du nicht.

    hoe? was braucht man nicht?

    meine berechnung war simpel:
    QCIF bild hat ~25000pixel, wenn du von bild zu bild die differenz pro pixel berechnest, hast du at least 3kbyte die dabei resultieren (bei 1bit/pixel). somit sind die interpolierten bilder schon zu groß für seine belangen, er muss ja 8bilder/10kbyte übertragen.

    oder schlägst du vor für die 16pixel abzuspeichern welchen zeit-farb-verlauf sie haben?

    CMatt schrieb:

    Ich glaube das überschätz du etwas.

    ich schätze nicht, ich hab's programmiert ;), um mehr redundanz zu haben hab ich es sogar auf 256color indices runterkonvertiert. bei 160*120 bin ich auf ca 3-7kb/bild gekommen beim T3 trailer.

    rapso->greets();



  • hoe? was braucht man nicht?

    meine berechnung war simpel:
    QCIF bild hat ~25000pixel, wenn du von bild zu bild die differenz pro pixel berechnest, hast du at least 3kbyte die dabei resultieren (bei 1bit/pixel). somit sind die interpolierten bilder schon zu groß für seine belangen, er muss ja 8bilder/10kbyte übertragen.

    ich glaube wir reden an aneinder vorbei 😉
    Ich rede nicht von der pixel-für-pixel differenz zweier bilder, sondern von den pixeln in einer reihe.
    Das intra frame wird so gecoded wie beschrieben, die danachfolgenen bestehen aus motion vectoren & einzelen intra blocks, da natürlich block-weise nicht pixel weise 🤡

    ich schätze nicht, ich hab's programmiert , um mehr redundanz zu haben hab ich es sogar auf 256color indices runterkonvertiert. bei 160*120 bin ich auf ca 3-7kb/bild gekommen beim T3 trailer.

    hmm... sehr interessant. Kann das bei mir was mit der RGB-YUV convertierung zu tun haben (das bild durch die convertierung deutlich 'weicher'). Habs eben noch mit ein paar anderen bildern versucht: ich bekomme da immer so zwichen 55-75% an RLE comprimierbaren pixelfolgen raus. 😮



  • Hat einer von euch beiden mal den Code um RGB nach YCbCr und zurück zu Konventieren?
    ala:

    Y  =  0,2990*R + 0,5870*G + 0,1140*B
    Cb = -0,1687*R - 0,3313*G + 0,5000*B
    Cr =  0,5000*R - 0,4187*G - 0,0813*B
    

    Entweder bin ich mitlerweile zu doof geworden um simple dinge zu proggen, durch das ganze, oder die Quellen sind Fehlerhaft.
    (Ja, ich prüfe auf - zu 0 und >255 = 255)



  • DerPacker schrieb:

    Entweder bin ich mitlerweile zu doof geworden um simple dinge zu proggen

    ... oder zu faul für mr google, aber nun gut, mach ich das mal für dich 😉

    http://www02.so-net.ne.jp/~koujin/jpeg/RGB2YCbCr.html

    DerPacker schrieb:

    durch das ganze, oder die Quellen sind Fehlerhaft. (Ja, ich prüfe auf - zu 0 und >255 = 255)

    es ist auch möglich *0.95+0.25 zu rechnen (für werte von 0-1). was das bringt? bei konvertieren zu YCbCr udn zurück zu RGB ersparrst du dir, auf kosten von ein bisschen kontrast bzw sättigung, so einiges an konditional jumps, das kann ein wenig performance bringen ;)... (falls du es nicht gerade mit sse oder mmx machst.

    rapso->greets();


Anmelden zum Antworten