namespace cpp {}

C++ lernen, kennen, anwenden

Benutzer-Werkzeuge

Webseiten-Werkzeuge


anwenden:images
no way to compare when less than two revisions

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.


anwenden:images [2020-07-26 17:20] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1
Zeile 1: Zeile 1:
 +====== Image : Grafik-Programmierung ohne Grafik-Treiber ======
 +
 +> Du sollst dir kein Bildnis noch irgendein Gleichnis machen,
 +> weder des, das oben im Himmel,
 +> noch des, das unten auf Erden,
 +> oder des, das im Wasser unter der Erde ist.
 +>>---  2. Mose 20, 4
 +
 +
 +Wir verstoßen ständig gegen das zweite Gebot. 
 +Schlachten wir eine weitere heilige Kuh:
 +"Grafikprogrammierung ist nichts für Anfänger.
 +Dazu braucht man schnelle Rechner,
 +teure Grafikkarten und Programmierbibliotheken
 +mit hohem Einarbeitungsaufwand (OpenGL, DirectX, SDL, ...)."
 +Nichts da. Es geht nicht um 3D-Ego-Shooter.
 +Es geht nicht um:
 +"Mein Grafikprozessorkühler ist 2 cm länger als deiner."
 +Servergenerierte Aktiencharts brauchen keine Framerate.
 +
 +Vor dem Jahr 1990 habe ich 9-Nadel-Drucker punktweise angesteuert
 +im Epson-Escape(P)-Befehlssatz,
 +weil ich computerberechnete Ergebnisse in Bildform ausdrucken wollte.
 +Grafikkarte jenseits von Basic-Kleincomputern? Fehlanzeige.
 +Man braucht einen geordneten Zugriff auf Bildpunktdaten im Hauptspeicher
 +und einen Speicher, auf dem Bilder abzulegen sind. Alles weitere ist Routine.
 +Und es gibt eine Menge dabei zu lernen.
 +Willkommen im Bereich der Retroprogrammierung.
 +
 +===== Aufgabe =====
 +Erstelle die Grundlagen der Computergrafik.
 +Gehe in folgenden Schritten vor:
 +
 +
 +  - Definiere 32-Bit-Farben (je 8 Bit für rot, grün, blau, Transparenz).
 +  - Bilder beliebiger Größe sind als Klasse zu vereinbaren.
 +  - Speichere das Bild als Datei (z.B. BMP, einfaches Datenformat).
 +Der Zugriff auf die Farben einzelner Bildpunkte soll einfach und robust sein.
 +
 +===== Lösung =====
 +
 +
 +
 +==== Klasse Color ====
 +Die vier Farbinformationen werden in einer Klasse gebündelt.
 +
 +<code cpp color.h>
 +//: color.h : Grafik-Bibliothek ohne Grafiktreiber - R.Richter 2011-01-15
 +/////////////////////////////////////////////////////////////////////////
 +
 +#ifndef COLOR_H
 +#define COLOR_H
 +
 +// Farben, 24 bit Farbtiefe mit Transparenz (Alpha-Kanal)
 +
 +class Color
 +{
 +public:
 +  typedef unsigned char Channel;
 +  typedef unsigned long RGBAlpha;
 +
 +  enum 
 +  {
 +    NONE   = 0xFF000000,
 +    BLACK  = 0x00000000,
 +    WHITE  = 0x00FFFFFF,
 +    RED    = 0x00FF0000,
 +    GREEN  = 0x0000FF00,
 +    BLUE   = 0x000000FF,
 +    YELLOW = 0x00FFFF00
 +  };
 +
 +  Color(Channel red, Channel green, Channel blue, Channel alpha = 0)
 +  : value( rgba(red, green, blue, alpha ) )
 +  {
 +  }
 +
 +  Color(RGBAlpha color = 0xff000000) // default: transparent
 +  : value(color)
 +  {
 +  }
 +
 +  Channel alpha() const { return Channel(value>>24); }
 +  Channel red()   const { return Channel(value>>16); }
 +  Channel green() const { return Channel(value>>8);  }
 +  Channel blue()  const { return Channel(value);     }
 +
 +  operator unsigned long() const { return value; }
 +private:
 +  RGBAlpha value;
 +
 +  static RGBAlpha rgba(Channel red, Channel green, Channel blue, Channel alpha)
 +  {
 +    return   RGBAlpha(alpha)<<24 | RGBAlpha(red)<<16
 +    | RGBAlpha(green)<< | RGBAlpha(blue);
 +  }
 +};
 +
 +#endif // COLOR_H
 +//~
 +</code>
 +Intern werden die Daten zu einer Langzahl zusammengefasst.
 +Für den einfachen Umgang werden einige Standardfarben festgelegt.
 +Die Farbklasse ist unvollständig:
 +
 +
 +  * Welche weiteren Farben sind als Standardfarben zu definieren?
 +  * Welche Rechengesetze gelten für Farben ?
 +
 +
 +
 +
 +==== Klasse Image ====
 +Ein Bild hat eine bestimmte Breite und eine bestimmte Länge,
 +die nachfolgend nicht mehr änderbar ist.
 +Solange noch kein Bildpunkt bemalt wurde, ist das Bild durchsichtig,
 +es sei denn, eine Hintergrundfarbe wurde festgelegt.
 +Einzelne Bildpunkte können als ''pixel(x,y)'' abgefragt 
 +und auf eine neue Farbe gesetzt werden.
 +Der Zugriff auf Punkte außerhalb des Bildes bleibt folgenlos.
 +
 +<code cpp image.h>
 +//: image.h : Grafik-Bibliothek ohne Grafiktreiber - R.Richter 2011-01-15
 +/////////////////////////////////////////////////////////////////////////
 +
 +#ifndef IMAGE_H
 +#define IMAGE_H
 +
 +#include <algorithm>
 +#include <vector>
 +#include "color.h"
 +
 +class Image
 +{
 +public:
 +  Image(unsigned int width, unsigned int height, Color background = 0)
 +  : width_(width), height_(height), pixels_(width * height, background)
 +  {
 +  }
 +
 +  unsigned int width()  const { return width_;  }
 +  unsigned int height() const { return height_; }
 +
 +  Color& pixel(unsigned int x, unsigned int y) 
 +  {
 +    return x>=width() || y>=height() ? outside() : pixels_[y*width() + x];
 +  }
 +  
 +  Color const& pixel(unsigned int x, unsigned int y) const 
 +  {
 +    return x>=width() || y>=height() ? outside() : pixels_[y*width() + x];
 +  }
 +private:
 +  unsigned int width_, height_;
 +  std::vector<Color> pixels_; // width_ x height_ pixels
 +
 +  static Color& outside() { static Color c; return c = Color::NONE; }
 +};
 +
 +// ===[ Speichern als BMP 24bit unkomprimiert, ohne Transparenz ]===========
 +
 +#include <fstream>
 +#include <iostream>
 +#include <iomanip>
 +#include <string>
 +
 +// Achtung, nicht portabel: Intel Byte-order vorausgesetzt
 +
 +inline  // a bit too long for ...
 +void saveBMP(std::string filename, Image const& image)
 +{
 +  unsigned long const linesize  = 3*image.width();  // 24 bit per pixel
 +  unsigned long const fillbytes = (4-linesize%4)%4; // at end of line to quad boundary
 +  unsigned long Image constsize = (linesize+fillbytes)*image.height();
 +
 +  // byte alignment, no padding
 +  // #if defined( _MSC_VER ) || defined( __MINGW32__ )
 +  #pragma pack(1)
 +  // #endif
 +  struct BMPheader
 +  {
 +    // file info
 +    char ID[2];
 +    unsigned long filesize, reserved, offset;
 +
 +    // BMP info
 +    unsigned long  infosize, width, height;
 +    unsigned short planes, bitsperpixel;
 +    unsigned long  compression, imagesize,
 +                   xPixelPerMeter, yPixelPerMeter,
 +                   colorsUsed, colorsImportant;
 +  } header =
 +  { 
 +    // file info
 +    { 'B', 'M' },
 +    unsigned(sizeof(header)) + imagesize, // 24 bits per pixel
 +    0, sizeof(header),          // 0x36
 +
 +    // BMP info
 +    40, image.width(), image.height(),
 +    1, 24,
 +    0, imagesize,
 +    1000, 1000,
 +    0, 0
 +  };
 +  // #if defined( _MSC_VER ) || defined( __MINGW32__ )
 +  #pragma pack()
 +  // #endif
 +
 +  std::ofstream file(filename.c_str(), std::ios::out|std::ios::binary);
 +  file.write( (char*)&header, sizeof(header)); // Intel byte order
 +
 +  for (unsigned y = 0; y < image.height(); ++y)
 +  {
 +    for (unsigned x = 0; x < image.width(); ++x)
 +    {
 +      Color c= image.pixel(x,y);
 +      unsigned char b = c.blue(), g = c.green(), r = c.red();
 +      file.write( (char*) &b, 1);
 +      file.write( (char*) &g, 1);
 +      file.write( (char*) &r, 1);
 +    }
 +    if (fillbytes)
 +    {
 +      int zero = 0;
 +      file.write( (char*) &zero, fillbytes);
 +    }
 +  }
 +}
 +
 +#endif // IMAGE_H
 +//~
 +</code>
 +
 +
 +
 +===== Dateiformat =====
 +Das BMP-Format wurde hier gewählt, weil es 
 +einen relativ einfachen Aufbau hat (ohne Kompression) und
 +24-Bit-Farben erlaubt. Jedoch geht die Transparenz-Infornation verloren.
 +Für das PNG-Format (mit Transparenz) gibt es einen 
 +[[http://members.gamedev.net/lode/projects/LodePNG/|quelloffenen Code]],
 +welcher die Bytefolge ABGR statt  
 +der in SDL, HTML und hier verwendeten Folge (A)RGB benutzt.
 +Andere Dateiformate (Targa, GIF, JPEG, ...)
 +sind weitergehende Übungsaufgaben. Quellen: Günter Born, Dateiformate.
 +
 +
 +
 +
 +===== Testprogramm =====
 +Das Hauptprogramm zeigt, wie einfach der Umgang mit Bildern ist.
 +Der Inhalt eines Bildes kann als Zahlenkolonne (plain text)
 +oder als Bitmap-Datei gespeichert werden:
 +
 +<code cpp grafik.cpp>
 +//: grafik.cpp : Grafik-Bibliothek ohne Grafiktreiber - R.Richter 2011-01-15
 +////////////////////////////////////////////////////////////////////////////
 +
 +#include <fstream>
 +#include <iostream>
 +#include <iomanip>
 +#include "image.h"
 +
 +void print(std::ostream& out, Image const& image)
 +{
 +  out << "\n\nRGB-Alpha-Bild "
 +      << image.width() << " x " << image.height() << '\n';
 +
 +  for (unsigned y = 0; y < image.height(); ++y)
 +  {
 +    for (unsigned x = 0; x < image.width(); ++x)
 +    {
 +      out << std::setw(9) << std::hex << image.pixel(x,y);
 +    }
 +    out << '\n';
 +  }
 +}
 +
 +int main()
 +{
 +  Color c(255, 0, 0, 127); // red, 50% transparency
 +  Image image(100, 75);
 +
 +  for (unsigned x = 0; x < image.height(); ++x)
 +  {
 +    image.pixel(x, x) = c;                             // rising line
 +    image.pixel(x, image.height()/ ) = Color::BLUE;  // mid horizon line
 +    image.pixel(x, image.height()-1-x) = Color::GREEN; // falling line
 +  }
 +  image.pixel(-1, 1) = Color::WHITE; // outside ignored, doesn't crash!
 +
 +  std::ofstream file("image.dat");
 +  print(file, image);
 +  saveBMP("image24.bmp", image);
 +
 +  return 0;
 +}
 +//~
 +</code>
 +Das Testprogramm erzeugt eine Bilddatei mit
 +
 +
 +  * aufsteigender roter Linie
 +  * waagerechter blauer Linie und
 +  * fallender grüner Linie:
 +
 +{{anwenden:image24.png|}}
 +
 +Weitergehende Übungen führen in verschiedene Richtungen:
 +
 +
 +  * 2D-Grafik (Linien, Balken, Polygone, Kurven, Farbverläufe),
 +  * Bildbearbeitung (Überlagern, Ausschneiden, Bildeffekte),
 +  * 3D-Grafik (Projektion, Verdeckungsrechnung, Beleuchtungsgeometrie),
 +  * Simulation und Visualisierung (2D, 3D),
 +  * Bild-Datei-Konversion (Kompressionsalgorithmen).
 +Viel Spaß!
 +
  
anwenden/images.txt · Zuletzt geändert: 2020-07-26 17:20 von 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki