📄 rpng-win.c.orig
字号:
/* if the user didn't specify a background color on the command line, * check for one in the PNG file--if not, the initialized values of 0 * (black) will be used */ if (have_bg) sscanf(bgstr+1, "%2x%2x%2x", &bg_red, &bg_green, &bg_blue); else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) { readpng_cleanup(TRUE); fprintf(stderr, PROGNAME ": libpng error while checking for background color\n"); exit(2); } /* do the basic Windows initialization stuff, make the window and fill it * with the background color */ if (rpng_win_create_window(hInst, showmode)) exit(2); /* decode the image, all at once */ Trace((stderr, "calling readpng_get_image()\n")) image_data = readpng_get_image(display_exponent, &image_channels, &image_rowbytes); Trace((stderr, "done with readpng_get_image()\n")) /* done with PNG file, so clean up to minimize memory usage (but do NOT * nuke image_data!) */ readpng_cleanup(FALSE); fclose(infile); if (!image_data) { fprintf(stderr, PROGNAME ": unable to decode PNG image\n"); exit(3); } /* display image (composite with background if requested) */ Trace((stderr, "calling rpng_win_display_image()\n")) if (rpng_win_display_image()) { free(image_data); exit(4); } Trace((stderr, "done with rpng_win_display_image()\n")) /* wait for the user to tell us when to quit */ printf( "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"); fflush(stdout); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } /* OK, we're done: clean up all image and Windows resources and go away */ rpng_win_cleanup(); return msg.wParam;}static int rpng_win_create_window(HINSTANCE hInst, int showmode){ uch *dest; int extra_width, extra_height; ulg i, j; WNDCLASSEX wndclass;/*--------------------------------------------------------------------------- Allocate memory for the display-specific version of the image (round up to multiple of 4 for Windows DIB). ---------------------------------------------------------------------------*/ wimage_rowbytes = ((3*image_width + 3L) >> 2) << 2; if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) + wimage_rowbytes*image_height))) { return 4; /* fail */ }/*--------------------------------------------------------------------------- Initialize the DIB. Negative height means to use top-down BMP ordering (must be uncompressed, but that's what we want). Bit count of 1, 4 or 8 implies a colormap of RGBX quads, but 24-bit BMPs just use B,G,R values directly => wimage_data begins immediately after BMP header. ---------------------------------------------------------------------------*/ memset(dib, 0, sizeof(BITMAPINFOHEADER)); bmih = (BITMAPINFOHEADER *)dib; bmih->biSize = sizeof(BITMAPINFOHEADER); bmih->biWidth = image_width; bmih->biHeight = -((long)image_height); bmih->biPlanes = 1; bmih->biBitCount = 24; bmih->biCompression = 0; wimage_data = dib + sizeof(BITMAPINFOHEADER);/*--------------------------------------------------------------------------- Fill in background color (black by default); data are in BGR order. ---------------------------------------------------------------------------*/ for (j = 0; j < image_height; ++j) { dest = wimage_data + j*wimage_rowbytes; for (i = image_width; i > 0; --i) { *dest++ = bg_blue; *dest++ = bg_green; *dest++ = bg_red; } }/*--------------------------------------------------------------------------- Set the window parameters. ---------------------------------------------------------------------------*/ memset(&wndclass, 0, sizeof(wndclass)); wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = rpng_win_wndproc; wndclass.hInstance = hInst; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = progname; wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&wndclass);/*--------------------------------------------------------------------------- Finally, create the window. ---------------------------------------------------------------------------*/ extra_width = 2*(GetSystemMetrics(SM_CXBORDER) + GetSystemMetrics(SM_CXDLGFRAME)); extra_height = 2*(GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYDLGFRAME)) + GetSystemMetrics(SM_CYCAPTION); global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, image_width+extra_width, image_height+extra_height, NULL, NULL, hInst, NULL); ShowWindow(global_hwnd, showmode); UpdateWindow(global_hwnd); return 0;} /* end function rpng_win_create_window() */static int rpng_win_display_image(){ uch *src, *dest; uch r, g, b, a; ulg i, row, lastrow; RECT rect; Trace((stderr, "beginning display loop (image_channels == %d)\n", image_channels)) Trace((stderr, "(width = %ld, rowbytes = %ld, wimage_rowbytes = %d)\n", image_width, image_rowbytes, wimage_rowbytes))/*--------------------------------------------------------------------------- Blast image data to buffer. This whole routine takes place before the message loop begins, so there's no real point in any pseudo-progressive display... ---------------------------------------------------------------------------*/ for (lastrow = row = 0; row < image_height; ++row) { src = image_data + row*image_rowbytes; dest = wimage_data + row*wimage_rowbytes; if (image_channels == 3) { for (i = image_width; i > 0; --i) { r = *src++; g = *src++; b = *src++; *dest++ = b; *dest++ = g; /* note reverse order */ *dest++ = r; } } else /* if (image_channels == 4) */ { for (i = image_width; i > 0; --i) { r = *src++; g = *src++; b = *src++; a = *src++; if (a == 255) { *dest++ = b; *dest++ = g; *dest++ = r; } else if (a == 0) { *dest++ = bg_blue; *dest++ = bg_green; *dest++ = bg_red; } else { /* this macro (copied from png.h) composites the * foreground and background values and puts the * result into the first argument; there are no * side effects with the first argument */ alpha_composite(*dest++, b, a, bg_blue); alpha_composite(*dest++, g, a, bg_green); alpha_composite(*dest++, r, a, bg_red); } } } /* display after every 16 lines */ if (((row+1) & 0xf) == 0) { rect.left = 0L; rect.top = (LONG)lastrow; rect.right = (LONG)image_width; /* possibly off by one? */ rect.bottom = (LONG)lastrow + 16L; /* possibly off by one? */ InvalidateRect(global_hwnd, &rect, FALSE); UpdateWindow(global_hwnd); /* similar to XFlush() */ lastrow = row + 1; } } Trace((stderr, "calling final image-flush routine\n")) if (lastrow < image_height) { rect.left = 0L; rect.top = (LONG)lastrow; rect.right = (LONG)image_width; /* possibly off by one? */ rect.bottom = (LONG)image_height; /* possibly off by one? */ InvalidateRect(global_hwnd, &rect, FALSE); UpdateWindow(global_hwnd); /* similar to XFlush() */ }/* last param determines whether or not background is wiped before paint InvalidateRect(global_hwnd, NULL, TRUE); UpdateWindow(global_hwnd); */ return 0;}static void rpng_win_cleanup(){ if (image_data) { free(image_data); image_data = NULL; } if (dib) { free(dib); dib = NULL; }}LRESULT CALLBACK rpng_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP){ HDC hdc; PAINTSTRUCT ps; int rc; switch (iMsg) { case WM_CREATE: /* one-time processing here, if any */ return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); /* dest */ rc = StretchDIBits(hdc, 0, 0, image_width, image_height, /* source */ 0, 0, image_width, image_height, wimage_data, (BITMAPINFO *)bmih, /* iUsage: no clue */ 0, SRCCOPY); EndPaint(hwnd, &ps); return 0; /* wait for the user to tell us when to quit */ case WM_CHAR: switch (wP) { /* only need one, so ignore repeat count */ case 'q': case 'Q': case 0x1B: /* Esc key */ PostQuitMessage(0); } return 0; case WM_LBUTTONDOWN: /* another way of quitting */ case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, iMsg, wP, lP);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -