JPEG Bilder die 2te
-
Raderfindungspädagoge schrieb:
Schön. Und ich denke, dass er anders noch bessere Fortschritte machen könnte. Aber OK, das kann ich halt nicht belegen, also schaun wir mal.

Das ist nett das du mir helfen willst aber ich würde das gerne lernen. Klar gibt es bessere Wege. Das sehe ich ein aber kann man mir den nicht einfach damit helfen? Wenn ihr mir nicht dabei helfen wollte, ist das auch ok aber dann müsst ihr mir hier nicht die ganze Zeit erzählen das ich anders besser lernen würde.
-
Enno schrieb:
Athar schrieb:
Was möchtest du denn jetzt erreichen? Im ersten Post redest du von Komprimieren und jetzt vom JPEG-Decodieren.
Wenn du ein Bild als JPEG speichern möchtest, nimmst du als Quellformat sinnigerweise etwas einfaches wie BMP oder PPM.Ich will JPEGs Decodieren und Encodieren?
Zum Dekomprimieren musst du im Prinzip die Schritte vom Komprimieren in umgekehrter Reihenfolge durchführen. Das ist dir schon klar, oder? Weil du das so schön mit dem Punkt "Bild laden" abgespeist hast. Bis du an die endgültigen Pixel vom Bild kommst, hast du noch einiges zu tun.
Ich würde mich ehrlich gesagt auch erst einmal an etwas leichterem versuchen, z.B. einem BMP -> PPM - Konverter (inklusiver Unterstützung von selten genutzten Features wie RLE und Bitmasken). Wenn du das fertig hast, dann sollten die Basics und Bitfummelei sitzen und damit bist du dann auch in der Lage, die Sache mit JPEG etwas souveräner anzugehen.
-
[quote="Enno"]
Raderfindungspädagoge schrieb:
Das ist nett das du mir helfen willst aber ich würde das gerne lernen.
Ja eben, mir gehts auch darum, dass du genau das lernst, was du lernen willst. Wenn jemand lernen will, den Mount Everest zu besteigen, würde ich ihm auch raten, sich an kleineren Bergen zu üben, deren Höhe immer weiter zu steigern, bis er so trainiert ist, dass er den großen auch packt. Aber gut, mach halt mal.

-
Bei JPEG ist das Problem halt auch, dass extrem viele Zwischenschritte notwendig sind, die du nur schwer einzeln validieren kannst. Am Schluss setzt du alle Komponenten zusammen, und sehrwahrscheinlich funktioniert nicht alles auf Anhieb.
Hier zu debuggen und mögliche Fehler zu finden braucht nicht nur wahnsinnig viel Zeit, sondern kann auch sehr frustrierend sein (du hast schon so viel Zeit in die Implementierung gesteckt, und nun funktioniert nichts, und du weisst nicht wo anfangen zu suchen). Daher ist es sinnvoller, wenn du versucht, Teilprobleme zu lösen und dir sicher sein kannst, dass diese funktionieren. Dann kannst du später alles zusammensetzen.
Sogar als erfahrener Programmierer kann man nicht davon ausgehen, dass man bei der Implementierung direkt alles 100% richtig macht. Debugging nimmt man bei solchen Sachen in Kauf. Wenn aber die Erfahrung im Bezug auf Fehlersuche fehlt, weil ein JPEG-Encoder das erste Projekt ist, kann es ganz schön schwierig werden.
Enno, ich will dich nicht demotivieren, sondern dich vor Demotivation bewahren

-
Nexus schrieb:
Enno, ich will dich nicht demotivieren, sondern dich vor Demotivation bewahren

Danke! Allerdings hab auch ich schon mal 2-3 Tage nach einem Fehler gesucht. Ich weiß wirklich das ihr alle angst hab meine Motivation wird nach lassen aber das wird sie nicht.

