Carl-Zeiss-Gymnasium Jena
Mirko König
Darstellen von BMP-Bildern in einem ColorPlane-Fenster
Vortrag zur Lehrerfortbildung  13. 3. 2001

1.  Bitmaps
2.  Aufbau einer Bitmap-Datei
3.  Benötigte Oberon-Module
4.  Die Programme
5.  Resümee
  Literatur


1. Bitmaps

Als Bitmaps werden im engeren Sinne die Bilddateien im Format *.BMP, des Hausformates von MS Windows und OS/2 für Pixelbilder, bezeichnet. Im weiteren Sinne gilt der Begriff für sämtliche Pixelbilder und darüberhinaus für Datenmengen in einem nicht näher spezifizierten Byte-Format.
Diese Arbeit stellt sich zum Ziel, Möglichkeiten der Darstellung von BMP-Bildern im einem Oberon-2-Programm unter Pow! aufzuzeigen.

Bitmaps gibt es in den in der Tabelle gezeigten Formen (von MS Paint verwendete Bezeichnungen):
 
Art des Bitmaps Anzahl der Farben Bits pro Pixel
Monochrom 2 (schwarz und weiß) 1
16-Farben-Bitmap 16 4
256-Farben-Bitmap 256 8
24-Bit-Bitmap 16777216 24 (je 8 für rot, grün, blau)

Von jeder Form gibt es eine unkomprimierte und eine komprimierte Form. Letztere wird jedoch selten verwendet, insbesondere nicht von MS Paint. Das führt insbesondere bei 24-Bit-Bitmaps zu enormen Dateigrößen. Ein Rechenbeispiel: ein Bild von 800*600 Punkten mit 3 Bytes pro Pixel hat 1440000 Byte an Bilddaten, paßt also etwa auf eine Diskette. Trotzdem lohnt es sich, die BMP-Dateien genauer anzusehen, denn ein Bildbearbeitungsprogramm braucht den Zugriff auf jedes Pixel. So erzeugt eine harmlos aussehende JPG-Datei von 218 kB im Hauptspeicher des Browsers eine Speicherreservierung von 5,7 MB, wie ein Blick auf die Statusleiste von Paint Shop zeigt - ein Grund dafür, daß manche Rechner mit kleinem Speicher manche schnell gestrickten HTML-Seiten nicht richtig zeigen können:

So ist das BMP-Format sozusagen ein ehrliches Format, denn es sagt uns, was wir im Speicher zu erwarten haben.

Ich verwende an dieser Stelle unkomprimierte Bitmaps in 24-Bit-Farbe, d. h. jeder Punkt ist mit je 8 Bit für die Grundfarben der additiven Farbmischung, nämlich Rot, Grün und Blau kodiert. Dafür gibt es 2 Gründe: Erstens kann ColorPlane sehr schön Bilder in 24-Bit-Farbe zeigen, da eben für jeden Punkt die 3 Byte zur Verfügung stehen. Außerdem sind Monochrombilder relativ uninteressant, und die 16- sowie 256-Farben-Bilder benötigen eine Liste der verwendeten Farben, was die Arbeit erschwert und zudem wenig interessante Ergebnisse bringt.

24-Bit-Bilder stellen ein Optimum der Bildschirmanzeige dar, da das menschliche Auge mehr Farbnuancen schon nicht mehr wahrnehmen kann, wie die Gebrüder Geiß bereits festgestellt haben [1]. Jedoch macht sich bei Scannern 30- oder 36-Bit-Farbe erforderlich. Den Grund werden wir in Abschnitt 4  sehen


2. Aufbau einer Bitmap-Datei

Die Bitmap-Datei enthält einen Vorspann (Header) und die Daten der Pixel selbst [2].
 
Datum Bytes Kommentar
File ID 2 immer "BM"
Länge der Datei 4 der Vorspann und die Bilddaten
Datenoffset 4 = 0
reserviert 4 für spätere Verwendung
Infoheader 4 Offset des Datenbereiches - dort fangen die Pixel an (= 54 bei 24-Bit-Farbe)
Breite 4 Breite des Bildes in Pixeln
Höhe 4 Höhe des Bildes in Pixeln
Farbebenen 2 immer 1 (Farbebenen wurden bei BMPs nie eingeführt)
Bits pro Pixel 2 24 in unserem Fall
weitere für 24-Bit-Farbe unwichtige Informationen 24
16- und 256-Bit-BMPs haben an dieser Stelle noch die Liste der verwendeten Farben. Diese ist bei 16 Millionen verwendeten Farben nicht sinnvoll.
Pixeldaten 3 pro Pixel. Nach jeder Zeile wird die Pixelfolge mit Null-Bytes auf eine durch 4 teilbare Anzahl ergänzt. in der Reihenfolge blau, grün, rot. Der erste Punkt steht links unten.

3. Benötigte Oberon-Module

