C语言集锦(二) 图像显示 Windows和Linux
关于图像显示有很多库可以用,Windows下有GDI,GDI+,D3D等,Linux下有X Window和Wayland,此外还有OpenGL ,SDL等图形库以及各种GUI库。
了解最原始的方式,对于加深理解依然是有帮助的。下面给Windows和Linux下显示位图的最简单例子:
1.Windows用GDI显示图像的例子:
1 /* 2 * FileName: Image_Win.c 3 * Usage: tcc -luser32 -lgdi32 -run Image_Win.c 4 */ 5 6 #include <windows.h> 7 #include <stdlib.h> 8 // 9 typedef unsigned char byte; 10 11 typedef struct { 12 int Width; 13 int Height; 14 byte *Data; 15 } Image; 16 17 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l) 18 { 19 HDC hdc; 20 RECT rect; 21 Image img; 22 BITMAPINFO bmi; 23 PAINTSTRUCT ps; 24 int iRowLength; 25 // 26 ZeroMemory(&bmi, sizeof(BITMAPINFO)); 27 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 28 bmi.bmiHeader.biPlanes = 1; 29 bmi.bmiHeader.biBitCount = 24; 30 bmi.bmiHeader.biCompression = BI_RGB; 31 // 32 switch (msg) { 33 case WM_DESTROY: 34 PostQuitMessage(1); 35 break; 36 case WM_PAINT: 37 hdc = BeginPaint (hwnd, &ps) ; 38 GetClientRect(hwnd,&rect); 39 img.Width = rect.right - rect.left; 40 iRowLength = ((img.Width*8 * 3 + 31) & ~31) >> 3; 41 img.Height = rect.bottom - rect.top; 42 img.Data = (byte*)malloc(iRowLength*img.Height); 43 for(int i=0;i<iRowLength*img.Height;i++) 44 img.Data[i] = rand()%256; 45 bmi.bmiHeader.biWidth = img.Width; 46 bmi.bmiHeader.biHeight = img.Height; 47 SetDIBitsToDevice(hdc, 0, 0, img.Width, img.Height, 48 0, 0, 0, img.Height, img.Data, &bmi, DIB_RGB_COLORS); 49 break; 50 default: 51 return DefWindowProc(hwnd, msg, w, l); 52 } 53 return 0; 54 } 55 56 int main(int argc, char* argv[]) 57 { 58 static TCHAR szAppName[] = TEXT("RandColor"); 59 HWND hwnd; 60 MSG msg; 61 WNDCLASS wndclass; 62 int iCmdShow = 1; 63 HINSTANCE hInstance = NULL; 64 // 65 wndclass.style = CS_HREDRAW | CS_VREDRAW; 66 wndclass.lpfnWndProc = WndProc; 67 wndclass.cbClsExtra = 0; 68 wndclass.cbWndExtra = 0; 69 wndclass.hInstance = hInstance; 70 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 71 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); 72 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 73 wndclass.lpszMenuName = NULL; 74 wndclass.lpszClassName = szAppName; 75 if (!RegisterClass(&wndclass)) { 76 MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); 77 return 0; 78 } 79 hwnd = CreateWindow(szAppName, TEXT("Image"), WS_OVERLAPPEDWINDOW^WS_THICKFRAME, 80 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 81 NULL, NULL, hInstance, NULL); 82 //The message loop. 83 ShowWindow(hwnd, iCmdShow); 84 UpdateWindow(hwnd); 85 86 while (GetMessage(&msg, NULL, 0, 0)) { 87 TranslateMessage(&msg); 88 DispatchMessage(&msg); 89 } 90 return 0; 91 }
2.Linux下用X Window显示图像的例子:
1 /* 2 * FileName: Image_Linux.c 3 * Usage: tcc -lX11 -run Image_Linux.c 4 */ 5 #include <X11/Xlib.h> 6 #include <X11/Xutil.h> 7 8 #include <stdlib.h> 9 10 #define WIDTH 640 11 #define HEIGHT 480 12 13 int main(int argc, char **argv) 14 { 15 int win_b_color; 16 int win_w_color; 17 XEvent xev; 18 Window window; 19 Visual *visual; 20 XImage *ximage; 21 GC gc; 22 23 char*buffer=(char*)malloc(WIDTH*HEIGHT*4*sizeof(char)); 24 25 Display *display = XOpenDisplay(NULL); 26 win_b_color = BlackPixel(display, DefaultScreen(display)); 27 win_w_color = BlackPixel(display, DefaultScreen(display)); 28 window = XCreateSimpleWindow(display,DefaultRootWindow(display),0, 0, WIDTH, HEIGHT, 0,win_b_color, win_w_color); 29 visual = DefaultVisual(display, 0); 30 //XSelectInput(display, window, ExposureMask | KeyPressMask); 31 XMapWindow(display, window); 32 XFlush(display); 33 gc = XCreateGC(display, window, 0, NULL); 34 //XEvent event; 35 while (1) { 36 for (int i = 0; i < WIDTH*HEIGHT*4; i ++) 37 buffer[i] = rand()%256; 38 ximage=XCreateImage(display, visual, 24,ZPixmap, 0, buffer,WIDTH, HEIGHT, 32, 0); 39 XPutImage(display, window,gc, ximage, 0, 0, 0, 0,WIDTH, HEIGHT); 40 } 41 return 0; 42 }
下一次将介绍矢量图方面的知识,主要以EMF,SVG和PostScript进行说明。