Ich werde das durch ziehen und wenn irgendwer mir noch jemand hier Tipps, Tricks oder gute Seiten empfehlen möchte immer raus damit. Ansonsten komme ich grade ein bisschen weiter durch das was ihr hier schon erzählt habt.
Weitere fragen kommen dann wohl mit Code denke ich.
-
So ich hab mal bissel was gebastelt. Das ist jetzt noch nicht viel ich weiß. Ich hab versucht alles zu kommentieren damit ihr versteht was ich da machen will. Geschrieben hab ich das btw in KDI.
Frage: Hab ich da denk Fehler drin oder sieht das schon mal ganz gut aus?start.cpp:
#include <vector> #include <cmath> #include <iterator> #include "start.h" /* * Constructor */ Start::Start(){ imgFile = new ImgFile(); //new ImgFile object from imagefile.h } /* * Destructor */ Start::~Start(){ delete imgFile; //delete imgFile object } /* * function to save the image or frame in vector tmp */ void Start::saveImage(){ do{ const char* SOI = imgFile->getSOIPos(); //get the start point of image / index[0] const char* EOI = imgFile->getEOIPos(); //get the end point of image size_t length = SOI-(EOI+3); //calculate length of image from SOI to EOI... +3 cause ff d9 decoderBlox(SOI, length); //give decoderBlox function start point and length }while(imgFile->nextImage()); //as long as nextImage is true } /* * Build 8x8 Matrix to do a iDCT(inverse Discrete Cosine Transformation) */ void Start::decoderBlox(std::vector<char>::iterator SOI, size_t length){ for(int x = 0; x<length; x++){ //not longer the length ///length or length+1? for(int i=0; i<8; ++i){ //2 loops to build 8x8 matrix for(int j=0; j<8; ++j){ blox[i][j] = *SOI + x; //save position in blox ++x; //next char }//j }//i doiDCT(); //do a iDCT }//x }start.h:
#include <vector> #include "../MyStuff/mxpw/src/imagefile.h" class Start{ public: Start(); ~Start(); void saveImage(); void decoderBlox(); void clearPOS(); private: ImgFile *imgFile; double blox[8][8]; };
-
Ist das ein Psycho-Test?
-
volkard schrieb:
Ist das ein Psycho-Test?
Doch so schlecht?
-
Warum erstellst du imgFile mit new?
und es heißt "Destruktor", nicht "Dekonstruktor"
-
daddy_felix schrieb:
Warum erstellst du imgFile mit new?
Ich versteh nicht was das Problem ist? Hab ich da was schlechtes gelern?

daddy_felix schrieb:
und es heißt "Destruktor", nicht "Dekonstruktor"
Ups.

