📄 rpng2-win.c
字号:
} if (!filename) { ++error; } else if (!(infile = fopen(filename, "rb"))) { fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename); ++error; } else { incount = fread(inbuf, 1, INBUFSIZE, infile); if (incount < 8 || !readpng2_check_sig(inbuf, 8)) { fprintf(stderr, PROGNAME ": [%s] is not a PNG file: incorrect signature\n", filename); ++error; } else if ((rc = readpng2_init(&rpng2_info)) != 0) { switch (rc) { case 2: fprintf(stderr, PROGNAME ": [%s] has bad IHDR (libpng longjmp)\n", filename); break; case 4: fprintf(stderr, PROGNAME ": insufficient memory\n"); break; default: fprintf(stderr, PROGNAME ": unknown readpng2_init() error\n"); break; } ++error; } if (error) fclose(infile); } /* usage screen */ if (error) { int ch; fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname); readpng2_version_info(); fprintf(stderr, "\n" "Usage: %s [-gamma exp] [-bgcolor bg | -bgpat pat] [-timing]\n"#if (defined(__i386__) || defined(_M_IX86)) " %*s [[-nommxfilters] [-nommxcombine] [-nommxinterlace] | -nommx]\n"#endif " %*s file.png\n\n" " exp \ttransfer-function exponent (``gamma'') of the display\n" "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" "\t\t to the product of the lookup-table exponent (varies)\n" "\t\t and the CRT exponent (usually 2.2); must be positive\n" " bg \tdesired background color in 7-character hex RGB format\n" "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" "\t\t used with transparent images; overrides -bgpat option\n" " pat \tdesired background pattern number (1-%d); used with\n" "\t\t transparent images; overrides -bgcolor option\n" " -timing\tenables delay for every block read, to simulate modem\n" "\t\t download of image (~36 Kbps)\n"#if (defined(__i386__) || defined(_M_IX86)) " -nommx*\tdisable optimized MMX routines for decoding row filters,\n" "\t\t combining rows, and expanding interlacing, respectively\n"#endif "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n" "Press Q or Esc to quit this usage screen. ", PROGNAME,#if (defined(__i386__) || defined(_M_IX86)) strlen(PROGNAME), " ",#endif strlen(PROGNAME), " ", default_display_exponent, num_bgpat); fflush(stderr); do ch = _getch(); while (ch != 'q' && ch != 'Q' && ch != 0x1B); exit(1); } else { fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); fprintf(stderr, "\n [console window: closing this window will terminate %s]\n\n", PROGNAME); fflush(stderr); } /* set the title-bar string, but make sure buffer doesn't overflow */ alen = strlen(appname); flen = strlen(filename); if (alen + flen + 3 > 1023) sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023)); else sprintf(titlebar, "%s: %s", appname, filename); /* set some final rpng2_info variables before entering main data loop */ if (have_bg) { unsigned r, g, b; /* this approach quiets compiler warnings */ sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b); rpng2_info.bg_red = (uch)r; rpng2_info.bg_green = (uch)g; rpng2_info.bg_blue = (uch)b; } else rpng2_info.need_bgcolor = TRUE; rpng2_info.done = FALSE; rpng2_info.mainprog_init = rpng2_win_init; rpng2_info.mainprog_display_row = rpng2_win_display_row; rpng2_info.mainprog_finish_display = rpng2_win_finish_display; /* OK, this is the fun part: call readpng2_decode_data() at the start of * the loop to deal with our first buffer of data (read in above to verify * that the file is a PNG image), then loop through the file and continue * calling the same routine to handle each chunk of data. It in turn * passes the data to libpng, which will invoke one or more of our call- * backs as decoded data become available. We optionally call Sleep() for * one second per iteration to simulate downloading the image via an analog * modem. */ for (;;) { Trace((stderr, "about to call readpng2_decode_data()\n")) if (readpng2_decode_data(&rpng2_info, inbuf, incount)) ++error; Trace((stderr, "done with readpng2_decode_data()\n")) if (error || feof(infile) || rpng2_info.done) break; if (timing) Sleep(1000L); incount = fread(inbuf, 1, INBUFSIZE, infile); } /* clean up PNG stuff and report any decoding errors */ fclose(infile); Trace((stderr, "about to call readpng2_cleanup()\n")) readpng2_cleanup(&rpng2_info); if (error) { fprintf(stderr, PROGNAME ": libpng error while decoding PNG image\n"); exit(3); } /* wait for the user to tell us when to quit */ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } /* we're done: clean up all image and Windows resources and go away */ Trace((stderr, "about to call rpng2_win_cleanup()\n")) rpng2_win_cleanup(); return msg.wParam;}/* this function is called by readpng2_info_callback() in readpng2.c, which * in turn is called by libpng after all of the pre-IDAT chunks have been * read and processed--i.e., we now have enough info to finish initializing */static void rpng2_win_init(){ ulg i; ulg rowbytes = rpng2_info.rowbytes; Trace((stderr, "beginning rpng2_win_init()\n")) Trace((stderr, " rowbytes = %ld\n", rpng2_info.rowbytes)) Trace((stderr, " width = %ld\n", rpng2_info.width)) Trace((stderr, " height = %ld\n", rpng2_info.height)) rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height); if (!rpng2_info.image_data) { readpng2_cleanup(&rpng2_info); return; } rpng2_info.row_pointers = (uch **)malloc(rpng2_info.height * sizeof(uch *)); if (!rpng2_info.row_pointers) { free(rpng2_info.image_data); rpng2_info.image_data = NULL; readpng2_cleanup(&rpng2_info); return; } for (i = 0; i < rpng2_info.height; ++i) rpng2_info.row_pointers[i] = rpng2_info.image_data + i*rowbytes;/*--------------------------------------------------------------------------- Do the basic Windows initialization stuff, make the window, and fill it with the user-specified, file-specified or default background color. ---------------------------------------------------------------------------*/ if (rpng2_win_create_window()) { readpng2_cleanup(&rpng2_info); return; }}static int rpng2_win_create_window(){ uch bg_red = rpng2_info.bg_red; uch bg_green = rpng2_info.bg_green; uch bg_blue = rpng2_info.bg_blue; uch *dest; int extra_width, extra_height; ulg i, j; WNDCLASSEX wndclass; RECT rect;/*--------------------------------------------------------------------------- Allocate memory for the display-specific version of the image (round up to multiple of 4 for Windows DIB). ---------------------------------------------------------------------------*/ wimage_rowbytes = ((3*rpng2_info.width + 3L) >> 2) << 2; if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) + wimage_rowbytes*rpng2_info.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 = rpng2_info.width; bmih->biHeight = -((long)rpng2_info.height); bmih->biPlanes = 1; bmih->biBitCount = 24; bmih->biCompression = 0; wimage_data = dib + sizeof(BITMAPINFOHEADER);/*--------------------------------------------------------------------------- Fill window with the specified background color (default is black), but defer loading faked "background image" until window is displayed (may be slow to compute). Data are in BGR order. ---------------------------------------------------------------------------*/ if (bg_image) { /* just fill with black for now */ memset(wimage_data, 0, wimage_rowbytes*rpng2_info.height); } else { for (j = 0; j < rpng2_info.height; ++j) { dest = wimage_data + j*wimage_rowbytes; for (i = rpng2_info.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 = rpng2_win_wndproc; wndclass.hInstance = global_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, rpng2_info.width+extra_width, rpng2_info.height+extra_height, NULL, NULL, global_hInst, NULL); ShowWindow(global_hwnd, global_showmode); UpdateWindow(global_hwnd);/*--------------------------------------------------------------------------- Now compute the background image and display it. If it fails (memory allocation), revert to a plain background color. ---------------------------------------------------------------------------*/ if (bg_image) { static const char *msg = "Computing background image..."; int x, y, len = strlen(msg); HDC hdc = GetDC(global_hwnd); TEXTMETRIC tm; GetTextMetrics(hdc, &tm); x = (rpng2_info.width - len*tm.tmAveCharWidth)/2; y = (rpng2_info.height - tm.tmHeight)/2; SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); /* this can still begin out of bounds even if x is positive (???): */ TextOut(hdc, ((x < 0)? 0 : x), ((y < 0)? 0 : y), msg, len); ReleaseDC(global_hwnd, hdc); rpng2_win_load_bg_image(); /* resets bg_image if fails */ } if (!bg_image) { for (j = 0; j < rpng2_info.height; ++j) { dest = wimage_data + j*wimage_rowbytes; for (i = rpng2_info.width; i > 0; --i) { *dest++ = bg_blue; *dest++ = bg_green; *dest++ = bg_red; } } } rect.left = 0L; rect.top = 0L; rect.right = (LONG)rpng2_info.width; /* possibly off by one? */ rect.bottom = (LONG)rpng2_info.height; /* possibly off by one? */ InvalidateRect(global_hwnd, &rect, FALSE); UpdateWindow(global_hwnd); /* similar to XFlush() */ return 0;} /* end function rpng2_win_create_window() */static int rpng2_win_load_bg_image(){ uch *src, *dest; uch r1, r2, g1, g2, b1, b2; uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv; int k, hmax, max; int xidx, yidx, yidx_max = (bgscale-1); int even_odd_vert, even_odd_horiz, even_odd; int invert_gradient2 = (bg[pat].type & 0x08); int invert_column; ulg i, row;/*--------------------------------------------------------------------------- Allocate buffer for fake background image to be used with transparent images; if this fails, revert to plain background color. ---------------------------------------------------------------------------*/ bg_rowbytes = 3 * rpng2_info.width; bg_data = (uch *)malloc(bg_rowbytes * rpng2_info.height); if (!bg_data) { fprintf(stderr, PROGNAME ": unable to allocate memory for background image\n"); bg_image = 0; return 1; }/*--------------------------------------------------------------------------- Vertical gradients (ramps) in NxN squares, alternating direction and colors (N == bgscale). ---------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -