You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GDI+文本绘制不一致:ASCII艺术转PNG代码跨Windows设备输出变形

问题根源

  • 不同设备的系统DPI缩放配置不同,你创建的GDI+ Bitmap默认继承当前设备的DPI,而你写死了8*12的字符尺寸、图片宽高的计算逻辑,DPI变化后光栅字体的实际渲染大小和预设值不匹配,就会出现错位变形。
  • Terminal是Windows原生光栅字体,仅内置了固定几个字号的点阵资源,你当前CreateFont传入的参数在高DPI设备上无法匹配到对应字号的光栅字体时,系统会自动拉伸点阵或者兜底用矢量字体渲染,直接破坏ASCII艺术的等宽等距布局。
  • 你当前用了DT_WORDBREAK参数绘制文本,会自动触发换行逻辑,打乱ASCII艺术原本的固定行结构。

修复方案

1. 强制渲染使用标准DPI

创建Bitmap之后手动设置为标准96DPI,避免不同设备的DPI缩放干扰渲染尺寸:

Bitmap art_output(image_width, image_height);
// 新增这行,固定DPI为标准值
art_output.SetResolution(96.0f, 96.0f);
Graphics g(&art_output);

2. 强制使用光栅字体,避免兜底适配

修改CreateFont的输出精度参数,强制仅匹配光栅字体,避免系统自动替换字体:

// 把OUT_RASTER_PRECIS改成OUT_ONLY_RASTER_PRECIS
HFONT hfont = CreateFont(-8, -12, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET, OUT_ONLY_RASTER_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH, L"Terminal");

3. 动态获取字符尺寸,不要写死宽高

字体创建后先校验实际的字符宽高,用实际值计算图片尺寸,避免硬编码不兼容:

HDC hdc = g.GetHDC();
SelectObject(hdc, hfont);
// 新增获取实际字符尺寸的逻辑
TEXTMETRICA tm = {0};
GetTextMetricsA(hdc, &tm);
// 用tm.tmMaxCharWidth、tm.tmHeight重新计算图片宽高和布局,替换原本的8、12硬编码值

4. 移除自动换行参数

修改DrawTextA的参数,去掉自动换行逻辑:

DrawTextA(hdc, this->decoded_art, -1, &rc, DT_LEFT | DT_TOP | DT_NOCLIP);

内容的提问来源于stack exchange,提问作者Apollyion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 19:12:02