首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

圖形模式下中文字顯示:BGI 字庫程式設計完整指南

     編輯:關於C++

前言

文字模式下有中文系統支援即可直接 printf 輸出中文;但圖形模式 (BGI) 需自行讀取字庫檔案 (如 UCDOS HZK16, HZK24S) 繪製點陣。

16x16 點陣字庫 (HZK16) 顯示

核心函式

// 開啟字庫
int handle;
int OpenHz(const char *Hz16Path) {
    return (handle = open(Hz16Path, O_RDONLY | O_BINARY));
}

// 顯示字串
// x,y: 起始座標; z: 字間距; color: 顏色; p: 中文字串
int WrtHz16(int x, int y, int z, int color, char *p) {
    unsigned int i, c1, c2, f = 0;
    int i1, i2, i3, rec;
    long l;
    char by[32];
    if (handle < 0) return -1;

    while ((i = *p++) != 0) {
        if (i > 0xA1) {
            if (f == 0) { c1 = (i - 0xA1) & 0x7F; f = 1; }
            else {
                c2 = (i - 0xA1) & 0x7F; f = 0;
                rec = c1 * 94 + c2;           // 區位碼轉序號
                l = rec * 32L;                // 每字 32 bytes (16行 x 2bytes)
                lseek(handle, l, SEEK_SET);
                read(handle, by, 32);
                for (i1 = 0; i1 < 16; i1++)
                    for (i2 = 0; i2 < 2; i2++)
                        for (i3 = 0; i3 < 8; i3++)
                            if (GetBit(by[i1*2 + i2], 7 - i3))
                                putpixel(x + i2*8 + i3, y + i1, color);
                x += z + 16;
            }
        }
    }
    return x;
}

// 取得位元值
int GetBit(unsigned char c, int n) { return (c >> n) & 1; }

void CloseHz(void) { close(handle); }

主程式範例

#include "Hz.h"
#include <graphics.h>
#include <conio.h>

const char* Hz16Path = "\\UCDOS\\HZK16";
const char* HzStr = "苦丁香C語言輔助學習軟體";

void main() {
    int gd = DETECT, gm;
    initgraph(&gd, &gm, "\\TC\\BGI");
    OpenHz(Hz16Path);
    WrtHz16(20, 20, 4, RED, HzStr);
    CloseHz();
    getch();
    closegraph();
}

24x24 點陣與縮放顯示 (HZK24S)

擴展函式

// m: X 方向放大倍數; n: Y 方向放大倍數
int WrtHz24(int x, int y, int z, int color, int m, int n, char *p) {
    unsigned int i, c1, c2, f = 0;
    int i1, i2, i3, i4, i5, rec;
    long l;
    char by[72];  // 24x24 = 576 bits = 72 bytes
    if (handle < 0) return -1;

    while ((i = *p++) != 0) {
        if (i > 0xA1) {
            if (f == 0) { c1 = (i - 0xA1) & 0x7F; f = 1; }
            else {
                c2 = (i - 0xA1) & 0x7F; f = 0;
                rec = (c1 - 1) * 94 + c2;   // HZK24 索引計算不同
                l = rec * 72L;
                lseek(handle, l, SEEK_SET);
                read(handle, by, 72);
                for (i1 = 0; i1 < 24 * m; i1 += m)
                    for (i4 = 0; i4 < m; i4++)
                        for (i2 = 0; i2 < 3; i2++)   // 24/8 = 3 bytes per row
                            for (i3 = 0; i3 < 8; i3++)
                                if (GetBit(by[(i1/m)*3 + i2], 7 - i3))
                                    for (i5 = 0; i5 < n; i5++)
                                        putpixel(x + i1 + i4, y + i2*8*n + i3*n + i5, color);
                x += 24 * m + z;
            }
        }
    }
    return x;
}

使用範例

const char* Hz24Path = "C:\\UCDOS\\FNT\\HZK24S";
OpenHz(Hz24Path);
WrtHz24(20, 20, 4, RED, 2, 4, HzStr); // X放大2倍, Y放大4倍
CloseHz();

關鍵技術點總結

  • 區位碼對應:中文內碼高位/低位皆 > 0xA1,減 0xA1 後得區碼/位碼 (1~94)。
  • 字庫索引:HZK16 為 (區-1)*94 + (位-1),每字 32 bytes;HZK24 類似但每字 72 bytes。
  • 點陣展開:每 byte 8 點,從高位 (bit 7) 到低位 (bit 0) 對應左到右。
  • 放大算法:以最近鄰插值方式,將每個邏輯像素繪製為 m x n 實體像素塊。

注意:此為 DOS 年代 BGI 程式設計技術,現代 Windows/Linux 圖形程式請使用 FreeType、DirectWrite、Qt/QFont 等支援 TrueType/OpenType 字型的庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved