Programowanie w systemie UNIX/c grafika

Z Wikibooks, biblioteki wolnych podręczników.
Przejdź do nawigacji Przejdź do wyszukiwania
Grafika w Linuksie

Tworzenie plików graficznych[edytuj]

Bezpośrednie tworzenie plików graficznych[edytuj]

z użyciem basha[edytuj]

./a.out >h.pgm

Z poziomu c[edytuj]

Przykład użycia tej techniki, sekwencyjny dostęp do danych (kod źródłowy)
Przykład użycia tej techniki, swobodny dostęp do danych (kod źródłowy)

Najprostszym przykładem rastrowego pliku graficznego jest plik PPM. Poniższy program pokazuje jak utworzyć plik w katalogu roboczym programu. Do zapisu:[1]

  • nagłówka pliku używana jest funkcja fprintf, która zapisuje do plików binarnych lub tekstowych
  • tablicy do pliku używana jest funkcja fwrite, która zapisuje do plików binarnych,
 #include <stdio.h>
 int main() {
        const int dimx = 800; 
        const int dimy = 800;
        int i, j;
        FILE * fp = fopen("first.ppm", "wb"); /* b - tryb binarny */
        fprintf(fp, "P6\n%d %d\n255\n", dimx, dimy);
        for(j=0; j<dimy; ++j){
          for(i=0; i<dimx; ++i){         
                        static unsigned char color[3];
                        color[0]=i % 255; /* red */
                        color[1]=j % 255; /* green */
                        color[2]=(i*j) % 255; /* blue */
                        fwrite(color,1,3,fp);
                }
        }
        fclose(fp);
        return 0;
 }

W powyższym przykładzie dostęp do danych jest sekwencyjny. Jeśli chcemy mieć swobodny dostęp do danych to:

  • korzystać z funkcji: fsetpos, fgetpos oraz fseek,
  • utworzyć tablicę (dla dużych plików dynamiczną), zapisać do niej wszystkie dane a następnie zapisać całą tablicę do pliku. Ten sposób jest prostszy i szybszy. Należy zwrócić uwagę, że do obliczania rozmiaru całej tablicy nie możemy użyć funkcji sizeof.


// save dynamic "A" array to pgm file 
int SaveArray_2_PPM_file (unsigned char A[], int k)
{

  FILE *fp;
  const unsigned int MaxColorComponentValue = 255;	/* color component is coded from 0 to 255 ;  it is 8 bit color file */
  
  char name [100]; /* name of file */
  snprintf(name, sizeof name, "%d", k); /*  */
  char *filename =strncat(name,".ppm", 4);
  
  
  
  char *comment = "# ";		/* comment should start with # */

  
  
  
  
  /* save image to the pgm file  */
  fp = fopen (filename, "wb");	/*create new file,give it a name and open it in binary mode  */
  fprintf (fp, "P6\n %s\n %u %u\n %u\n", comment, iWidth, iHeight, MaxColorComponentValue);	/*write header to the file */
  fwrite (A, MemmorySize, 1, fp);	/*write A array to the file in one step */
  printf ("File %s saved. \n", filename);
  fclose (fp);

  return 0;
}


Bardzo łatwo również utworzyć plik SVG[2]

/*  

c console program based on :
cpp code by Claudio Rocchini

http://commons.wikimedia.org/wiki/File:Poincare_halfplane_eptagonal_hb.svg


http://validator.w3.org/ 
The uploaded document "circle.svg" was successfully checked as SVG 1.1. 
This means that the resource in question identified itself as "SVG 1.1" 
and that we successfully performed a formal validation using an SGML, HTML5 and/or XML 
Parser(s) (depending on the markup language used). 

*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>



const double PI = 3.1415926535897932384626433832795;

const int  iXmax = 1000,
           iYmax = 1000,
           radius=100,
           cx=200,
           cy=200;
const char *black="#FFFFFF", /* hexadecimal number as a string for svg color*/
           *white="#000000";
           
 FILE * fp;

void draw_circle(FILE * FileP,int radius,int cx,int cy)
{
    fprintf(FileP,"<circle cx=\"%f\" cy=\"%f\" r=\"%f\" style=\"stroke:%s; stroke-width:2; fill:%s\"/>\n",
    cx,cy,radius,white,black);
}

void beginSVG(

int main(){
    FILE * fp;
    char *filename="circle.svg";
    fp = fopen(filename,"w");
	char *comment = "<!-- sample comment in SVG file  \n can be multi-line -->";

	fprintf(fp,
		    "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
		    "%s \n "
           "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \n"
           "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
           "<svg width=\"20cm\" height=\"20cm\" viewBox=\"0 0 %f %f \"\n"
           " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n",
           comment,iXmax,iYmax);


	draw_circle(fp,radius,cx,cy);
	

	
    
    
    fprintf(fp,"</svg>\n");
	fclose(fp);
	printf(" file %s saved \n",filename ); 
	getchar();
	return 0;
}

Biblioteki[edytuj]

liblot[edytuj]

Biblioteka libplot[3] służy do tworzenia grafiki 2D, zarówno wektorowej jak i rastrowej. Przykłady użycia w C: [4]

pgplot[edytuj]

Przykład [5]

#include "cpgplot.h"
#include "math.h"

int main()
{
   int i;
   float xs[9], ys[9];
   float xr[101], yr[101];

   /* Compute numbers to be plotted. */

   for (i=0; i<101; i++) {
     xr[i] = 0.1*i;
     yr[i] = xr[i]*xr[i]*exp(-xr[i]);
   }
   for (i=0; i<9; i++) {
     xs[i] = i+1;
     ys[i] = xs[i]*xs[i]*exp(-xs[i]);
   }

   /* Open graphics device. */

   if (cpgopen("?") < 1)
     return 1;

   /* Define coordinate range of graph (0 < x < 10, 0 < y < 0.65),
      and draw axes. */

   cpgenv(0., 10., 0., 0.65, 0, 0);
   
   /* Label the axes (note use of \\u and \\d for raising exponent). */
   
   cpglab("x", "y", "PGPLOT Graph: y = x\\u2\\dexp(-x)");

   /*  Plot the line graph. */
    
   cpgline(101, xr, yr);

   /* Plot symbols at selected points. */

   cpgpt(9, xs, ys, 18);

   /* Close the graphics device */

   cpgclos();
   return 0;
}

Zewnętrzne programy[edytuj]

Gnuplot[edytuj]

Gnuplot

Potok[edytuj]

#!/bin/bash

# http://mathr.co.uk/blog/
creal=0.258385930
cimag=0.00148483651
rot=34
den=$(echo "2^${rot}-1" | bc)
for i in $(seq 0 $((rot-1)))
do
  num=$(echo "2^${i}" | bc)
  ./julia-exray "${creal}" "${cimag}" "${num}/${den}"
  echo
  echo
done > "${rot}.txt"
gnuplot <<EOF
set terminal png size 1024,1024
set output "${rot}.png"
plot [-0.2:1] [-0.2:1] "${rot}.txt" using 1:2:(column(-2)%8) with lines lc variable title "quadratic Julia set external rays at 2^k/(2^${rot}-1) for c = ${creal} + ${cimag} i"
EOF

Plik z danymi[edytuj]

Przygotowanie pliku z danymi[edytuj]

Ten program tworzy w swoim katalogu roboczym plik tekstowy data.txt zawierający dane w formacie, który akceptuje gnuplot. Zawiera nagłówek poprzedzony znakiem "#", który przy rysowaniu jest ignorowany, oraz 2 kolumny liczb rozdzielone spacjami.

#include <stdio.h>
#include <stdlib.h>
int main(void) {
  int i;
  double x,y;
  char *output_filename="data.txt";
  FILE *output_file;
  output_file = fopen(output_filename, "w");  
  if (output_file  == NULL) {
    fprintf(stderr, "Nie moge otworzyc %s\n", output_filename);
    getchar();
    return 1;

  } else {
    /* nagłówek */
    fprintf(output_file,"%s %s      %s \n","#","x","y");
    y = 0.005;
    x = 0.0;
    /* 2 kolumny liczb rozdzielone spacjami */
    fprintf(output_file,"% 6.2f % 6.2f \n",x,y);
    for(i=0;i<5;++i) {
      x += y;
      /* 2 kolumny liczb rozdzielone spacjami */
      fprintf(output_file,"% 6.2f % 6.2f \n",x,y);
    }; /* for(i */
  }; /* if ((output_file ... else */
  fclose(output_file);

  fprintf(stderr,"file saved");
  getchar();
  
  
  return 0;
}

Zawartość pliku wygląda następująco:

# x      y 
 0.00   0.01 
 0.01   0.01 
 0.01   0.01 
 0.01   0.01 
 0.02   0.01 
 0.03   0.01
Rysowanie danych z pliku[edytuj]
Przykładowy wykres zawierający dane z pliku oraz wykresy dwóch funkcji

Uruchom gnuplot:

gnuplot

i w linii komend wprowadź polecenie:

plot "data.txt" 

W cudzysłowie jest nazwa pliku, może być poprzedzona ścieżką.

Plotutils[edytuj]

Pakiet Plotutils [6][7][8] korzysta z biblioteki libplot.

Obrazy utworzone z użyciem plotutils )( kod na stronie):

Przygotowanie plików z danymi[edytuj]

