Praktikum: Bilddaten an CImage senden

Fachdiskussionen rund um Themen und Veranstaltungen ohne Zuordnung zu einem bestimmten Semester (Allgemeine organisatorische und verwaltungstechnische Themen, die NICHT in unmittelbarem und direktem Zusammenhang mit einer Veranstaltung zu sehen sind, bitte in "Studienverwaltung allgemein" einsortieren!)

Moderator: (M) Mod.-Team Allgemein

Antworten
xenom
TalkING. Newbie
TalkING. Newbie
Beiträge: 29
Registriert: Sa, 17. Okt. 09, 14:46
Wohnort: Hamburg / Bramfeld

Praktikum: Bilddaten an CImage senden

Beitrag von xenom » Di, 15. Jun. 10, 12:31

Hallo!

Ich habe ein Problem mit dem Praktikum in dem Kommentar von der Methode read() heißt es:

"...Dazu werden zunächst die Dimensionen des Bildes eingelesen und
in das CImage übertragen und dann die Bilddaten in das CImage kopiert."

Die Dimensionen habe ich aus dem .pgm file ausgelesen und in das CImage Objekt per Konstruktor übertragen. Um die Bilddaten zu übertragen, wird ja wahrscheinlich nur die Adresse auf den Anfang der Daten (also nach dem Header), in die private Membervariable *m_data übertragen.

Die Frage ist nur, wie soll ich das machen?

Per Konstruktor geht es doch nicht, weil ich dadurch die Signatur ändern müsste, was verboten ist. Ebenso darf man keine neuen Funktionen implementieren und anders wüsste ich nicht, wie man auf die private Variable zugriff haben könnte.

Anscheinend hab ich echt ein Brett vorm Kopf, für Hilfe wäre ich sehr dankbar!

Viele Grüße

:)
TalkING. Freak
TalkING. Freak
Beiträge: 136
Registriert: Fr, 24. Apr. 09, 11:02

Beitrag von :) » Di, 15. Jun. 10, 16:11

hallo xenom,

nur die adresse der bilddaten zu speichern wäre etwas sinnfrei. nicht umsonst wird m_data im konstruktor mit "new" und einer berechneten größe initialisiert. schau dir mal die methoden
unsigned char* begin() const;
und
unsigned char* end() const;
an. die sollten dir helfen ;)

gruß
martin

xenom
TalkING. Newbie
TalkING. Newbie
Beiträge: 29
Registriert: Sa, 17. Okt. 09, 14:46
Wohnort: Hamburg / Bramfeld

Beitrag von xenom » Mi, 16. Jun. 10, 19:24

Hallo,

vielen Dank für dein Tipp, jedoch hilft mir das glaub ich nicht viel weiter. Man soll die Daten ja in einem zusammenhängenden Bildbereich speichern. Das könnte man ja mit einem Array realisieren, jedoch gibt es in der Klasse kein Array als Variable.
Ich weiß auch nicht wie ich den Zeiger auf die Anfangsadresse in die CImage Klasse befördern soll, weil ich an die private Membervariable *m_data nicht herankomme.

Hoffe jemand hat noch eine Idee für mich!

Viele Grüße

Benutzeravatar
NightStalker
TalkING. Champion
TalkING. Champion
Beiträge: 891
Registriert: Mo, 21. Okt. 02, 20:40
Wohnort: Downloadbereich

Beitrag von NightStalker » Mi, 16. Jun. 10, 19:41

Also, für mich sieht

Code: Alles auswählen

unsigned char* begin() const;
gerade aus, als ob diese Funktion einen Pointer auf den Anfang (= engl. begin ;) des Speicherbereich zurückliefert. Steht da in der Implementierung für begin() vielleicht "zufällig" return(m_data); ?
-- Chrząszcz brzmi w trzcinie w Szczebrzeszynie.
-- 好好学习,天天向上!

:)
TalkING. Freak
TalkING. Freak
Beiträge: 136
Registriert: Fr, 24. Apr. 09, 11:02

