> 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/get-started/samples/jbig2test.md).

# Compress PDF Images Using JBIG2: Sample Code

Sample code for using Apryse SDK to recompress bitonal (black and white) images in existing PDF documents using JBIG2 compression (lossless or lossy). Sample code provided in Python, C++, C#, Java, No

Sample code for using Apryse SDK to recompress bitonal (black and white) images in existing PDF documents using JBIG2 compression (lossless or lossy). The sample is intended to show how to specify hint information for the image encoder and is not meant to be a generic PDF optimization tool. To demonstrate the possible compression rates, we recompressed a document containing 17 scanned pages. The original input document is \~1.4MB and is using standard CCITT Fax compression. Lossless JBIG2 compression shrunk the filesize to 641KB, while lossy JBIG2 compression shrunk it to 176KB. Capabilities include programatically creating new fields and widget annotations, form filling, modifying existing field values, form templating, and flattening form fields.

Learn more about our [Server SDK](/core/get-started/get-started.md).

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

```csharp
//
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
//

using System;
using System.Drawing;
using System.Collections;

using pdftron;
using pdftron.Common;
using pdftron.Filters;
using pdftron.SDF;
using pdftron.PDF;

namespace JBIG2TestCS
{
	/// <summary>
	/// This sample project illustrates how to recompress bi-tonal images in an 
	/// existing PDF document using JBIG2 compression. The sample is not intended 
	/// to be a generic PDF optimization tool.
	/// 
	/// You can download a sample scanned document using the following link:
	///   http://www.pdftron.com/net/samplecode/data/US061222892.pdf
	///
	/// Also a sample page compressed using CCITT Fax compression is located under 
	/// 'PDFNet/Samples/TestFiles' folder.
	/// </summary>
	public class Class1
	{

		private static pdftron.PDFNetLoader pdfNetLoader = pdftron.PDFNetLoader.Instance();
		static Class1() {}
		
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		static void Main() 
		{
			// Initialize PDFNet before calling any other PDFNet function.
			PDFNet.Initialize(PDFTronLicense.Key);

			string input_path = "../../../../TestFiles/";
			string output_path = "../../../../TestFiles/Output/";
			string input_filename = "US061222892-a.pdf";
			
			PDFDoc pdf_doc = new PDFDoc(input_path + input_filename);
			pdf_doc.InitSecurityHandler();
			
			SDFDoc cos_doc = pdf_doc.GetSDFDoc();
			int num_objs = cos_doc.XRefSize();

			for (int i=1; i<num_objs; ++i) 
			{
				Obj obj = cos_doc.GetObj(i);
				if (obj!=null && !obj.IsFree()&& obj.IsStream()) 
				{
					// Process only images
					DictIterator itr = obj.Find("Subtype");
					if (!itr.HasNext() || itr.Value().GetName() != "Image") 
						continue; 
					
					pdftron.PDF.Image input_image = new pdftron.PDF.Image(obj);
					pdftron.PDF.Image new_image = null;

					// Process only gray-scale images
					if (input_image.GetComponentNum() != 1) 
						continue; 
					
					int bpc = input_image.GetBitsPerComponent();
					if (bpc != 1) // Recompress 1 BPC images
						continue;
					
					// Skip images that are already compressed using JBIG2
					itr = obj.Find("Filter");
					if (itr.HasNext() && itr.Value().IsName() && 
						itr.Value().GetName() == "JBIG2Decode") 
						continue; 

					FilterReader reader = new FilterReader(obj.GetDecodedStream());
					
					ObjSet hint_set = new ObjSet();
					Obj hint = hint_set.CreateArray();
					hint.PushBackName("JBIG2");
					hint.PushBackName("Lossless");
					hint.PushBackName("Threshold");
					hint.PushBackNumber(0.4);
					hint.PushBackName("SharePages");
					hint.PushBackNumber(10000);
					
					new_image = pdftron.PDF.Image.Create(
						cos_doc, 
						reader, 							
						input_image.GetImageWidth(), 
						input_image.GetImageHeight(), 
						1, 
						ColorSpace.CreateDeviceGray(),
						hint  // A hint to image encoder to use JBIG2 compression
						);

					Obj new_img_obj = new_image.GetSDFObj();

					// Copy any important entries from the image dictionary
					itr = obj.Find("ImageMask");
					if (itr.HasNext()) new_img_obj.Put("ImageMask", itr.Value());

					itr = obj.Find("Mask");
					if (itr.HasNext()) new_img_obj.Put("Mask", itr.Value());

					cos_doc.Swap(i, new_image.GetSDFObj().GetObjNum());
				}
			}
			
			pdf_doc.Save(output_path + "US061222892_JBIG2.pdf", SDFDoc.SaveOptions.e_remove_unused);
			pdf_doc.Close();
			PDFNet.Terminate();
		}
	}
}
```

