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 nichtfuer konkrete hilfe waere ich sehr dankbar da sich schon richtiger frust breit macht...
gruss
Guenniwow, 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 richtigdie 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 zeitaber 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/Wund 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 displaysgruss
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...