Wie erstellt man einfache Grafiken?



  • @wob sagte in Wie erstellt man einfache Grafiken?:

    Einfach irgendwie einen Punkt auf den Bildschirm malen - das geht nicht - das verbietet dir i.d.R. das Betriebssystem.

    Auf alten Architekturen konnt man aber die Zeichen austauschen und so Pseudografik im Textmodus nutzen. So wurden in den 80ern einige Spiele programmiert. Keine Ahnung ob das heute nooch so einfach geht.



  • @Ein-Gast sagte in Wie erstellt man einfache Grafiken?:

    @Fragender ASCII-Graphiken wären etwas zu wenig, es sollten schon kleine Punkte sein, die man mit einer gewissen Genauigkeit positionieren und aneinanderreihen kann.

    Ja, ich habe die Frage falsch verstanden, sorry noch mal.


  • Mod

    @Tyrdal sagte in Wie erstellt man einfache Grafiken?:

    Auf alten Architekturen konnt man aber die Zeichen austauschen und so Pseudografik im Textmodus nutzen. So wurden in den 80ern einige Spiele programmiert. Keine Ahnung ob das heute nooch so einfach geht.

    Wenn du das einfach nennst...

    Moderne Grafikframeworks machen es einem vielleicht schwierig, einen einzelnen Pixel auf dem Schirm gezielt zu setzen, aber das ist so, weil man das für ernsthafte moderne Grafik gar nicht braucht. Wer das will, soll halt, wie erklärt, eine Bitmap malen. Dafür ist es mit dem modernen Framework 1000x einfacher hochkomplizierte Effekte zu erzielen, die man sich in der Zeit des Einzelpixelsetzens nicht einmal erträumen konnte.



  • @Tyrdal sagte in Wie erstellt man einfache Grafiken?:

    Auf alten Architekturen konnt man aber die Zeichen austauschen und so Pseudografik im Textmodus nutzen. So wurden in den 80ern einige Spiele programmiert. Keine Ahnung ob das heute nooch so einfach geht.

    Bei 80x25 Zeichen (im Textmodus) kann man 1000 Zeichen auf dem Schirm darstellen. Man hatte aber nur 256 (oder 128) verschiedene Zeichen zur Verfügung.

    Einfach ist das nicht.



  • @Ein-Gast sagte in Wie erstellt man einfache Grafiken?:

    Gibt es also nicht, ähnlich zu printf, so etwas wie eine Funktion, sagen wir "pix", die von zwei Variablen abhängt und wo z. B. pix(0.6,0.4) dazu führt, daß von der linken unteren Bildschirmecke um 60% der Breite nach rechts und 40% der Höhe nach oben gerückt und an der erreichten Position ein Punkt gezeichnet wird? Oder eine Funktion "pic", die als Variable ein Feld oder was weiß ich mit lauter Einträgen für Koordinaten und Farbwerte hat und diese auf den Bildschirm bringt?

    C selber kennt das nicht.

    Aber C-Compiler für MS-DOS (z.B. Quick-C oder Turbo-C) hatten Erweiterungen, womit man das machen konnte.

    Meist aber mit Absolutkoordinaten, da man Pixel zählen kann.

    Mit dem aufkommen von GUI und Fenstern, ist das aber ins Betriebssystem (oder dem Fenstermanager) gewandert.

    Evtl. wirst du noch auf Mikrocontrollern mit einem grafischen LCD und entsprechender Bibliothek fündig.

    Was willst du letztendlich machen/darstellen.

    • Bilder (zb. von Phozoshop/Paint)
    • Grafiken (CAD, Inkscape)
    • Plots/Charts (wie in Excel)
    • Videos


  • @DirkB sagte in Wie erstellt man einfache Grafiken?:

    Was willst du letztendlich machen/darstellen.

    • Bilder (zb. von Phozoshop/Paint)
    • Grafiken (CAD, Inkscape)
    • Plots/Charts (wie in Excel)
    • Videos

    Z. B. Funktionsgraphen oder andere Muster, die sich ähnlich einfach beschreiben lassen. Vielleicht auch einfache aus so etwas gebildete Bewegtbilder, aber keine "richtigen" Fotos oder Videos.
    Das ganze sollte innerhalb von Programmen ohne graphische Benutzeroberfläche funktionieren, vielleicht z. B. in der Art, daß man mithilfe des anderswo erwähnten "ncurses" die Bildschirmanzeige unterteilt und in einem der Teile dann eine Grafik erzeugen kann.

    @wob sagte in Wie erstellt man einfache Grafiken?:

    Für C fällt mir z.B. https://www.gtk.org/ ein. Eine andere Grafikbibliothek für C ist https://www.libsdl.org/ ein (aber ich habe außer mit Qt keine Erfahrungen!)

    Auf den ersten Blick sieht das alles so aus, als sei es für das Erstellen grafischer Benutzeroberflächen und Arbeiten innerhalb solcher gedacht. Ist das so? Falls ja, was nimmt man, wenn keine grafische Benutzeroberfläche erzeugt werden soll?


  • Mod

    Mach es erst einmal als Text. Das wäre ungefähr die gleiche Vorgehensweise, und dann kannst du das später auf "richtige" Grafik hochskalieren. Dann kannst du nach Programmierung der Textausgabe einschätzen, ob du das Projekt überhaupt noch weiter führen möchtest.



  • @Ein-Gast: Grafiken in der Windows Konsole? Dann schau dir mal das C++ Projekt Table and Graph Libraries (bes. ab Graphs/Plots) an.

    Ein einfacheres, nur in C, gibt es unter ConsoleGraphics, auch direkt mit einer drawpixel-Funktion.



  • @Th69 Vielen Dank, aber "ConsoleGraphics" sieht doch auch eher nach C++ aus?

    Abgesehen davon funktioniert es bei mir auch nicht. Wie geht man mit in dieser Form servierten Dateien denn um? Ich habe die .h- und .cpp-Dateien in den Ordner auf meinem Rechner kopiert, wo auch z. B. stdio.h liegt, und dann das kurze Beispielprogramm mit dem dort genannten Befehl kompiliert. Fehlt da noch etwas? Daraufhin kamen nur Fehlermeldungen, als erstes z. B.

    c:\mingw\include\consolegraphics-main\PolyDraw.cpp:63:81: error: 'PCONSOLE_FONT_INFOEX' has not been declared

    Ach ja, auf die Frage nach dem Betriebssystem habe ich nie reagiert... Eigentlich wäre Windows und Linux von Interesse.



  • wir hatten im studium mal die aufgabe, ein einfaches windows-programm mit kommentaren zu versehen und dabei ist dann das hier rausgekommen. im prinzip musst du unter WM_PAINT einfach nur SetPixel (google -> setpixel) aufrufen und alles außer BeginPaint und EndPaint entfernen. der rest (funktionen im internet nachschlagen, programm zum laufen bringen usw) ist dann im selbststudium zu erledigen. unter linux kannst du sowas glaube ich mit den xlibs bzw. xcb machen, aber da habe ich mich nie mit beschäftigt. winapi ist heutzutage soweit ich weiß auch schon sehr speziell und auf der "freakliste" ziemlich weit oben angesiedelt, aber man kann damit toll C lernen.

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //Prototyp der Callback-Funktion
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
    	static TCHAR szAppName[] = TEXT("Aufgäbe 1"); //Name der Anwendung
    	HWND hwnd; //Handle aufs Fenster
    	MSG msg; //MSG Struktur
    	WNDCLASS wndclass; //Window Class Struktur, enthält die Window Class Attribute, die mit RegisterClass() registriert werden. Wurde durch WNDCLASSEX ersetzt und ist daher eigentlich veraltet.
    
    	wndclass.style = CS_HREDRAW | CS_VREDRAW; //Window Class Styles
    	wndclass.lpfnWndProc = WndProc; //Pointer auf die "Window-Prock"
    	wndclass.cbClsExtra = 0; //Anzahl der Extra-Bytes, die auf die Window Class folgend alloziiert werden sollen.
    	wndclass.cbWndExtra = 0; //Anzahl der Extra-Bytes, die auf die Window Instance folgend alloziiert werden sollen.
    	wndclass.hInstance = hInstance; //Handle auf die Instanz, die die Window-Prozedur für diese Window Class enthält.
    	wndclass.hIcon = LoadIcon(0, IDI_APPLICATION); //Handle auf das Class Icon, das in der Titelleiste und in der Taskleiste angezeigt werden soll
    	wndclass.hCursor = LoadCursor(0, IDC_HAND); //Handle auf den Cursor, aufgrund persönlicher Vorlieben des Programmierers ein Hand-Symbol 
    	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //Handle auf den Background Brush. Sorgt in diesem Fall für einen weißen Hintergrund.
    	wndclass.lpszMenuName = 0; //Festlegung eines Menüs. Hier kein Menü, daher 0
    	wndclass.lpszClassName = szAppName; //Name der Fensterklasse
    
    	
    
    	if (!RegisterClass(&wndclass)) //Registriert die Window Class für nachfolgende Aufrufe von CreateWindow. Wurde durch RegisterClassEx ersetzt und ist daher eigentlich veraltet.
    	{
    		MessageBox(0, TEXT("Fehler!"), szAppName, MB_ICONERROR); //Gibt eine Nachricht aus, falls der Aufruf von RegisterClass() fehlschlagen sollte
    		return 0;
    	}
    
    	hwnd = CreateWindow(szAppName, TEXT("Aufgabe 1"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, 0); //Erstellt das Fenster. Wurde durch CreateWindowEx ersetzt und ist daher eigentlich veraltet. Sendet WM_CREATE an die Window-Prock
    
    	ShowWindow(hwnd, iCmdShow); //Setzt den spezifizierten Anzeigestatus des Fensters
    	UpdateWindow(hwnd); //Aktualisiert die "client area" des Fensters, indem es eine WM_PAINT-Nachricht sendet.
    
    	while (GetMessage(&msg, 0, 0, 0)) //Ruft die nächste Nachricht ab
    	{
    		TranslateMessage(&msg); //Nachrichten, die von der Tastatur erzeugt wurden, umwandeln
    		DispatchMessage(&msg); //Nachrichten an die Window-Prock senden bzw. die Window-Prock aufrufen
    	}
    
    	return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	HDC hdc; //Handle für einen Gerätekontext ("device context")
    	PAINTSTRUCT ps; //Struktur für Zeichenoperationen
    	RECT rect; //Struktur, die einen rechteckigen Bereich beschreibt ("rectangle")
    
    	
    
    	switch (message) 
    	{
    	case WM_CREATE: //Wurde von CreateWindow() geschickt. Hier finden also weitere Initialisierungen statt.
    		return 0;
    	case WM_PAINT:  //Informiert ein Fenster darüber, dass der Inhalt teilweise oder komplett ungültig ist.
    		hdc = BeginPaint(hwnd, &ps); //Bereitet des Fenster auf die Zeichenoperationen vor und füllt die PAINTSTRUCT mit den nötigen Informationen
    
    		SetTextColor(hdc, 0x00FF00FF); //Ändert die Textfarbe in ein nettes Rosa. Scheint keinen ARGB-Wert zu akzeptieren, also ein gutes Beispiel dafür, dass 32 Bit Farbtiefe oft nur 24 Bit Farbtiefe sind.
    
    		GetClientRect(hwnd, &rect); //Kopiert die Dimensionen des Fensterinhalts in die RECT-Struktur. 
    
    		DrawText(hdc, TEXT("Hallo Welt!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); //Schreibt einen Text in das Fenster.
    
    		EndPaint(hwnd, &ps); //Beendet die Zeichenoperation.
    		return 0;
    	case WM_DESTROY: //Wird von Windows als Reaktion auf einen Klick das Schließen-Feld ("X"), die Tastenkombination Alt + F4 usw erzeugt. 
    		PostQuitMessage(0); //Fügt WM_QUIT in die Nachrichten-Warteschlange ein. Hiermit wird die Endlosschleife in der WinMain beendet.
    		return 0;
    	}
    
    	return DefWindowProc(hwnd, message, wParam, lParam); //Ruft die Default-Window-Prock auf, damit sich diese um die Nachrichten kümmern kann, die hier nicht bearbeitet werden.
    }
    

    PS: SetPixel ist saumäßig langsam, jedenfalls gegenüber opengl, aber es ist bestimmt mal ein anfang.



  • Also ich selbst hab vor kurzem folgendes gemacht:

    Hab mir ein canvas gebaut, wo ich locker flockig Pixel nach Farbe beschreiben kann

    Dann ein BMP writer geschrieben der das in ne .BMP Datei schmeißt. Das nutze ich für mein Raytracer später

    Vielleicht auch eine Idee für dich. Hier mein source Code für den BMP writer, ist ziemlich simple

    https://github.com/TheUnlimited64/the-raytracer-challenge/blob/master/src/filewriter/bmpWriter.c

    Und in c geschrieben


Anmelden zum Antworten