解決依賴內嵌字體才能正常顯示的電子書亂碼問題

2021-02-14 書伴BookFere

有一位名為「行雲」的小夥伴留言反饋了一個問題,說他在網上找到一本電子書,但是裡面的內容使用了特殊的字體,只要轉換成其它格式就會亂碼,並且也不能正常複製字體,問如何解除這種限制。

一、問題表現

簡單實測了一下樣本電子書,發現在 Kindle 設備或 Calibre 內置閱讀器中閱讀一切正常:

但是在使用 Calibre 將其轉換成 MOBI 格式後,發現內容中大部分文字都變成了「亂碼」:

用 KindleUnpack 把樣本電子書拆解成源碼後,發現裡面實際的文本內容確實是「亂碼」:

另外,還在源碼的 Fonts 文件夾中發現了一枚字體文件,在 CSS 文件中也可以看到強制指定該字體的相關屬性。經測試,電子書中的內容一旦應用該字體,內容就會變得正常刻度,否則就呈亂碼狀。

這看似是個很奇怪的問題,但是並不是太難解決,下面我們先來分析一下到底是怎麼回事。

二、問題分析

一本 Kindle 電子書想要被正常閱讀,需要遵循亞馬遜為其制定的實現標準,這些實現標準都是公開的透明的(你可隨時可以通過亞馬遜持續維護著的《Kindle 電子書發布指南》來了解相關信息),因此不可能脫離這個實現標準對電子書做什麼額外操作,除非是利用實現標準中所具備的特性搞一些障眼法。

這位小夥伴所提供的樣本電子書便利用了實現標準的一項本應是提升閱讀體驗的特性,有(惡)意地對電子書內容做了混淆,使得電子書必須依賴字體才能正常顯示,這一特性就是「嵌入字體」。

正常情況下「字符」與字體中的「字形」應該是一一對應的。如果一個字符是「人」,那麼應用字體後的字形看起來也應該是「人」。而該樣本電子書卻沒這麼做。假設有一句話是「人人為我,我為人人」,它就會將其故意寫成「㭃㭃㘣㝒,㝒㘣㭃㭃」,然後再通過修改字體文件,將裡面的字符和字形的故意錯誤映射,如字符「㭃」映射到「人」字形、字符「㘣」映射到「為」字形等。這樣你就只能依賴這個字體文件才能看到那句話的正確顯示「人人為我,我為人人」,但實際文本的字符卻是「㭃㭃㘣㝒,㝒㘣㭃㭃」。

用字體編輯軟體 FontForge 打開在原始碼中的字體,就可以看到很多字符與字形的錯亂映射:

▲ 每個方框上方的小字是「字符」,下方的大字是與字符相對應的「字形」

在上圖中,按從左到右、從上到下的順序,可以看到「㕟㕡㕣㕤㕿㖂㖐㖓㖚㗊」這十個字符,其對應字形卻是「提場展因大世意事沒年」。這就是為何電子書內容是亂碼,應用字體後卻是正常的原因。

該樣本電子書正是挑選了一些常用的高頻字符,將它們的字形根據製作者自己制定的規則逐一映射到「亂碼」字符上,然後再根據這個規則反向把電子書中的正常字符替換成「亂碼」字符。這樣,通過把字體嵌入到電子書中,並在 CSS 中為「亂碼」內容指定該字體,就可以讓亂碼內容正常顯示了。當時當你得到這樣一本經過處理的電子書後,卻無法對它進行編輯和格式轉換,更不能正常使用標註、查詞等功能。

三、解決方法

知道了問題所在,解決方法就顯而易見了,我們只需要將亂碼字符替換成他所對應字形的正確字符即可。大體思路為:先整理出字體文件中所有映射正常字形的亂碼字符,然後把這些亂碼字符所映射的字形抄下來(也就是將其轉化成字符),並使其與亂碼字符逐一配對,製成替換規則,最後用 Calibre 轉換功能中的「查找替換」功能把亂碼字符替換成正常字符。下面就以樣本電子書文件為例說一下具體步驟。

1、確定字符範圍

首先用 FontForge(也可使用其它字體編輯軟體)查看樣本電子書所使用的字體文件,藉助 Unicode 十六進位編碼確認錯誤映射字形的亂碼字符範圍。不同字體文件其範圍會有所不同,個數可能比較多也可能比較少,分布可能比較集中也可能比較分散,但是只要是字符和字形不匹配就是需要篩選出來的。

比如在本例中,字符的分布比較集中,所以可以很方便的確定它們的範圍。如上圖所示,第一個出現錯誤映射字形的字符是「㐨」,選中它就可以在軟體界面上方看到 Unicode 編碼 0x3428,用同樣的方法找到最後一個字符的 Unicode 編碼 0x4dbc,這樣就可以確認這些亂碼字符的範圍是從 0x3428 到 0x4dbc。

