Filter是用來壓縮PDF還是用來加密的?之前介紹過,Office文檔是用zip壓縮數據的,把文字和圖像等打包在一起。如果你用7z解壓PPTX/DOCX/XLSX文檔,就可以輕松獲得文檔中的文字和圖片等資源。
解壓PPTX,可見其中圖片
PDF的大部分Filter确實是用來壓縮的,然而ASCIIHexDecode和ASCII85Decode編碼後隻會讓文件變大。這不是逗你嗎?把ASCIIHex和ASCII85用來加密數據,有種此地無銀三百兩的感覺。現在很多人看見亂碼就說加密,舉個Base64的例子。
Base64編碼用到的字符
<img src="data:image/png;base64,iVBORw0KGgoAAA
ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU
5ErkJggg==" alt="Red dot" />
PDF支持的filter可以分為三大類:
[1] 轉碼Filter,把原數據映射到可顯示的字符範圍。ASCIIHex映射為16進制的字符,ASCII85映射為ASCII表中的85個可顯示字符範圍。
[2] 壓縮Filter,文本和圖像使用不同的Filter,這才是用來壓縮文件的。如LZWDecode,FlateDecode, RunLengthDecode, CCITTFaxDecode, JBIG2Decode, DCTDecode, JPXDecode。
[3] 加密Filter,這是用來加密PDF文件的。
ASCIIHex, ASCII85字符範圍
ASCIIHex從2^8映射為2^4 2^4,因此壓縮比是2:1=200%,怪不得現在已經絕迹了。而ASCII85的壓縮比為5:4=125%,畢竟還有用途,但用的也不是太多。
Specifically, ASCII base-85 encoding produces 5 ASCII characters for every 4 bytes of binary data. Each group of 4 binary input bytes, (b1 b2 b3 b4), is converted to a group of 5 output bytes, (c1 c2 c3 c4 c5), using the relation:
ASCII85映射關系
這個代碼寫出來也很簡單,大家可以親手試一試,比刷Leecode簡單多了,就是從一個範圍映射到另一個字符範圍。ASCIIHex不區分16進制中A-F的大小寫,PDF中使用'>'作為結尾。
String name = "欣爸爸";
ByteArrayInputStream bais = new ByteArrayInputStream(name.getBytes());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
asciiHex.encode(bais, baos, new COSDictionary(), 0);
log.d(baos.toString()); // E6ACA3E788B8E788B8
baos.reset();
bais = new ByteArrayInputStream("e6aCA3e788B8E788B8>".getBytes());
asciiHex.decode(bais, baos, new COSDictionary(), 0);
log.d(baos.toString()); // 欣爸爸
String name = "欣爸爸";
ascii85.encode(bais, baos, new COSDictionary(), 0);
baos.reset();
bais = new ByteArrayInputStream("k,b?@Lq)W(\\,~>".getBytes());
ascii85.decode(bais, baos, new COSDictionary(), 0);
log.d(baos.toString()); // 欣爸爸
從PDF1.5開始,還可以把多個Obj對象放到同一個stream對象中壓縮,可進一步壓縮文件大小。這也是為什麼,我們分析PDF的時候Obj number不連續的原因,有些Obj被打包在一起了。
讀到這裡,你是否有點感覺了?Base64 / ASCIIHex / ASCII85 既沒壓縮數據,也沒加密數據,有什麼存在價值呢?這問題要從ASCII碼談起。一個字節的範圍是從0000 0000 到 1111 1111,但這256個數據并不全是可顯示字符,有些是控制字符。當以字符方式讀文件的時候,這些控制字符不會被當作數據處理,而會變成換行或者退格,或者終止等。
把二進制文件數據,映射到一個可顯示字符範圍,在傳輸和處理過程中不會被誤解,可以容易地反解出來,這可不是什麼加密技術。仔細觀察Base64、ASCII85包含一些編程語言的特殊字符,因此也有Base64和ASCII85的一些變種,把特殊符号換成其它字符。
以下是解析ASCIIHex的部分參考代碼:
while (true) {
int first = readHexDigit(); // 先讀取一個Hex
int second = readHexDigit();// 再讀取一個Hex
if (first == -1) { // Done
break;
} else if (second == -1) { // 如01110110 0010情況
baos.write((byte) (first << 4));
break;
} else { // 合在一起
baos.write((byte) ((first << 4) second));
}
}
下次,我們介紹壓縮算法LZWDecode和FlateDecode。歡迎關注點贊~
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!