SDL: Bild aus Binary lesen

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

SDL: Bild aus Binary lesen

Beitrag von Lemon »

Hallo Zusammen!!

Ich habe ein Code der ein "Jpg"Bild in ein Binary lädt!!
Wie kann ich dieses Jpg wieder auslesen und an die Funktion SDL_Surface* loadedImage = IMG_Load(char* file) übergeben?

so schreib ich das Jpg rein:

Code: Alles auswählen

        //File /Picture
        fstream m_pfileJpg;
        fstream m_pfile;

        //Data size
        char* m_data;
        unsigned long m_FileSize;


    m_pfileJpg.open("./SDL_Images/SDL-800x600.jpg", ios::in | ios::out | ios::binary);

   m_pfileJpg.seekg(0, ios::end);
   m_FileSize = m_pfileJpg.tellg();
   m_pfileJpg.seekg(0, ios::beg);

   m_data = new char[m_FileSize];
   m_pfileJpg.read(m_data, m_FileSize);
   m_pfileJpg.close();

   m_pfile.open("Test.pff", ios::in | ios::out | ios::binary);

   m_pfile.write(m_data, m_FileSize);
   m_pfile.close();
Benutzeravatar
Schrompf
Moderator
Beiträge: 4858
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: SDL: Bild aus Binary lesen

Beitrag von Schrompf »

Was Du da hast, ist nur Code, um den Binärinhalt einer beliebigen Datei zu lesen. Ein JPEG-Bild besteht aber aus einer Menge spezieller Daten, die Du jetzt Byte für Byte aus diesen Binärdaten rausziehen müsstest. Das ist eine nicht ganz triviale Aufgabe, die u.a. eine Fourier-Transformation enthält. Ich rate Dir daher eher, eine fertige Bibliothek zu benutzen. Schau Dir z.B. decodePNG an, zu dem es unter http://www.developia.de/developia/viewa ... ?cid=31356 ein kleines Tutorial gibt. PNGs sind im Gegensatz zu JPEGs verlustfrei, das heißt, Du bekommst Pixel für Pixel exakt den Farbwert, den Du im Malprogramm dort hingesetzt hast. JPEGs dagegen verfälschen die Farben leicht - das kann je nach Verwendungszweck ziemlichen Ärger machen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

Re: SDL: Bild aus Binary lesen

Beitrag von Lemon »

Wenn ich jetzt mit decodePNG(); ein "png" geladen habe, kann ich dieses png nur mit OpenGL ins Game integrieren, oder geht dass auch mit SDL ?
Benutzeravatar
Schrompf
Moderator
Beiträge: 4858
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: SDL: Bild aus Binary lesen

Beitrag von Schrompf »

Das geht auch mit der SDL. Die Funktion gibt anscheinend nur ein Array aus Pixeln zurück. Wo Du die dann hinkopierst bzw. was Du damit machst, ist ja Dir überlassen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
TheTom
Beiträge: 4
Registriert: 15.10.2009, 21:37
Kontaktdaten:

Re: SDL: Bild aus Binary lesen

Beitrag von TheTom »

Warum verwendest du denn nicht gleich direkt IMG_Load mit dem Dateinamen? Wenn du das Bild wirklich nur im Speicher hast kannst du es auch mit den SDL_RWops versuchen:

Code: Alles auswählen

SDL_Surface *surface = IMG_Load_RW( SDL_RWFromMem(m_data, m_FileSize), 1 );
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

Re: SDL: Bild aus Binary lesen

Beitrag von Lemon »

Dieses Tutorial dass du angegeben hast Schrompf, ist nicht mehr auf dem neusten Stand! Die Funktion decodePNG() giebt es nichtmehr. Stadtdessen giebt es mehrere Funktionen eine davon ist:
unsigned LodePNG_decode32f(unsigned char** out, unsigned* w, unsigned* h, const char* filename)
ich habs mal mit dieser versuch und so siehts in etwa aus:

