24Bit in 1Bit BMP wandeln



  • hallo maedels,

    kann mir bitte jemand helfen indem er mir sagt wie ich meinen (nicht wirklich komplett von mir) code zum speichern eines bitmap umstelle so dass ich die daten als 1Bit Bmp abspeicher.
    ich hab schon ewig viele seiten und erklaerungen durchgeschaut jedoch verstehe ich den teil mit der umstellung auf eine andere palette nicht

    fuer konkrete hilfe waere ich sehr dankbar da sich schon richtiger frust breit macht...

    gruss
    Guenni

    wow, voll den ahnhang vergessen 😃

    ... und warum ist mein BLAUES gekritzel im gespeicherten bmp schwarz?

    ich habs echt nicht drauf und ich kapier es auch einfach nicht---soll heissen:
    ICH BRAUCH DRINGEND HILFE!!!

    bool CTest1Dlg::WriteBitmap(LPTSTR szFile, HBITMAP hbitmap, HDC memdc)
    {
    	CRect rect;
    	GetClientRect(&rect);
    
    	CClientDC dc(this);
    
    	int x = 240*3;		//rect.right*3; // 24Bit pro pixel
    	int y = 120;		//rect.bottom;
    
    	char* pixel = new char[x*y];
    
    	// Pixel
    	int xpos = 0;
    	int ypos = rect.bottom;		// Upside-down format
    	int index=0;
    
    //CString test="";
    
    	while(ypos>rect.bottom-y)		//0
    	{	
    		while(xpos<(x/3))				//rect.right)
    		{
    			// Pixel auslesen und in die einzelnen Farben spalten
    			//int dummy = 0;
    
    			COLORREF col_ref = dc.GetPixel(xpos,ypos);
    
    			/*
    			col_ref = dc.GetPixel(xpos,ypos);
    			if (col_ref != 0)
    			{
    				dummy += 128;
    			}
    			xpos++;
    
    			col_ref = dc.GetPixel(xpos,ypos);
    			if (col_ref != 0)
    			{
    				dummy += 64;
    			}
    			xpos++;
    
    			col_ref = dc.GetPixel(xpos,ypos);
    			if (col_ref != 0)
    			{
    				dummy += 32;
    			}
    			xpos++;
    
    			col_ref = dc.GetPixel(xpos,ypos);
    			if (col_ref != 0)
    			{
    				dummy +=16;
    			}
    			xpos++;
    
    			col_ref = dc.GetPixel(xpos,ypos);
    			if (col_ref != 0)
    			{
    				dummy +=8;
    			}
    			xpos++;
    
    			col_ref = dc.GetPixel(xpos,ypos);
    			if (col_ref != 0)
    			{
    				dummy +=4;
    			}
    			xpos++;
    
    			col_ref = dc.GetPixel(xpos,ypos);
    			if (col_ref != 0)
    			{
    				dummy +=2;
    			}
    			xpos++;
    
    			col_ref = dc.GetPixel(xpos,ypos);
    			if (col_ref != 0)
    			{
    				dummy +=1;
    			}
    			xpos++;
    
    			pixel[index]=(char)(dummy);
    
    			test = test + pixel[index];
    */
    
    			// Rot
    			pixel[index]=(char)(col_ref);
    			index++;
    
    			// Grün
    			pixel[index]=(char)(col_ref);
    			index++;
    
    			// Blau
    			pixel[index]=(char)(col_ref);
    			index++;
    
    			xpos++;
    
    		}
    
    		xpos=0;
    		ypos--;
    	}
    //	m_test = test;
    //	UpdateData(false);
    
    	BITMAPINFOHEADER infoheader;
    	infoheader.biSize=sizeof(infoheader);
    	infoheader.biWidth=(x/3);//rect.right; //150 Breite der Bitmap
    	infoheader.biHeight=y;//rect.bottom; //100 Höhe der Bitmap
    	infoheader.biPlanes=1;
    	infoheader.biBitCount=24; // Farbtiefe
    	infoheader.biCompression=0;
    	infoheader.biSizeImage=0; // Größe der Bitmap (darf 0 sein)
    	infoheader.biXPelsPerMeter=0;
    	infoheader.biYPelsPerMeter=0;
    	infoheader.biClrUsed=0; // Alle Farben werden benützt
    	infoheader.biClrImportant=0; // Alle Farben sind Wichtig
    
    	BITMAPFILEHEADER fileheader;
    	fileheader.bfType=19778; // BM - Dateityp
    	fileheader.bfSize=x*y+sizeof(infoheader)+sizeof(fileheader);
    	fileheader.bfReserved1=0;
    	fileheader.bfReserved2=0;
    	fileheader.bfOffBits=(DWORD)(sizeof(fileheader)+
    	sizeof(infoheader)); // Ab hier: Pixel
    
    	// Auf Festplatte speichern
    	CFile file;
    	LPTSTR path = _T("\\bitmap.bmp");
    
    	if(!file.Open(path,CFile::modeWrite|CFile::modeCreate))
    	return false;
    
    	// Fileheader + Infoheader
    	file.Write(&fileheader,sizeof(fileheader));
    	file.Write(&infoheader,sizeof(infoheader));
    
    	// (hier: Palette für 16-256 Farben)
    
    /*	typedef struct tagRGBQUAD 
    	{ 
    		BYTE rgbBlue;
    		BYTE rgbGreen;
    		BYTE rgbRed;
    		BYTE rgbReserved;
    	} RGBQUAD;
    
      	RGBQUAD Colors[255,255,255,0];
    	RGBQUAD Colors[0,0,0,0];
    */
    
    	int nFullLength=WIDTHBYTES( infoheader.biWidth*infoheader.biBitCount );
    
    	// Pixel
    	for(int nLine=0; nLine<y; ++nLine)
    	file.Write(&pixel[nLine*x],x);
    	file.Write(&pixel[nLine*x],nFullLength-x);
    
    	file.Close();
    
    	delete[] pixel;
    	delete memdc;
    
    	return true;
    }
    


  • Eine Bitmap mit einer 1Bit Palette kann nunmal nur 2 Farben darstellen.

    1 Bit = 0 oder 1, wahr oder falsch, Licht an oder Licht aus, Weiß oder Schwarz
    ( Informatik Grundlagen, Erster Tag, Erste Stunde )



  • nun...soweit war ich schon vor 15 jahren

    aber da musste ich noch nicht c proggen

    und nu?!



  • ich hab zwischenzeitlich mal was ganz neues aus einem uralt posting rausgeklaut und probiert

    geht wunderbar und hat auch den gewuenschten effekt mit einer ausnahme:
    ich mache einen screenshot der gesamten oberflaeche!!

    jetzt hab ich auch mal ein paar dinge geaendert um dies abzuaendern auf meine zeichenflaeche anstatt des gesamten desktop
    ...und kaum fummel ich dran rum gehts wieder nicht richtig

    die geanderten sachen in der "dc2bitmap" habe ich auskommentiert und durch meine handles getauscht

    hat wer 'ne idee was ich uebersehen hab? 😕 😕

    ach ja: momentan erhalte ich scheinbar den selben ausschnitt nur werden diesmal buttons auf der oberflaeche komplett schwarz dargestellt

    uebrigens kann ich durch meine aenderungen auch wieder auf dem display schreiben...aber wie schon gesagt: es wird nicht korrekt gespeichert

    void CTest1Dlg::OnNext() 
    {
    	CPaintDC pc(this);
    	//jetzt das ganze als Bitmap abspeichern 
    	CDC *dc=new CDC; //ein neuer unabhängiger DC 
    	CBitmap *membmp=new CBitmap; //eine Bitmap die den DC representiert 
    	RECT cr;    //für die Grösse des Clients 
    
    	dc->CreateCompatibleDC(GetDC());  
    	GetClientRect(&cr); //Ausdehnung des Clientsbereichs ermitteln 
    	//passende Bitmap in der Grösse des Clients anlegen 
    	membmp->CreateCompatibleBitmap(GetDC(), cr.right,cr.bottom); 
    
    	//Speicherkontext mit der Bitmap verbinden 
    	dc->SelectObject(membmp); 
    	//In den Speicherkontext (eigentlich in die Bitmap!) den Inhalt des dc kopieren 
    	dc->BitBlt(0,0,cr.right,cr.bottom,GetDC(),0,0,SRCCOPY); 
    
    	//Jetzt die Bitmap speichern 
    	//WriteBitmap(_T("\\testbitmap.bmp"),membmp->operator HBITMAP(), dc->m_hDC); 
    
    	int weite = 240;
    	int hoehe = 120;
    
    	dc2bitmap(dc->m_hDC, /*weite, hoehe*/ membmp->operator HBITMAP(), _T("\\schwarzweiss.bmp"));
    
    	dc->DeleteDC(); 
    	delete dc; 
    
    	membmp->DeleteObject(); 
    	delete membmp; 
    }
    
    int CTest1Dlg::dc2bitmap(HDC hdc, /*int width, int height*/ HBITMAP aBmp, LPTSTR szFile2)
    {
    	int width = 240;
    	int height = 120;
    	HDC hdc2; 
        //HBITMAP aBmp; 
        HGDIOBJ OldObj; 
        void *dibvalues; 
        HANDLE fileHandle; 
    
        BITMAPFILEHEADER bmfh; 
    
        DWORD bytes_write; 
        DWORD bytes_written; 
    
        hdc2=CreateCompatibleDC(hdc); 
    
        DWORD sizeBI = sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)); 
        LPBITMAPINFO lpbi = (LPBITMAPINFO) new char[sizeBI]; 
        ZeroMemory(lpbi,sizeBI); 
    
        lpbi->bmiHeader.biSize        = sizeof(BITMAPINFOHEADER); 
        lpbi->bmiHeader.biWidth       = width; 
        lpbi->bmiHeader.biHeight      = height; 
        lpbi->bmiHeader.biPlanes      = 1; 
        lpbi->bmiHeader.biBitCount    = 1; 
        lpbi->bmiHeader.biCompression = BI_RGB; 
        lpbi->bmiHeader.biSizeImage   = ((((lpbi->bmiHeader.biWidth * lpbi->bmiHeader.biBitCount) + 31) & ~31) >> 3) * lpbi->bmiHeader.biHeight; 
    
        /*for(int i = 0; i < 256; i++) 
        { 
            lpbi->bmiColors[i].rgbRed   = i; 
            lpbi->bmiColors[i].rgbGreen = i; 
            lpbi->bmiColors[i].rgbBlue  = i; 
        }*/ 
    
    	lpbi->bmiColors[1].rgbRed   = 255; 
    	lpbi->bmiColors[1].rgbGreen = 255; 
    	lpbi->bmiColors[1].rgbBlue  = 255;
    
        aBmp = CreateDIBSection(hdc,lpbi,DIB_RGB_COLORS,(void**)&dibvalues,NULL,NULL); 
    
        if (aBmp==NULL) 
        { 
            //OutputDebugString("CreateDIBSection failed!\n"); 
            return 0; 
        } 
    
        OldObj=SelectObject(hdc2,aBmp); 
        BitBlt(hdc2,0,0,width,height,hdc,0,0,SRCCOPY); 
    
        ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER)); 
        bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeBI; 
        bmfh.bfSize=(lpbi->bmiHeader.biHeight*lpbi->bmiHeader.biWidth)+sizeof(BITMAPFILEHEADER)+sizeBI; 
        bmfh.bfType=0x4d42; 
    
        fileHandle=CreateFile(szFile2,GENERIC_READ | GENERIC_WRITE,(DWORD)0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL); 
        if (fileHandle==INVALID_HANDLE_VALUE) 
        { 
            //OutputDebugString("CreateFile failed!\n"); 
            return 0; 
        } 
    
        // Write the BITMAPFILEHEADER 
        bytes_write=sizeof(BITMAPFILEHEADER); 
        if (!WriteFile(fileHandle,(void*)&bmfh,bytes_write,&bytes_written,NULL)) 
        { 
            //OutputDebugString("WriteFile failed!\n"); 
            return 0; 
        } 
    
        //Write the BITMAPINFOHEADER 
        bytes_write=sizeBI; 
        if (!WriteFile(fileHandle,(void*)lpbi,bytes_write,&bytes_written,NULL)) 
        { 
            //OutputDebugString("WriteFile failed!\n"); 
            return 0; 
        } 
    
        //Write the Color Index Array??? 
        bytes_write=lpbi->bmiHeader.biSizeImage;//3*bmih.biHeight*bmih.biWidth; 
        if (!WriteFile(fileHandle,(void*)dibvalues,bytes_write,&bytes_written,NULL)) 
        { 
            //OutputDebugString("WriteFile failed!\n"); 
            return 0; 
        } 
    
        CloseHandle(fileHandle); 
    
        DeleteObject(SelectObject(hdc2,OldObj)); 
        DeleteDC(hdc2);
    
    	return 1;
    }
    


  • Eine Bitmap mit einer 1Bit-Farb-Palette kann nur 2 Farben darstellen.

    Und du willst jetzt also die 24Bit Palette mit einer 1Bit Palette austauschen? Richtig oder?

    Zum besseren Verständnis. Öffne mal deine 24 Bit Bitmap in MS-Paint und dann klicke da auf -> Ansicht -> Attribute und dort wähle die Option Schwarzweiß unter Farben.
    Wenn du diese Bitmap nun speicherst hast nun eine 1 Bit Bitmap und ich vermute das sie genau dem Ergebnis entspricht was du uns schon geschildert hast.

    Evtl. würde dir das hier weiter helfen:
    http://www.catb.org/~esr/faqs/smart-questions.html



  • mensch foren troll 😃

    ich weiss leider nicht wie ich anders fragen soll da mir der fachliche wortschatz dafuer fehlt was ich hier realisieren muss...

    dass man bitmaps umwandeln kann mit dementsprechenden grafikprogrammen ist mir wohl bewusst
    ebenso ist mir bewusst dass es sich bei einem 1bit bmp um ein bitmap mit lediglich 2farben handelt (schon klar)

    aber ich komme nicht mit den handels und dem dateiformat(DATENSTRUKTUR) eines bitmaps klar
    ich verstehe nicht wie sich diese datei binaer aufbaut und wie ich vorgehen muss um meinem krueppelscomputer mitzuteilen dass er farbenblind ist und lediglich B&W screenis macht um damit auf weniger als 5kb speicherbedarf runterzukommen da ich das gekritzel meines pocketpc ueber gprs zum server schicken moechte
    und 188kb pro datei wie bisher kosten bei hunderten von dateien echt kohle und nebenbei zeit

    aber wie du siehst bin ich was den code angeht umgestiegen auf eine recht gut funktionierende methode eines anderen
    leider weiss ich noch nicht wie ich den oberen teil meines screenshots abschneide (natuerlich per c++...und nicht mit photoshop 😉 )

    waere cool wenn du da was weisst denn damit kennen sich scheinbar kaum leute aus

    Guenni 😃



  • Dies [msdn]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/vcrefcimagebitblt.asp[/msdn] sollte dir weiter helfen 😃

    Und soweit ich gesehen hatte, wird das in dem unten von dir geposteten Source 2 mal gemacht.
    Einmal an der Stelle an der der Screenshot vorgenommen wird, ( OnNext-Func) und
    in der dc2Bitmap-Func.



  • danke dir!!

    hab nu feierabend und echt dicke augen 😮

    aber ich schau gleich morgen frueh mal rein und teste...melde mich dann wieder

    schoenen feierabend wuensch ich dir und mir 😃

    guenni



  • eine frage

    der eine sagte ja man kann mit prog ( photoshof ) oder so aus SW stellen, und hat dann 1 bit. sicher??? sind das nicht zig grautöne in der regel??? also 24bit farbe auf 24bit grautöne

    dann musste das file ja auch nach deiner mehode auch super schrumpfen, da man nicht 24 sondern nur 1 bit farbwert abspeichern muss



  • ich habe sowas schonmal gemacht für ne zahlenerkennung und das hat auch soweit gefunzt gehabt...
    ist schon ne weile her und nur zusammengehackt aber das hier war mein code dazu
    ich weiss nicht ob das für alle bitmapformate gilt aber mit dem das ich hatte hats gefunzt

    //hiermit aus dem 24bitfarbendatei einlesen
    unsigned char* file2char(char* filename,int x,int y){
    
    unsigned char* rv = new unsigned char[x*y];
    int i,j,k,x;
    FILE *in=fopen(filename,"rb");
    fseek(in,54,SEEK_SET);
    
    y=25;
    while(!feof(in)&&k){
    
    	--k;
    	for(j=0;j<x;j++){
    		x=0;
    		for(i=0;i<3;i++)
    			x+=fgetc(in)*((int)pow(256,i));
    		if( (( (x>>16) + ((x>>8)%256) + (x%256) )/3) >128) rv[k*90+j]=1;else rv[k*x+j]=0;
    	}
             for(i=0;i<x%4;++i)fgetc(in);
    
    }
    
    fclose(in);
    
    return rv;
    
    }
    
    //hiermit das 1bit-sw bild erstellen
    das ist noch für x=90 und y=25 dimension muss man dann halt anpassen um das variable zu halten
    void char2file(char* filename, unsigned char* pic){
    
    FILE *out=fopen(filename,"wb");
    
    fputc(66,out);fputc(77,out);	//Magic Number
    fputc(0xE2,out);fputc(0xe1,out);fputc(0,out);fputc(0,out);//dateilänge
    fputc(0,out);fputc(0,out);fputc(0,out);fputc(0,out);//4 reservierte Byts
    fputc(0x3e,out);fputc(0,out);fputc(0,out);fputc(0,out);//4 reservierte Byts
    
    fputc(40,out);fputc(0,out);fputc(0,out);fputc(0,out);//Format-Header-Laenge
    fputc(0x5A,out);fputc(0,out);fputc(0,out);fputc(0,out);//Bildbreite						
    fputc(0x19,out);fputc(0,out);fputc(0,out);fputc(0,out);//Bildhoehe						
    fputc(1,out);fputc(0,out);				//Anzahl der Ebenen
    fputc(1,out);fputc(0,out);				//Bits pro Pixel
    fputc(0,out);fputc(0,out);fputc(0,out);fputc(0,out);	//Kompression
    fputc(0xa4,out);fputc(0x01,out);fputc(0,out);fputc(0,out);	//Groesse der Pixeldaten						
    
    fputc(0xc4,out);fputc(0x0e,out);fputc(0,out);fputc(0,out);	//x-Auflösung(in Pixel pro Meter)	
    fputc(0xc4,out);fputc(0x0e,out);fputc(0,out);fputc(0,out);	//y-Auflösung(in Pixel pro Meter)
    fputc(0,out);fputc(0,out);fputc(0,out);fputc(0,out);	//Anzahl genutzter Farben
    fputc(0,out);fputc(0,out);fputc(0,out);fputc(0,out);	//Anzahl wichtiger Farben
    
    fputc(0,out);fputc(0,out);fputc(0,out);fputc(0,out);
    
    fputc(0xFF,out);fputc(0xFF,out);fputc(0xFF,out);fputc(0,out);
    
    int i,j,k,x;
    
    	for(j=25-1;j>=0;j--){
    		for(i=0;i<11;i++){
    			for(x=k=0;k<8;k++){
    				x+=pic[j*90+i*8+k]?pow(2,7-k):0;	
    			}
    			fputc(x,out);
    		}
    		fputc(128*pic[j*90+88]+64*pic[j*90+89],out);
    	}
    
    fclose(out);
    
    }
    


  • hi newkid

    du kannst in photoshop und jedem anderen halbwegs anstaendigen grafikprogram S/W einstellen
    die funktionen im menue heissen dann 1BIT, Monochrome oder S/W

    und natuerlich schrumpft dann die dateigroesse extrem, da du pro bildpunkt nur 1 bit verwendest um farbinformationen(farbe?!) zu speichern

    bei meinem pocketpcscreenshot schrumpft die datei von 188kb auf 9,5kb 😃
    aber ich brauch nur den unteren teil des displays 😡

    gruss
    guenni



  • ICH HABS!!!!!!!

    und wem hab ich das zu verdanken?!: dem FORENTROLL!!! VIELEN DANK

    und auch danke an Windalf und NewKid fuer die hilfe...

    mit dem link auf die msdn vom forentroll habe ich am ende durch rumprobieren endlich fast komplett verstanden was ich da mache und vor allem warum

    so konnte ich endlich meinen ausschnitt begrenzen

    DANKE NOCHMAL!!

    😃 😃 😃 Guenni 😃 😃 😃

    ach so: 1 letzte frage haette ich noch!!

    weiss zufaellig jemand von euch wie man auf dem pocketpc den "roten kreis" deaktiviert welcher den rechten mousebutton ersetzt und immer dann aktiviert wird wenn man laenger aufs display drueckt??

    eine antwort darauf waere dann echt der ueberhammer fuer heute... 😃


Anmelden zum Antworten