Beitrag von :) » Mi, 16. Jun. 10, 19:54

NightStalker hat geschrieben:Also, für mich sieht

Code: Alles auswählen

unsigned char* begin() const;
gerade aus, als ob diese Funktion einen Pointer auf den Anfang (= engl. begin ;) des Speicherbereich zurückliefert. Steht da in der Implementierung für begin() vielleicht "zufällig" return(m_data); ?
genau so ist es ;)

@xenom:
wenn es kein array in der klasse gibt, was ist m_data dann?
und wie gesagt, begin() liefert dir einen zeiger auf den anfang von m_data. begin() ist doch eine methode der klasse und hat somit auch auf private-elemente zugriff!

xenom
TalkING. Newbie
TalkING. Newbie
Beiträge: 29
Registriert: Sa, 17. Okt. 09, 14:46
Wohnort: Hamburg / Bramfeld

Beitrag von xenom » Mi, 16. Jun. 10, 21:17

:) hat geschrieben:
NightStalker hat geschrieben:Also, für mich sieht

Code: Alles auswählen

unsigned char* begin() const;
gerade aus, als ob diese Funktion einen Pointer auf den Anfang (= engl. begin ;) des Speicherbereich zurückliefert. Steht da in der Implementierung für begin() vielleicht "zufällig" return(m_data); ?
genau so ist es ;)

@xenom:
wenn es kein array in der klasse gibt, was ist m_data dann?
und wie gesagt, begin() liefert dir einen zeiger auf den anfang von m_data. begin() ist doch eine methode der klasse und hat somit auch auf private-elemente zugriff!

Hallo ;)

danke für eure Antworten, aber...

Das begin und end Zugriff auf die Membervariable haben ist mir klar, was mein Problem aber immer noch ist, ich weiß nicht auf welche Art und Weise ich *m_data auf die Adresse des ersten Elements zeigen lassen soll.

Mein erster Schritt war es mit

CImage *bild = new CImage(width, height);

Ein Objekt zu erstellen und der Konstruktor bastelt mir dann ein dynamisches Array m_data mit der größe width*height, aber das Array ist leer, weil *m_data nicht weiß wohin es zeigen soll.

Mit bild->m_data=anfangDaten; geht es wegen dem private natürlich nicht. Über den Konstruktor kann ich die Adresse auch nicht wegen der Signatur übergeben, gleiches gilt für die Methode begin.

Viele Grüße

Benutzeravatar
NightStalker
TalkING. Champion
TalkING. Champion
Beiträge: 891
Registriert: Mo, 21. Okt. 02, 20:40
Wohnort: Downloadbereich

Beitrag von NightStalker » Do, 17. Jun. 10, 12:43

xenom hat geschrieben:ich weiß nicht auf welche Art und Weise ich *m_data auf die Adresse des ersten Elements zeigen lassen soll.
Ganz einfach, das sollst du nämlich GAR NICHT. Was dir fehlt, ist grundlegendes Verständnis für das Konzept der Objektorientierten Programmierung. Wenn m_data als eine private Membervariable definiert ist, dann genau aus dem Grund, damit du dich nicht um die Existenz dieser Variable, ihren Namen oder ihre Funktion scheren sollst. Und damit du es nicht trotzdem tust, verbietet die Sprache dir den Zugriff einfach. Also verabschiede dich von der Annahme, dass die Lösung deines Problems aus dem Zuweisen eines Pointers an diese private Variable besteht.

Außerdem stand bereits im zweiten Beitrag, dass jedes Bild-Objekt im Konstruktor seinen eigenen Speicher reserviert. Auch vor diesem Hintergrund ist eine Zuweisung eines bereits bestehenden Speicherbereiches über Objektgrenzen hinweg äußerst fragwürdig. Das macht man bei C (aus Effizienzgründen) aber selten in OOP. Jedes Objekt ist für seinen eigenen Kram zuständig, also auch für seinen Speicher. Wenn ich einem Objekt extern reservierten Speicher zuweise, wann wird der wieder freigeben? Wer entscheidet das? Das wäre 'ne eklatante Missachtung der Kapselungseigenschaft von OOP-Code.

Und was ist dann die richtige Lösung ? Hier eine Analogie:

Vor dir liegen zwei Blatt Papier, eines beschrieben, das andere leer. Dein Ziel ist es nun, den Text vom linken auf's rechte Blatt zu bekommen, egal was dabei mit dem linken Blatt passiert.

Dein Ansatz: Beide Blätter in Streifen schneiden, um dann die Fetzen vom linken Blatt am rechten anzukleben. Überzählige, leere Streifen des rechten, die du entfernt hast, um "Platz" zu schaffen (rechts soll ein A4 Blatt bleiben), ignorierst du. Fertig.

Und wie haben wir das statt dessen nicht-invasiv in der Grundschule gemacht ? Richtig, wir haben es ABGESCHRIEBEN. Und welche Informationen fehlt dir, um dein Objekt "abzuschreiben" ? Ich glaube keine.

Nebenbei bemerkt, dein Ansatz führt sehr wahrscheinlich zu Speicherleaks, weil du Speicher (oder Papierstreifen), welche nun mal schon da sind, nicht einfach ignorieren darfst.
-- Chrząszcz brzmi w trzcinie w Szczebrzeszynie.
-- 好好学习,天天向上!

xenom
TalkING. Newbie
TalkING. Newbie
Beiträge: 29
Registriert: Sa, 17. Okt. 09, 14:46
Wohnort: Hamburg / Bramfeld

Beitrag von xenom » Do, 17. Jun. 10, 14:14

Hallo Night Stalker, danke das du dir wieder Zeit genommen hast, um mir zu helfen. Ich sitze da jetzt schon seit zwei Tagen dran und finde keine Lösung.
NightStalker hat geschrieben: Und wie haben wir das statt dessen nicht-invasiv in der Grundschule gemacht ? Richtig, wir haben es ABGESCHRIEBEN. Und welche Informationen fehlt dir, um dein Objekt "abzuschreiben" ? Ich glaube keine.
Ich hab jetzt verstanden, dass die Daten kopiert werden müssen, aber wie das geschehen soll, ist mir immer noch ein Rätsel.

Die read() Methode, aus der die Daten kommen, hat wie gesagt keinen Zugriff auf m_data und die begin() Methode der Klasse in die die Daten rein sollen hat keinen Zugriff auf die Daten aus der read() Methode.
Ebenso ist es nicht möglich irgendeine temporären Variable zum kopieren zu benutzen, weil dort ebenfalls die Zugriffsrechte fehlen.

Viele Grüße

:)
TalkING. Freak
TalkING. Freak
Beiträge: 136
Registriert: Fr, 24. Apr. 09, 11:02

Beitrag von :) » Do, 17. Jun. 10, 18:10

nochmal zusammengefasst:
du willst in der methode read() daten in m_data schreiben. zugriff hast du auf m_data nicht direkt, das hast du richtig erkannt. doch kannst du die daten dennoch schreiben: es ist nämlich egal, ob du direkten zugriff auf die variable m_data hast oder weißt, wo sie im speicher liegt (--> pointer!). begin() liefert dir den pointer auf m_data. wenn du in read() die methode begin() ausführst, bekommst du den zeiger auf den speicher, in dem der inhalt von m_data steht. und genau so bekommst du indirekt zugriff auf m_data, da du jetzt den pointer benutzen kannst, um m_data zu verändern.

xenom
TalkING. Newbie
TalkING. Newbie
Beiträge: 29
Registriert: Sa, 17. Okt. 09, 14:46
Wohnort: Hamburg / Bramfeld

Beitrag von xenom » Do, 17. Jun. 10, 19:23

Vielen Dank, es hat jetzt endlich geklappt :oops:

Viele Grüße!

Antworten