7

我正在尝试在 MATLAB 的图例命令中使用变音符号。一个快速的谷歌告诉我我想要的形式是char(146),它可以很好地显示文件,或者将它打印到 tif。

但是当我打印为 EPS 格式(或 epsc、eps2、epsc2)时,文件中会显示一个不同的字符。我试过打印前 300 多个字符,它们肯定会发生变化(尽管速度很慢,其中一半是紧接着带有符号的“A”),但这似乎是一种相当缓慢的方法,而且我不是保证真正找到我想要的符号。那么,这里有人对我可以尝试什么有任何想法吗?

我正在使用 MATLAB R2011a,我的默认字符集是 UTF-8,我的打印行看起来像..

legend( plot_id , strcat('lala',char(146)) )

我的打印线看起来像..

print -depsc2 -tiff -r600 <filename>

(但关闭 tiff 缩略图生成没有任何效果)

4

2 回答 2

10

当 MATLAB 字符编码为 UTF-8 时出现问题,Linux 用户通常是这种情况(因此 Amro 使用 CP1252 的配置没有问题)。当 MATLAB 字符集编码(使用slCharacterEncoding()UTF-8 获取)时,MATLAB eps 导出函数存在错误(至少在 R2011b 之前),因为它以八进制转义 UTF-8 格式(2 个字节)导出非 ASCII 字符,而 Postscript解释器设置为解码 1 字节格式。

让我们用字符 ö U+00F6 来说明这个错误,它的一些表示是:

  • UTF-16:0x00F6
  • UTF-8:0xC3 0xB6
  • 八进制转义 UTF-8:\303\266
  • XML 十进制实体:ö

MATLAB 创建的 eps 文件包含:

/Helvetica /ISOLatin1Encoding 120 FMSR
(\303\266) s

MATLAB 在 eps 文件中定义了一个FMSR将 Helvetica 字体重新编码为另一种编码的函数,这里ISOLatin1Encoding是两个内置编码向量之一,并且与 ISO-8859-1 (Latin1) 标准非常匹配(参见第 329 页) 330 的 Postscript 语言参考手册了解更多详细信息)。简而言之,编码向量是将字符名称与字符代码相关联的 256 元素数组。所以它只读取 1 字节的字符代码。在 ISO-8859-1 中,\303=195=à 和 \266=182=¶。结果,它打印出ö。

使用 UTF-8 语言环境导出非 ASCII ISO-8859-1 字符的选项

  1. 将八进制 UTF-8 代码转换为八进制 ISO-8859-1 代码,这很容易,因为非 ASCII ISO-8859-1 字符在 UTF-8 中遵循相同的布局。例如,使用可以从命令窗口或导出脚本运行的程序 sed:

    !sed -i -e 's/\\302\(\\2[4-7][0-7]\)/\1/g' -e 's/\\303\\2\([0-7][0-7]\)/\\3\1/g' file.eps
    

    因此,\303\266变为\366=246=ö。您可以在 MATLAB 中直接键入非 ASCII 字符。

  2. 在将文本添加到图窗之前更改 MATLAB 字符集编码slCharacterEncoding('ISO-8859-1'),如果您从命令窗口添加文本,请对非 ASCII 字符使用 char(number)。如果使用绘图工具直接在图中添加文本,则可以输入非 ASCII 字符。此解决方案并不理想,因为非 ASCII 字符不会以默认字体(Linux 上的 MATLAB 默认使用 Helvetica)出现在图形上,并且如果您编写图形创建脚本,则需要使用 char(number)。

  3. 稍后通过使用用户提交的 MATLAB 函数(例如 LaPrint 或其分支之一)使用 LaTex 渲染文本,该函数会创建一个包含图形文本的 tex 文件和一个包含图形非文本部分的 eps 文件。一个类似的解决方案是 matlab2tikz,它创建一个 tikz/pgfplot 文件和一个 tex 文件。

  4. 使用 MATLAB 的 Latex 解释器:\"{o}. MATLAB 通过将 ASCII 字符与其变音符号组合来创建字符,但由于相对定位不好(变音符号与字符相比在右侧有点过多),结果质量低下。MATLAB 使用 Computer Modern 字体中的字形并将字体嵌入到 eps 文件中(增加了 ~ 80 Ko)。此外,从 eps 创建的 pdf 中的原始文本不包含öbut o ̈

导出非 ISO-8859-1 字符

对于导出不在 ISO-8859-1 中字符,如果需要的字符数少于 256(8 位格式)并且理想情况下在标准编码集中,则可能有一个合理的解决方案。它涉及以下步骤:

  1. 将八进制代码转换为 Unicode 字符;
  2. 将文件保存为目标编码标准(8位格式);
  3. 添加目标编码集的编码向量。