{% endcode %}
{% endtab %}

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

```java
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

import com.pdftron.filters.Filter;
import com.pdftron.filters.FilterReader;
import com.pdftron.pdf.*;
import com.pdftron.sdf.DictIterator;
import com.pdftron.sdf.Obj;
import com.pdftron.sdf.ObjSet;
import com.pdftron.sdf.SDFDoc;

// This sample project illustrates how to recompress bi-tonal images in an 
// existing PDF document using JBIG2 compression. The sample is not intended 
// to be a generic PDF optimization tool.
//
// You can download the entire document using the following link:
//   http://www.pdftron.com/net/samplecode/data/US061222892.pdf
public class JBIG2Test {

    public static void main(String[] args) {
        PDFNet.initialize(PDFTronLicense.Key());

        String input_path = "../../TestFiles/";
        String output_path = "../../TestFiles/Output/";

        try (PDFDoc pdf_doc = new PDFDoc(input_path + "US061222892-a.pdf")) {
            pdf_doc.initSecurityHandler();

            SDFDoc cos_doc = pdf_doc.getSDFDoc();
            int num_objs = (int) cos_doc.xRefSize();
            for (int i = 1; i < num_objs; ++i) {
                Obj obj = cos_doc.getObj(i);
                if (obj != null && !obj.isFree() && obj.isStream()) {
                    // Process only images
                    DictIterator itr = obj.find("Subtype");
                    if (!itr.hasNext() || !itr.value().getName().equals("Image"))
                        continue;

                    Image input_image = new Image(obj);
                    // Process only gray-scale images
                    if (input_image.getComponentNum() != 1)
                        continue;
                    int bpc = input_image.getBitsPerComponent();
                    if (bpc != 1)    // Recompress only 1 BPC images
                        continue;

                    // Skip images that are already compressed using JBIG2
                    itr = obj.find("Filter");
                    if (itr.hasNext() && itr.value().isName() &&
                            !itr.value().getName().equals("JBIG2Decode")) continue;

                    Filter filter = obj.getDecodedStream();
                    FilterReader reader = new FilterReader(filter);

                    ObjSet hint_set = new ObjSet();
                    Obj hint = hint_set.createArray(); // A hint to image encoder to use JBIG2 compression
                    hint.pushBackName("JBIG2");
                    hint.pushBackName("Lossless");

                    Image new_image = Image.create(cos_doc, reader,
                            input_image.getImageWidth(),
                            input_image.getImageHeight(), 1, ColorSpace.createDeviceGray(), hint);

                    Obj new_img_obj = new_image.getSDFObj();
                    itr = obj.find("Decode");
                    if (itr.hasNext())
                        new_img_obj.put("Decode", itr.value());
                    itr = obj.find("ImageMask");
                    if (itr.hasNext())
                        new_img_obj.put("ImageMask", itr.value());
                    itr = obj.find("Mask");
                    if (itr.hasNext())
                        new_img_obj.put("Mask", itr.value());

                    cos_doc.swap(i, new_img_obj.getObjNum());
                }
            }

            pdf_doc.save(output_path + "US061222892_JBIG2.pdf", SDFDoc.SaveMode.REMOVE_UNUSED, null);
        } catch (Exception e) {
            e.printStackTrace();
        }

        PDFNet.terminate();
    }

}
```

