> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/core/low-level-pdf-api/filters.md).

# Filters and streams on Server/Desktop

Learn about SDF stream objects and filter pipelines in PDF documents with Apryse SDK. Explore how to efficiently process streams using various filters for data transformation and extraction. The Aprys

One of the basic building blocks of a PDF document is an SDF stream object. For example, in a PDF document all page content, images, embedded fonts, and files are represented using object streams that can be compressed and encrypted using various Filter chains. See the "Stream Objects" and "Filters" chapters in the PDF Reference Manual for more details.

Apryse SDK supports an efficient and flexible architecture for processing streams using filter pipelines.

A *filter* is an abstraction of a sequence of bytes, such as a file, an input/output device, an inter-process communication pipe, or a TCP/IP socket. A filter can also perform certain transformations of input/output data (e.g. data compression/decompression, color conversion, and so on).

## Input filters/streams

Apryse SDK enables generic input from external files using the MappedFile filter. Use MappedFile to open, read from, and close files on a file system. For example:

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
MappedFile file = new MappedFile(filename);
SDFDoc doc_stream = new SDFDoc(file);
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
MappedFile file(filename);
SDFDoc doc_stream(file);
```

{% endcode %}
{% endtab %}

{% tab title="Go" %}
{% code lineNumbers="true" %}

```go
file := NewMappedFile(filename)
docStream := NewSDFDoc(file)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
MappedFile file = new MappedFile(filename);
SDFDoc doc_stream = new SDFDoc(file);
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
async function main() {
  const file = await PDFNet.Filter.createURLFilter(filename);
  const doc_stream = await PDFNet.SDFDoc.createFromFilter(file);
}
PDFNet.runWithCleanup(main);
```

{% endcode %}

[PDFNet.Filter.createURLFilter ](https://sdk.apryse.com/api/web/Core.PDFNet.Filter.html#.createURLFilter__anchor)[PDFNet.PDFDoc](https://sdk.apryse.com/api/web/Core.PDFNet.PDFDoc.html#.createFromFilter__anchor)
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
val file = MappedFile(filename)
val doc_stream = SDFDoc(file)
```

{% endcode %}
{% endtab %}

{% tab title="Obj-C" %}
{% code lineNumbers="true" %}

```objc
PTMappedFile *file = [[PTMappedFile alloc] initWithFilename: filename];
PTSDFDoc *doc_stream = [[PTSDFDoc alloc] initWithStream: file];
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code lineNumbers="true" %}

```swift
let file: PTMappedFile = PTMappedFile(filename: filename)
let doc_stream: PTSDFDoc = PTSDFDoc(stream: file)
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
$file = new MappedFile($filename);
$doc_stream = new SDFDoc($file);
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
file = MappedFile(filename)
doc_stream = SDFDoc(file)
```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code lineNumbers="true" %}

```ruby
file = MappedFile(filename)
doc_stream = SDFDoc.new(file)
```

{% endcode %}
{% endtab %}

{% tab title="VB" %}
{% code lineNumbers="true" %}

```vb
Dim file As MappedFile = New MappedFile(filename)
Dim doc_stream As SDFDoc = New SDFDoc(file)
```

{% endcode %}
{% endtab %}
{% endtabs %}

Opens an external image file for reading. MappedFile buffers input and output for better performance. Although it is possible to read input data directly through the Filter interface (MappedFile is a subclass of Filter), it is more convenient to attach a FilterReader to the filter and then read data through FilterReader interface:

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
long file_sz = file.FileSize();
FilterReader file_reader = new FilterReader(file);
byte[] mem = new byte[(int) file_sz];
long bytes_read = file_reader.Read(mem);
SDFDoc doc_mem = new SDFDoc(mem, file_sz);
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
size_t file_sz = file.FileSize();
FilterReader file_reader(file);
unsigned char* mem = new unsigned char[file_sz];
file_reader.Read((unsigned char*)mem, file_sz);
SDFDoc doc_mem(mem, file_sz);
```

{% endcode %}
{% endtab %}

{% tab title="Go" %}
{% code lineNumbers="true" %}

```go
fileSZ := file.FileSize()
fileReader := NewFilterReader(file)
mem := fileReader.Read(fileSZ)
memBytes := make([]byte, int(mem.Size()))
for i := 0; i < int(mem.Size()); i++{
  memBytes[i] = mem.Get(i)
}
doc := NewSDFDoc(&memBytes[0], fileSZ)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
long file_sz = file.fileSize();
FilterReader file_reader = new FilterReader(file);
byte[] mem = new byte[(int) file_sz];
long bytes_read = file_reader.read(mem);
SDFDoc doc_mem = new SDFDoc(mem, file_sz);
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
async function main() {
  const file_sz = await file.size();
  const file_reader = await PDFNet.FilterReader.create(file);
  const mem = await file_reader.read(file_sz);
  const doc_mem = await PDFNet.SDFDoc.createFromBuffer(mem);
}
PDFNet.runWithCleanup(main);
```

{% endcode %}

[PDFNet.FilterReader.create](https://sdk.apryse.com/api/web/Core.PDFNet.FilterReader.html#.create__anchor) [PDFNet.FilterReader.read](https://sdk.apryse.com/api/web/Core.PDFNet.FilterReader.html#read__anchor)
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
val file_sz = file.fileSize()
val file_reader = FilterReader(file)
val mem = ByteArray(file_sz.toInt())
val bytes_read = file_reader.read(mem)
val doc_mem = SDFDoc(mem)
```

{% endcode %}
{% endtab %}

{% tab title="Obj-C" %}
{% code lineNumbers="true" %}

```objc
unsigned long file_sz = [file FileSize];
PTFilterReader *file_reader = [[PTFilterReader alloc] initWithFilter: file];
NSData *mem = [file_reader Read: file_sz];
PTSDFDoc *doc_mem = [[PTSDFDoc alloc] initWithBuf: mem buf_size: file_sz];
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code lineNumbers="true" %}

```swift
let file_sz: UInt = file.fileSize()
let file_reader: PTFilterReader = PTFilterReader(filter: file)
let mem: Data = file_reader.read(file_sz)
let doc_mem: PTSDFDoc = PTSDFDoc(buf: mem, buf_size: file_sz)
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
$file_sz = $file->FileSize();
$file_reader = new FilterReader($file);
$mem = $file_reader->Read($file_sz);
$doc_mem = new SDFDoc($mem, $file_sz);
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
file_sz = file.FileSize()
file_reader = FilterReader(file)
mem = file_reader.Read(file_sz)
doc_mem = SDFDoc(bytearray(mem), file_sz)
```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code lineNumbers="true" %}

```ruby
file_sz = file.FileSize()
file_reader = FilterReader.new(file)
mem = file_reader.Read(file_sz)
doc_mem = SDFDoc.new(mem, file_sz)
```

{% endcode %}
{% endtab %}

{% tab title="VB" %}
{% code lineNumbers="true" %}

```vb
Dim file_sz As Long = file.FileSize()
Dim file_reader As FilterReader = New FilterReader(file)
Dim mem(file_sz) As Byte
Dim bytes_read As Long = file_reader.Read(mem)
Dim doc_mem As SDFDoc = New SDFDoc(mem, file_sz)
```

{% endcode %}
{% endtab %}
{% endtabs %}

Data associated with SDF stream objects can be accessed using `Stream.GetRawStream()` or `Stream.GetDecodedStream()` methods.

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
Obj stream = doc.GetTrailer();
Filter dec_stm = stream.GetDecodedStream();
FilterReader reader = new FilterReader(dec_stm);
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
Obj stream = doc.GetTrailer();
Filter dec_stm = stream.GetDecodedStream();
FilterReader reader(dec_stm);
```

{% endcode %}
{% endtab %}

{% tab title="Go" %}
{% code lineNumbers="true" %}

```go
stream := doc.GetTrailer()
decStm := stream.GetDecodedStream()
fileReader := NewFilterReader(decStm)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
Obj stream = doc.getTrailer();
Filter dec_stm = stream.getDecodedStream();
FilterReader reader = new FilterReader(dec_stm);
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
async function main() {
  const stream = await doc.getTrailer();
  const dec_stm = await stream.getDecodedStream();
  const reader = await PDFNet.FilterReader.create(dec_stm);
}
PDFNet.runWithCleanup(main);
```

{% endcode %}

[PDFNet.SDFDoc.getTrailer](https://sdk.apryse.com/api/web/Core.PDFNet.SDFDoc.html#getTrailer__anchor) [PDFNet.Obj.getDecodedStream](https://sdk.apryse.com/api/web/Core.PDFNet.Obj.html#getDecodedStream__anchor) [PDFNet.FilterReader.create](https://sdk.apryse.com/api/web/Core.PDFNet.FilterReader.html#.create__anchor)
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
val stream = doc.trailer()
val dec_stm = stream.getDecodedStream();
val reader = FilterReader(dec_stm)
```

{% endcode %}
{% endtab %}

{% tab title="Obj-C" %}
{% code lineNumbers="true" %}

```objc
PTObj *stream = [doc GetTrailer];
PTFilter *dec_stm = [stream GetDecodedStream];
PTFilterReader *reader = [[PTFilterReader alloc] initWithFilter: dec_stm];
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code lineNumbers="true" %}

```swift
let stream: PTObj = doc.getTrailer()
let dec_stm: PTFilter = stream.getDecodedStream()
let reader: PTFilterReader = PTFilterReader(filter: dec_stm)
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
$stream = $doc->GetTrailer();
$dec_stm = $stream->GetDecodedStream();
$reader = new FilterReader($dec_stm);
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
stream = doc.GetTrailer()
dec_stm = stream.GetDecodedStream()
reader = FilterReader(dec_stm)
```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code lineNumbers="true" %}

```ruby
stream = doc.GetTrailer()
dec_stm = stream.GetDecodedStream()
reader = FilterReader.new(dec_stm)
```

{% endcode %}
{% endtab %}

{% tab title="VB" %}
{% code lineNumbers="true" %}

```vb
Dim stream As Obj = doc.GetTrailer()
Dim dec_stm As Filter = stream.GetDecodedStream()
Dim reader As FilterReader = New FilterReader(dec_stm)
```

{% endcode %}
{% endtab %}
{% endtabs %}

`Stream.GetRawStream()` creates a Filter used to extract raw data as it appears in a serialized SDF document (or a decrypted version of the stream if the document is secured). `Stream.GetDecodedStream()` creates a Filter pipeline and returns the last filter in the chain. For example, a given stream may be compressed using JPEG (DCTDecode) compression and encoded using ASCII85 into an ASCII stream. When `GetDecodedStream()` is invoked on this SDF stream, it will return the last filter in a chain that composed of three filters (the file segment input Filter, the DCTDecode Filter, and the ASCII85Decode Filter, respectively). Data extracted from the returned Filter will be raw image data (i.e. RGB byte triples).

It's possible to iterate through the Filter chain using the `Filter.GetAttachedFilter()` method. It's also possible to construct new filter chains, and to edit existing ones, using the `Filter.AttachFilter()` method.

## Output filters/streams

To write a filter to a file, simply use `Filter.WriteToFile():`

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
dec_stm.WriteToFile(output_filename, false);
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
dec_stm.WriteToFile(output_filename, false);
```

{% endcode %}
{% endtab %}

{% tab title="Go" %}
{% code lineNumbers="true" %}

```go
decStm.WriteToFile(output_filename, false)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
dec_stm.writeToFile(output_filename, false);
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
async function main() {
  const reader = await PDFNet.FilterReader.create(dec_stm);
  const buf = await reader.read(data_length);

  //optionally save the blob to a file or upload to a server
  const blob = new Blob([buf], { type: 'application/octet-stream' });
}
PDFNet.runWithCleanup(main);
```

{% endcode %}

