This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pdfbox-jbig2.git


The following commit(s) were added to refs/heads/master by this push:
     new fed4a68  PDFBOX-6162: add javadoc; add unit tests
fed4a68 is described below

commit fed4a68a5b70730bcbe0b7b994ab994bb64a0dbf
Author: Maruan Sahyoun <[email protected]>
AuthorDate: Fri Apr 24 15:20:59 2026 +0200

    PDFBOX-6162: add javadoc; add unit tests
---
 .../apache/pdfbox/jbig2/decoder/arithmetic/CX.java |  41 +++-
 .../pdfbox/jbig2/decoder/arithmetic/CXTest.java    | 206 +++++++++++++++++++++
 2 files changed, 243 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/apache/pdfbox/jbig2/decoder/arithmetic/CX.java 
b/src/main/java/org/apache/pdfbox/jbig2/decoder/arithmetic/CX.java
index a5037ba..b791608 100644
--- a/src/main/java/org/apache/pdfbox/jbig2/decoder/arithmetic/CX.java
+++ b/src/main/java/org/apache/pdfbox/jbig2/decoder/arithmetic/CX.java
@@ -18,8 +18,29 @@
 package org.apache.pdfbox.jbig2.decoder.arithmetic;
 
 /**
- * CX represents the context used by arithmetic decoding and arithmetic 
integer decoding. It selects the probability
- * estimate and statistics used during decoding procedure.
+ * Arithmetic coding context used during JBIG2 bitstream decoding.
+ * 
+ * <p>Represents a context in the arithmetic decoder that selects probability
+ * estimates and statistics used during decoding procedures, as defined in
+ * ITU-T Rec. T.88 (2000 E), ISO/IEC 14492:2001.</p>
+ * 
+ * <p><b>Context State:</b></p>
+ * <ul>
+ *   <li>{@code cx} array: Stores the probability estimate index (0-127) for 
each context state</li>
+ *   <li>{@code mps} array: Stores the most probable symbol (0 or 1) for each 
context state</li>
+ *   <li>{@code index}: Current context index, selected based on the 
neighborhood pattern
+ *       (template-specific arrangement of previously decoded pixels)</li>
+ * </ul>
+ * 
+ * <p><b>Usage:</b>
+ * The index is set before each decision to select which context state to use.
+ * After decoding, the arithmetic decoder updates the selected context's 
probability
+ * estimate and MPS based on the decoded symbol (see Annex A, T.88).</p>
+ * 
+ * <p><b>Reuse:</b>
+ * When arithmetic coding contexts are retained and reused across segments 
(§7.4.2.2),
+ * a {@link #copy()} must be created to avoid sharing mutable probability state
+ * between decoders.</p>
  */
 public final class CX
 {
@@ -29,8 +50,11 @@ public final class CX
     private final byte mps[];
 
     /**
-     * @param size - Amount of context values.
-     * @param index - Start index.
+     * Creates a new context with the specified number of context states.
+     * All probability estimates are initialized to 0, and all MPS values are 
initialized to 0.
+     * 
+     * @param size the number of context states
+     * @param index the initial context index
      */
     public CX(int size, int index)
     {
@@ -70,6 +94,15 @@ public final class CX
         return index;
     }
 
+    /**
+     * Sets the context index used for subsequent decoding decisions.
+     * The index selects which context state's probability estimate and MPS 
will be used.
+     * 
+     * <p>The index value is typically computed from the neighboring pixels in 
the template
+     * (§6.2.5.1 for generic regions, §6.4.7.1 for text regions).</p>
+     * 
+     * @param index the context index (0 to size-1)
+     */
     public void setIndex(int index)
     {
         this.index = index;
diff --git 
a/src/test/java/org/apache/pdfbox/jbig2/decoder/arithmetic/CXTest.java 
b/src/test/java/org/apache/pdfbox/jbig2/decoder/arithmetic/CXTest.java
new file mode 100644
index 0000000..01543a9
--- /dev/null
+++ b/src/test/java/org/apache/pdfbox/jbig2/decoder/arithmetic/CXTest.java
@@ -0,0 +1,206 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.pdfbox.jbig2.decoder.arithmetic;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CXTest
+{
+
+    @Test
+    public void testInitialization()
+    {
+        // Test that CX is initialized with correct size and index
+        CX cx = new CX(512, 5);
+        
+        Assert.assertEquals(5, cx.getIndex());
+        // After initialization, cx value should be 0 (unset)
+        Assert.assertEquals(0, cx.cx());
+        // After initialization, mps should be 0
+        Assert.assertEquals(0, cx.mps());
+    }
+
+    @Test
+    public void testSetAndGetIndex()
+    {
+        CX cx = new CX(100, 0);
+        
+        cx.setIndex(50);
+        Assert.assertEquals(50, cx.getIndex());
+        
+        cx.setIndex(99);
+        Assert.assertEquals(99, cx.getIndex());
+        
+        cx.setIndex(0);
+        Assert.assertEquals(0, cx.getIndex());
+    }
+
+    @Test
+    public void testSetAndGetCx()
+    {
+        CX cx = new CX(512, 0);
+        
+        cx.setCx(42);
+        Assert.assertEquals(42, cx.cx());
+        
+        cx.setIndex(1);
+        cx.setCx(127); // Maximum value (7 bits)
+        Assert.assertEquals(127, cx.cx());
+        
+        // Verify that different indices have independent values
+        cx.setIndex(0);
+        Assert.assertEquals(42, cx.cx());
+    }
+
+    @Test
+    public void testCxMasking()
+    {
+        // CX should mask to 7 bits (0-127)
+        CX cx = new CX(512, 0);
+        
+        cx.setCx(0xFF); // Set with all bits set
+        Assert.assertEquals(0x7F, cx.cx()); // Should be masked to 7 bits
+        
+        cx.setCx(0x80); // Bit 7 set
+        Assert.assertEquals(0, cx.cx()); // Should be masked out
+    }
+
+    @Test
+    public void testToggleMps()
+    {
+        CX cx = new CX(512, 0);
+        
+        // Initial state should be 0
+        Assert.assertEquals(0, cx.mps());
+        
+        // Toggle to 1
+        cx.toggleMps();
+        Assert.assertEquals(1, cx.mps());
+        
+        // Toggle back to 0
+        cx.toggleMps();
+        Assert.assertEquals(0, cx.mps());
+        
+        // Toggle again
+        cx.toggleMps();
+        Assert.assertEquals(1, cx.mps());
+    }
+
+    @Test
+    public void testMpsIndependent()
+    {
+        CX cx = new CX(512, 0);
+        
+        cx.toggleMps();
+        Assert.assertEquals(1, cx.mps());
+        
+        // Change index and verify MPS is independent
+        cx.setIndex(1);
+        Assert.assertEquals(0, cx.mps());
+        
+        cx.toggleMps();
+        Assert.assertEquals(1, cx.mps());
+        
+        // Back to index 0, should still be 1
+        cx.setIndex(0);
+        Assert.assertEquals(1, cx.mps());
+    }
+
+    @Test
+    public void testCopyDeepCopy()
+    {
+        CX original = new CX(512, 10);
+        original.setCx(50);
+        original.toggleMps();
+        
+        CX copy = original.copy();
+        
+        // Verify copy has same state
+        Assert.assertEquals(10, copy.getIndex());
+        Assert.assertEquals(50, copy.cx());
+        Assert.assertEquals(1, copy.mps());
+    }
+
+    @Test
+    public void testCopyIndependence()
+    {
+        CX original = new CX(512, 0);
+        original.setCx(42);
+        original.toggleMps();
+        
+        CX copy = original.copy();
+        
+        // Modify original
+        original.setCx(100);
+        original.toggleMps();
+        original.setIndex(5);
+        
+        // Copy should be unaffected
+        Assert.assertEquals(42, copy.cx());
+        Assert.assertEquals(1, copy.mps());
+        Assert.assertEquals(0, copy.getIndex());
+    }
+
+    @Test
+    public void testCopyMultipleIndices()
+    {
+        CX original = new CX(512, 0);
+        
+        // Set values at different indices
+        original.setCx(10);
+        original.toggleMps();
+        
+        original.setIndex(1);
+        original.setCx(20);
+        
+        original.setIndex(2);
+        original.setCx(30);
+        original.toggleMps();
+        
+        // Create copy
+        CX copy = original.copy();
+        
+        // Verify all indices were copied
+        copy.setIndex(0);
+        Assert.assertEquals(10, copy.cx());
+        Assert.assertEquals(1, copy.mps());
+        
+        copy.setIndex(1);
+        Assert.assertEquals(20, copy.cx());
+        Assert.assertEquals(0, copy.mps());
+        
+        copy.setIndex(2);
+        Assert.assertEquals(30, copy.cx());
+        Assert.assertEquals(1, copy.mps());
+    }
+
+    @Test
+    public void testLargeSizeContext()
+    {
+        // Test with large context size (typical for bitmap decoding)
+        CX cx = new CX(65536, 0);
+        
+        cx.setIndex(65535);
+        cx.setCx(127);
+        Assert.assertEquals(127, cx.cx());
+        
+        cx.toggleMps();
+        Assert.assertEquals(1, cx.mps());
+    }
+}

Reply via email to