ich möchte den ov7670-output als Bitmap speichern. Der Sensor liefert 16bit-Pixel. Kennt jemand Programmcode zur Generierung der 54 Bytes Bitmap-header?
Du musst die Ausgabedaten noch umrechnen und den Header nach dieser Struktur schreiben: http://de.wikipedia.org/wiki/Windows_Bitmap#Dateikopf Nimm' beispielsweise 24 Bit Bitmap. Dazu musst du das packed-Format halt "strecken", bei 565-RGB eben Pixel1[0]=AusgabeByte1>>3; Pixel1[1]=((0b00000111 & Ausgabebyte1)<<3) | (Ausgabebyte2>>5); Pixel1[2]=(0b00011111 & Ausgabebyte2); Solltest du die YUV-Ausgabe verwenden, musst du sogar richtig rechnen lassen. Edit: Grade gesehen, Bitmap kann auch 16Bit, dachte zunächst, das geht nur mit komprimierten Daten. Also einfach 16-Bit-RGB speichern, und alles sollte passen.
:
Bearbeitet durch User
leluno schrieb: > ich möchte den ov7670-output als Bitmap speichern. Der Sensor liefert > 16bit-Pixel. Kennt jemand Programmcode zur Generierung der 54 Bytes > Bitmap-header? 1) Ein Bitmapheader hat keine konstante Länge, da er offene Arrays enthält (bzw. zumindest enthalten kann). 2) Ein Bitmapheader enthält Daten, die das Bild beschreiben. Dementsprechend kann es keinen universellen Code geben, um ihn zu schreiben. So ein Code könnte nur eine Funktion sein, dem man die entsprechenden Informationen als Parameter übergeben müßte, damit er sie dann in die Struktur schreibt. Da kann man dann die Informationen auch gleich selber in die Struktur schreiben. Insbesondere, wenn man sowieso nur den Header für ein bestimmtes feststehendes Bildformat schreiben will, dann kann man ihn nämlich komplett zur Entwurfszeit vordefinieren/vorberechnen und der Laufzeitcode macht nichts anderes mehr, als den Blob in eine Datei zu schreiben. Das "Vorberechnen" hält sich dabei übrigens sehr in Grenzen, es gibt nur maximal drei berechnete Felder im Header. 3) "16Bit-Pixel" ist nicht exakt genug, denn es gibt etliche verschiedene Spielarten von 16Bit-Pixeln. RGB555, RGB565 und diverse YUV-Formate. Der Header muß zum Inhalt passen, sonst sieht das Ergebnis etwas bis sehr komisch aus. Kurzfassung: du wirst nicht drumrumkommen, deine Faulheit zu überwinden und dich selber mit der Struktur zu beschäftigen.
leluno schrieb: > ich möchte den ov7670-output als Bitmap speichern. Der Sensor > liefert > 16bit-Pixel. Kennt jemand Programmcode zur Generierung der 54 Bytes > Bitmap-header? Wenn du immer konstante Einstellungen hast und selbst über alle Details bestimmen kannst ist der einfachste und praktikabelste weg dir ein BMP dieser Größe und dieses Formats am PC zu erstellen und den Header daraus auszuschneiden und als Template zu verwenden. Du brauchst ja keine eierlegende Wollmilchsau.
danke für die Antworten c-hater schrieb: > Das "Vorberechnen" hält > sich dabei übrigens sehr in Grenzen, es gibt nur maximal drei berechnete > Felder im Header. genau dafür hätte ich gern den code > Kurzfassung: du wirst nicht drumrumkommen, deine Faulheit zu überwinden > und dich selber mit der Struktur zu beschäftigen. Programmieren ist nun mal auch das Zusammensuchen von brauchbaren Code-Schnipseln. Das Gebiet ist für einen interessierten Laien viel zu komplex, um alles selbst zu machen. Maxx schrieb: > Template Das habe ich natürlich schon versucht. Scheiterte zunächst daran, dass das Kopieren im unteren Ascii-Bereich nicht so ganz einfach ist. Es gibt hier eine Seite, in der es einigermaßen nachvollziehbar ist: http://blog.csdn.net/pathuang68/article/details/4219681 Unklar ist mir der Aufbau des RGBQUAD-arrays. Da ist wohl definiert, was das Programm mit den 5-6-5-Pixeln machen muss. Mann könnte wahrscheinlich auch z.b. 5-5-6-Bitmaps machen. Dirk K. schrieb: > Dirk K. Wie geht es denn bei dir voran? Ich habe inzwischen Dateien mit 16bit-Pixeln auf der sd-karte, die ich leider noch nicht lesen und überprüfen kann. Wenn das geklappt hat, ist der nächste Schritt, das Bildformat auf 300k Pixel hochzusetzen.
Habe gestern Abend mal ein SD-Card-Modul ausgekramt, das MicroSD-Modell ist zu sehr auf Arduino (5V) angepasst. Hadere noch immer mit DMA. Könnte aber via Polling einfach mal mit einer SD-lib was wegschreiben und gucken, ob die Daten überhaupt sinnvoll sind. Mit dem Wiki-Link oben kann man sich einen Header doch ganz schnell selber tackern? Einige Felder musst du ohnehin anpassen, andere als konstant annehmen. Sonst nimm halt das hier ;) http://forum.arduino.cc/index.php?topic=159557.msg1507008#msg1507008
leluno schrieb: > Programmieren ist nun mal auch das Zusammensuchen von brauchbaren > Code-Schnipseln. Das Gebiet ist für einen interessierten Laien viel zu > komplex, um alles selbst zu machen. Was ist zu komplex? Das Ausrechnen, aus wievielen Pixel eine Bitmap besteht die zb 320 mal 240 Pixel gross ist? Und wenn 1 Pixel aus 2 Byte besteht (wegen 16 Bit), wieviele Bytes das dann sind? Das ist Stoff der 3. Klasse Grundschule. Wenn dir das zu komplex ist, dann solltest du dir ein anderes Hobby suchen. Das einzige, was rudimentär einer irgendwie gearteten Definition von 'komplex' entsprechen könnte, das ist, dass die Bytelänge einer Zeile in einer BMP immer ein Vielfaches von 4 ist. Und das wirst du ja wohl noch alleine hinkriegen, dass wenn ich zu dir 23 sage, du als Antwort 24 gibst, weil 4 die nächst größere Zahl zu 23 ist, die auch durch 4 teilbar ist. Aber komplizierter als das wird es nicht, wenn es darum geht die einzelnen Felder in einem BMP Bitmap Header auszufüllen. Man muss natürlich wissen, welche Bedeutung die einzelnen Felder in dieser Struktur haben. Aber dazu gibt es ja Doku bis zum Abwinken.
:
Bearbeitet durch User
Karl Heinz schrieb: > Was ist zu komplex? danke für den Hinweis. Komplex ist das Gesamtprojekt. Ich habe nicht den Anspruch, z.B. das Fat-System selbst zu entwickeln. Ich verwende den foolproof-code von Chan -war immer noch schwierig genug. Ich habe mir meine Lcd-lib nicht komplett anhand des Datenblatts selbst geschrieben, sondern habe auf Codebeispielen aufgebaut. Die Initialisierung des ov7670 habe ich selbstverständlich nicht selbst gemacht sondern verwende hierfür Beispielcode von avrman. Mein Ethernetteil stammt von Ulrich Radig. Alles irgendwo abgeschrieben. Respekt vor Grundschülern, die anscheinend heute schon in der dritten Klasse solchen Code selbst entwickeln können. War zu meiner Zeit noch nicht so. Natürlich bin ich in der Lage, den Bmp-header selbst zu entwickeln. Das dauert aber mindestens zwei Stunden - vielleicht auch wesentlich länger. Das beabsichtigte Gesamtsystem ist komplex. Wenn ich da zwei Stunden Entwicklungszeit dadurch einspare, dass ich den von Dirk aufgezeigten arduino-code benutze, dann mach ich das. Ich habe wirklich nicht den Anspruch jeden Teil des Gesamtcodes bis ins kleinste Detail selbst zu entwickeln. Die einzelnen Codeschnipsel sinnvoll zusammenzusetzen ist zumindest für meine Verhältnisse anspruchsvoll genug.
leluno schrieb: > Alles irgendwo abgeschrieben. Respekt vor Grundschülern, die anscheinend > heute schon in der dritten Klasse solchen Code selbst entwickeln können. Davon habe ich nicht geschrieben. Deine Frage dreht sich um die Member eines Bitmap Headers. Und deine Aussage war, den auszufüllen wäre so wahnsinnig komplex. > Natürlich bin ich in der Lage, den Bmp-header selbst zu entwickeln. Das > dauert aber mindestens zwei Stunden - vielleicht auch wesentlich länger. Wahnsinn. Mitlerweile sind fast 12 Stunden seit deiner Frage ins Land gezogen. Ich würde mal sagen - mit den 2 Stunden wärst du besser bedient gewesen. Zumal es keine 2 Stunden dauert, für die überschaubare Anzahl an Membern in dieser Datenstruktur Belegungen zu finden. Da bewegen wir uns selbst bei jemandem, der das noch nie gemacht hat, eher bei 20 Minuten. Hat das jemand schon mal gemacht, dann sind das eher 2 Minuten. Du willst es einfach nur nicht machen. Lass uns doch der Wahrheit ins Auge sehen und nicht dauern fadenscheinige Ausreden dafür finden. > Das beabsichtigte Gesamtsystem ist komplex. Deine Frage geht um Bitmap Header. Punkt. Bleib beim Thema.
Karl Heinz schrieb: > Du willst es einfach nur nicht machen. ...und das völlig zu recht. Das Problem ist RGB565. Das Umrechnen auf 24bit -während des Schreibvorgangs - scheidet wegen dem damit verbundenen Performanceverlust aus. 16bit-Bitmaps sind eher ungebräuchlich. Es wird eine Farbtabelle benötigt. Die Informationen zum Aufbau und zur Einbindung dieser Farbtabelle muss man sich mühsam zusammensuchen. Wenn du das in weniger als 2 Stunden schaffst, bist du wirklich gut.
leluno schrieb: > ...und das völlig zu recht. Das Problem ist RGB565. Das Umrechnen auf > 24bit -während des Schreibvorgangs - scheidet wegen dem damit > verbundenen Performanceverlust aus. 16bit-Bitmaps sind eher > ungebräuchlich. Immerhin hast du wenigstens mitlerweile bei Wikipedia den Headeraufbau nachgelesen. :-) > Es wird eine Farbtabelle benötigt. Nö. 'ungebräuchlich' heißt in diesem Zusammenhan, dass du wohl eher selten ein Malprogramm findest, welches 16 Bit Bilder speichern kann. Aber öffnen und anzeigen können sie das alle. So wie jedes andere Programm, welches BMP einlesen kann. > Die Informationen zum > Aufbau und zur Einbindung dieser Farbtabelle muss man sich mühsam > zusammensuchen. Wenn du das in weniger als 2 Stunden schaffst, bist du > wirklich gut. Lass es gut sein. Das was du hier rumlametierst hab ich schon zur Genüge gemacht. Vor 20 Jahren das erste mal, als man von so etwas wie einem Internet oder Online-Foren nur träumen konnte. Also erzähl mir da besser nicht, wie lange was dauert.
:
Bearbeitet durch User
leluno schrieb: > Das Problem ist RGB565. Nein. > 16bit-Bitmaps sind eher > ungebräuchlich. HEUTE ja. Anfang bis Mitte der 90er des letzten Jahrhunderts sah das noch ganz anders aus. Und übrigens: Informationen dazu gab es damals im I-Net tatsächlich auch schon und es gibt sie heute auch noch. Es ist heute sogar viel einfacher, sie zu finden, denn heute gibt es Google. Man muß die Suchmaschine nur kompetent benutzen können. > Es wird eine Farbtabelle benötigt. Nein. RGB565 ist ganz im Gegenteil sogar eines der ganz wenigen Bitmap-Formate, was nicht nur keine Farbtabelle zwingend braucht, sondern obendrein auch keine der normalerweise möglichen optionale Farbtabelle haben darf. Du hast die Deklaration des Headers immer noch nicht verstanden. Da gibt es eine Union... > Die Informationen zum > Aufbau und zur Einbindung dieser Farbtabelle muss man sich mühsam > zusammensuchen. Also ich würde die Farbtabellensache innert 2 Sekunden wiederfinden, obwohl ich mich das letzte Mal vor ca. 20 Jahren aktiv damit beschäftigt habe. Allerdings weiß ich schon vorab, daß es sinnlos ist, sie in diesem Zusammenhang zu suchen, denn hier sind Farb*MASKEN* gefragt. Der andere Zweig der Uniondeklaration... Und woher weiß man das? Weil man die verschissene Dokumentation zu bmih.biCompression tatsächlich gelesen hat und weiß, was die Konstante BI_BITFIELDS an dieser Stelle bedeutet...
Problem war wirklich nur die Suche nach dem Headeraufbau. Das Programmieren geht dann tatsächlich in 20 Minuten. If we are dealing with 16-bit or 32-bit images, then the Color Table contains a set of bit masks used to define which bits in the pixel data to associate with each color. Note that the original Version 3 BMP format did not support these image types. Instead, these were an extension of the format developed for WindowsNT. For both the 16-bit and the 32-bit variants, the color masks are 32-bits long with the green mask being first and the blue mask being last. In both cases the bit masks start with the most significant bits, meaning that for the 16-bit images the least significant two bytes are zero. The format requires that the bits in each mask be contiguous and that the masks be non-overlapping. The most common bit masks for 16-bit images are RGB555 and RGB565 while the most common bitmasks for 32-bit images are RGB888 and RGB101010. If we are dealing with a 24-bit image, then there is no Color Table present.
1 | void f_write_Bmpheader(u16 px,u16 py) { |
2 | //nur RGB565 + no padding: px%4==0
|
3 | |
4 | |
5 | uint8_t bmpFileHeader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54+16,0,0,0}; |
6 | uint8_t bmpInfoHeader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 16,0,3,0}; |
7 | uint8_t bmpcolorTable[16] = {0xf8,0,0,0,0xf8,0,0,0,0xf8,0,0,0,0x00,0,0,0}; |
8 | |
9 | |
10 | |
11 | //bmpInfoHeader[16]=3;//compression bitfields
|
12 | // u32 rowSize = 4 * ((3*px + 3)/4);
|
13 | u32 fileSize = 54 + 16 + py*px; |
14 | |
15 | //u8 pad = rowSize-3*px; //Number of zeros needed;
|
16 | |
17 | bmpFileHeader[ 2] = (uint8_t)(fileSize ); |
18 | bmpFileHeader[ 3] = (uint8_t)(fileSize >> 8); |
19 | bmpFileHeader[ 4] = (uint8_t)(fileSize >> 16); |
20 | bmpFileHeader[ 5] = (uint8_t)(fileSize >> 24); |
21 | |
22 | bmpInfoHeader[ 4] = (uint8_t)( px ); |
23 | bmpInfoHeader[ 5] = (uint8_t)( px >> 8); |
24 | bmpInfoHeader[ 6] = (uint8_t)( px >> 16); |
25 | bmpInfoHeader[ 7] = (uint8_t)( px >> 24); |
26 | bmpInfoHeader[ 8] = (uint8_t)( py ); |
27 | bmpInfoHeader[ 9] = (uint8_t)( py >> 8); |
28 | bmpInfoHeader[10] = (uint8_t)( py >> 16); |
29 | bmpInfoHeader[11] = (uint8_t)( py >> 24); |
30 | |
31 | f_write(&Fil, bmpFileHeader, 14, &bw); |
32 | f_write(&Fil, bmpInfoHeader, 40, &bw); |
33 | f_write(&Fil, bmpcolorTable, 16, &bw); |
34 | }
|
Karl Heinz schrieb: > Lass es gut sein. Ach Karlheinz, da rackerst du dich redlich ab und kriegst als Antwort "Programmieren ist nun mal auch das Zusammensuchen von brauchbaren Code-Schnipseln." Bei sowas wird mir schlecht. an den TO: Ich habe ja gar nix dagegen, wenn jemand sich passable Algorithmen in Form von Codeschnipseln zulegt. Sowas macht sicherlich jeder. ABER: Daraus besteht eben nicht das Programmieren. Laß dir das gesagt sein. Lerne logisches und analytisches Denken, wende es auf digitalelektronische Probleme an und entwickle daraus Lösungsstrategien - daraus besteht Programmieren. W.S.
W.S. schrieb: > Bei sowas wird mir schlecht. Dem ist nur zuzustimmen. Der vom TO vorgestellte code funktioniert nicht einmal. Richtig muss es lauten:
1 | void f_write_Bmpheader(int16_t px,int16_t py) { |
2 | //nur RGB565 + no padding: px%4==0
|
3 | |
4 | py=py*(-1); |
5 | uint8_t bmpFileHeader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54+12,0,0,0}; |
6 | uint8_t bmpInfoHeader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 16,0,3,0,0,0,0,128,1}; |
7 | uint8_t bmpcolorTable[12] = {0,0xf8,0,0,224,7,0,0,31,0,0,0}; |
8 | |
9 | |
10 | //bmpInfoHeader[16]=3;//compression bitfields
|
11 | // u32 rowSize = 4 * ((3*px + 3)/4);
|
12 | u32 fileSize = 54 +12 + py*px*2; |
13 | |
14 | //u8 pad = rowSize-3*px; //Number of zeros needed;
|
15 | |
16 | bmpFileHeader[ 2] = (uint8_t)(fileSize ); |
17 | bmpFileHeader[ 3] = (uint8_t)(fileSize >> 8); |
18 | bmpFileHeader[ 4] = (uint8_t)(fileSize >> 16); |
19 | bmpFileHeader[ 5] = (uint8_t)(fileSize >> 24); |
20 | |
21 | bmpInfoHeader[ 4] = (uint8_t)( px ); |
22 | bmpInfoHeader[ 5] = (uint8_t)( px >> 8); |
23 | bmpInfoHeader[ 6] = (uint8_t)( px >> 16); |
24 | bmpInfoHeader[ 7] = (uint8_t)( px >> 24); |
25 | bmpInfoHeader[ 8] = (uint8_t)( py ); |
26 | bmpInfoHeader[ 9] = (uint8_t)( py >> 8); |
27 | bmpInfoHeader[10] = (uint8_t)( py >> 16); |
28 | bmpInfoHeader[11] = (uint8_t)( py >> 24); |
29 | |
30 | UINT bw; |
31 | f_write(&Fil, bmpFileHeader, 14, &bw); |
32 | f_write(&Fil, bmpInfoHeader, 40, &bw); |
33 | f_write(&Fil, bmpcolorTable, 12, &bw); |
34 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.