2、導出字符編碼

確定好範圍後,接下來就要獲取這個範圍內所有字符的 Unicode 十六進位編碼,以便在查找替換時匹配它們。不過需要注意,並不是每一個字符都含有字形的,我們所需要的只是含有字形的字符。

為了避免重複的手工操作,可以使用一個名為 fonttools 可處理字體的三方 Python 庫來提高效率。如果你的電腦已裝有 Python 及其包管理器,可直接使用  pip  命令在命令行中運行以下指令安裝該庫。

安裝完成 fonttools 後,就可以在命令行上使用  ttx  命令執行下方的指令,來導出字體的 CMAP 表(即字符和字形的映射索引)以批量獲取字體文件中所有字符編碼,並且會自動忽略無字形的字符。

* 注意!指令中的 font.otf 要換成你自己拆解出來的字體文件名

執行完命令後,可以在字體文件所在目錄看到命令生成名為 font.ttx 的 XML 文件,內容如下:

<?xml version="1.0" encoding="UTF-8"?><ttFont sfntVersion="OTTO" ttLibVersion="3.44">
<cmap> <tableVersion version="0"/> <cmap_format_4 platformID="3" platEncID="1" language="0"> <map code="0x20" name=""/> <map code="0x21" name=""/> <map code="0x22" name=""/> <map code="0x23" name=""/> <map code="0x25" name=""/> <map code="0xff1a" name=""/> <map code="0xff1b" name=""/> <map code="0xff1f" name=""/> <map code="0xff5b" name=""/> <map code="0xff5d" name=""/> </cmap_format_12> </cmap></ttFont>

這是字體文件中所有字符的 Unicode 編碼,接下來需要提取之前確定的範圍並轉製成替換規則。

3、轉制替換規則

本例中之前確定的字符範圍是 0x3428 到 0x4dbc,所以從 XML 中把這個範圍內的字符編碼提取出來。

<map code="0x3428" name=""/><map code="0x343c" name=""/><map code="0x343d" name=""/><map code="0x3445" name=""/><map code="0x344d" name=""/><map code="0x4d56" name=""/><map code="0x4d99" name=""/><map code="0x4dae" name=""/><map code="0x4db6" name=""/><map code="0x4dbc" name=""/>

想要把這些 XML 格式的字符編碼轉換成 Calibre 替換規則格式還需要處理一下。可以用 Sublime Text 之類的代碼編輯器,開啟正則替換模式,查找 ^.*"?0x(.*?)".* 替換成 [\\u$1]\n\n。替換完成後,這些字符的 Unicode 編碼就已經按照 Calibre 替換規則格式每間隔兩個空行排列好了,如下所示。

[\u355f]

[\u3561]

[\u3563]

[\u3564]

[\u3572]

[\u357f]

[\u3590]

[\u3593]

[\u359a]

[\u35ca]

* 提示:這裡替換的目的是將字符的 Unicode 編碼轉換成匹配字符的正則表達式

當然現在這個替換規則文件只能匹配亂碼字符,下面還要為其填充替換內容。現在先這些內容另存一下,文件名隨意,後綴名為 .csr(即 Calibre 的替換規則文件格式),如 pattern.csr。

4、填充替換規則

填充替換規則是個力氣活。仍以之前圖示顯示的「㕟㕡㕣㕤㕿㖂㖐㖓㖚㗊」這十個字符為例。

你只需要按照 FontForge 中從左到右、從上到下的順序,將字符編碼對應字形輸入在其下方即可。注意,一個字符編碼及其對應字形所代表的真正字符為一組,每一組之間有一個空行,如下所示。

[\u355f]提
[\u3561]場
[\u3563]展
[\u3564]因
[\u3572]大
[\u357f]世
[\u3590]意
[\u3593]事
[\u359a]沒
[\u35ca]年

這些抄寫工作比較枯燥(本例有 400+ 個字符),不過對於打字熟練的人來說,輸入幾百個常用漢字應該花不了幾分鐘的時間。當然,如果你想要節省時間,或者說電子書製作者使得每本電子書的字體都不一樣,那可能就需要 OCR 相關的編程技術等來提高效率了,不過限於篇幅,這裡不便展開討論。

編輯完成後保存一下。現在你就得到了一個可以把電子書的「亂碼」恢復成正常字符的替換規則文件。

5、使用替換規則

轉換電子書時,在轉換設置面板中,切換到【搜索替換】界面,點擊上面的【加載】按鈕,載入之前編輯好的 .csr 規則文件,然後點擊【確定】按鈕開始轉換,最終得到的電子書內容就恢復正常了。