{% endcode %}
{% endtab %}

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

```go
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2021 by PDFTron Systems Inc. All Rights Reserved.
// Consult LICENSE.txt regarding license information.
//---------------------------------------------------------------------------------------

package main
import (
	. "pdftron"
)

import  "pdftron/Samples/LicenseKey/GO"

// This sample project illustrates how to recompress bi-tonal images in an 
// existing PDF document using JBIG2 compression. The sample is not intended 
// to be a generic PDF optimization tool.
//
// You can download the entire document using the following link:
//   http://www.pdftron.com/net/samplecode/data/US061222892.pdf
// Relative path to the folder containing the test files.
var inputPath = "../../TestFiles/"
var outputPath = "../../TestFiles/Output/"

func main(){
    PDFNetInitialize(PDFTronLicense.Key)
    
    pdfDoc := NewPDFDoc(inputPath + "US061222892-a.pdf")
    pdfDoc.InitSecurityHandler()
    
    cosDoc := pdfDoc.GetSDFDoc()
    numObjs := cosDoc.XRefSize()
    
    i := uint(1)
    for i < numObjs{
        obj := cosDoc.GetObj(i)
        if obj != nil && ! obj.IsFree() && obj.IsStream(){
            // Process only images
            itr := obj.Find("Subtype")
            //if not itr.HasNext() or not itr.Value().GetName() == "Image":
            if !itr.HasNext() || !(itr.Value().GetName() == "Image"){
                i = i + 1
                continue
            }
            inputImage := NewImage(obj)
            // Process only gray-scale images
            if inputImage.GetComponentNum() != 1{
                i = i + 1
                continue
            }
            // Skip images that are already compressed using JBIG2
            itr = obj.Find("Filter")
            if (itr.HasNext() && itr.Value().IsName() && itr.Value().GetName() == "JBIG2Decode"){
                i = i + 1
                continue
            }

            filter := obj.GetDecodedStream()
            reader := NewFilterReader(filter)
            
            hintSet := NewObjSet()     // hint to image encoder to use JBIG2 compression
            hint := hintSet.CreateArray()
            
            hint.PushBackName("JBIG2")
            hint.PushBackName("Lossless")
            
            newImage := (ImageCreate(cosDoc, reader, 
                                     inputImage.GetImageWidth(), 
                                     inputImage.GetImageHeight(), 
                                     1, 
                                     ColorSpaceCreateDeviceGray(), 
                                     hint))
            
            newImgObj := newImage.GetSDFObj()
            itr = obj.Find("Decode")
            
            if itr.HasNext(){
                newImgObj.Put("Decode", itr.Value())
            }
            itr = obj.Find("ImageMask")
            if itr.HasNext(){
                newImgObj.Put("ImageMask", itr.Value())
            }
            itr = obj.Find("Mask")
            if itr.HasNext(){
                newImgObj.Put("Mask", itr.Value())
            }

            cosDoc.Swap(i, newImgObj.GetObjNum())
        }
        i = i + 1
    }

    pdfDoc.Save(outputPath + "US061222892_JBIG2.pdf", uint(SDFDocE_remove_unused))
    pdfDoc.Close()                
    PDFNetTerminate()
}
```

{% endcode %}
{% endtab %}

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