Code: Alles auswählen

    const char* filename "./SDL_Images/Test.png";
  
  unsigned error;
  unsigned char* image;
  size_t w, h;
  
        /*load the PNG in one function call*/
        error = LodePNG_decode32f(&image, &w, &h, filename);

        /*stop if there is an error*/
        if(error)
        {
            cout<<"Error LoadPNG."<<endl;
            return;
        }

        SDL_Surface* m_pPicture;

        m_pPicture = IMG_Load_RW( SDL_RWFromMem(&image, sizeof(image)), 1 );
        if(NULL == m_pPicture )
        {
           cout<<"Error: can't load Picture."<<endl;
           return false;
        }
        return true;


Irgendwie funktioniert das ganze nicht. Beim aufruf von "LodePNG_decode32f()" giebts kein Fehler, aber wenn ich "IMG_Load_RW()" aufrufe kommt "cout<<"Error: can't load Picture."<<endl;" . Ich weiss nicht ob ich die Daten falsch Speichere, oder ob ich sie falsch übergebe.

Das Beispiel, aus dem ich diesen Code zusammengesetzt habe, findet ihr hier http://members.gamedev.net/lode/project ... examples.c .
Benutzeravatar
Schrompf
Moderator
Beiträge: 4858
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: SDL: Bild aus Binary lesen

Beitrag von Schrompf »

Hmm... kann das sein, dass Dir die Grundlagen von C fehlen und es gar nicht am Bildladen scheitert? Der LodePNG()-Aufruf geht anscheinend gut. Danach benutzt Du dann aber nochmal die SDL-Bildlade-Funktionen. Und denen gibst Du als Quelle einen Zeiger auf Deinen Image-Zeiger und dessen Größe (4 Bytes). Dass der Aufruf schiefgehen muss, ist doch offensichtlich. Folgerichtig bekommst Du dann die cout-Fehlermeldung.

Der LodePNG-Aufruf reicht aus. Du hast dann die Breite und Höhe des Bildes und einen Zeiger auf die Pixeldaten. Die müsstest Du jetzt ganz einfach in eine SDL-Surface passender Größe kopieren können.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

Re: SDL: Bild aus Binary lesen

Beitrag von Lemon »

Danke für eure hilfe!! Jetzt funktionierts.

Ich dacht ich muss das Bild dass ich decoded habe nochmals laden, aber stimmt Schropmpf, ich kann es einfach in die Surface kopieren. War wohl etwas auf dem Holzweg. Ich habs jetzt genau so gemacht wi im Beispiel das ich gepostet habe.

Das decodete Bild in eine Binary zu speichern und wieder auslesen, sollte jetzt kein Problem mehr sein.

A ja, dass mit den Zeigern, muss ich mir wirklich nochmals anschauen. Habe jetzt zwei Jahre Programmierpause gemacht, da ist mir so einiges Verloren gegengen.
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

Re: SDL: Bild aus Binary lesen

Beitrag von Lemon »

Ich habe trozdem noch ein Problem. Wenn ich das decodierte bild direkt in die Screen-Surface kopiere, wie im Beispil im Link den ich oben gepostet habe, gehts. Aber wenn ich extra eine Surface für das Bild anlege und das Bild dort rein kopieren will, geht es irgendwie nichtmehr.

Ich poste hier zur sicherheit mal mein Code!!

Code: Alles auswählen

#include "PicturePNG.hpp"
C_PicturePNG::C_PicturePNG()
{
    m_filename = "./SDL_Images/Test.png";
}

