Jpg Bilder einlesen und skalieren



  • So mal kleines Update was ich bis jetzt hab:

    #include <iostream>
    #include <vector>
    #include "mxpw.h"
    
    Huffamn{
    private:
      //Vektor für ??
      std::vector<char> veki;
      //Der virtuelle Datenstrom
      std::vector<char> datastream;
    public:
      //Constructer
      Huffman{};
      //Deconstructer
      ~Huffamn{};
      //JPEG Encoder
      void encoder();
      //JPEG Decoder
      void decoder();
      //Baum bauen
      void buildtree();
      //Knoten übersetzung bauen
      void buildbook();
      //Knoten bauen
      void buildnode();
      //Characters lesen
      void readChar();
      //Baum lesen
      void readtree();
      //Zählen und Wahrscheinlichkeiten
      void count();
    
      // Reserviert eine Datengröße
      void ReserveSize(size_t Bytes) datastream.reserve(Bytes); }
      // Löscht den Stream
      void ReleaseStream() { datastream.clear(); }
    };
    
    #include <iostream>
    #include <vector>
    #include "huffman.h"
    
    //Fügt Daten ein
    /*template<typename T> void Assign(T data)
    {
        char *tmpdata = new char[sizeof(T)];
        memcpy((void**)&tmpdata, data, sizeof(T));
        for(int i = 0; i < sizeof(T); i++)
            datastream.push_back(tmpdata[i]);
    }
    
    //Liest Daten aus dem Datenstream
    template<typename T> const bool GetData(T *val, unsigned int position) const
    {
        if(sizeof(T) + position > datastream.size()) return false;
        char *tmpdata = new char[sizeof(T)];
        for(int i = 0; i < sizeof(T); i++)
            tmpdata[i] = datastream[i+position];
        memcpy((void**)&val, tmpdata, sizeof(T));
        return true;
    }*/
    
    //Encoded das JPEG
    void Huffman::encoder(){
      readChar();
      count();
      buildtree();
      buildbook();
    }
    
    //Decoded das JPEG
    void Huffman::decoder(){
      readtree();
      buildtree();
    }
    
    //Liest den erstellten Baum
    void Huffman::readtree(){
      std::iterator it;
      for(it; veki.begin() < veki.end(); it++){
        if(it == x09){
        }
      }      
    }
    
    //Zum Knoten Baum bauen
    void Huffman::buildtree(){
    
    }
    
    //Zum Knoten übersetzung bauen
    void Huffman::buildbook(){
    
    }
    
    //Knoten bauen
    void Huffman::buildnode(){
    
    }
    
    //Lesen des erstellten Baumes
    void Huffman::readtree(){
    
    }
    
    //Characters einlesen in Datenstrom
    void Huffman::readChar(){
      read.input();
    
    }
    
    //Zählen und Wahrscheinlichkeiten
    void Huffman::count(){
    
    }
    

    Das ist jetzt erstmal so eine Übersicht wie ich mir das vorgestellt hab. Musste viel lesen und werde jetzt anfangen das alles weiter aus zubauen. Wollte nur mal wissen ob euch das so gefällt oder ob ihr jetzt schon Anregungen habt.



  • Ja, dein Interface ist schon zu gross. Das wirkt als ob du zig verschiedene Funktion anbietest. Im Prinzip ist das doch aber nur das nötige zum Einlesen?!

    Und welche Funktion du da nutzt/anbietest braucht den Nutzer ja nicht zu sehen, daher -> diese Hilfsfunktionen privatisieren:

    class JPG_Reader
    {
    public:
        // ...
        void readJPG(std::istream & is) // z.B.
        {
            readStream(is);
            buildTree();
            buildbook();
            // blabla...
        }
    
        // ... andere öffentliche Methoden
    
    private:
        void readStream(std::istream& is);
        void buildTree();
        void buildbook();
        // ... usw.
    };
    

    So kannst du von aussen sagen:

    int main()
    {
        JPG_Reader r;
        r.readPJG(std::cin);
    
        r.print(std::cout);
    }
    

    Mit deiner Methode wäre das eventuell zu sowas ausgeufert:

    int main()
    {
    	Huffman h;
    	h.decode();
    	h.buildtree();
    	h.readtree(); // Ups, readtree muss eigentlich vor buildtree ausgeführt werden
    	h.buildnode(); 
    	// ..
    }
    

    Einen Grund habe ich dran kommentiert.



  • Danke das du schon so schnell antwortest! 😃

    Ich werde mich ran machen und deine Vorschläge, die mir sehr zusagen, umsetzen. Wenn ich weiter bin werde ich hier wieder ein Update machen. 🙂



  • Nur um's mal erwähnt zu haben: http://libjpeg.sourceforge.net/



  • Wenn du mit solchen Low-Level-Algorithmen arbeitest, mache dich unbedingt mit der Funktionsweise von Zeigern, RAM und Datenstrukturen im Detail vertraut. Auch RAII musst du unbedingt anschauen. Du wirst sonst wahnsinnig viel Zeit mit Debugging verbraten, viel mehr als wenn du die Zeit in die Lektüre von C++ investiert hättest. Ich fürchte, alleine die Implementierung der Algorithmen wird schon genügend Zeit (auch für Debugging) benötigen -- wenn du dann noch Probleme mit der Programmiersprache hast, wirst du sehr schnell die Motivation verlieren 😉

    dot schrieb:

    Nur um's mal erwähnt zu haben: http://libjpeg.sourceforge.net/

    Es seien auch Boost.GIL und SFML erwähnt, wobei ich mit ersterem noch nie gearbeitet habe.



  • Vielen Danke für die ganzen Tipps. Bin auch schon wieder ein Stückchen voran gekommen.

    Ich hab jetzt auch gleich mal ein Frage. Und zwar versuche ich grade die Zeichen in meinem Vector zu zählen. Allerdings nicht die gesamt Zahl sondern wie oft ein einzel Zeichen vorkommt. Irgendwie finde ich da nichts.

    std::vector<char> veki;
    int Anzahl = veki.size();
    

    Sowas hilft mir da ja leider irgendwie nicht.
    Meinet wegen hab ich ein Text eingelesen der so aussieht: 11001010001 Jetzt würde ich gerne wissen wie oft die 1 und wie oft die 0 vorkommt. Habt ihr dort mal ein Tipp für mich? Problem ist auch das ich ja nicht einfach nach einem bestimmten Zeichen suche.



  • also grade für vector<char> (was im Prinzip eine Zeichenkette ist) bietet sich std::string eher an.

    Zu deinem Problem:

    #include <algorithm>
    //...
    std::vector<char> v;
    // füllen
    auto countZeros = std::count(std::begin(v), std::end(v), '0');
    

    Referenz



  • Ja das sieht ganz gut aus. Allerdings wären in meinem Text ja ziemlich viele verschiedene Zeichen und ich will für jedes wissen wie oft es drin ist. D.h. so müsste ich ja zig std::counts schreiben um das für jedes zu wissen. Also ich such nicht nach bestimmten Zeichen sondern will wissen wie oft welches vorkommt.

    Oder kann ich da auch beliebig viel dran hängen?

    auto countZeros = std::count(std::begin(v), std::end(v), '0', '1');
    

    EDIT:
    Ah ich glaube ich hab grade gefunden was ich will:

    Lauflängencodierung:
    Substitution von Folgen identischer Symbole durch Symbole eines anderen Alphabets.
    


  • Nein, das geht nicht.
    Du solltest dir erstmal im Klaren drüber werden, wie du die Ergebnisse speichern oder nutzen willst.

    hast du z.B. eine überschaubare Anzahl von zu zählenden Zeichen (wie etwa '0', '1' und '2' als Beispiel), dann kannst du entweder mehrere Counts schreiben oder dir eine Liste bzw. map aufsetzen über die dann rüber iterierst.

    Wenn du sämtliche Ascii-Zeichen zählen musst, dann dann setzt dir ein Zahlen Array auf und nutz die Zeichen als Index:

    std::vector<std::size_t> count Chars(std::vector<char> const& s)
    {
    	std::vector<std::size_t> v(std::numeric_limits<char>::max(), 0);
    
    	for(std::size_t i = 0; i < v.size(); ++i)
    	{
    		v[i] = std::count(std::begin(s), std::end(s), static_cast<char>(i));
    	}
    
    	return v;
    } // ungetestet
    

    Wobei das nicht sonderlich gut ist und auch recht langsam sein dürfte, also es gibt da bessere Möglichkeiten



  • Enno schrieb:

    Also ich such nicht nach bestimmten Zeichen sondern will wissen wie oft welches vorkommt.

    Du möchtest ein Histogramm erstellen.



  • vector<size_t> countChars(vector<char> const& s)
    {
       vector<size_t> v(256);
       for(auto x:s)
          ++v[static_cast<unsigned char>(x)]
       return v;
    } // ungetestet
    


  • Das wäre eine schneller Lösung, z.B.



  • DirkB schrieb:

    Enno schrieb:

    Also ich such nicht nach bestimmten Zeichen sondern will wissen wie oft welches vorkommt.

    Du möchtest ein Histogramm erstellen.

    Hm ne ich glaube nicht.

    Skym0sh0 schrieb:

    std::vector<std::size_t> count Chars(std::vector<char> const& s)
    {
    	std::vector<std::size_t> v(std::numeric_limits<char>::max(), 0);
    	
    	for(std::size_t i = 0; i < v.size(); ++i)
    	{
    		v[i] = std::count(std::begin(s), std::end(s), static_cast<char>(i));
    	}
    	
    	return v;
    } // ungetestet
    

    volkard schrieb:

    vector<size_t> countChars(vector<char> const& s)
    {
       vector<size_t> v(256);
       for(auto x:s)
          ++v[static_cast<unsigned char>(x)]
       return v;
    } // ungetestet
    

    Ok das schau ich mir jetzt auch noch mal an. Was ich mich grade frage ob es schlau ist das über die Lauflänge zu machen oder so wie ihr mir das jetzt grade gezeigt habt?
    Bei der Lauflänge hätte ich ja nicht alle gesamt aber könnte trotzdem ja ein Huffman Baum mit Knoten draus bauen. Weiß nicht, was haltet ihr für besser?

    Mit der Lauflänge hab ich mir das so gedacht:

    const std::string source;
      std::ostringstream input("../M00001.jpg");
      input << my_file.rdbuf();
      source = input.str();
      std::stringstream ss_dest;
    
      std::string::const_iterator it_last(source.begin());
      for (std::string::const_iterator it(source.begin()); it != source.end(); ++it){
        if (*it_last != *it){
          ss_dest << std::distance(it_last, it) << *it_last;
          it_last = it;
        }
      }
    


  • Skym0sh0 schrieb:

    also grade für vector<char> (was im Prinzip eine Zeichenkette ist) bietet sich std::string eher an.

    Nein! Er hat rohe Bytes und keine Zeichen. std::string wäre nicht nur irreführend sondern auch falsch (zb der Output-Operator ist komplett sinnfrei überladen wenn es um Binärdaten geht).



  • Enno schrieb:

    Hey Leute,

    ich habe vor Bilder zu skalieren. Das erstmal vorweg.

    Im Prinzip soll das erstmal so laufen, das ich meine .jpg datei öffne und dann nach einzelnen Hex Zeichen suchen kann. (--> http://developer.mobotix.com/docs/mxpeg_frame.html)

    Problem für mich ist irgendwie finde ich sehr wenig zu dem Thema oder ich suche mit falschen Schlagwörtern.

    Ich hab mir jetzt gedacht das ich die Datei in mit ifstream öffne und in einen Vektor schiebe damit ich leichter nach den Zeichen suchen kann. So in dieser art hier:

    ifstream img; 
    img.open("test.jpg" ios::binary); 
    img.close();
    

    Fragen:
    Frag ist komm ich da dann auch an die Hex Zeichen?
    Versteht ihr überhaupt was ich will? Braucht ihr mehr Infos?

    So geht das nicht. Das JPG-Format ist nicht so gebaut, daß Du mit unerheblichem Aufwand an die Pixels kommst. Fang mit unkomprimiertem BMP oder TGA an.

    Installiere Dir http://www.imagemagick.org/script/convert.php und rufe das auf, wannimmer Du es in Deine Anwendung brauchst. Das erfüllt schon mal die meisten Wünsche direkt. Und für die anderen kannste ImageMagick benutzen, um Dir ein leicht einlesbares Format bereitzustellen.

    Für JPG schau erstmal auf http://de.wikipedia.org/wiki/JPEG#Blockbildung_und_diskrete_Kosinustransformation

    Lass auch unbedingt Optimierungen wie reserve zunächst weg. Insbesondere, wenn sie in die Schnittstelle der Klasse wandern. Außerdem ist reserve eh total überbewertet. Um dafür vorher einen Betriebssystemaufruf zu bezahlen, muß man schon kerngesund sein.

    Optimierungen dann beim zweiten mal, wenn Du es implementierst.

    Und falls es um Screenshots aus Anwendungen geht, nimm PNG statt JPG, das komprimiert in diesem Fall viel stärker und artefuckt nicht so rum.



  • Skym0sh0 schrieb:

    char c;
    		f.read(&c, sizeof(c));
    

    wie groß ist sizeof(char) nochmal?



  • ich weiss nicht, wie groß ein char ist. aber dank c++ gibt es dafür den sizeof operator, der es mir sagt, ohne dass ich detailwissen aus dem standard oder der implementierung benötige 🙂



  • [quote="volkard"]

    Enno schrieb:

    So geht das nicht. Das JPG-Format ist nicht so gebaut, daß Du mit unerheblichem Aufwand an die Pixels kommst. Fang mit unkomprimiertem BMP oder TGA an.

    Installiere Dir http://www.imagemagick.org/script/convert.php und rufe das auf, wannimmer Du es in Deine Anwendung brauchst. Das erfüllt schon mal die meisten Wünsche direkt. Und für die anderen kannste ImageMagick benutzen, um Dir ein leicht einlesbares Format bereitzustellen.

    Für JPG schau erstmal auf http://de.wikipedia.org/wiki/JPEG#Blockbildung_und_diskrete_Kosinustransformation

    Lass auch unbedingt Optimierungen wie reserve zunächst weg. Insbesondere, wenn sie in die Schnittstelle der Klasse wandern. Außerdem ist reserve eh total überbewertet. Um dafür vorher einen Betriebssystemaufruf zu bezahlen, muß man schon kerngesund sein.

    Optimierungen dann beim zweiten mal, wenn Du es implementierst.

    Und falls es um Screenshots aus Anwendungen geht, nimm PNG statt JPG, das komprimiert in diesem Fall viel stärker und artefuckt nicht so rum.

    Hey danke erstmal für deine Antwort.
    ich weiß nicht ob du alles gelesen hast aber:

    Enno schrieb:

    Das wird wohl drauf hinaus laufen das ich das Rad neu erfinden werde. Aber danke für die Tipps. Bin auch schon auf Imagemagick und CImg gestoßen.

    Trotzdem werde ich deine Tipps mir zu Herzen nehmen(reserve).

    nichtkenner der chars schrieb:

    ich weiss nicht, wie groß ein char ist. aber dank c++ gibt es dafür den sizeof operator, der es mir sagt, ohne dass ich detailwissen aus dem standard oder der implementierung benötige 🙂

    Ein Char ist doch ein Zeichen also dem entsprechen = 1?



  • Enno schrieb:

    Was ich mich grade frage ob es schlau ist das über die Lauflänge zu machen oder so wie ihr mir das jetzt grade gezeigt habt?
    Bei der Lauflänge hätte ich ja nicht alle gesamt aber könnte trotzdem ja ein Huffman Baum mit Knoten draus bauen. Weiß nicht, was haltet ihr für besser?

    RLE bringt nur was, wenn Du lange Zeilen lang unveränderte Werte hast. Wie bei Screenshots wenn keine Farbverläufe oder Bilder beteiligt sind. Aber wenn RLE mal paßt, dann komprimiert es gewaltig stark.

    Huffman bring nur was, wenn Du nicht gleichverteilte Daten hast (also fast immer). Aber Huffman komprimiert nie gewaltig stark.

    Deswegen kombiniert man gerne beide. Erst RLE, dann Huffman.



  • Jain, RLE komprimiert mit zunehmender Länge besser.
    Also am wenn der zu komprimierende Wert nur 1 lang ist dann erhöht sich der Speicher sogar noch. Aber je länger die sich wiederholende Buchstabenkette wird, desto effizienter ist es.


Anmelden zum Antworten