```cpp
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

#include <iostream>
#include <PDF/PDFNet.h>
#include <PDF/PDFDoc.h>
#include <PDF/ElementBuilder.h>
#include <Filters/FilterReader.h>
#include <SDF/ObjSet.h>
#include "../../LicenseKey/CPP/LicenseKey.h"

using namespace std;
using namespace pdftron;
using namespace Filters;
using namespace PDF;
using namespace SDF;
using namespace Common;

// This sample project illustrates how to recompress bi-tonal images in an 
// existing PDF document using JBIG2 compression. The sample is not intended 
// to be a generic PDF optimization tool.
//
// You can download the entire document using the following link:
//   http://www.pdftron.com/net/samplecode/data/US061222892.pdf
//
int main(int argc, char *argv[]) 
{
	PDFNet::Initialize(LicenseKey);
	
	try 
	{
		PDFDoc pdf_doc("../../TestFiles/US061222892-a.pdf");
		pdf_doc.InitSecurityHandler();

		SDFDoc& cos_doc = pdf_doc.GetSDFDoc();
		int num_objs = cos_doc.XRefSize();
		for(int i=1; i<num_objs; ++i) 
		{
			Obj obj = cos_doc.GetObj(i);
			if(obj && !obj.IsFree() && obj.IsStream()) 
			{
				// Process only images
				DictIterator itr = obj.Find("Subtype");
				if(!itr.HasNext() || strcmp(itr.Value().GetName(), "Image"))
					continue;
				
				Image input_image(obj);
				// Process only gray-scale images
				if(input_image.GetComponentNum() != 1)
					continue;
				int bpc = input_image.GetBitsPerComponent();
				if(bpc != 1)	// Recompress only 1 BPC images
					continue;

				// Skip images that are already compressed using JBIG2
				itr = obj.Find("Filter");
				if (itr.HasNext() && itr.Value().IsName() && 
					!strcmp(itr.Value().GetName(), "JBIG2Decode")) continue; 

				Filter filter=obj.GetDecodedStream();
				FilterReader reader(filter);


				ObjSet hint_set; 	// A hint to image encoder to use JBIG2 compression
				Obj hint=hint_set.CreateArray();
			
				hint.PushBackName("JBIG2");
				hint.PushBackName("Lossless");

				Image new_image = Image::Create(cos_doc, reader, 
					input_image.GetImageWidth(), 
					input_image.GetImageHeight(), 1, ColorSpace::CreateDeviceGray(), hint);

				Obj new_img_obj = new_image.GetSDFObj();
				itr = obj.Find("Decode");
				if(itr.HasNext())
					new_img_obj.Put("Decode", itr.Value());
				itr = obj.Find("ImageMask");
				if (itr.HasNext())
					new_img_obj.Put("ImageMask", itr.Value());
				itr = obj.Find("Mask");
				if (itr.HasNext())
					new_img_obj.Put("Mask", itr.Value());

				cos_doc.Swap(i, new_img_obj.GetObjNum());
			}
		}

		pdf_doc.Save("../../TestFiles/Output/US061222892_JBIG2.pdf", SDFDoc::e_remove_unused, 0);
	}
	catch(Common::Exception& e)
	{
		cout << e << endl;
		cout << "Please make sure that the pathname to the test file is correct." << endl;
	}
	catch(...)
	{
		cout << "Unknown Exception" << endl;
	}

	PDFNet::Terminate();
	return 0;
}
```

{% endcode %}
{% endtab %}

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

```js
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------


// This sample project illustrates how to recompress bi-tonal images in an 
// existing PDF document using JBIG2 compression. The sample is not intended 
// to be a generic PDF optimization tool.
//
// You can download the entire document using the following link:
//   http://www.pdftron.com/net/samplecode/data/US061222892.pdf
//

const { PDFNet } = require('@pdftron/pdfnet-node');
const PDFTronLicense = require('../LicenseKey/LicenseKey');

((exports) => {
  'use strict';

  exports.runJBIG2Test = () => {
    const main = async () => {
      try {
        const pdf_doc = await PDFNet.PDFDoc.createFromFilePath('../TestFiles/US061222892-a.pdf');
        pdf_doc.initSecurityHandler();

        const cos_doc = await pdf_doc.getSDFDoc();
        const num_objs = await cos_doc.xRefSize();
        for (let i = 1; i < num_objs; ++i) {
          const obj = await cos_doc.getObj(i);
          if (obj && !(await obj.isFree()) && await obj.isStream()) {
            // Process only images
            let itr = await obj.find('Subtype');
            if (!(await itr.hasNext()) || await (await itr.value()).getName() !== 'Image')
              continue;
            const input_image = await PDFNet.Image.createFromObj(obj);
            // Process only gray-scale images
            if (await input_image.getComponentNum() != 1)
              continue;
            if (await input_image.getBitsPerComponent() != 1) // Recompress only 1 BPC images
              continue;

            // Skip images that are already compressed using JBIG2
            itr = await obj.find('Filter');
            if (await itr.hasNext()) {
              const value = await itr.value();
              if (await value.isName() && await value.getName() === 'JBIG2Decode') continue;
            }

            const filter = await obj.getDecodedStream();
            const reader = await PDFNet.FilterReader.create(filter);

            const hint_set = await PDFNet.ObjSet.create();
            const hint = await hint_set.createArray();

            hint.pushBackName('JBIG2');
            hint.pushBackName('Lossless');

            const new_image = await PDFNet.Image.createFromStream(cos_doc, reader, await input_image.getImageWidth(),
              await input_image.getImageHeight(), 1, await PDFNet.ColorSpace.createDeviceGray(), hint);

            const new_img_obj = await new_image.getSDFObj();
            itr = await obj.find('Decode');
            if (await itr.hasNext())
              new_img_obj.put('Decode', await itr.value());
            itr = await obj.find('ImageMask');
            if (await itr.hasNext())
              new_img_obj.put('ImageMask', await itr.value());
            itr = await obj.find('Mask');
            if (await itr.hasNext())
              new_img_obj.put('Mask', await itr.value());

            await cos_doc.swap(i, await new_img_obj.getObjNum());
          }
        }

        pdf_doc.save('../TestFiles/Output/US061222892_JBIG2.pdf', PDFNet.SDFDoc.SaveOptions.e_remove_unused);
      } catch (err) {
        console.log(err);
      }
    };
    PDFNet.runWithCleanup(main, PDFTronLicense.Key).catch(function(error) {
      console.log('Error: ' + JSON.stringify(error));
    }).then(function(){ return PDFNet.shutdown(); });
  };
  exports.runJBIG2Test();
})(exports);
// eslint-disable-next-line spaced-comment
//# sourceURL=JBIG2Test.js
```

{% endcode %}
{% endtab %}

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