bool C_PicturePNG::load()
{

  unsigned error;

        /*load the PNG in one function call*/
        error = LodePNG_decode32f(&m_image, &m_w, &m_h, m_filename);

        /*stop if there is an error*/
        if(error)
        {
            cout<<"Error LoadPNG."<<endl;
            return false;
        }

    /*avoid too large window size by downscaling large image*/
    size_t jump = 1;
    if(m_w / 1024 >= jump) jump = m_w / 1024 + 1;
    if(m_h / 1024 >= jump) jump = m_h / 1024 + 1;

    size_t x, y;

    /*plot the pixels of the PNG file*/
    for(y = 0; y + jump - 1 < m_h; y += jump)
    for(x = 0; x + jump - 1 < m_w; x += jump)
    {
      int checkerColor;
      Uint32* bufp;
      Uint32 r, g, b, a;

      /*get RGBA components*/
      r = m_image[4 * y * m_w + 4 * x + 0]; /*red*/
      g = m_image[4 * y * m_w + 4 * x + 1]; /*green*/
      b = m_image[4 * y * m_w + 4 * x + 2]; /*blue*/
      a = m_image[4 * y * m_w + 4 * x + 3]; /*alpha*/

      /*make translucency visible by placing checkerboard pattern behind image*/
      checkerColor = 191 + 64 * (((x / 16) % 2) == ((y / 16) % 2));
      r = (a * r + (255 - a) * checkerColor) / 255;
      g = (a * g + (255 - a) * checkerColor) / 255;
      b = (a * b + (255 - a) * checkerColor) / 255;

      /*give the color value to the pixel of the screenbuffer*/
      bufp = (Uint32 *)m_pPicture->pixels + (y * m_pPicture->pitch / 4) / jump + (x / jump);
      *bufp = 65536 * r + 256 * g + b;
    }

    return true;
    cout<<"PictureW: "<<m_pPicture->w;
}

void C_PicturePNG::draw()
{

  m_srect.x = 0;
  m_srect.y = 0;
  m_srect.w = (m_pPicture->w)/2;  // das halbe Bild
  m_srect.h = m_pPicture->h;   // das gesamte Bild
  // Setzen des Zielbereichs
  m_drect.x = 0;
  m_drect.y = 0;
  m_drect.w = (m_pPicture->w)/2;
  m_drect.h = m_pPicture->h;
  // kopiere surface auf display-surface
  SDL_BlitSurface(m_pPicture, &m_srect, g_pFramework->GetScreen(), &m_drect);

  // den veränderten Bildschirm-Bereich auffrischen
  SDL_UpdateRects(g_pFramework->GetScreen(),1,&m_drect);
}

void C_PicturePNG::clear()
{
    SDL_FreeSurface(m_pPicture);
}
Noch ne Frage. Was hatt es sich eigentlich mit dieser jump-Variabel aufsich? Für wass ist die genau?
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

Re: SDL: Bild aus Binary lesen

Beitrag von Lemon »

okey, ich glaubs ich vergesse dass mit der Extra Surface fürs Bild. Ich habe in einem Tutorial gelesen, dass es schneller ist, direkt in die Screen-Surface zu kopieren, als erst zu Bliten.

aber ich habe ein wenig probleme den code zu verstehen.

m_image: ist dasBild dass ich geladen habe.
posX und posY: ist die Position auf dem Screen. //dass funktioniert!
m_w: ist länge des Bildes.
m_h: ist höhe des Bildes.

code:

Code: Alles auswählen


    size_t posX = 0;
    size_t posY = 0;

    size_t x, y;
    /*plot the pixels of the PNG file*/
    for(y = 0; y <= m_h - 1 ; y ++)
    for(x = 0; x <= m_w - 1 ; x ++)
    {
      int checkerColor;
      Uint32* bufp;
      Uint32 r, g, b, a;

      /*get RGBA components*/
      r = m_image[4 * y * m_w + 4 * x + 0]; /*red*/
      g = m_image[4 * y * m_w + 4 * x + 1]; /*green*/
      b = m_image[4 * y * m_w + 4 * x + 2]; /*blue*/
      a = m_image[4 * y * m_w + 4 * x + 3]; /*alpha*/

      /*make translucency visible by placing checkerboard pattern behind image*/
      checkerColor = 191 + 64 * (((x / 16) % 2) == ((y / 16) % 2));
      r = (a * r + (255 - a) * checkerColor) / 255;
      g = (a * g + (255 - a) * checkerColor) / 255;
      b = (a * b + (255 - a) * checkerColor) / 255;

      /*give the color value to the pixel of the screenbuffer*/
      bufp = (Uint32 *)g_pFramework->GetScreen()->pixels + ((y+posY) * g_pFramework->GetScreen()->pitch / 4) + (x+posX);
      *bufp = 65536 * r + 256 * g + b;
    }
Meine frage ist, wass muss ich wo angeben, um ein bild um 40 pixel nach x(Breite) und 40 pixel nach y(Höhe)zu vergrössern? oder auch verkleinern!!
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

Re: SDL: Bild aus Binary lesen

Beitrag von Lemon »

Ich will hier nicht stressen, tut mir leid wenn es so vorkommt.
Ich habe mich jetzt mehrere Tage mit der Materie beschäftigt. Ich erzähle euch mal wass ich vorhabe. Ich will ein Game machen und ein Editor dazu. Wichtig ist, im Game habe ich 3 Screen auflösungen, 1024x768, 800x600 und 640x480.(Variante1) Entweder mach ich jetzt drei Bilder für jede auflösung oder(Variante2) ich mache nur ein Bild und zoome es dann auf die jeweilige Screen-Auflösung.

Bei (Variante1) müsste ich im Editor ein Bild laden es zoomen, und dann in der jewiligen Screengrösse abspeichern.
Ich weiss nicht ob das ein grosses Problem wird mit WinForms.

Bei(Variante2) muss ich im Game ein Bild laden und dies anschliesend zoomen. Ich weiss nicht wie und ob ich ein Bild mit LodePNG direkt zoomen und dann in die screen-Surface schreiben kann.
Ich könnte auch das Bild mit LodePNG in eine extra angelegte Surface fürs Bild laden, und dann mit SDLgfx zoomen. Ich weiss allrdings immernochnicht, wie das ganze mit der Extrasurface geht. Irgendwie funktioniert es nicht wie ich es mache.

Wass würdet Ihr machen?
Benutzeravatar
Schrompf
Moderator
Beiträge: 4858
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: SDL: Bild aus Binary lesen

Beitrag von Schrompf »

Das ist ein nicht-triviales Thema. Ich würde alles immer in 1024x768 rendern und dann jedes Frame beim Anzeigen auf dem Bildschirm skalieren. Bzw. wäre für Deinen Kenntnisstand das Beste, wenn Du alle Varianten bis auf 1024x768 komplett weglässt. Keine der genannten Auflösungen ist eine natürliche TFT-Auflösung, die müssen also sowieso immer skalieren. Also kannst Du auch eine feste Auflösung nehmen und Dich auf die externe Skalierung der Anzeigegeräte verlassen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

Re: SDL: Bild aus Binary lesen

Beitrag von Lemon »

Ich würde alles immer in 1024x768 rendern und dann jedes Frame beim Anzeigen auf dem Bildschirm skalieren.
Ich würde schon eher diese Variante vorziehen, da ich das Game auch in verschiedenen Fenstermoden laufenlassen will. Wie würdest du es runterskalieren? Mit SDLgfx, oder giebt da auch eine andere Variante?

Noch nebenbei, falls es jemanden interessiert, ich habs geschafft, das mit lodePNG geladene bild, in eine extra-Surface fürs bild zu laden! einfach zuerst die Surface als screen-Surface convertieren, mit SDL_ConvertSurface() und ändert anschliesend die grösse mit SDL_CreateRGBSurface(), dann einfach das Bild reinladen!!
Benutzeravatar
Schrompf
Moderator
Beiträge: 4858
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: SDL: Bild aus Binary lesen

Beitrag von Schrompf »

Keine Ahnung, wie Du mit SDL Grafiken skalierst. Schau in die Doku. DirectX macht das automatisch, da kann man den BackBuffer in einer anderen Auflösung als der Bildschirmauflösung erzeugen und um den Rest kümmert sich DirectX.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

Re: SDL: Bild aus Binary lesen

Beitrag von Lemon »

