日语的节省空间的字符编码?

Con*_*tin 6 unicode character-encoding shift-jis

在我看来,一个常见的问题是:字符编码与位图字体结合使用.大多数多语言编码在不同的字符类型之间有很大的空间,甚至还有很多未使用的代码点.因此,如果我想使用它们,我会浪费大量内存(不仅仅是为了保存多字节文本 - 我的意思是专门用于我的位图字体中的空格) - 而且VRAM大部分都非常有价值......所以唯一合理的东西似乎要:在我的纹理上使用自定义映射,即UTF-8字符(这样就不会浪费空间).但是:这种努力似乎与使用自己的专有字符编码相同(因此我的纹理中也有自己的字符顺序).在我的特殊情况下,我获得了4096个不同角色的纹理空间,并且需要角色来显示拉丁语言和日语(它是一个混乱的utf-8,只支持generall cjk代码页).有人有类似的问题(我真的很想知道,如果没有)?如果已经有任何办法?

编辑:这里描述了同样的问题http://www.tonypottier.info/Unicode_And_Japanese_Kanji/但它没有提供真正的解决方案如何将这些bitmapfont映射保存到utf-8空间效率.所以欢迎任何进一步的帮助!

EDIT2:

非常感谢您的回答.对不起,我的问题描述得不够明确.

我真正想要解决的是:CJK Unicode范围超过20000个字符.但是,只有大约2000个字符的子集才能正确显示日文文本.这些特征在U + 4E00到U + 9FA5的范围内传播.所以我需要以某种方式将这些Unicode代码点(仅限2000日语)转换为我创建的纹理的坐标(我可以按照我想要的方式对字符进行排序).

即U + 4E03是日文字符,但U + 4E04,U + 4E05,U + 4E06不是.那么U + 4E07也是日本人.所以最简单的解决方案,我可以看到:字符U + 4E03在我的纹理中留下三个空格(或者写出不必要的字符U + 4E04,U + 4E05,U + 4E06那里),然后写入U + 4E07.但这会浪费太多的纹理空间(20000个字符,即使只需要2000个字符).所以我希望能够只放入我的纹理:"...... U + 4E03,U + 4E07 ......".但我不知道如何编写我的displayText函数 - 因为我不知道我想要显示的字形的纹理坐标在哪里.会有一个hashmap或类似的东西,但是我不知道如何存储这些数据(为每个字符编写会很麻烦...... {U + 4E03,128},{U + 4E07, 129} ...填写hasmap).

问题:1)没有特定的格式 - 所以我将自己编写displayText函数.2)没有理由反对unicode - 它只是我的bitmapfont的CJK范围问题.3)我认为,这通常是平台和语言无关的,但就我而言,我在Mac OS X/iOS上使用C++和OpenGL.

非常感谢您的帮助!如果您对此有任何进一步的想法,它将真的帮助我很多!

Rol*_*lig 3

您想要解决的真正问题是什么?

难道UTF-8编码的字符串每个字符占用三个字节?如果是,请切换到 UTF-16。否则就不要怪罪UTF-8。(说明:UTF-8 只是一种将整数序列转换为字节序列的算法。它与代码页中的字符分组无关。而这正是Unicode 代码点的用途。)

Unicode 代码点是否分布在许多“代码页”上(其中“代码页”表示由 256 个相邻 Unicode 代码点组成的块)?如果是,请发明从 Unicode 代码点 (0x000000 - 0x10FFFF) 到较小整数集的映射。就内存而言,这应该不超过 4 个字节乘以您真正需要的字符数。查找时间大约为 24 次内存访问、24 次整数比较和 24 次分支指令。(事实上​​,这将是树形图中的二分搜索。)如果这太昂贵,您可以使用基于哈希表的映射。

难道是别的什么?那么请给我们一些例子,以便更好地理解您的问题。

据我了解,您可能应该编写一个小型实用程序,该程序将您想要在应用程序中使用的一组 Unicode 代码点作为输入,然后生成用于显示文本的代码和数据。这就提出了以下问题:

  1. 您必须使用特定的位图字体格式还是您displayText自己编写该函数?
  2. 是否有任何理由反对对所有字符串使用 Unicode 并仅在渲染文本时将它们转换为位图优化编码?编码转换当然是displayText方法内部的,并且对正常应用程序代码不可见。
  3. 只是出于兴趣:问题是否特定于某种编程语言或环境?

更新

我假设你的主要问题是这样的函数:

Rectangle position(int codepoint)
Run Code Online (Sandbox Code Playgroud)

如果我必须这样做,我会首先为每个角色准备一个位图。位图的文件名将是代码点,以便可以轻松重新生成“大图片”,以防万一您找到更多需要的字符。准备工作包括以下步骤:

  1. 加载所有位图并确定它们的尺寸。此步骤的结果是从整数到(宽度,高度)对的映射。
  2. 为大图片中的角色图像计算一个良好的布局,并记住每个角色的放置位置。保存大局。将从代码点到(x,y,宽度,高度)的映射保存到另一个文件。这可以是文本文件,如果没有磁盘空间,也可以是二进制文件。细节并不重要。

displayText函数将按如下方式工作:

void displayText(int x, int y, String s) {
  for (char c : s.toCharArray()) { // TODO: handle code points correctly
    int codepoint = c;
    Rectangle position = positions.get(codepoint);
    if (position != null) {
      // draw bitmap
      x += position.width;
    }
  }
}

Map<Integer, Rectangle> positions = loadPositionsFromFile();
Run Code Online (Sandbox Code Playgroud)

现在剩下的唯一问题是如何使用尽可能少的内存在内存中表示该映射,并且仍然足够快。当然,这取决于您的编程语言。

内存中的表示可以是一些包含 x、y、宽度、高度的数组。对于每个元素,一个 16 位整数就足够了。无论如何,您可能只需要 8 位的宽度和高度。然后,另一个数组会将代码点映射到索引positionData(如果代码点不可用,则映射到某个特殊值)。这将是一个包含 20000 个 16 位整数的数组,因此总而言之,您有:

  • 2000 * (2 + 2 + 1 + 1) = 12000 字节(对于positionXpositionYpositionWidthpositionHeight
  • codepointToIndexInPositionArrays如果使用数组而不是映射,则20000 * 2 = 40000 字节。

与位图本身的大小相比,这应该足够小。由于数组不会改变,因此它们可以位于只读存储器中。