```php
<?php
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
// Consult LICENSE.txt regarding license information.
//---------------------------------------------------------------------------------------
if(file_exists("../../../PDFNetC/Lib/PDFNetPHP.php"))
include("../../../PDFNetC/Lib/PDFNetPHP.php");
include("../../LicenseKey/PHP/LicenseKey.php");

// Relative path to the folder containing the test files.
$input_path = getcwd()."/../../TestFiles/";
$output_path = $input_path."Output/";

// This sample project illustrates how to recompress bi-tonal images in an 
// existing PDF document using JBIG2 compression. The sample is not intended 
// to be a generic PDF optimization tool.
//
// You can download the entire document using the following link:
//   http://www.pdftron.com/net/samplecode/data/US061222892.pdf

	PDFNet::Initialize($LicenseKey);
	PDFNet::GetSystemFontList();    // Wait for fonts to be loaded if they haven't already. This is done because PHP can run into errors when shutting down if font loading is still in progress.

	$pdf_doc = new PDFDoc("../../TestFiles/US061222892-a.pdf") ;
	$pdf_doc->InitSecurityHandler();

	$cos_doc = $pdf_doc->GetSDFDoc();
	$num_objs = $cos_doc->XRefSize();
	for($i = 1; $i < $num_objs; ++$i) 
	{
		$obj = $cos_doc->GetObj($i);
		if($obj && !$obj->IsFree() && $obj->IsStream()) 
		{
			// Process only images
			$itr = $obj->Find("Subtype");
			if(!$itr->HasNext() || $itr->Value()->GetName() != "Image")
				continue;
			
			$input_image = new Image($obj);
			// Process only gray-scale images
			if($input_image->GetComponentNum() != 1)
				continue;
			$bpc = $input_image->GetBitsPerComponent();
			if($bpc != 1)	// Recompress only 1 BPC images
				continue;

			// Skip images that are already compressed using JBIG2
			$itr = $obj->Find("Filter");
			if ($itr->HasNext() && $itr->Value()->IsName() && 
				$itr->Value()->GetName() == "JBIG2Decode") continue; 

			$filter=$obj->GetDecodedStream();
			$reader = new FilterReader($filter);


			$hint_set = new ObjSet(); 	// A hint to image encoder to use JBIG2 compression
			$hint=$hint_set->CreateArray();
			
			$hint->PushBackName("JBIG2");
			$hint->PushBackName("Lossless");

			$new_image = Image::Create($cos_doc, $reader, 
				$input_image->GetImageWidth(), 
				$input_image->GetImageHeight(), 1, ColorSpace::CreateDeviceGray(), $hint);

			$new_img_obj = $new_image->GetSDFObj();
			$itr = $obj->Find("Decode");
			if($itr->HasNext())
				$new_img_obj->Put("Decode", $itr->Value());
			$itr = $obj->Find("ImageMask");
			if ($itr->HasNext())
				$new_img_obj->Put("ImageMask", $itr->Value());
			$itr = $obj->Find("Mask");
			if ($itr->HasNext())
				$new_img_obj->Put("Mask", $itr->Value());

			$cos_doc->Swap($i, $new_img_obj->GetObjNum());
		}
	}

	$pdf_doc->Save("../../TestFiles/Output/US061222892_JBIG2.pdf", SDFDoc::e_remove_unused);
	$pdf_doc->Close();
	PDFNet::Terminate();
	echo "Done.";
?>
```

{% endcode %}
{% endtab %}

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

```python
#---------------------------------------------------------------------------------------
# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
# Consult LICENSE.txt regarding license information.
#---------------------------------------------------------------------------------------

import site
site.addsitedir("../../../PDFNetC/Lib")
import sys
from PDFNetPython import *

sys.path.append("../../LicenseKey/PYTHON")
from LicenseKey import *


# This sample project illustrates how to recompress bi-tonal images in an 
# existing PDF document using JBIG2 compression. The sample is not intended 
# to be a generic PDF optimization tool.
#
# You can download the entire document using the following link:
#   http://www.pdftron.com/net/samplecode/data/US061222892.pdf

def main():
    PDFNet.Initialize(LicenseKey)
    
    pdf_doc = PDFDoc("../../TestFiles/US061222892-a.pdf")
    pdf_doc.InitSecurityHandler()
    
    cos_doc = pdf_doc.GetSDFDoc()
    num_objs = cos_doc.XRefSize()
    
    i = 1
    while i < num_objs:
        obj = cos_doc.GetObj(i)
        if obj is not None and not obj.IsFree() and obj.IsStream():
            # Process only images
            itr = obj.Find("Subtype")
            if not itr.HasNext() or not itr.Value().GetName() == "Image":
                i = i + 1
                continue
            
            input_image = Image(obj)
            # Process only gray-scale images
            if input_image.GetComponentNum() != 1:
                i = i + 1
                continue
            
            # Skip images that are already compressed using JBIG2
            itr = obj.Find("Filter")
            if (itr.HasNext() and itr.Value().IsName() and itr.Value().GetName() == "JBIG2Decode"):
                i = i + 1
                continue
            
            filter = obj.GetDecodedStream()
            reader = FilterReader(filter)
            
            hint_set = ObjSet()     # hint to image encoder to use JBIG2 compression
            hint = hint_set.CreateArray()
            
            hint.PushBackName("JBIG2")
            hint.PushBackName("Lossless")
            
            new_image = (Image.Create(cos_doc, reader, 
                                     input_image.GetImageWidth(), 
                                     input_image.GetImageHeight(), 
                                     1, 
                                     ColorSpace.CreateDeviceGray(), 
                                     hint))
            
            new_img_obj = new_image.GetSDFObj()
            itr = obj.Find("Decode")
            
            if itr.HasNext():
                new_img_obj.Put("Decode", itr.Value())
            itr = obj.Find("ImageMask")
            if itr.HasNext():
                new_img_obj.Put("ImageMask", itr.Value())
            itr = obj.Find("Mask")
            if itr.HasNext():
                new_img_obj.Put("Mask", itr.Value())
                
            cos_doc.Swap(i, new_img_obj.GetObjNum())
        i = i + 1
            
    pdf_doc.Save("../../TestFiles/Output/US061222892_JBIG2.pdf", SDFDoc.e_remove_unused)
    pdf_doc.Close()                
    PDFNet.Terminate()

if __name__ == '__main__':
    main()
```

{% endcode %}
{% endtab %}

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

```ruby
#---------------------------------------------------------------------------------------
# Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
# Consult LICENSE.txt regarding license information.
#---------------------------------------------------------------------------------------

require '../../../PDFNetC/Lib/PDFNetRuby'
include PDFNetRuby
require '../../LicenseKey/RUBY/LicenseKey'

$stdout.sync = true

# This sample project illustrates how to recompress bi-tonal images in an 
# existing PDF document using JBIG2 compression. The sample is not intended 
# to be a generic PDF optimization tool.
#
# You can download the entire document using the following link:
#   http://www.pdftron.com/net/samplecode/data/US061222892.pdf

	PDFNet.Initialize(PDFTronLicense.Key)
	
	pdf_doc = PDFDoc.new("../../TestFiles/US061222892-a.pdf")
	pdf_doc.InitSecurityHandler
	
	cos_doc = pdf_doc.GetSDFDoc
	num_objs = cos_doc.XRefSize
	
	i = 1
	while i < num_objs do
		obj = cos_doc.GetObj(i)
		if !obj.nil? and !obj.IsFree and obj.IsStream
			# Process only images
			itr = obj.Find("Subtype")
			if !itr.HasNext or !itr.Value.GetName == "Image"
				i = i + 1
				next
			end
			
			input_image = Image.new(obj)
			# Process only gray-scale images
			if input_image.GetComponentNum != 1
				i = i + 1
				next
			end			

			# Skip images that are already compressed using JBIG2
			itr = obj.Find("Filter")
			if itr.HasNext and itr.Value.IsName and itr.Value.GetName == "JBIG2Decode"
				i = i + 1
				next
			end
			
			filter = obj.GetDecodedStream
			reader = FilterReader.new(filter)
			
			hint_set = ObjSet.new	 # hint to image encoder to use JBIG2 compression
			hint = hint_set.CreateArray
			
			hint.PushBackName("JBIG2")
			hint.PushBackName("Lossless")
			
			new_image = Image.Create(cos_doc, reader, 
						input_image.GetImageWidth, 
						input_image.GetImageHeight, 
						1, 
						ColorSpace.CreateDeviceGray, 
						hint)
			
			new_img_obj = new_image.GetSDFObj
			itr = obj.Find("Decode")
			
			if itr.HasNext
				new_img_obj.Put("Decode", itr.Value)
			end
			itr = obj.Find("ImageMask")
			if itr.HasNext
				new_img_obj.Put("ImageMask", itr.Value)
			end
			itr = obj.Find("Mask")
			if itr.HasNext
				new_img_obj.Put("Mask", itr.Value)
			end
				
			cos_doc.Swap(i, new_img_obj.GetObjNum)
		end
		i = i + 1
	end
			
	pdf_doc.Save("../../TestFiles/Output/US061222892_JBIG2.pdf", SDFDoc::E_remove_unused)
	pdf_doc.Close
	PDFNet.Terminate
```