總的說來,這個問題的解決方法並不複雜,但是操作起來還是要花費一些功夫的。如果能通過其它渠道找到替代文件,感覺沒必要這樣去做。不過,通過這件事真是見識了「盜版界」的奇技淫巧,本來感覺往電子書裡插廣告就夠噁心的了,這種故意混淆字符硬生生退化電子書功能的做法更是刷新了下限。

---- · END · ----

【推廣】書伴推送服務:push.bookfere.com

微信ID:kindle-fere「書伴」為靜心閱讀而

相關焦點

  • CAD字體不顯示怎麼解決?
    豬年大吉很多人在打開CAD圖紙的時候會出現這個問題?解決方法:第一種就是直接按鍵盤左上方:Esc鍵,打開圖紙。出現這個問題主要是電腦沒有相應的字體導致,這個也跟CAD本身的字體樣式有關。這裡不做詳細解說。打開圖紙後,出現文字顯示「?」怎麼解決?
  • 加載Windows系統字體到圖上,解決PDF導出字體無法顯示的問題
    作圖的時候常出現一個問題,我把windows系統字體Times New Roman指定為圖形裡的字體,雖然在RStudio圖形窗口會顯示指定字體,但是在保存為PDF時出現問題,出現字體類別錯誤,指定字體無法顯示。
  • CAD字體問題匯總(字體顯示問號,文字無法編輯......
    原因可能是:①對應的字型沒有使用漢字字體,如HZTXT.SHX等;②當前系統中沒有漢字字體形文件;應將所用到的形文件複製到AutoCAD的字體目錄中(一般為...\FONTS\);③對於某些符號,如希臘字母等,同樣必須使用對應的字體形文件,否則會顯示成?號。
  • 受字體顯示問題影響 阿拉伯書法遭遇網絡化挑戰
    大多數阿拉伯網站使用的阿拉伯字體都是如出一轍的。那些希望使用專屬字體的網站,為實現這一設想,必須面對一系列問題,其中便有不同系統的手機和電腦終端上阿拉伯字體的顯示問題。必須提到的是,雖然PhotoShop等設計軟體可以支持數十種阿拉伯字體,但這些軟體只適用於圖像的編輯,並不適用於閱讀內容的編輯。目前可利用的阿拉伯數位化字體不超過500種,其中很多還並不適用於網頁。
  • 【求知探新】Unity中字體名對依賴關係的影響
    當然需要說明的是,一個好的問題沒有標準的答案,在此也歡迎大家來積極拍磚!今天分享的內容,來自我們對UWA問答社區中《求助有關字體依賴的問題》一帖的研究。一、問題描述兩個沒有相關性的字體,在Unity裡導入的時候,會產生依賴關係。
  • 安的電子推出一系列內嵌式微功率讀寫器
    廣州安的電子科技有限公司是業內知名的專注於RFID設備研發、生產、銷售和提供解決方案的高科技公司,該公司日前推出了一系列內嵌式微功率讀寫器。其中有:RL15E內嵌式微功率一體機RL86S內嵌式微功率一體機
  • AutoCAD字體不顯示或者亂碼怎麼辦
    今天來給大家講一下有關AutoCAD字體的小知識,經常用CAD的朋友會發現,有時候當你看圖紙時裡面的字體都是亂碼或者符號,不知道的朋友會以為是文件損壞或者CAD中病毒了,其實這是一個很常見的CAD問題,因為電腦中缺少字體(或者CAD專用字體)導致的,因為沒有對應的字體所以字體顯示出現了問題就會產生亂碼。
  • 導致電子天平無法顯示的原因及解決方法
    實驗室電子天平是精密儀器,客戶常常報怨這種問題或那種問題的,出現問題一般都是需要專業的人員才能維修,我們客戶自己能不能自行解決呢?電子天平普通常規出現的問題有開機後完全無顯示,以下給大家詳細介紹7種無顯示的常見現象的原因:  1、開啟問題_開啟後完全無顯示  (1)天平放置的環境太差改善環境;  (2)天平菜單中的參數設置不好調入菜單後,用「RESET」功能,正確退出菜單,回到出廠設置;  (3)稱重室內留有手的體溫儘量減少這一人為因素  (4)被稱量物體的溫度未與天平達到等溫將樣品放置在天平旁等溫
  • 一分鐘永久解決CAD字體亂碼顯示不全,早該知道了
    AutoCAD繪圖日常,打開CAD圖紙使用,總是顯示文字顯示不全,或者是直接的字體亂碼,有的時候甚至是直接的看不見,怎麼辦?相信這個問題一定是困擾了太多的小夥伴,如何解決?掌握這3種方法,永久解決,遇到字體問題再不是煩惱,早就應該知道了。方法1:文件版本不兼容文件版本不兼容出現字體亂碼確實是很正常的操作,如何進行解決?
  • @font-face之解決web頁面自定義字體問題
    在前端開發中,也許你有被客戶要求用各種不用的字體。但實際開發中,每個瀏覽器都有自己的安全字體(這個對字體(font-family)的定義就是一個安全字體。每種作業系統都有自己默認安裝的字體,瀏覽器只能正常顯示作業系統中安裝了的字體。
  • Word使用高級字體如何在其他電腦中正常顯示?
    我們有時候在word文檔中使用高級的字體,但是放到其他的電腦中,可能不顯示,下面教大家如何來嵌入字體。1.首先我們將文字修改為比較罕見的字體。3.點擊保存,找到字體嵌入的選項。5.這個時候無論在哪一臺電腦上,都能正常的顯示了。
  • Chrome 86安全性提升,造成Google字體顯示問題
    Google Chrome 86後加入緩存分區功能以防止跨網站關注,但代價是造成Google字體可能無法顯示,不過其他瀏覽器可能很快也會出現這問題。 Google字體源自Google希望開發跨系統、語系的通用字體,Google於2014年免費開源這套字體資源,受到許多網頁及應用開發商的歡迎,目前全球有超過4,200萬個網站使用。
  • 電子天平上顯示-E是怎麼回事?我們又要如何來解決問題呢?
    日常使用電子天平的時候,我們肯定還是應該經常關注一下顯示器上呈現出來的數據情況,這樣就可以讓我們知道測量的結果,同時也可以知道設備是否有其他方面的一些問題。確實如果真的是出現了什麼樣的問題不好解決,但是有一些小毛病,如果核對說明書,其實解決問題還是很簡單的。
  • CAD字體出現問號亂碼的解決方法
    這是由於自己的電腦缺少相應字體的原因所導致,當然了如果軟體上安裝了相應的字體,這些亂碼也就不會出現。那麼在不安裝相應字體的情況下,該如何把那些問號亂碼完整的顯示出字體呢?下面介紹兩種方法來解決這個問題。
  • 字體界「視覺中國」?方正「釣魚維權」成習慣 頻訴用戶字體「侵權」
    對此,王雪認為:廣告公司下載使用時,明確為網絡免費版;使用完成時,方正電子並未發布聲明;方正電子完全具備協調搜尋引擎公司禁止盜版字體下,而至今很多「迷你版」仍舊可以下載。在王雪看來,方正電子在網絡渠道「誘導下載」,然後再要求侵權賠償,實質上就是一種「釣魚維權」。針對索賠的合理性,責任主體的認定等問題,經濟觀察報記者致電前述方正電子的銷售經理王凱。
  • 微軟解決Win10低分屏UI顯示問題
    在此之前,我曾在IT之家發過一篇文章:《IT之家學院:解決win10 1703版本1366x768解析度部分顯示問題》其中就Windows 10在1366x768解析度上的字體顯示問題,做了簡要的說明,並提供了一個粗暴的解決辦法:替換成win8原始字體。
  • 史上最硬核的Linux依賴問題解決方案
    上面的方案幾乎可以解決80%的安裝依賴問題。這個文件裡的內容,也是dpkg -l 命令顯示內容的信息來源。也是我們上面說的,依賴檢測時檢索系統內是否滿足依賴的信息來源。所以,依賴不滿足的時候,你可以直接打開這個文件,仿照其他軟體的寫法,照抄一段加上,把文件名改為缺失的依賴包的名字就可以!dpkg就會認為,系統裡有安裝這個包,從而解決依賴導致的無法安裝的問題。
  • CAD中三大字體問題
    ,也有單位之間的,收到一張圖紙打開後經常會因為沒有字體而導致有些字顯示為?號,遇到此類問題如何解決呢?    首先,必須對字體文件的格式有所了解。打開圖紙的時候會因為缺少大、小字體,文字無法顯示或雖然有此字體但版本不同,缺少某些文字的定義而使文字顯示為?號。    解決這類問題,最好的方法是讓對方把字體文件發過來,其次是自己從網上搜同名的字體(同名的字體的內容不一定完全相同)。如果實在找不到的話,只能幫你想辦法了。
  • 完美解決AE CC 2017/2018/2019字體BUG問題
    1完美解決AE CC 2017/2018/2019字體BUG問題相信很多人自動升級AE到CC2017以後對這個彈窗不陌生了,在AE中給文字層改字體類型時,或者在中打開AE模版時出現:報錯窗口After Effects error: CT generic:
  • 抖音黃色字體設置不了怎麼回事 黃色字體正常顯示辦法
    最近很多小夥伴們都在討論評論區討論黃色字體的設置方法,不過,也有小夥伴表示不能設置黃色字體。那麼,抖音黃色字體設置不了是怎麼回事?解決辦法是什麼呢?  最近很多小夥伴們都在討論評論區討論黃色字體的設置方法,不過,有不少小夥伴們反映自己無法設置。抖音黃色字體設置不了是怎麼回事?該怎麼解決呢?