-
Naja, wenn du new verwendest muss das Gründe haben. Theoretisch ist es (fast) dasselbe wie ohne new, aber es hat halt in der Praxis Auswirkungen.
Denn Zu jedem new gehört genau ein delete. Und genau das muss sichergestellt sein, dass dieses ausgeführt wird.
Dann gibt es die Regel der großen 3 (die sich aushebeln lässt wie ich vor 2-3 Wochen gemerkt hab ;)), diese besagt, dass wenn du auch nur einen der folgenden Dinge selbst definierst, die anderen auch selbst definieren musst/sollst:
- Kopierkonstruktor
- Destruktor
- Zuweisungsoperator (Ok, lässt sich über das Copy'n'Swap Idiom implementieren und ist damit ein 2 Zeiler in jeder Klasse)Des Weiteren wäre noch die sogenannte Initialisierungsliste zu nennen.
Du gehst davon aus, dass sich ein Zeiger auf einen const char (const char
implizit zu einem vector<char>::iterator konvertieren lässt, die mannigfaltigen Möglichkeiten des Iterators nutzt du dennoch aber nicht, da hättest ja bei einem Zeiger bleiben können (zumal ein Iterator ja was anderes ist und für andere Dinge zuständig ist als nur zu zeigen).
-
Das ist ja schön und gut mit dem new. Allerdings mach ich doch den delete also ist doch alles ok? Ansonsten wollte ich eigentlich nur mal wissen ob mein Gedenken weg da logisch ist oder ob das Quark ist.
Das mit dem const char sehe ich ein, hab ich auch geändert.

-
In C++ verwaltet man Speicher sehr selten manuell --
new,new[],deleteunddelete[]trifft man in gutem Code nicht häufig an. Oder vielleicht nochnew, aber nicht die anderen.Schau dir dazu mal das RAII-Idiom an. Grundsätzlich geht es darum, dass Objekte selbstständig für ihre Ressourcen (einschliesslich Speicher) zuständig sind. Statt eines
ImgFile*könnte man Smart-Pointer wiestd::unique_ptr<ImgFile>verwenden, oder noch besser direktImgFile. Wozu brauchst du den Zeiger?
-
Nexus schrieb:
In C++ verwaltet man Speicher sehr selten manuell --
new,new[],deleteunddelete[]trifft man in gutem Code nicht häufig an. Oder vielleicht nochnew, aber nicht die anderen.Ok danke für die erklärung.
Nexus schrieb:
Schau dir dazu mal das RAII-Idiom an. Grundsätzlich geht es darum, dass Objekte selbstständig für ihre Ressourcen (einschliesslich Speicher) zuständig sind. Statt eines
ImgFile*könnte man Smart-Pointer wiestd::unique_ptr<ImgFile>verwenden, oder noch besser direktImgFile. Wozu brauchst du den Zeiger?Ok das mit dem Smart-Pointer schau ich mir an.
ImgFileliefert mir das JPEG Bild. D.h. das ist eine eigene Klasse. Meinst du mit direktImgFilezu benutzen, dass ich das vererben soll? Ansonsten hab ich das grade nicht verstanden.
-
Nein, er meinte so etwas:
class foo {}; clss bar {foo f;}
-
Nein, vererben nicht, komponieren sollst du.
class A { }; class B { A my_a; // das meint er, das nennt man Komposition }; // B "hat-ein" Aclass Base { }; class Derive : public Base // das ist Vererbung, etwas ganz anderes { }; // Derive "ist-ein" Base
-
Enno schrieb:
ImgFileliefert mir das JPEG Bild. D.h. das ist eine eigene Klasse. Meinst du mit direktImgFilezu benutzen, dass ich das vererben soll? Ansonsten hab ich das grade nicht verstanden.Nein, du schreibst ja auch
int i = 5;und nicht
int* i = new int(5);Wenn du keine dynamische Speicherverwaltung brauchst, benutze sie nicht. In deinem Fall solltest du die Konstruktor-Initialisierungsliste verwenden.
class Start { public: Start(); // kein Destruktor mehr notwendig private: ImgFile imgFile; }; Start::Start() : imgFile() // <- hier könnte man Argumente an den ImgFile-Konstruktor übergeben { // eigentlicher Konstruktorrumpf // keine Zuweisungen hier! }
-
Ok allerdings kommt das für mich irgendwie auf das gleiche raus ob ich nun ein Pointer auf das Objekt mache oder das Objekt direkt anspreche.
Meine eigentlich frage ist nicht auf das new bezogen sondern ob das generell Quark ist oder ob mein angehen jetzt in die richtige Richtung geht.
-
Ja, ist Quark.
Du brauchst überhaupt keinen Pointer und kannst einfach mit . auf die Member zugreifen.
Ein Pointer ist hier absolut überflüssig.
-
Nathan schrieb:
Ja, ist Quark.
Du brauchst überhaupt keinen Pointer und kannst einfach mit . auf die Member zugreifen.
Ein Pointer ist hier absolut überflüssig.Es geht gar nicht um den Pointer mehr! Das hab ich ja schon jetzt grade oft genug verstanden. Danke.