matrices - Muestra una matriz de colores en C
matrices en c (1)
Mi programa escribe y lee arreglos de colores como este:
struct Image {
size_t width;
size_t height;
struct Color *data;
}
struct Color {
char r;
char g;
char b;
}
¿Cómo puedo mostrar esa matriz en la pantalla en C?
Representación gráfica:
Estoy acostumbrado a entornos win32 y Borland C ++, así que me apego a él, pero las diferencias en otros entornos son principalmente solo en nombres de clase. Primero algunos enfoques:
modos de consola / texto
puede usar gráficos de texto ( arte ASCII , creo en inglés). Donde el punto está representado por el carácter . La intensidad está compuesta por caracteres más o menos llenos. Usualmente tiene una tabla de caracteres ordenados por intensidad como
" ..:+*#"
y la usa en lugar de colores. Para imprimir algo se puede usariostream
comocout << "text" << endl;
oprintf
desdestdio
, creo (sin usar la salida de la consola de estilo antiguo durante más de una década).El videoramram de modos de texto ( VRAM ) comienza en
0B000:0000
si tiene los privilegios para ello puede hacer acceso directo de esta manera:char far *scr=(char far*)0x0B0000000; scr[0]=''A''; // print A to left upper corner
pero en Windows puedes olvidarte del acceso directo
Modo VGA gfx
en Windows también puedes olvidarte de esto ... Aquí pequeño ejemplo:
//============================================================================== 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; } } //==============================================================================
El acceso VESA es similar, pero debe lidiar con el cruce de segmentos y la paginación. Aquí pequeño ejemplo de 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;y<VESA_ys;y++) { adr0=adr; adr+=dy; if (adr0>adr) { 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<VESA_pages;i++) { VESApage(i); asm { push es mov ax,0xA000 mov es,ax mov di,0x0000 mov ax,0 mov cx,32000 rep stosw pop es } } } //============================================================================== void VESApnt(int x,int y,unsigned int c) { unsigned int adr; int p; // inside screen? if ((x>=0)&&(x<VESA_xs)) if ((y>=0)&&(y<VESA_ys)) { // low 16 bit of address adr=y; adr*=VESA_xs; adr+=x; adr*=(VESA_bpp>>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]<y) continue; if (VESA_page_xy[p+p+0]>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<VESA_xs)) if ((y>=0)&&(y<VESA_ys)) { // low 16 bit of address adr=y; adr*=VESA_xs; adr+=x; adr*=(VESA_bpp>>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]<y) continue; if (VESA_page_xy[p+p+0]>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<VESA_ys;y++) for (x=0;x<VESA_xs;x++) { if (VESA_bpp== 8) { c=x+y; VESApnt(x,y,c); } if (VESA_bpp==16) { c=(x&31)+((y&63)<<5); VESApnt(x,y,c); } if (VESA_bpp==32) VESApnt32(x,y,x,x+y,y); } VESAexit(); } //============================================================================== //=== End. ===================================================================== //==============================================================================
GDI
Canvas
es un subcomponente gráfico de componentes visuales en Windows. En borland es la claseTCanvas
llamadaCanvas
. Todas las ventanas lo tienen tambiénPaintBoxes,Bitmaps,...
Es la interfaz GDI entre Windows y su aplicación. Tiene subcomponentes comoPen,Brush,Font
para líneas, rellenos o papel de texto, textos de tinta.Form1->Canvas->Pen->Color=clYellow; Form1->Canvas->MoveTo(10,10); Form1->Canvas->LineTo(100,150);
donde
Form1
es mi ventana VCL , este código dibuja una línea amarilla.GDI tiene muchas funciones como
Arc,Ellipse,Pixels[][],...
ver build en ayuda de tu IDE para más información.Mapa de bits GDI
este es un objeto especial, es un mapa de bits con el controlador gráfico del sistema operativo (contexto del dispositivo DC ). Esto permite que el mapa de bits sea algo así como una ventana y tenga acceso 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
esto crea un mapa de bits VCL y lo establece en
100x100x32bit
con acceso directo. Ahora puede acceder a la propiedadScanLine
. También está presentebmp->Canvas
para que pueda hacer todas las cosas GDI también.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
Tenga cuidado de quedarse con
x,y
dentro del mapa de bits o se lanzará una excepción. La codificación de color depende delpixelformat
depixelformat
generalmente es0x00RRGGBB
o0x00BBGGRR
. Creo que este enfoque es la mejor opción para ti; también puedes dibujar cualquier objeto GDI a cualquier otro objeto GDIForm1->Canvas->Draw(0,0,bmp);
esto dibuja su mapa de bits en la ventana para que pueda verlo en realidad.
Biblioteca de gráficos
Hay muchos pero los más usados son OpenGL y DirectX . Prefiero OpenGL porque es más simple de implementar (al menos para los principiantes) y también OpenGL es multiplataforma y DirectX solo para Windows. Además, cuando comencé a codificar no había DirecX . Cuando comencé a usar OpenGL, todos los proveedores lo tienen incluido en los controladores. Ahora los únicos proveedores que todavía están actualizados son nVidia y ATI (AMD) . Casi siempre hay algún problema con el controlador entre ellos, pero en general, nVidia es mejor para OpenGL (tiene errores en la implementación de DirectX) y ATI (solo versiones de AMD) es mejor para DirectX (tiene errores en la implementación de OpenGL ). Pero para las operaciones básicas estás bien (los problemas se ponen en funciones más avanzadas)
Vendedores como Intel, SiS , ... han detenido sus implementaciones en versiones OpenGL más nuevas, al menos no conozco ningún controlador mejor que OpenGL 3.3 para ellos.
Para comenzar con OpenGL, consulte OpenGL get Device Context
Recomiendo comenzar primero con GDI + Bitmap. puedes hacer mucho con ellos, todavía lo estoy usando para renderizado no complejo.
Como mencioné antes, soy amigo de Borland (estilo VCL ), así que si usa un compilador / IDE diferente, cambie los nombres de los objetos GDI para que se correspondan con su entorno. Creo que Canvas es el mismo y el mapa de bits es HBitmap
pero es mejor que revise su ayuda / documentos, al menos que sepa qué buscar.
Espero que ayude un poco.
[Edit1] otras plataformas
- gfx simple en Linux aquí: X11 / Xlib.h ejemplo