先前已经能基于GDI显示png图像,但是窗口大小和图像尺寸并不一致。注意到opencv中的imshow的窗口和图像尺寸一致,这里进行设置。

原理

CreateWindow阶段并不能确定窗口大小,但是在窗口处理函数的绘制阶段可以重新调整窗口大小。具体步骤按先后顺序:

  • 首先读取图像(而不是像之前的博客中缩写的,每次窗口paint时都重新读取图像)

  • 注册窗口

  • CreateWindowEx时候随便设置一个窗口大小

  • case WM_PAINT:阶段判断一下,如果没有调整过窗口大小,就调整

代码

  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <windows.h>
  4. #include "png.h"
  5. #pragma comment(lib, "D:/work/libfc/lib/libpng.lib")
  6. #pragma comment(lib, "D:/work/libfc/lib/zlib.lib")
  7. //#pragma comment(lib, "msimg32.lib") // for png's alpha channel
  8. typedef struct MyWindow {
  9. HDC dc;
  10. //HGDIOBJ image;
  11. HBITMAP hBmp;
  12. unsigned char* imdata;
  13. int im_width;
  14. int im_height;
  15. int win_pos_x; // window position, top left point's x coordinate
  16. int win_pos_y; // window posttion, top left point's y coordinate
  17. bool adjusted;
  18. } MyWindow;
  19. MyWindow* my_window;
  20. enum ImageType {BMP, PNG};
  21. long ReadPngData(const char *szPath, int *pnWidth, int *pnHeight, unsigned char **cbData)
  22. {
  23. FILE *fp = NULL;
  24. long file_size = 0, pos = 0, mPos = 0;
  25. int color_type = 0, x = 0, y = 0, block_size = 0;
  26. png_infop info_ptr;
  27. png_structp png_ptr;
  28. png_bytep *row_point = NULL;
  29. fp = fopen(szPath, "rb");
  30. if (!fp) return -1; //文件打开错误则返回 FILE_ERROR
  31. png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); //创建png读取结构
  32. info_ptr = png_create_info_struct(png_ptr); //png 文件信息结构
  33. png_init_io(png_ptr, fp); //初始化文件 I\O
  34. png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0); //读取png文件
  35. *pnWidth = png_get_image_width(png_ptr, info_ptr); //获得图片宽度
  36. *pnHeight = png_get_image_height(png_ptr, info_ptr); //获得图片高度
  37. color_type = png_get_color_type(png_ptr, info_ptr); //获得图片色彩深度
  38. file_size = (*pnWidth) * (*pnHeight) * 4; //计算需要存储RGB(A)数据所需的内存大小
  39. *cbData = (unsigned char *)malloc(file_size); //申请所需的内容, 并将 *cbData 指向申请的这块内容
  40. row_point = png_get_rows(png_ptr, info_ptr); //读取RGB(A)数据
  41. block_size = color_type == 6 ? 4 : 3; //根据是否具有a通道判断每次所要读取的数据大小, 具有Alpha通道的每次读4位, 否则读3位
  42. //将读取到的RGB(A)数据按规定格式读到申请的内存中
  43. for (x = 0; x < *pnHeight; x++)
  44. for (y = 0; y < *pnWidth*block_size; y += block_size)
  45. {
  46. (*cbData)[pos++] = row_point[x][y + 2]; //B
  47. (*cbData)[pos++] = row_point[x][y + 1]; //G
  48. (*cbData)[pos++] = row_point[x][y + 0]; //R
  49. (*cbData)[pos++] = row_point[x][y + 3]; //alpha
  50. }
  51. png_destroy_read_struct(&png_ptr, &info_ptr, 0);
  52. fclose(fp);
  53. return file_size;
  54. }
  55. //int DEFAULT_WIDTH, DEFAULT_HIGHT;
  56. void SetWindowSize(HWND hWnd)
  57. {
  58. if (my_window->adjusted == false) {
  59. RECT WindowRect;
  60. RECT ClientRect;
  61. GetWindowRect(hWnd, &WindowRect);
  62. GetClientRect(hWnd, &ClientRect);
  63. WindowRect.right += (my_window->im_width - ClientRect.right);
  64. WindowRect.bottom += (my_window->im_height - ClientRect.bottom);
  65. MoveWindow(hWnd, WindowRect.left, WindowRect.top, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, true);
  66. }
  67. my_window->adjusted = true;
  68. }
  69. LRESULT __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
  70. {
  71. int image_type = PNG;
  72. switch (msg)
  73. {
  74. case WM_CREATE:
  75. if (image_type == BMP) {
  76. my_window->hBmp = (HBITMAP)LoadImage(NULL, "D:/work/libfc/imgs/lena512.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  77. }
  78. else if (image_type == PNG) {
  79. //
  80. my_window->hBmp = CreateBitmap(my_window->im_width, my_window->im_height, 32, 1, my_window->imdata);
  81. }
  82. if (my_window->hBmp == NULL)
  83. MessageBox(window, "Could not load image!", "Error", MB_OK | MB_ICONEXCLAMATION);
  84. break;
  85. case WM_PAINT:
  86. {
  87. SetWindowSize(window);
  88. BITMAP bm;
  89. PAINTSTRUCT ps;
  90. HDC hdc = BeginPaint(window, &ps);
  91. SetStretchBltMode(hdc, COLORONCOLOR);
  92. my_window->dc = CreateCompatibleDC(hdc);
  93. HBITMAP hbmOld = SelectObject(my_window->dc, my_window->hBmp);
  94. GetObject(my_window->hBmp, sizeof(bm), &bm);
  95. #if 1
  96. //原样拷贝,不支持拉伸
  97. BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, my_window->dc, 0, 0, SRCCOPY);
  98. //AlphaBlend(hdc, 100, 0, bm.bmWidth, bm.bmHeight, my_window->dc, 0, 0, bm.bmWidth, bm.bmHeight, bf);
  99. #else
  100. RECT rcClient;
  101. GetClientRect(window, &rcClient);//获得客户区的大小
  102. int nWidth = rcClient.right - rcClient.left;//客户区的宽度
  103. int nHeight = rcClient.bottom - rcClient.top;//客户区的高度
  104. StretchBlt(hdc, 0, 0, nWidth, nHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);//拉伸拷贝
  105. #endif
  106. SelectObject(my_window->dc, hbmOld);
  107. DeleteDC(my_window->dc);
  108. EndPaint(window, &ps);
  109. }
  110. break;
  111. case WM_DESTROY:
  112. printf("\ndestroying window\n");
  113. PostQuitMessage(0);
  114. return 0L;
  115. case WM_LBUTTONDOWN:
  116. printf("\nmouse left button down at (%d, %d)\n", LOWORD(lp), HIWORD(lp));
  117. // fall thru
  118. default:
  119. //printf(".");
  120. return DefWindowProc(window, msg, wp, lp);
  121. }
  122. }
  123. const char* szWindowClass = "myclass";
  124. ATOM MyRegisterClass(HINSTANCE hInstance)
  125. {
  126. WNDCLASSEX wc;
  127. wc.cbSize = sizeof(WNDCLASSEX);
  128. /* Win 3.x */
  129. wc.style = CS_DBLCLKS;
  130. wc.lpfnWndProc = WindowProcedure;
  131. wc.cbClsExtra = 0;
  132. wc.cbWndExtra = 0;
  133. wc.hInstance = GetModuleHandle(0);
  134. wc.hIcon = LoadIcon(0, IDI_APPLICATION);
  135. wc.hCursor = LoadCursor(0, IDC_ARROW);
  136. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  137. wc.lpszMenuName = 0;
  138. wc.lpszClassName = szWindowClass;
  139. /* Win 4.0 */
  140. wc.hIconSm = LoadIcon(0, IDI_APPLICATION);
  141. return RegisterClassEx(&wc);
  142. }
  143. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  144. {
  145. my_window->win_pos_x = 600;
  146. my_window->win_pos_y = 300;
  147. DWORD defStyle = WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;
  148. HWND hwnd = CreateWindowEx(0, szWindowClass, "title",
  149. defStyle, my_window->win_pos_x, my_window->win_pos_y,
  150. my_window->im_width, my_window->im_height, 0, 0, hInstance, 0);
  151. if (!hwnd)
  152. {
  153. return FALSE;
  154. }
  155. ShowWindow(hwnd, nCmdShow);
  156. UpdateWindow(hwnd);
  157. return TRUE;
  158. }
  159. void create_my_window(MyWindow** _my_window) {
  160. MyWindow* my_window = (MyWindow*)malloc(sizeof(MyWindow));
  161. my_window->dc = NULL;
  162. my_window->imdata = NULL;
  163. my_window->hBmp = NULL;
  164. my_window->adjusted = false;
  165. *_my_window = my_window; // write back
  166. }
  167. void destroy_my_window(MyWindow* my_window) {
  168. if (my_window) {
  169. free(my_window);
  170. }
  171. }
  172. int main()
  173. {
  174. printf("hello world!\n");
  175. create_my_window(&my_window);
  176. int im_width, im_height;
  177. unsigned char* imdata;
  178. ReadPngData("D:/work/libfc/imgs/op.png", &im_width, &im_height, &imdata);
  179. my_window->im_width = im_width;
  180. my_window->im_height = im_height;
  181. my_window->imdata = imdata;
  182. HINSTANCE hInstance = GetModuleHandle(0);
  183. int nCmdShow = SW_SHOWDEFAULT;
  184. MyRegisterClass(hInstance);
  185. if (!InitInstance(hInstance, nCmdShow))
  186. {
  187. return FALSE;
  188. }
  189. MSG msg;
  190. while (GetMessage(&msg, 0, 0, 0)) {
  191. DispatchMessage(&msg);
  192. }
  193. destroy_my_window(my_window);
  194. free(imdata);
  195. return 0;
  196. }

参考

设置窗口客户区大小的一种办法

GDI显示图像时设定窗口大小为图像大小的更多相关文章

  1. C# (GDI+相关) 图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果) (转)

    C#图像处理   (各种旋转.改变大小.柔化.锐化.雾化.底片.浮雕.黑白.滤镜效果)     一.各种旋转.改变大小   注意:先要添加画图相关的using引用.   //向右旋转图像90°代码如下 ...

  2. Matlab绘图基础——图形绘制的插值  以及 图像大小的重采样

    使用说明:图形绘制时的插值 interp1   %1-D data interpolation interpft  %使用fft算法插值     %将原数据x转换到频率域,再逆转换回来更密集的数据采样 ...

  3. [译]Android调整图像大小的一些方法

    翻译自 某大神在Stack Overflow里的自问自答 (一般我们将Bitmap翻译为位图,但为了更好理解,在本文中我将它翻译成图像): 我们在开发的时候,经常需要从服务器中加载图像到客户端中,但有 ...

  4. AForge,Emgu.CV抓拍图像大小

    原文:AForge,Emgu.CV抓拍图像大小 2017年,忙忙碌碌地过去了,象往年一样,依然没有时间上CSDN,博客园. 这一年是打工以来最辛苦的一年. 这一年用了不少自己没有接触过的东西.如人脸识 ...

  5. CSS 是怎样确定图像大小的?

    本文转自奇舞周刊学习使用侵权删 先来看个例子,热热身. 上面这张图像的原始尺寸是:宽 54px 高 49px. 那么,在以下代码中,每张图像显示的最终尺寸是多少? https://p1.ssl.qhi ...

  6. python 修改图像大小和分辨率

    1 概念: 分辨率,指的是图像或者显示屏在长和宽上各拥有的像素个数.比如一张照片分辨率为1920x1080,意思是这张照片是由横向1920个像素点和纵向1080个像素点构成,一共包含了1920x108 ...

  7. 如何在 HTML 中调整图像大小?

    了解在 HTML 中调整图像大小的不同技术.何时应避免在浏览器端调整大小,以及在 Web 上操作和提供图像的正确方法. 如果您的图像不适合布局,您可以在 HTML 中调整其大小.在 HTML 中调整图 ...

  8. C#中如何调整图像大小

    在本篇文章中,我将介绍如何在C#中来调整你想要的图像大小.要实现这一目标,我们可以采取以下几个步骤: 1.首先要获取你想要调整大小的图像: string path = Server.MapPath(& ...

  9. VC++ 在使用 CImage 的Draw 输入一个图像时,有时候会造成图像失真严重,解决的方法如下

    VC++  在使用 CImage 的Draw 输入一个图像时,有时候会造成图像失真严重,解决的方法如下 失真主要是由于变形造成的.只要设置一下变形的模式就可以了 ::SetStretchBltMode ...

随机推荐

  1. [转]TrueType字体结构

    TrueType字体通常包含在单个TrueType字体文件中,其文件后缀为.TTF. OpenType字体是以类似于TrueType字体的格式编码的POSTSCRIPT字体.OPENTYPE字体使用. ...

  2. 查找算法(5)--Tree table lookup--树表查找

    1.树表查找 (1) 最简单的树表查找算法——二叉树查找算法. [1]基本思想:二叉查找树是先对待查找的数据进行生成树,确保树的左分支的值小于右分支的值,然后在就行和每个节点的父节点比较大小,查找最适 ...

  3. ETF:pcf文件制作

    pcf文件依赖数据: ETF基本信息() 指数权重文件(次日权重文件,中证指数公司) 现金替代标志文件(根据中证指数的停复牌文件) 净值文件(基金公司估值系统计算) 成分股数量计算公式: 1.估值系统 ...

  4. 你该怎么学习C++——思想层面

    Javascript是世界上最受误解的语言,其实C++何尝不是.坊间流传的错误的C++学习方法一抓就是一大把.我自己在学习C++的过程中也走了许多弯路,浪费了不少时间. 为什么会存在这么多错误认识?原 ...

  5. 使用清华源进行pip install

    pypi 镜像使用帮助 pypi 镜像每 5 分钟同步一次. 临时使用 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-pac ...

  6. Python之路【第十六篇】:Python并发编程|进程、线程

    一.进程和线程 进程 假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I/O操作), 而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源. 是 ...

  7. java知识精要(二)

    java知识精要(一) 集合 Iterable v.s. Iterator 两者都是接口,在Collection继承的是Iterable. Iterable表达了集合具备迭代访问的能力,而Iterat ...

  8. 学java必须知道的那些queue

    队列是我们学java必须接触到的知识,很多内容都和它相关,但是你真的了解它们的概念和使用方法吗?在本文,你可以获取关于queue的一切信息,希望我能够帮助你在java的学习道路上乘风破浪. 概念 队列 ...

  9. golang基础学习---log

    package main import ( "log" ) func init() { log.SetPrefix("TRACE: ") log.SetFlag ...

  10. ubuntu安装texlive2019

    1.下载texlive2019的iso文件,清华镜像地址:https://mirrors.tuna.tsinghua.edu.cn/CTAN/systems/texlive/Images/texliv ...