Danke für deine Hilfe Schrompf! Bin durch dich einwenig meinem Ziel entgegen gekommen!

Ich habe mal SDLgfx ausprobiert. Anscheinend kann ich dort Grafiken nur raufzoomen und nicht runter. Beim 800x600 auf 1024x768 zoomen sehe ich eigentlich keine wirkliche Grafikeinbuse. Bei 640x480 auf 1024x768 habe ich das gefül sieht es etwas anders aus, allerdings ist es auch kein grosser verlust.

Ich habe in einem Post in einem anderen Forum gelesen, dass das Skalieren von Bildern mit SDL selbst nicht geht. Es gebe zwar schnittschtellen dafür bei SDL, aber dies ist mir schon etwas zu Hardecore!

Mit OpenGL würde es gehen, zu Skalieren.
Ich bin mir jetzt am überlegen, ob ich den Grafikverlust in kauf nehme, oder ob ich doch OpenGL einbinde.

Auf jedenfall vielen Dank!!
Benutzeravatar
Lord Delvin
Establishment
Beiträge: 577
Registriert: 05.07.2003, 11:17

Re: SDL: Bild aus Binary lesen

Beitrag von Lord Delvin »

Lemon hat geschrieben:Ich bin mir jetzt am überlegen, ob ich den Grafikverlust in kauf nehme, oder ob ich doch OpenGL einbinde.
Wie wärs mit SFML? Ist imo ein großer Fortschritt gegenüber SDL, wird aktiv weiterentwickelt und ist in meinen Augen besser zu bedienen.
http://www.sfml-dev.org
XML/JSON/EMF in schnell: OGSS
Keine Lust mehr auf C++? Versuche Tyr: Get & Get started
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

Re: SDL: Bild aus Binary lesen

Beitrag von Lemon »

Klingt gut, sieht gut aus! Habe mich schon fast entschieden auf SFML umzusteigen.

Kennst du vieleicht gute Einsteiger-Tutorials, sonstige Tutorials, vieleicht eine deutsche Docu oder gute Foren, Bücher?
Bin um jeden Link froh!
Benutzeravatar
Lord Delvin
Establishment
Beiträge: 577
Registriert: 05.07.2003, 11:17

Re: SDL: Bild aus Binary lesen

Beitrag von Lord Delvin »

Mir haben die Tutorials auf der Seite gereicht. Ich hatte da aber auch schon Direct3D, OpenGL, SDL und mein eigenes Framework hinter mir. Das Forum auf der Seite ist glaub ich das aktivste, es gibt aber auch noch ein deutschsprachiges in dems n paar Leute hat.

Bücher gibts soweit ich weis keine, das Projekt ist glaub auch erst zwei Jahre alt.

Ich würd einfach versuchen das mit der Dokumentation von der Seite zu machen und wenn das nicht reicht mal bei denen im Forum zu schauen/fragen.
Gruß
XML/JSON/EMF in schnell: OGSS
Keine Lust mehr auf C++? Versuche Tyr: Get & Get started
Lemon
Beiträge: 11
Registriert: 21.12.2009, 02:37

Re: SDL: Bild aus Binary lesen

Beitrag von Lemon »

kk!
Ich habe mich jetzt wirklich entschlossen auf SFML umzusteigen!! Danke für den Tip!!
Benutzeravatar
Lord Delvin
Establishment
Beiträge: 577
Registriert: 05.07.2003, 11:17

Re: SDL: Bild aus Binary lesen

Beitrag von Lord Delvin »

Kein Problem, ich wäre selbst manchmal für so Tipps dankbar und hier bekommt man die auch manchmal. Aber wenn man feststellt, dass man sich nurnoch mit irgendeiner lib befasst und nicht mehr mit dem eigentlichen Problem, dann findet man dieser Tage meistens eine bessere Implementierung, die man dann nurnoch finden muss.
Gruß
XML/JSON/EMF in schnell: OGSS
Keine Lust mehr auf C++? Versuche Tyr: Get & Get started
Antworten