int SaveFiles(double A[Length][2], int p)
{

  int p;
  int i;
  char name [30]; /* name of the file */
  char *filename;
  FILE * fp;

 // save ray from A array to the text file
 sprintf(name,"Ray%d", p); /* create name from number */
 filename =strcat(name,".dat");
 fp= fopen(filename,"wb"); /*create new file,give it a name and open it in binary mode  */
 fprintf(fp ,"%s %s      %s \n","#","x","y");
 for (i=0; i<Length ; ++i) fprintf(fp ,"% 1.12f % 1.12f \n",A[i][0],A[i][1]);
 fclose(fp);
 printf("file %s  saved \n", filename);
  
 return 0;
}


bezpieczniej :

char name [100]; /* name of file */
  snprintf(name, sizeof name, "%d", k); /*  */
  char *filename =strncat(name,".ppm", 4);

Tworzenie grafiki[edytuj]

Wykonanie jednego rysunku z jednego pliku:

graph -T svg < inter.dat > inter.svg

Wykonanie jednego rysunku (do pliku all.png) z kilku plików z rozszerzeniem dat:

 graph -T png *.dat> all.png

lub poprzez podanie nazw:

graph -T png Ray0.dat Ray1.dat Ray2.dat Ray3.dat > all.png

Standardowo każdy zbiór danych jest rysowany w innym stylu (ang. line mode), np. pierwszy w stylu nr 1, drugi w stylu nr 2 itd. Jeśli chcemy to wyłączyć to użyjemy opcji B (--toggle-auto-bump) wyłączającej autoinkrementację:

graph -T png -B -m 1 *.dat> all.png

GPU[edytuj]

OpenGl[edytuj]

OpenGL

Cg[edytuj]

Cg czyli C dla grafiki


Główny program dla CPU jest napisany w C. Ten program otwiera i uruchamia program w Cg (dla GPU).[12][13]


Potrzebne oprogramowanie:

  • edytor tekstu
  • Cg Toolkit
    • kompilator Cg (cgc.exe)
    • Cg/CgFX biblioteki dla graficznego API (OpenGL lub Direct X)
  • kompilator C, np. gcc

Etapy:

  • Cg / GPU
    • utworzenie kodu Cg w postaci osobnego pliku , np. Fragment.cg
    • prekompilacja kodu Cg do assemblera specyficznego dla danego GPU i sterownika
  • C / CPU
    • utworzenie programu C w postaci osobnego pliku, np. main.c
      • dołączenie bibliotek Cg [13]
      • wczytanie podprogramu napisanego w Cg [14]
    • skompilowanie programu
    • uruchomienie programu

Biblioteki Cg dołączamy poprzez umieszczenie w programie napisanym w C następującego kodu:

#include <cg\cg.h> // Cg Header
#include <cg\cggl.h> // Cg OpenGL Specific Header

GUI[edytuj]

Gtk[edytuj]

Podręcznik Gtk+

Przykładowy kod w języku C wyświetlający puste okienko:

#include <gtk/gtk.h>

int main(int argc, char* argv[])
{
  GtkWidget* window;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "GTK+");
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

  gtk_widget_show(window);

  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

  gtk_main();

  return 0;
}

Qt[edytuj]

Qt

#include <QtGui>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QLabel label("Hello, world!");
    label.show();
    return app.exec();
}

Opis kompilacji

Glut[edytuj]

Glut. Przykład: [19]

#include<GL/glut.h> 

void main(int argc, char**argv) { 
    glutInit(&argc, argv); 
    glutInitWindowPosition(100,100); 
    glutInitWindowSize(500,500); 
    glutCreateWindow(“Hello World”); 
    glutMainLoop(); 
}

Odnośniki[edytuj]

  1. PBMPAK is a collection of C routines for creating and reading Portable Bit Map files (PBM).
  2. Tworzenie pliku SVG - Claudio Rocchini
  3. libplot, a 2-D Vector Graphics Library
  4. Programowanie w c z użyciem biblioteki libplot
  5. PGPLOT Examples
  6. Pakiet Plotutils
  7. Fossies Dox: plotutils-2.6.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)
  8. Popularity contest statistics for plotutils
  9. Using GNU plotutils for your assignments by Luke Hutchison
  10. Plot coordinate pairs - rosettacode
  11. GSL example program
  12. Cg Bumpmapping by Razvan Surdulescu at GameDev
  13. 13,0 13,1 Lesson: 47 from NeHe Productions
  14. Cg & HLSL Shading Language FAQ by Fusion Industries
  15. cgui - a library for making graphical user interfaces (GUI) by Christer Sandberg
  16. 2D Graphics Using C in Linux by Anthoniraj Amalan
  17. Graphics.h in Linux for c/c++ 02/29/2012 ~ Mandeep Simak
  18. IUP is a multi-platform toolkit for building graphical user interfaces. It offers a simple API in three basic languages: C, Lua and LED.
  19. Graphics Programming in Linux