std::vector<unsigned char> in (const char*) casten



  • Hallo zusammen!!

    Der Titel sagt es eigentlich schon.
    Wie kann ich ein "std::vector<unsigned char>" vector in ein "const char*" casten?



  • Gibts einen bestimmten Grund mit const char* rumzufuchteln?



  • Irgendwie sagt mir meine Glaskugel, dass du so etwas, wie einen string hast..
    Und somit rate ich dir eher std::string zu benutzen, als ein vector von char..
    Dort kannst du auch Elementweise drüber iterieren, wenn du das brauchst und du hast auch netterweise eine Memberfunktion, die c_str heisst und dir ein const char* zurück gibt..



  • jo!! Ich bin gerade daran ein Game zu programmieren mit SFML http://www.sfml-dev.org/. Bin erst gerade darauf umgestiegen von SDL.
    Ich habe eine Library namens LodePNG
    http://members.gamedev.net/lode/projects/LodePNG/ mit der ich ein Bild als Binär decodieren kann. Der sinn dahinter ist, dass ich dieses Bild in einem File, binär abspeichern kann und es wieder auslesen. Mein Problem ist dass die Decodierung auf ein "vector<unsigned char>" zurückgegeben wird. Und um das Bild mit SFML zu laden muss es aber "const char*" sein.

    Ich währe auch froh um andere Forschläge, um Bilder in Dateien zu packen. Der Sinn dahinter ist, dass mir Niemand kann die Grafiken klauen, oder der Spieler die nachkommenden Game-Levels nicht im Ordner nachschauen gehen kann. Das ganze ist auchnoch eine Estetische Sache.



  • Da ist mir wohl jemand zuvor gekommen!!

    Ich würde mir eine neue Glaskugel kaufen!! 😉
    aber Danke für deine Bemühung!



  • Du könntest natürlich auch das PNG von SFML lesen und schreiben lassen, schliesslich bietet es diese Funktionalität ( sf::Image::LoadFromFile() und sf::Image::SaveToFile() ). Um das Bild unkenntlich zu machen, könntest du vor dem Speichern eine Art Verschlüsselung darüber laufen lassen. Dafür modifizierst du die einzelnen Pixel im sf::Image . Nach dem Laden machst du das wieder rückgängig. Nur so eine Idee...

    Falls du deine Vorgehensweise beibehältst, könntest du den std::vector<unsigned char> in einen std::vector<char> umkopieren:

    std::vector<unsigned char> Source;
    std::vector<char> Dest(Source.begin(), Source.end());
    const char* PixelArray = &Dest[0]
    

    Alternativ kannst du den Speicher reinterpretieren, das sollte bei char und unsigned char eigentlich gehen:

    std::vector<unsigned char> Source;
    const char* PixelArray = reinterpret_cast<const char*>(&Source[0]);
    


  • Nexus schrieb:

    Um das Bild unkenntlich zu machen, könntest du vor dem Speichern eine Art Verschlüsselung darüber laufen lassen. Dafür modifizierst du die einzelnen Pixel im sf::Image . Nach dem Laden machst du das wieder rückgängig. Nur so eine Idee...

    Verschlüsseln der PNG-Bytes wäre besser, da sonst der PNG encoder das verfremdete Bild (Rauschen) nicht wirklich komprimieren kann. Also erst komprimieren und dann verschlüsseln.

    Nexus schrieb:

    std::vector<unsigned char> Source;
    const char* PixelArray = reinterpret_cast<const char*>(&Source[0]);
    

    Source[0] darf man natürlich nur aufrufen, falls Source.size()>0 gilt.



  • Nexus:

    Du könntest natürlich auch das PNG von SFML lesen und schreiben lassen, schliesslich bietet es diese Funktionalität (sf::Image::LoadFromFile() und sf::Image::SaveToFile()). Um das Bild unkenntlich zu machen, könntest du vor dem Speichern eine Art Verschlüsselung darüber laufen lassen. Dafür modifizierst du die einzelnen Pixel im sf::Image. Nach dem Laden machst du das wieder rückgängig. Nur so eine Idee...

    Währe eine gute Idee. Nur will ich noch ein Editor für das Game machen und dort muss ich die Bilder unkenntlich machen. Nichts gegen deine Idee, aber ich finde es auch estetisch schöner wenn die Bilder alle in ein File gepackt werden.

    Bis jetzt habe ich mit Vectoren nicht soviel am Hut!
    Wieso muss ich erst abfragen, ob ein Vector nicht null ist befor ich ihn aufrufe?

    Ich Danke euch für Eure hilfe, jedoch funktioniert das ganze nicht. Ich weiss nicht wass ich falsch mache.
    Mein Code sieht so aus:

    FromFilePNG.hpp

    #ifndef FROMFILEPNG_HPP_INCLUDED
    #define FROMFILEPNG_HPP_INCLUDED
    
    #include <SFML/Graphics.hpp>
    
    #include ".\LodePNG\lodepng.h"
    
    #include <iostream>
    using namespace std;
    
    class C_PNGFromFile
    {
        private://members for LodePNG
            vector<unsigned char>m_buffer, m_image;
    
        private://members for GetPicture
            const char* m_image_c;
            size_t m_size;
            sf::Image m_Picture;
    
        public://Public Member-Functions
            void LoadPNG(const char* filename);
            sf::Image& GetPicture();
    };
    
    #endif // FROMFILEPNG_HPP_INCLUDED
    

    FromFilePNG.cpp

    #include "FromFilePNG.hpp"
    
    //Lode PNG with LodePNG and Decode
    void C_PNGFromFile::LoadPNG(const char* filename)
    {
        //Lode Image from png-File, and given filename
        LodePNG::loadFile(m_buffer, filename);
    
        LodePNG::Decoder decoder;
        //Decode the Image in 32bit
        decoder.decode(m_image, m_buffer);
    }
    
    //Loade the Picture with SFML and give it back
    sf::Image& C_PNGFromFile::GetPicture()
    {
        //Cast in char-Vector
        vector<char> Dest(m_image.begin(), m_image.end());
    
        if(m_image.size() > 0)
        {
            //copie in const char*
            m_image_c = &Dest[0];
            //Calculate Size in Byte's
            m_size =  (sizeof(char)/strlen(m_image_c));
        }
        cout<<"Image: "<<m_image_c<<endl;
    
        //Lode File from Memory with SFML, and check
        if(false == m_Picture.LoadFromMemory(m_image_c, m_size));
        {
            cout<<"Error: Bild konnte nicht geladen werden."<<endl;
        }
        //return the Image
        return m_Picture;
    }
    

    In dem Shell-Feister kommt die Ausgabe:

    Image:
    Failed to load image from memory. Reason : unknown image Type
    Error: Bild konnte nicht geladen werden.

    Als Ausgabe auf den Bildschrim sehe ich nur ein weisses Rechteck, anstadt ein Bild. Die Decodierung müsste stimmen. Entweder mach ich etwas mit dem casten falsch, oder der zweite Parameter von
    "LoadFromMemory(const char* Data, size_t SizeInBytes)" ist nicht richtig. In der Doku von SFML steht, SizeInBytes : Size of the data to load, in bytes. Ich weiss nicht genau was sie damit meinen.

    Wie seht ihr dass?



  • m_size =  (sizeof(char)/strlen(m_image_c));
    

    Rechne mal nach...



  • m_size = ((strlen(m_image_c)) / (sizeof(char)));
    

    Meintest du so?
    Funktioniert immernoch nicht.



  • Nein, das ist natürlich immer noch falsch - nicht nur der Operator!

    Wenn du schon m_image.size() hast, warum versuchst du dann nochmal die Länge zu berechnen??? (du weißt schon, wie strlen() funktioniert, oder?)

    P.S. Wofür brauchst du überhaupt die Kopie von m_image (Dest)?



  • du weißt schon, wie strlen() funktioniert, oder?
    

    ja, strlen() giebt die länge an zeichen aus. Hatte ein kleinen blackout.

    P.S. Wofür brauchst du überhaupt die Kopie von m_image (Dest)?
    

    Dies wahr mein uhrsprüngliches Problem, wofür ich diesen Beitrag geschrieben habe. ich muste ein "vector<unsigned char>" in ein "const char*" casten. Und so geht es. Allerdings funktioniert das ganze Forhaben nicht, wie du siehst aus Eigenverschulden. Ich hoffe zumindest dass es schlussentlich nur eigenverschulden sind und nicht, dass das ganze überhauptnicht geht.

    Ich habe es jetzt so gemacht:

    //Cast in char-Vector
        vector<char> Dest(m_image.begin(), m_image.end());
    
        if(Dest.size() > 0)
        {
            //copie in const char*
            m_image_c = &Dest[0];
            //Calculate Size in Byte's
            m_size = Dest.size();
        }
    

    sollte eigentlich funktionieren. oder?



  • Ja, sollte jetzt so funktionieren.
    Und wenn du jetzt gleich noch 'm_image' statt 'Dest' benutzt, dann ist es auch noch performant (so wie Nexus schon geschrieben hatte):

    const char *image_c = reinterpret_cast<const char*>(&m_image[0]);
    size_t size = m_image.size();
    
    m_Picture.LoadFromMemory(image_c, size);
    

    So benötigst du dann auch nicht die unnötigen Member-Variablen 'm_iamge_c' und 'm_size'.



  • Danke! Danke für eure Hilfe!

    Ich habs jetzt so gemachd:

    if(m_image.size() > 0)
        {
            //Cast from "vector<unsigned char>" to "const char*"
            m_image_c = reinterpret_cast<const char*>(&m_image[0]);
            //Get size in Byte's
            m_size = m_image.size();
        }
    
        cout<<"Size: "<<m_size<<endl;
        //Lode File from Memory with SFML, and check
        if(false == m_Picture.LoadFromMemory(m_image_c, m_size));
        {
            cout<<"Error: Bild konnte nicht geladen werden."<<endl;
        }
        //return the Image
        return m_Picture;
    

    Alllerdings Funktioniert das ganze nicht. Als Ausgabe im Shell-Feister kriege ich:

    Size: 1228800
    Failed to load image from memory. Reason : Image not of any known type, or corrupt
    Error: Bild konnte nicht geladen werden.

    Weiss halt nicht an wass es liegen könnte. Ich gehe mal in einem SFML-Forum nachfragen. Wenn ihr eine Idee habt, nur her damit, bin um jede Hilfe froh.



  • Ich möchte mich nochmals für die Hilfe bedanken!

    Ich habs jetzt geschaft.
    Hier ein link http://www.sfml-dev.org/forum/viewtopic.php?t=2045 zu der lösung, fals jemand intresse daran hat.

    mfg Lumo!!


Anmelden zum Antworten