Decode a stream based on its /Filter declarations.
(data: Buffer, dict: string)
| 99 | |
| 100 | /** Decode a stream based on its /Filter declarations. */ |
| 101 | async function decodeStream(data: Buffer, dict: string): Promise<Buffer | null> { |
| 102 | // Detect filter — most common is FlateDecode (zlib). LZW/RunLength rare in modern PDFs. |
| 103 | const filterMatch = dict.match(/\/Filter\s*(?:\[\s*)?\/(FlateDecode|LZWDecode|ASCII85Decode|RunLengthDecode|ASCIIHexDecode|DCTDecode|CCITTFaxDecode)/); |
| 104 | if (!filterMatch) { |
| 105 | // No filter — return as-is |
| 106 | return data; |
| 107 | } |
| 108 | const filter = filterMatch[1]; |
| 109 | if (filter === 'FlateDecode') { |
| 110 | try { |
| 111 | return await inflate(data); |
| 112 | } catch { |
| 113 | try { return await inflateRaw(data); } catch { return null; } |
| 114 | } |
| 115 | } |
| 116 | // DCT (JPEG) / CCITT (fax) / etc — these are image streams, we skip them |
| 117 | if (filter === 'DCTDecode' || filter === 'CCITTFaxDecode') return null; |
| 118 | // Other filters not handled — skip |
| 119 | return null; |
| 120 | } |
| 121 | |
| 122 | /** |
| 123 | * Extract text from a PDF content stream. The stream contains a sequence of |