Problem mit char* bei int-Zuweisung



  • Achso und vector wollte ich mehr oder weniger nicht nehmen, wegen der Geschwindigkeit... Ein std::vector<char> ist um einiges langsamer als char*... korrigiert mich wenn ich falsch liege(aber bitte nicht zu heftig xD)
    

    Korrigiere: Stimmt nicht.
    std::vector ist beinahe so schnell, wie jegliches Array gedöns. Im Debug Mode ist sie klar um einiges langsamer, dafür hat man aber ein Haufen checks usw. Aber im release ist sie in etwa so schnell, wie Arrays.



  • ok, dann werd ichs damit auch versuchen, bloß kann ich irgendwie read, das direkt in den vector kopieren lassen oder muss ich das ganze jetz zeichenweise einlesen?... danke nochmal an alle



  • ich habs jetzt erst in ein char* kopiert und dann den string damit gefüttert, mit gccount un so diesma ;),

    ist das sehr unschön gelöst??

    wie kann ich mein code jetz möglichst verbessern, dass selbst ihr zufrieden seid? 🙂 um zu wissen was richtig un falsch is, muss mans mir schon sagen ^^



  • ich hab keine ahnung, ob das funktioniert - würde mich eigtl sehr wundern, wenn ja^^ ich hatte ein wenig lange weile:

    /*PPMReader.h*/
    
    #ifndef H_PPMREADER_200909202000
    #define H_PPMREADER_200909202000
    
    #include <vector>
    #include <utility>
    
    struct color_tuple
    {
    private:
    	unsigned int RGB[3];
    public:
    	unsigned int R() const {return RGB[0];}
    	unsigned int G() const {return RGB[1];}
    	unsigned int B() const {return RGB[2];}
    
    	color_tuple(const char* RGB, unsigned char bytes_per_color);
    	color_tuple(unsigned int R, unsigned int G, unsigned B);
    };
    
    class PPMReader
    {
    	private:
    		std::vector<char> image;
    		std::pair<unsigned int, unsigned int> size;
    
    		unsigned char color_bytes;
    	public:
    		PPMReader(const char *filepath);
    
    		color_tuple GetPixel(unsigned int x, unsigned int y) const;
    		unsigned char GetBytesPerColor() const;
    
    		void SetPixel(unsigned int x, unsigned int y, color_tuple color);
    
    		void SaveFile(const char *filename) const;
    		void ReadFile(const char *filepath);
    };
    
    #endif //#ifndef H_PPMREADER_200909202000
    
    /*PPMReader.cpp*/
    #include "PPMReader.h"
    
    #include <fstream>
    #include <string>
    #include <sstream>
    
    using std::ios;
    using std::ifstream;
    using std::ofstream;
    using std::getline;
    using std::pair;
    using std::string;
    using std::stringstream;
    
    const char* header_tag = "P6";
    
    #include <stdexcept>
    typedef std::runtime_error      EXCEPTION_CANNOT_CREATE_FILE;
    typedef std::runtime_error      EXCEPTION_CANNOT_OPEN_FILE;
    typedef std::invalid_argument   EXCEPTION_WRONG_HEADER;
    typedef std::runtime_error      EXCEPTION_NOT_IMPLEMENTED;
    
    const char* read_file_exception_text = "Cannot open file for reading an image";
    const char* save_file_exception_text = "Cannot create file for saving the image";
    const char* wrong_header_text = "Expected other Header-Tag";
    const char* not_implementet_colordepth_text = "Sorry, no support for this picture (to high maximum values for each color-value)";
    
    //color_tuple
    color_tuple::color_tuple(const char* rgb, unsigned char color_depth)
    {
    	const char *last;
    	for(std::size_t i(0); i != 3; rgb = last, ++i)
    	{
    		last = rgb+color_depth;
    		stringstream ss;
    		ss.write(rgb, last-rgb);
    		ss >> RGB[i];
    	}
    }
    
    color_tuple::color_tuple(unsigned int R, unsigned int G, unsigned B)
    {
    	RGB[0] = R;
    	RGB[1] = G;
    	RGB[2] = B;
    }
    
    //helper
    unsigned int pumuckls_pow(unsigned int b, unsigned int e) //^^
    {
    	unsigned int r = 1;
    
    	while(e != 0)
    	{ 
    		if(e%2 != 0) 
    			r *= b; 
    		e /= 2; 
    		b *= b; 
    	}
    	return r;
    }
    
    unsigned int get_max_from_depth(unsigned int depth)
    {
    	unsigned int R = 0;
    	for(depth *= 8; depth != 0; --depth)
    	{
    		R += pumuckls_pow(2, depth-1);
    	}
    
    	return R;
    }
    
    void ignore_trash(ifstream &in)
    {
    	for(char delemiter; in.get(delemiter) && delemiter == '#'; )
    	{
    		std::string trash;
    		getline(in, trash);
    	}
    	in.unget();
    }
    
    std::pair<int/*w*/, int/*h*/> read_size(const std::string &buffer)
    {
    	std::pair<int, int> R;
    
    	stringstream ss;
    	ss << buffer;
    	ss >> R.first;
    	ss >> R.second;
    
    	return R;
    }
    
    unsigned char read_color_bytes(const std::string &buffer)
    {
    	unsigned int max;
    
    	stringstream ss;
    	ss << buffer;
    	ss >> max;
    
    	unsigned char bits(0);
    	for(; max != 0; max >>= 1, ++bits)
    		;
    	unsigned char bytes = unsigned char(bits/8.f+.5f);
    	return bytes != 3 ? bytes : 4;
    }
    
    //class
    PPMReader::PPMReader(const char *filepath)
    {
    	ReadFile(filepath);
    }
    
    color_tuple PPMReader::GetPixel(unsigned int x, unsigned int y) const
    {
    	return color_tuple(
    		&image[x*3*color_bytes + y*size.first*3*color_bytes],
    		color_bytes
    	);
    }
    
    unsigned char PPMReader::GetBytesPerColor() const
    {
    	return color_bytes;
    }
    
    void PPMReader::SetPixel(unsigned int x, unsigned int y, color_tuple color)
    {
    	//TODO: testen 
    	//TODO: staticassert(sizeof(char) == 1), staticassert(sizeof(short) == 2), staticassert(sizeof(int) == 4)
    	std::vector<char>::size_type
    		at1 = x*3*color_bytes + y*size.second*3*color_bytes + 0*color_bytes,
    		at2 = x*3*color_bytes + y*size.second*3*color_bytes + 1*color_bytes,
    		at3 = x*3*color_bytes + y*size.second*3*color_bytes + 2*color_bytes;
    	switch(color_bytes)
    	{
    	case 1:
    		image[at1] = static_cast<char>(color.R());
    		image[at2] = static_cast<char>(color.G());
    		image[at3] = static_cast<char>(color.B());
    		break;
    	case 2:
    		*reinterpret_cast<short*>(&image[at1]) = static_cast<short>(color.R());
    		*reinterpret_cast<short*>(&image[at2]) = static_cast<short>(color.G());
    		*reinterpret_cast<short*>(&image[at3]) = static_cast<short>(color.B());
    		break;
    	case 4:
    		*reinterpret_cast<int*>(&image[at1]) = static_cast<int>(color.R());
    		*reinterpret_cast<int*>(&image[at2]) = static_cast<int>(color.G());
    		*reinterpret_cast<int*>(&image[at3]) = static_cast<int>(color.B());
    		break;
    	default:
    		throw EXCEPTION_NOT_IMPLEMENTED(not_implementet_colordepth_text);
    	}
    }
    
    void PPMReader::SaveFile(const char *filename) const
    {
    	ofstream out(filename, ios::out | ios::binary);
    
    	if(out.bad())
    		throw EXCEPTION_CANNOT_CREATE_FILE(save_file_exception_text);
    
    	out << "P6\n"
    		<< size.first << " " << size.second << "\n"
    		<< get_max_from_depth(color_bytes) << "\n";
    
    	out.write(&image[0], image.size());
    }
    
    void PPMReader::ReadFile(const char *filepath)
    {
    	ifstream in(filepath, ios::in | ios::binary);
    
    	if(in.bad())
    		throw EXCEPTION_CANNOT_OPEN_FILE(read_file_exception_text);
    
    	string buffer;
    	getline(in, buffer);
    
    	if(buffer != header_tag)
    		throw EXCEPTION_WRONG_HEADER(wrong_header_text);
    
    	ignore_trash(in);
    	getline(in, buffer);
    	size = read_size(buffer);
    	ignore_trash(in);
    	getline(in, buffer);
    	color_bytes = read_color_bytes(buffer);
    
    	unsigned int length = color_bytes * size.first * size.second;
    	image.resize(length);
    
    	in.read(&image[0], length);
    }
    

    so in der richtung würd ichs jedenfalls lösen^^
    gefallen tuts mir trotzdem nicht, aber vll hat jmd anderes ja lust, die fehler darin zu beseitigen und das iwie eleganter zu lösen 😉

    bb



  • xD ich hab mich jetz an das angeben der größe beim string erstellen gehalten und habe anstatt vector<char> string genommen, was wenn ich mich nich irre sich doch sehr ähnlich ist, ansonsten geht meins jetzt auch...
    versuch mich grad bei dir einzulesen, aber so ein paar sachen wie exception handling hab ich noch nich oft gemacht (c++ mach ich auch erst seit geraumen 2 monaten)...

    was mich jetzt aber richtig interessiert ist:
    WARUM GEHT FOLGENDES?: in.read(&image[0], groeße);?? das erscheint mich wegen eig unterschiedlicher datentypen zunächst sinnlos ^^ habs so jetzt für meins auch übernommen, da ich nich ünnötig erneut kopieren möchte, also danke!



  • achso und das mit der pixelklasse werd ich auch noch einbaun, weil stimmt schon, dass man sonst vllt mal ein delete vergisst, danke



  • wie, wegen des typs?
    naja - ob string oder vector, nimmt sich fast nichts - ich hätt aber trotzdem vector genommen ^^

    http://www.cplusplus.com/reference/

    dort siehst du, was read für parameter entgegen nimmt, eine überladung ist in etwa so:

    istream& read(char *first, size_t count)

    in.read(&image[0], length);
    ruft dieses auf:
    image[0] = 1. element
    &image[0] = adresse des 1. elements
    length ist wohl selbsterklärend ;o)

    bb

    edit:

    achso und das mit der pixelklasse werd ich auch noch einbaun, weil stimmt schon, dass man sonst vllt mal ein delete vergisst, danke

    ich hoffe, dir fällt was eleganteres ein 😃
    ist das, was mir am allerwenigsten gefällt - aber ich hab erst am ende mal in die doku geguckt und gesehen, dass es so was gibt^^



  • joa guck ich morgen mal in meiner info stunde bei ^^
    also hauptsächlich war ich verwundert, weil vector doch eine art lineare liste ist und read() muss doch irgendwoher wissen, welche der variablen in dieser klasse auf das nächste element verweist, weil vector doch eig total anders is als char* und das kann read doch eig alles nich wissen ^^ deswegen versteh ichs nich ganz, warum das funktioniert



  • "vector doch eine art lineare liste"
    es ist ein array... (ne liste ist immer linear^^) es gibt 3 lineare container in der standard-lib: deque, list, vector

    und vector ist nur ein wrapper für ein array - also von aufbau + funktionsweise in etwa so:

    struct vector
    {
      int *x;
    
      vector(int laenge)
      {
        x = new int[laenge];
      }
    
      ~vector()
      {
        delete x;
      }
    
      int& operator[] (int index) {return x[index];}
    };
    

    also kann man sicher sein, dass es ein stück zusammenhängender speicher ist (im gegensatz zu deque oder list)...

    bb



  • aaaaah 🙂 dann macht das sinn, danke für die erklärung und schönen abend noch euch allen! (programmempfehlung: star wars 2 xD)


Anmelden zum Antworten