Ich verwende das 32-Bit-Pow!, da es die Speicherung der Pixel in einem ausreichend großen Array gestattet. Sinngemäß ist das Laden von Bitmaps auch mit dem 16-Bit-Pow! möglich, dann muß aber mit den Pixeln im Bildspeicher gearbeitet werden.
ColorPlane Open
SetForeColor(r,g,b)
Dot
WriteStr
Zeichenebene öffnen
Vordergrundfarbe setzen
Punkt zeichnen
Zeichenkette ausgeben
File Open
ReadBlock
WriteBlock
WriteChar
Close
Datei öffnen
Datum lesen
Datum schreiben
einzelnes Byte schreiben
Datei schließen
Strings Str Wandlung Zahl -> String
WinUser * GetActiveWindow, ShowWindow zum automatischen Maximieren des Fensters (kann weggelassen werden)
Didaktische Bemerkung: Das Anzeigen eines großen Bildes in ColorPlane kann sehr lange dauern. Natürlich kann man auch ein schnelles Windows-Programm schreiben, aber dann geht die Einfachheit der Arbeit mit ColorPlane verloren. Im Unterricht sollte es aber nicht das Ziel sein, die SEHR aufwendigen Windows-Programme zu schreiben, das sollte Delphi überlassen werden. So erzielt man mit dem einfachen ColorPlane sehr einfach überraschende Ergebnisse.

* Das Einbinden von WinUser erfordert die Aufnahme der Datei win32.lib in das Projekt:


4. Die Programme

Das Programm  LADEBILD.MOD


Das Programm lädt ein im aktuellen Verzeichnis stehendes Bild und zeigt es sowie einige seiner Daten an.
Es beginnt mit dem Festlegen der Variablen:

Es folgt das Einlesen der Daten:

Hierbei ist darauf zu achten, daß das aktuelle Verzeichnis bekannt ist. Anderenfalls kann man auch den absoluten Pfad angeben. Die Daten können jetzt wahlweise als INTEGER oder als LONGINT direkt mit BlockRead gelesen werden:
(Auszug)
Das Bild selbst wird - etwas großzügig, zugegeben - im Ganzen in das Array gelesen:

Die Datei wird geschlossen:

Die Angaben zum Bild werden mit WriteStr ausgegeben:

Die Ausgabe der Bilddaten erfolgt nun zeilenweise von links nach rechts und von unten nach oben. Die linke untere Ecke kann frei auf dem Bildschirm plaziert werden. Nach jeder Zeile ist die Korrektur auf durch 4 teilbare Breite zu vollziehen (s.  2. ):

 

Das Programm  INVERT.MOD

Dieses Programm soll demonstrieren, wie ein Pow!-Programm von der DOS-Kommandozeile aufgerufen wird.

Nach dem Aufruf wird eine Datei F.BMP (je nach Programmtext) geladen, invertiert und als INV.BMP gespeichert. Bemerkenswert ist, daß hier die Verwendung des Moduls File ausreicht.
Das Ergebnis läßt sich in Paint bewundern:

 

Das Programm  BIMP.MOD

Als Vorlage für den Namen diente das unerreichte Programm  gimp, das freie Gnu Image Manipulation Program.
Es stellt eine Benutzeroberfläche zum Laden, Speichern und Verändern von Bildern zur Verfügung.
Das Bild wird wie in  ladebild.mod in das Array bild geladen. Objekt der Veränderung sind die jeweils 3 Bytes eines jeden Bildpunktes. Nachdem die Mechanismen zum Laden und Anzeigen bekannt sind, kann nun reiche Ernte mit sehr einfachen Algorithmen eingefahren werden.

Invertieren

Ein Bildpunkt wird invertiert, indem seine Farbwerte im Wertebereich 0..255 gespiegelt werden:

Kontrast verringern (flauer)

Der Helligkeitswert jedes Farbbytes wird halbiert und um den Farbmittelwert gruppiert:

Kontrast verstärken (kontrastreicher)

Der Helligkeitswert jedes Farbbytes wird um 64 gesenkt und anschließend verdoppelt. Falls die Berechnung aus 0..255 herausführt, wird korrigiert:

Man sieht sehr gut, daß die letzten beiden Operationen nicht zueinander invers sind. Beim Verringern des Kontrasts gehen Daten verloren. Scannersoftware beugt diesem Effekt vor, indem deutlich mehr Bits pro Pixel als zum Anzeigen nötig eingelesen werden.
Ausgangsbild - flauer - kontrastreicher - kontrastreicher - flauer:

Schwarzweißbild erzeugen

Beim Schwarzweißbild - besser Graustufenbild - werden die rgb-Werte gemittelt und der Mittelwert gleichmäßig auf r, g, und b verteilt:

mittelwert ist dabei ein CHAR.


5. Resümee

Mit etwas Geduld beim Erforschen des Bitmap-Formates kann man sehr schöne Effekte beim Bearbeiten von Bildern mit dem eigenen Programm erzielen.
Es sind Anwendungen der Themen in reichem Maße vorhanden. Das sichtbare Ergebnis auf dem Bildschirm ist Ansporn für die Schüler (und für den Lehrer).

Literatur

Geiß/Geiß: Vom Anfänger zum GEM-Profi. Hüthig Buch Verlag Heidelberg 1991
Günter Born: Referenzhandbuch Dateiformate. Addison-Wesley 1995 (3. Auflage)