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
相关产品推荐
相关产品推荐

