una matriz matrices leer imprimir hacer funciones como caracteres cadenas cadena arreglo c image graphics bitmap

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:

  1. 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 usar iostream como cout << "text" << endl; o printf desde stdio , 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

  2. 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. ===================================================================== //==============================================================================

  3. GDI

    Canvas es un subcomponente gráfico de componentes visuales en Windows. En borland es la clase TCanvas llamada Canvas . Todas las ventanas lo tienen también PaintBoxes,Bitmaps,... Es la interfaz GDI entre Windows y su aplicación. Tiene subcomponentes como Pen,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.

  4. 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 propiedad ScanLine . También está presente bmp->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 del pixelformat de pixelformat generalmente es 0x00RRGGBB o 0x00BBGGRR . Creo que este enfoque es la mejor opción para ti; también puedes dibujar cualquier objeto GDI a cualquier otro objeto GDI

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

    esto dibuja su mapa de bits en la ventana para que pueda verlo en realidad.

  5. 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