Jpg Bilder einlesen und skalieren
-
Enno schrieb:
Besseren Vorschlag?
Enno schrieb:
Ah ok das wusste ich auch noch nicht.
Diese Fragen und Kommentare deuten darauf hin, dass du, wie auch schon von anderen vermutet, viel zu wenig Programmiererfahrung hast, um dein Problem selbstständig umzusetzen. Dir fehlen einfach die ganzen Grundmuster, die man in so gut wie jedem Programm benötigt. Eine Datei einlesen ist kleines Einmaleins. Dies und all die anderen wichtigen Grundmuster der Datenverarbeitung müssen sitzen, bevor du anfängst, komplizierte Algorithmen aus Fachbüchern umzusetzen. Du solltest ganz dringen erst einmal eine ganze Menge Übungsaufgaben aus guten(!) Lehrbüchern machen.
Zur direkten Frage:
Nicht ganz standardkonforme Antwort (die aber praktisch überall funktioniert): Dateigröße ermitteln (Betriebssystemfunktion fstat), Speicher reservieren, read.Standardkonforme Antwort, Variante a (schlecht): Wenn schon zeichenweise lesen, dann richtig. Erst lesen, dann prüfen, dann verarbeiten. Siehe obiger Absatz über Grundmuster. Alle Leseaktionen in C++ (und in C und vielen anderen Sprachen auch) müssen nach diesem Muster erfolgen. Prüfen, Lesen, Verarbeiten ist immer falsch.
Standardkonforme Antwort, Variante b (deutlich besser): Blockweise lesen (read, ein paar tausend Byte sind ein guter Richtwert), nach dem Lesen prüfen und gelesene Datenmenge (read-Dokumentatioon lesen!) verarbeiten.
-
SeppJ schrieb:
Diese Fragen deuten darauf hin, dass du, wie auch schon von anderen vermutet, viel zu wenig Programmiererfahrung hast, um dein Problem selbstständig umzusetzen. Dir fehlen einfach die ganzen Grundmuster, die man in so gut wie jedem Programm benötigt. Eine Datei einlesen ist kleines Einmaleins. Dies und all die anderen wichtigen Grundmuster der Datenverarbeitung müssen sitzen, bevor du anfängst, komplizierte Algorithmen aus Fachbüchern umzusetzen. Du solltest ganz dringen erst einmal eine ganze Menge Übungsaufgaben aus guten(!) Lehrbüchern machen.
Ja ich weiß ich bin echt nicht so der King. Ist auch ok das das kritisiert wird. Habe auch das Buch Der C++-Programmierer. Will mich jetzt auch nicht raus reden warum das bei mir alles so lange dauert.
SeppJ schrieb:
Zur direkten Frage:
Nicht ganz standardkonforme Antwort (die aber praktisch überall funktioniert): Dateigröße ermitteln (Betriebssystemfunktion fstat), Speicher reservieren, read.Standardkonforme Antwort, Variante a (schlecht): Wenn schon zeichenweise lesen, dann richtig. Erst lesen, dann prüfen, dann verarbeiten. Siehe obiger Absatz über Grundmuster. Alle Leseaktionen in C++ (und in C und vielen anderen Sprachen auch) müssen nach diesem Muster erfolgen. Prüfen, Lesen, Verarbeiten ist immer falsch.
Standardkonforme Antwort, Variante b (deutlich besser): Blockweise lesen (read, ein paar tausend Byte sind ein guter Richtwert), nach dem Lesen prüfen und gelesene Datenmenge (read-Dokumentatioon lesen!) verarbeiten.
Ich danke für die Anregungen und werde mich jetzt mal dran machen um zu versuchen da was hin zu bekommen.
Ansonsten hört ihr von mir!
-
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');
-
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?