[PDFNet.FilterReader.create](https://sdk.apryse.com/api/web/Core.PDFNet.FilterReader.html#.create__anchor) [PDFNet.FilterReader.read](https://sdk.apryse.com/api/web/Core.PDFNet.FilterReader.html#read__anchor)
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
dec_stm.writeToFile(output_filename, false);
```

{% endcode %}
{% endtab %}

{% tab title="Obj-C" %}
{% code lineNumbers="true" %}

```objc
[dec_stm WriteToFile: output_filename append: false];
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code lineNumbers="true" %}

```swift
dec_stm.write(toFile: output_filename, append: false)
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
$dec_stm->WriteToFile($output_filename, false);
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
dec_stm.WriteToFile(output_filename, false)
```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code lineNumbers="true" %}

```ruby
dec_stm.WriteToFile(output_filename, false)
```

{% endcode %}
{% endtab %}

{% tab title="VB" %}
{% code lineNumbers="true" %}

```vb
dec_stm.WriteToFile(output_filename, false)
```

{% endcode %}
{% endtab %}
{% endtabs %}

To modify or add to an output file filter/stream, simply use the FilterWriter class:

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
FilterWriter writer = new FilterWriter(dec_stm);
writer.WriteString("Hello World");
writer.Flush();
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
FilterWriter writer(dec_stm);
writer.WriteString("Hello World");
writer.Flush();
```

{% endcode %}
{% endtab %}

{% tab title="Go" %}
{% code lineNumbers="true" %}

```go
writer := NewFilterWriter(decStm)
writer.WriteString("Hello World")
writer.Flush()
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
FilterWriter writer = new FilterWriter(dec_stm);
writer.writeString("Hello World");
writer.flush();
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
async function main() {
  const writer = await PDFNet.FilterWriter.create(dec_stm);
  writer.writeString("Hello World");
  writer.flush();
}
PDFNet.runWithCleanup(main);
```

{% endcode %}

[PDFNet.FilterWriter.create](https://sdk.apryse.com/api/web/Core.PDFNet.FilterWriter.html#.create__anchor) [PDFNet.FilterWriter.writeString](https://sdk.apryse.com/api/web/Core.PDFNet.FilterWriter.html#writeString__anchor) [PDFNet.FilterWriter.flush](https://sdk.apryse.com/api/web/Core.PDFNet.FilterWriter.html#flush__anchor)
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
val writer = new FilterWriter(dec_stm);
writer.writeString("Hello World");
writer.flush();
```

{% endcode %}
{% endtab %}

{% tab title="Obj-C" %}
{% code lineNumbers="true" %}

```objc
PTFilterWriter *writer = [[PTFilterWriter alloc] initWithFilter: dec_stm];
[writer WriteString: @"Hello World"];
[writer Flush];
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code lineNumbers="true" %}

```swift
let writer: PTFilterWriter = PTFilterWriter(filter: dec_stm)
writer.write("Hello World")
writer.flush()
```

{% endcode %}
{% endtab %}

{% tab title="PHP" %}
{% code lineNumbers="true" %}

```php
$writer = new FilterWriter($dec_stm);
$writer.writeString("Hello World");
$writer.flush();
```

{% endcode %}
{% endtab %}

{% tab title="Python" %}
{% code lineNumbers="true" %}

```python
writer = FilterWriter(dec_stm)
writer.writeString("Hello World")
writer.flush()
```

{% endcode %}
{% endtab %}

{% tab title="Ruby" %}
{% code lineNumbers="true" %}

```ruby
writer = FilterWriter.new(dec_stm)
writer.writeString("Hello World")
writer.flush()
```

{% endcode %}
{% endtab %}

{% tab title="VB" %}
{% code lineNumbers="true" %}

```vb
Dim writer As FilterWriter = New FilterWriter(dec_stm)
writer.writeString("Hello World")
writer.flush()
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Implement custom filters

Apryse SDK provides full support for all common Filters used in PDF. Although included Filters should cover all common use case scenarios, advanced users may want to provide custom implementations for certain filters (e.g. custom color conversion, or a new compression method). Apryse SDK provides an open and expandable architecture for creation of custom filters. To implement a custom Filter, derive a new class from Filter base class and implement the required interface.

Please contact [support@apryse.com](https://docs.apryse.com) for more details.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/core/low-level-pdf-api/filters.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