例如,如果要导出波兰语文本,则需要将文件转换为 ISO-8859-2。这是在 Linux 上使用 Bash 的实现:

#!/bin/bash
name=$(basename "$1" .eps)
ascii2uni -a K "$1" > /tmp/eps_uni.eps
iconv -t ISO-8859-2 /tmp/eps_uni.eps -o "$name"_latin2.eps
sed -i -e '/%EndPageSetup/ r ISOLatin2Encoding.ps' -e 's/ISOLatin1Encoding/MyEncoding/' "$name"_latin2.eps

保存为 eps_lat2;然后运行该命令sh eps_lat2 file.eps会使用 Latin-2 编码创建 file_latin2.eps。文件 ISOLatin2Encoding.ps 包含以下内容:

/MyEncoding
% The first 144 entries are the same as the ISO Latin-1 encoding.
ISOLatin1Encoding 0 144 getinterval aload pop
% \22x
    /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
    /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
% \24x
    /nbspace /Aogonek /breve /Lslash /currency /Lcaron /Sacute /section
    /dieresis /Scaron /Scedilla /Tcaron /Zacute /hyphen /Zcaron /Zdotaccent
    /degree /aogonek /ogonek /lslash /acute /lcaron /sacute /caron
    /cedilla /scaron /scedilla /tcaron /zacute /hungarumlaut /zcaron /zdotaccent
% \30x
    /Racute /Aacute /Acircumflex /Abreve /Adieresis /Lacute /Cacute /Ccedilla
    /Ccaron /Eacute /Eogonek /Edieresis /Ecaron /Iacute /Icircumflex /Dcaron
    /Dcroat /Nacute /Ncaron /Oacute /Ocircumflex /Ohungarumlaut /Odieresis /multiply
    /Rcaron /Uring /Uacute /Uhungarumlaut /Udieresis /Yacute /Tcedilla /germandbls
% \34x
    /racute /aacute /acircumflex /abreve /adieresis /lacute /cacute /ccedilla
    /ccaron /eacute /eogonek /edieresis /ecaron /iacute /icircumflex /dcaron
    /dcroat /nacute /ncaron /oacute /ocircumflex /ohungarumlaut /odieresis /divide
    /rcaron /uring /uacute /uhungarumlaut /udieresis /yacute /tcedilla /dotaccent
256 packedarray def

这是 Python 的另一个实现(因此它也可以在 Windows 和 Mac 上工作):

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys,codecs
input = sys.argv[1]
fo = codecs.open(input[:-4]+'_latin2.eps','w','latin2')
with codecs.open(input,'r','string_escape') as fi:
    data = fi.readlines()
with open('ISOLatin2Encoding.ps') as fenc:
    for line in data:
        fo.write(line.decode('utf-8').replace('ISOLatin1Encoding','MyEncoding'))
        if line.startswith('%%EndPageSetup'):
            fo.write(fenc.read())
fo.close()

保存为 eps_lat2.py;然后运行该命令python eps_lat2.py file.eps会使用 Latin-2 编码创建 file_latin2.eps。

通过更改脚本中的编码向量和 iconv(或 codecs.open)参数,它可以很容易地适应其他 8 位编码标准。

于 2013-02-08T09:50:45.243 回答
3

这是一个简单的测试:

%# common text properties
props = {'FontSize',30};

%# LaTeX
str = '\"a\"o\"u';
subplot(121), plot(1:10)
text(5, 5, str, 'Interpreter','latex', props{:})
legend({str}, 'Interpreter','latex', props{:})
xlabel(str, 'Interpreter','latex', props{:})
title(str, 'Interpreter','latex', props{:})

%# normal text
str = 'äöü';
subplot(122), plot(10:-1:1)
text(5, 5, str, props{:})
legend({str}, props{:})
title(str, props{:})
xlabel(str, props{:})

%# export as EPS file
print -depsc2 -tiff -r600 file.eps

截屏

生成的EPS文件看起来相同。

笔记:

我在 Windows XP 上,默认字符编码是Windows-1252

>> feature('DefaultCharacterSet')
ans =
windows-1252

因此,您可以使用它们的(扩展)ASCII 代码直接输入这些变音符号:Alt+0228Alt+0246Alt+0252ä、ö、ü 分别:

>> char([228 246 252])
ans =
äöü

另请注意,我默认使用 Arial 字体:

>> get(0, 'defaultTextFontName')
ans =
Arial

>> get(0, 'defaultAxesFontName')
ans =
Arial
于 2012-08-09T22:24:15.763 回答