{% endcode %}
{% endtab %}

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

```vb
'
' Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
'
Imports System.Windows.Forms

Imports pdftron
Imports pdftron.Common
Imports pdftron.Filters
Imports pdftron.SDF
Imports pdftron.PDF

' This sample project illustrates how to recompress bi-tonal images in an 
' existing PDF document using JBIG2 compression. The sample is not intended 
' to be a generic PDF optimization tool.
' 
' You can download a sample scanned document using the following link:
'   http://www.pdftron.com/net/samplecode/data/US061222892.pdf
'
' Also a sample page compressed using CCITT Fax compression is located under 
' 'PDFNet/Samples/TestFiles' folder.

Module Program
    Dim pdfNetLoader As PDFNetLoader
    Sub New()
        pdfNetLoader = pdftron.PDFNetLoader.Instance()
    End Sub

    Sub Main(args As String())
        ' Initialize PDFNet before calling any other PDFNet function.
        PDFNet.Initialize(PDFTronLicense.Key)

        Dim pdfdoc As PDFDoc = New PDFDoc("../../../../TestFiles/US061222892-a.pdf")
        pdfdoc.InitSecurityHandler()
        Dim cos_doc As SDFDoc = pdfdoc.GetSDFDoc()
        Dim num_objs As Integer = cos_doc.XRefSize()

        For i As Integer = 1 To num_objs - 1
            Dim obj As Obj = cos_doc.GetObj(i)
            If Not (obj Is Nothing Or obj.IsFree()) Then
                ' Process only images
                If obj.IsStream() Then
                    Dim itr As DictIterator = obj.Find("Subtype")
                    If itr.HasNext() Then
                        If itr.Value().GetName() = "Image" Then
                            Dim input_image As pdftron.PDF.Image = New pdftron.PDF.Image(obj)
                            Dim new_image As pdftron.PDF.Image = Nothing

                            ' Process only gray-scale images
                            If input_image.GetComponentNum() = 1 Then
                                Dim bpc As Integer = input_image.GetBitsPerComponent()
                                If bpc = 1 Then
                                    Dim reader As FilterReader = New FilterReader(obj.GetDecodedStream())

                                    Dim hint_set As ObjSet = New ObjSet
                                    Dim hint As Obj = hint_set.CreateArray()
                                    hint.PushBackName("JBIG2")
                                    ' hint.PushBackName("Lossless")
                                    hint.PushBackName("Threshold")
                                    hint.PushBackNumber(0.4)
                                    hint.PushBackName("SharePages")
                                    hint.PushBackNumber(10000)

                                    new_image = pdftron.PDF.Image.Create(cos_doc, reader, input_image.GetImageWidth(), input_image.GetImageHeight(), 1, ColorSpace.CreateDeviceGray(), hint)
                                End If

                                If Not new_image Is Nothing Then
                                    Dim new_img_obj As Obj = new_image.GetSDFObj()

                                    ' Copy any important entries from the image dictionary
                                    itr = obj.Find("ImageMask")
                                    If itr.HasNext() Then
                                        new_img_obj.Put("ImageMask", itr.Value())
                                    End If
                                    itr = obj.Find("Mask")
                                    If itr.HasNext() Then
                                        new_img_obj.Put("Mask", itr.Value())
                                    End If
                                    cos_doc.Swap(i, new_image.GetSDFObj().GetObjNum())
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        Next

        pdfdoc.Save("../../../../TestFiles/Output/US061222892_JBIG2.pdf", SDFDoc.SaveOptions.e_remove_unused)
        pdfdoc.Close()
        PDFNet.Terminate()
    End Sub
End Module
```

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


---

# 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/get-started/samples/jbig2test.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.
