Bitmap speichern - WTF?!?!



  • Hallo,

    Versuche hier einfach irgendein Bitmap zu speichern aber da kommen die merkwürdigsten Resultate raus:

    width = 256; 
    height = 256;
    pData = new unsigned char[width*height*3];
    for(y=0; y<height; y++)
    {
        for(x=0; x<width; x++)
        {
             pData[pos++] = 0;
             pData[pos++] = col;
             pData[pos++] = 0;
             col++;
             col %= 100;
    
         }
    }
    save.open("aaa.bmp");
    SaveBmp24(save, width, height, pData);
    save.close();
    

    Dann noch die Funktion mit der ich speicher:

    void SaveBmp24 (ofstream& rkRGBStr, int width, int height, const unsigned char* pData) 
    {
        int quantity = width*height;
        int dataBytes = 3*quantity;
    
        BITMAPFILEHEADER kFileHeader;
        kFileHeader.bfType = 0x4d42;  // "BM"
        kFileHeader.bfSize =
            sizeof(BITMAPFILEHEADER) +
            sizeof(BITMAPINFOHEADER) +
            dataBytes;
        kFileHeader.bfReserved1 = 0;
        kFileHeader.bfReserved2 = 0;
        kFileHeader.bfOffBits =
            sizeof(BITMAPFILEHEADER) +
            sizeof(BITMAPINFOHEADER);
    
        BITMAPINFOHEADER kInfoHeader;
        kInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
        kInfoHeader.biWidth = width;
        kInfoHeader.biHeight = height;
        kInfoHeader.biPlanes = 1;
        kInfoHeader.biBitCount = 24;
        kInfoHeader.biCompression = BI_RGB;
        kInfoHeader.biSizeImage = 0;
        kInfoHeader.biXPelsPerMeter = 0;
        kInfoHeader.biYPelsPerMeter = 0;
        kInfoHeader.biClrUsed = 0;
        kInfoHeader.biClrImportant = 0;
    
        rkRGBStr.write((const char*)&kFileHeader,sizeof(BITMAPFILEHEADER));
        rkRGBStr.write((const char*)&kInfoHeader,sizeof(BITMAPINFOHEADER));
        rkRGBStr.write((const char*)pData,dataBytes*sizeof(unsigned char));
    }
    

    Als Resultat erhalte ich ein Bitmap das nicht nur den Grünen Farbkanal benutzt sondern sobald Grün auf 10 ist auf ein anderen Kanal wechselt... Also was zum Teufel passiert da?!?
    Hier das Resultatbitmap:
    http://www2.students.fh-vorarlberg.ac.at/~tst8639/pics/falschesbmp.bmp

    Dankeschön wäre super wenn mir jemand helfen könnte...



  • Habe jetzt das Problem eingeschrenkt. Es wird nur auf einen anderen Kanal gewechselt wenn col == 10. Wenn ich sowas einfüge wie

    if(col == 10)
    col = 10;
    

    funktionierts. Das kanns aber auch nicht sein oder 😮


  • Mod

    ist die zeilenbreite so wie es in der formatbeschriebung steht 32bit alligned?

    rapso->greets();



  • Ne an der Zeilenbreite liegt es nicht... Es liegt daran dass ich nem Pixel nicht die Farbe 10 geben darf sonst springts eins weiter..



  • versuchs mal so:

    #ifndef Bitmap_H 
    #define Bitmap_H 
    
    #include <stdio.h> 
    #include <string.h> 
    #include <string> 
    #include <iostream> 
    #include <math.h> 
    #include <ctime> 
    #include <fstream> 
    #include <windows.h>
    #include "Exception.h"
    using namespace std; 
    
    struct Color
    {
    	unsigned char		byRed;
    	unsigned char		byGreen;
    	unsigned char		byBlue;
    };
    
    class Bitmap
    {
    private:
    
    	struct BMPInfoHeader
    	{
    		unsigned long		nSize;
    		long				nWidth;
    		long				nHeight;
    		unsigned short		nPlanes;
    		unsigned short		nBitCount;
    		unsigned long		nCompression;
    		unsigned long		nSizeImage;
    		long				nXPelsPerMeter;
    		long				nYPelsPerMeter;
    		unsigned long		nClearUsed;
    		unsigned long		nClearImportant;
    	};
    
    	struct BMPFileHeader
    	{
    		unsigned short		nType;
    		unsigned long		nSize;
    		unsigned short		Reserved1;
    		unsigned short		Reserved2;
    		unsigned long		nOffBits;
    	};
    
    	ofstream m_stream; 
    	BMPInfoHeader  m_infoheader; 
    	BMPFileHeader  m_fileheader;
    
    	int m_Width;
    	int m_Height;
    
    	Color* m_pPixeldata;
    
    public:
    	Bitmap(int nWidth, int nHeight);
    	void setPixel(int x, int y, Color col);
    	void setPixel(int x, int y, unsigned int red, unsigned int green, unsigned int blue);
    	bool save(string filename);
    };
    
    Bitmap::Bitmap(int nWidth, int nHeight)
    {
    	if(nWidth <=0 || nHeight <=0)
    		throw Exception("::Bitmap constructor failed", __FILE__, __LINE__);
    
    	Color WhiteColor;
    	WhiteColor.byRed = 255;
    	WhiteColor.byGreen = 255;
    	WhiteColor.byBlue = 255;
    
    	m_pPixeldata = new Color[nWidth*nHeight];
    
    	for(int i = 0; i < nWidth*nHeight; i++)
    		m_pPixeldata[i] = WhiteColor;
    
    	m_Width = nWidth;
    	m_Height = nHeight;
    }
    
    void Bitmap::setPixel(int x, int y, Color col)
    {
    	if((x>=0 && x < m_Width) && (y>=0 && y < m_Height))
    		m_pPixeldata[x+y*m_Width] = col;
    	else
    		throw Exception("::setPixel failed", __FILE__, __LINE__);
    }
    
    void Bitmap::setPixel(int x, int y, unsigned int red, unsigned int green, unsigned int blue)
    {
    	if((x>=0 && x < m_Width) && (y>=0 && y < m_Height))
    	{
    			Color col;
    			col.byRed = static_cast<char>(red);
    			col.byGreen = static_cast<char>(green);
    			col.byBlue = static_cast<char>(blue);
    			m_pPixeldata[x+y*m_Width] = col;
    	}
    	else
    		throw Exception("::setPixel failed", __FILE__, __LINE__);
    }
    
    bool Bitmap::save(string filename)
    {
    	bool succeed = false;
    
    	try
    	{
    		int pos = filename.find(".");
    		string s1 = filename.substr(pos, filename.length());
    		if(s1 != ".bmp")
    			throw Exception("::save failed, unsupported bitmap format!", __FILE__, __LINE__);
    
    		// Datei oeffnen.
    		m_stream.open(filename.c_str(), ios::binary);
    
    		unsigned char* buffer;
    		unsigned long LineWidth;
    
    		// Zeilenbreite berechnen. (MUSS 32Bit breit sein!!!)
    		LineWidth = (m_Width*3+3)-((m_Width*3+3)%4);
    
    		// Speicher für den temporären Bildpuffer bereistellen.
    		buffer = new unsigned char[LineWidth*m_Height];
    
    		// fill the he aders with image data 
    		memset(&m_fileheader,0,sizeof(m_fileheader));
    		m_fileheader.nType				= 0x4d42;//"BM"
    		m_fileheader.nSize				= static_cast<unsigned int>(sizeof(BMPFileHeader) + sizeof(BMPInfoHeader) + (((m_Width*3+3)&0xFFFFFC)*m_Height));
    		m_fileheader.nOffBits			= 14+sizeof(BMPInfoHeader); // anstatt von 14 14 normalerweise sizeof(BMPFileHeader)
    
    		memset(&m_infoheader,0,sizeof(m_infoheader));
    		m_infoheader.nSize				= sizeof(BMPInfoHeader);
    		m_infoheader.nWidth				= m_Width;
    		m_infoheader.nHeight			= m_Height;
    		m_infoheader.nPlanes			= 1;
    		m_infoheader.nBitCount			= 24;
    		m_infoheader.nCompression		= BI_RGB;
    		m_infoheader.nXPelsPerMeter		= 2834;//72 DPI
    		m_infoheader.nYPelsPerMeter		= 2834;//72 DPI
    		m_infoheader.nSizeImage			= m_Width*m_Height;
    		m_infoheader.nClearUsed			= 0;
    		m_infoheader.nClearImportant	= 0;
    
    		// Strukturen in die Bitmap schreiben.
    		m_stream.write (reinterpret_cast <char*> (&m_fileheader.nType), 2);
    		m_stream.write (reinterpret_cast <char*> (&m_fileheader.nSize), 4);
    		m_stream.write (reinterpret_cast <char*> (&m_fileheader.Reserved1), 2);
    		m_stream.write (reinterpret_cast <char*> (&m_fileheader.Reserved1), 2);
    		m_stream.write (reinterpret_cast <char*> (&m_fileheader.nOffBits), 4);
    		m_stream.write (reinterpret_cast <char*> (&m_infoheader), 40);
    
    		// Speicher auf 0 setzen.
    		ZeroMemory(buffer, (LineWidth*m_Height));
    
    		// Bilddaten in den temporären speicher kopieren.
    		for(long lY = static_cast<long>(m_Height-1); lY >= 0; lY--)
    		{
    			for(long lX = 0; lX < static_cast<long>(m_Width); lX++)
    			{
    				buffer[lY*LineWidth+(lX*3)+2] = m_pPixeldata[(m_Height-1-lY)*m_Width+lX].byRed;
    				buffer[lY*LineWidth+(lX*3)+1] = m_pPixeldata[(m_Height-1-lY)*m_Width+lX].byGreen;
    				buffer[lY*LineWidth+(lX*3)+0] = m_pPixeldata[(m_Height-1-lY)*m_Width+lX].byBlue;
    			}
    		}
    
    		// Bildpuffer in die Bitmap schreiben.
    		m_stream.write (reinterpret_cast <char*>(buffer), (LineWidth*m_Height));
    
    		// Datei schließen.
    		m_stream.close();
    	}
    	catch(const Exception& Exception)
    	{
    		m_stream.close();
    		succeed = false;
    		Exception.show();
    	}
    	catch(...)
    	{
    		m_stream.close();
    		succeed = false;
    
    		throw Exception("::save failed", __FILE__, __LINE__);
    	}
    
    	return succeed;
    }
    
    #endif
    


  • Nette Klasse 😉



  • Hallo, da stimme ich dali voll zu!

    Wenn noch Jemad das Laden einer BMP dazuschreibt, währe es doch sicher etwas für die FAQ !!!!!!!!!!



  • Naja laden eines Bitmaps hab ich zwar auch schon aber das löst noch nicht mein Problem...

    int sm::GetImage (const char* name, int& width, int& height, unsigned char*& pData) {
        width = 0;
        height = 0;
        pData = 0;
    
        HBITMAP hImage = (HBITMAP) LoadImage(NULL,name,IMAGE_BITMAP,0,0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    
        if (!hImage) {
            return -1;
        }
    
        DIBSECTION dibSection;
        GetObject(hImage,sizeof(DIBSECTION),&dibSection);
    
        width = dibSection.dsBm.bmWidth;
        height = dibSection.dsBm.bmHeight;
        int quantity = dibSection.dsBm.bmWidth*dibSection.dsBm.bmHeight;
        if (dibSection.dsBm.bmBitsPixel != 24) {
            return -2;
        }
    
        // Allocate memory for pData
        pData = new unsigned char[3*quantity];
    
        // Windows BMP stores BGR, need to invert to RGB.
        unsigned char* aucSrc = (unsigned char*)dibSection.dsBm.bmBits;
        for (int i = 0; i < quantity; i++) {
            unsigned char b = aucSrc[3*i  ];
            unsigned char g = aucSrc[3*i+1];
            unsigned char r = aucSrc[3*i+2];
            pData[3*i  ] = r;
            pData[3*i+1] = g;
            pData[3*i+2] = b;
        }
    
        DeleteObject(hImage);
        return 0;
    }
    


  • dali schrieb:

    Ne an der Zeilenbreite liegt es nicht... Es liegt daran dass ich nem Pixel nicht die Farbe 10 geben darf sonst springts eins weiter..

    grins

    Speichere die Bilder doch mal binär... 😎

    Bye, TGGC



  • ich persönlich finde die Klasse nicht so schön...muss aber nichts heissen 😉

    //edit btw: das zeichen 10 entspricht einem line feed 😉



  • TGGC schrieb:

    dali schrieb:

    Ne an der Zeilenbreite liegt es nicht... Es liegt daran dass ich nem Pixel nicht die Farbe 10 geben darf sonst springts eins weiter..

    grins

    Speichere die Bilder doch mal binär... 😎

    Bye, TGGC

    Wenigstens einer der hier ne Ahnung hat 🤡 An den kopf greif 🤡


Anmelden zum Antworten