Mostra una matrice di colors in C

Il mio programma scrive sia un array di letture di colors come questo:

struct Image { size_t width; size_t height; struct Color *data; } struct Color { char r; char g; char b; } 

Come posso visualizzare una tale matrice sullo schermo in C?

Rendering grafico:

Sono abituato agli ambienti Win32 e Borland C ++, quindi mi limito ad attenervisi, ma le differenze su altri ambienti sono per lo più solo nei nomi delle classi. Prima alcuni approcci:

  1. modalità console / testo

    puoi usare la grafica testuale ( arte ASCII penso in inglese). Dove il punto è rappresentato dal carattere . L’intensità è composta da caratteri più o meno riempiti. Di solito hanno una tabella di caratteri ordinata per intensità come " ..:+*#" e la usano al posto dei colors. Per stampare qualcosa può usare iostream come cout < < "text" << endl; o printf da stdio penso (non usando l'output della console vecchio stile per più di un decennio).

    Modalità testo videoram ( VRAM ) inizia da 0B000:0000 se hai i privilegi per questo puoi fare un accesso diretto come questo:

     char far *scr=(char far*)0x0B0000000; scr[0]='A'; // print A to left upper corner 

    ma su Windows puoi dimenticarti dell'accesso diretto

  2. Modalità gfx VGA

    su Windows puoi anche dimenticarti di questo ... Ecco un piccolo esempio:

      //============================================================================== char far* scr; // VGA screen const _sx= 320; // physical screen size const _sy= 200; //============================================================================== void gfxinit(); void cls(); void pnt(int x,int y,char c); //============================================================================== void gfxinit() { asm { mov ax,19 // this swith VGA to 320*200*256 color mode (fits inside single 64KB segment so no funny stuff is needed) int 16 } for (int i=0;i<256;i++) asm { // this overwrites 256 color palette with some BW gradients mov dx,0x3C8 mov ax,i out dx,al // overwrite color al = i inc dx shr al,2 // al=al>>2 out dx,al // r,g,b or b,g,r not sure now out dx,al // all values are 6bit long therefore the shr al,2 out dx,al } scr=(char far*)0xA0000000; // VRAM start address } //============================================================================== void cls() // this clear screen with zero { asm { push es mov ax,0xA000 mov es,ax mov di,0x0000 sub ax,ax mov cx,32000 rep stosw pop es } } //============================================================================== void pnt(int x,int y,char c) // this draw single point of color c { unsigned int adr; if (x<_sx ) if (x>=0) if (y<_sy ) if (y>=0) { y=y*_sx; adr=x+y; scr[adr]=c; } } //============================================================================== 

    L' accesso VESA è simile ma devi affrontare l'attraversamento di segmenti e il paging. Ecco un piccolo esempio di Turbo C ++:

    VESA.h

     //============================================================================== //=== Globals: ================================================================= //============================================================================== char far* scr=(char far*)0xA0000000; // VGA/VESA memory pointer int VESA_page,VESA_pages; // actaul page and total pages int VESA_xs,VESA_ys,VESA_bpp; // video mode properties int VESA_page_xy[64]={-1,-1}; // starting x,y for each page const int VESAmodes[]= // usable video modes table { 320, 200, 8,0x150, 640, 480, 8,0x101, 800, 600, 8,0x103, 1024, 768, 8,0x105, 1280,1024, 8,0x107, 320, 200,16,0x10E, 640, 480,16,0x111, 800, 600,16,0x114, 1024, 768,16,0x117, 320, 200,32,0x10F, 640, 480,32,0x112, 800, 600,32,0x115, 0,0,0,0 }; //============================================================================== //=== Headers: ================================================================= //============================================================================== int VESAmode(int xs,int ys,int bpp); // set video mode void VESApage(int page); // set page void VESAexit(); // return to VGA text mode void VESAcls(); // clear with 0 void VESApnt(int x,int y,unsigned int c); // render 8/16 bpp point void VESApnt32(int x,int y,int r,int g ,int b); // render 32bpp point //============================================================================== //=== Graphic: ================================================================= //============================================================================== int VESAmode(int xs,int ys,int bpp) { int i,mode,x,y; unsigned int adr0,adr,dx,dy; // find video mode for (i=0;VESAmodes[i];i+=4) if (VESAmodes[i+0]==xs) if (VESAmodes[i+1]==ys) if (VESAmodes[i+2]==bpp) break; if (!VESAmodes[i]) return 0; mode=VESAmodes[i+3]; VESA_xs=xs; VESA_ys=ys; VESA_bpp=bpp; // compute start x,y for each page>0 dx=bpp>>3; dy=xs*dx; VESA_pages=1; for (adr=i=x=y=0;yadr) { while (adr>0) { adr-=dx; x--; } while (x<0) { x+=VESA_xs; y--; } VESA_page_xy[i]=x; i++; VESA_page_xy[i]=y+1; i++; VESA_pages++; } } VESA_page_xy[i]=-1; i++; VESA_page_xy[i]=-1; i++; // set vide mode asm { mov bx,mode mov ax,0x4F02 int 16 } VESApage(0); /* // set palette to grayscale if (VESAbpp==8) for (int i=0;i<256;i++) asm { mov dx,0x3C8 mov ax,i out dx,al inc dx shr al,2 out dx,al out dx,al out dx,al } */ return 1; } //============================================================================== void VESApage(int page) { int p=page; asm { mov dx,p mov bx,0 mov ax,0x4f05 int 16 } VESA_page=page; } //============================================================================== void VESAexit() { asm { // waut for key press mov ax,0 int 0x16 // VGA 80x25 text mode mov ax,3 int 16 } } //============================================================================== void VESAcls() { int i; for (i=0;i=0)&&(x=0)&&(y>3); // page for (p=0;VESA_page_xy[p+p+0]>=0;p++) { if (VESA_page_xy[p+p+1]>y) break; if (VESA_page_xy[p+p+1]x) break; } if (p!=VESA_page) VESApage(p); // render scr[adr]=c; if (VESA_bpp==16) { adr++; if (adr==0) VESApage(p+1); scr[adr]=(c>>8); } } } //============================================================================== void VESApnt32(int x,int y,int r,int g ,int b) { unsigned int adr; int p; // inside screen? if ((x>=0)&&(x=0)&&(y>3); // page for (p=0;VESA_page_xy[p+p+0]>=0;p++) { if (VESA_page_xy[p+p+1]>y) break; if (VESA_page_xy[p+p+1]x) break; } if (p!=VESA_page) VESApage(p); // render scr[adr]=b; adr++; if (adr==0) VESApage(p+1); scr[adr]=g; adr++; if (adr==0) VESApage(p+1); scr[adr]=r; } } //============================================================================== //=== End. ===================================================================== //============================================================================== 

    main.cpp

     //============================================================================== //=== Includes: ================================================================ //============================================================================== #include "vesa.h" //============================================================================== //=== Main: ==================================================================== //============================================================================== void main() { if (!VESAmode(800,600,32)) return; VESAcls(); int x,y; unsigned int c; for (y=0;y 
  3. GDI

    Canvas è un sottocomponente grafico di componenti visivi su Windows. In borland è la class TCanvas denominata Canvas . Tutte le windows ha anche PaintBoxes,Bitmaps,... È l'interfaccia GDI tra Windows e la tua app. Ha sottocomponenti come Pen,Brush,Font per linee, riempimenti o carta di testo, inchiostro per i testi.

     Form1->Canvas->Pen->Color=clYellow; Form1->Canvas->MoveTo(10,10); Form1->Canvas->LineTo(100,150); 

    dove Form1 è la mia finestra VCL questo codice disegna una linea gialla.

    GDI ha molte funzioni come Arc,Ellipse,Pixels[][],... vedi build in help del tuo IDE per maggiori informazioni.

  4. Bitmap GDI

    questo è un object speciale è una bitmap con l'handle grafico OS (contesto dispositivo DC ). Ciò consente alla bitmap di essere qualcosa di simile a una finestra e di accedere a GDI

     Graphics::TBitmap *bmp=new Graphics::TBitmap; bmp->Width=100; bmp->Height=100; bmp->HandleType=bmDIB; // allows use of ScanLine bmp->PixelFormat=pf32bit; // 32bit the same as int so we can use int* for pixels pointer 

    questo crea un bitmap VCL e lo imposta su 100x100x32bit con accesso diretto. Ora è ansible accedere ScanLine proprietà ScanLine . Anche bmp->Canvas è presente così puoi fare anche tutte le cose GDI .

     int *p=bmp->ScanLine[10]; // p = pointer to y=10 line of bitmap p[20]=0; // draw dot on x=20,y=10 color=0x00000000 which is black int c = p[15]; // read pixel x=15,y=10 from bitmap to c 

    Fai attenzione a rimanere con x,y all'interno della bitmap o verrà lanciata un'eccezione. La codifica dei colors dipende da pixelformat genere è 0x00RRGGBB o 0x00BBGGRR . Penso che questo approccio sia l'opzione migliore anche per te, puoi disegnare qualsiasi object GDI su qualsiasi altro object GDI

     Form1->Canvas->Draw(0,0,bmp); 

    questo disegna la tua bitmap alla finestra in modo che tu possa vederla realmente.

  5. Libreria grafica

    Ce ne sono molti ma i più usati sono OpenGL e DirectX . Preferisco OpenGL perché è più semplice da implementare (almeno per i principianti) e anche OpenGL è multipiattaforma e DirectX è solo Windows. Inoltre, quando ho iniziato a scrivere codice, non c'era DirecX . Quando ho iniziato a utilizzare OpenGL, tutti i fornitori lo hanno nei driver inclusi. Ora gli unici fornitori che sono ancora aggiornati sono nVidia e ATI (AMD) . C'è quasi sempre qualche problema di driver tra di loro, ma in generale nVidia è migliore per OpenGL (ha dei bug nell'implementazione di DirectX) e ATI (solo versioni di AMD) è meglio per DirectX (ha dei bug nell'implementazione di OpenGL ). Ma per le operazioni di base sei a posto (i problemi arrivano con funzioni più avanzate)

    Venditori come Intel, SiS , ... hanno interrotto le loro implementazioni su versioni OpenGL più recenti almeno non conosco alcun driver migliore di OpenGL 3.3 per loro

    Per iniziare con OpenGL vedere OpenGL ottenere Device Context

Consiglio vivamente di iniziare prima con GDI + Bitmap. puoi fare molto con loro lo sto ancora usando per rendering non complessi.

Come accennato prima, sono borland (stile VCL ) amichevole, quindi se usi un compilatore / IDE diverso, modifica i nomi degli oggetti GDI in modo che corrispondano al tuo ambiente. Penso che Canvas sia lo stesso e bitmap sia HBitmap ma è meglio controllare il tuo aiuto / documentazione almeno sai cosa cercare.

Spero che aiuti un po '.

[Modifica1] altre piattaforms

  • semplice gfx in linux qui: X11 / Xlib.h esempio