You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2017/10/16 18:09:21 UTC

[8/8] pdfbox-jbig2 git commit: initial commit of the JBig2 ImageIO plugin

initial commit of the JBig2 ImageIO plugin


Project: http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/repo
Commit: http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/commit/4619d28b
Tree: http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/tree/4619d28b
Diff: http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/diff/4619d28b

Branch: refs/heads/master
Commit: 4619d28b16a3160fc099d57eae99c2b8ab0d944c
Parents: 
Author: Andreas Lehmkühler <an...@lehmi.de>
Authored: Mon Oct 16 20:04:58 2017 +0200
Committer: Andreas Lehmkühler <an...@lehmi.de>
Committed: Mon Oct 16 20:04:58 2017 +0200

----------------------------------------------------------------------
 .gitignore                                      |   4 +
 .travis.yml                                     |  25 +
 LICENSE-HEADER.txt                              |  14 +
 LICENSE.txt                                     | 202 ++++
 README.md                                       |  80 ++
 pom.xml                                         | 208 ++++
 release-notes.md                                |  94 ++
 .../license-maven-plugin/additionalHeaders.xml  |  31 +
 .../java/org/apache/pdfbox/jbig2/Bitmap.java    | 198 ++++
 .../org/apache/pdfbox/jbig2/Dictionary.java     |  41 +
 .../org/apache/pdfbox/jbig2/JBIG2Document.java  | 344 +++++++
 .../org/apache/pdfbox/jbig2/JBIG2Globals.java   |  59 ++
 .../apache/pdfbox/jbig2/JBIG2ImageMetadata.java | 107 ++
 .../pdfbox/jbig2/JBIG2ImageMetadataFormat.java  |  53 +
 .../apache/pdfbox/jbig2/JBIG2ImageReader.java   | 316 ++++++
 .../pdfbox/jbig2/JBIG2ImageReaderSpi.java       | 124 +++
 .../java/org/apache/pdfbox/jbig2/JBIG2Page.java | 376 +++++++
 .../org/apache/pdfbox/jbig2/JBIG2ReadParam.java |  48 +
 .../java/org/apache/pdfbox/jbig2/Region.java    |  48 +
 .../org/apache/pdfbox/jbig2/SegmentData.java    |  43 +
 .../org/apache/pdfbox/jbig2/SegmentHeader.java  | 432 ++++++++
 .../java/org/apache/pdfbox/jbig2/TestImage.java | 242 +++++
 .../decoder/arithmetic/ArithmeticDecoder.java   | 262 +++++
 .../arithmetic/ArithmeticIntegerDecoder.java    | 155 +++
 .../pdfbox/jbig2/decoder/arithmetic/CX.java     |  69 ++
 .../jbig2/decoder/huffman/EncodedTable.java     |  91 ++
 .../jbig2/decoder/huffman/FixedSizeTable.java   |  29 +
 .../jbig2/decoder/huffman/HuffmanTable.java     | 117 +++
 .../jbig2/decoder/huffman/InternalNode.java     | 119 +++
 .../pdfbox/jbig2/decoder/huffman/Node.java      |  29 +
 .../jbig2/decoder/huffman/OutOfBandNode.java    |  40 +
 .../jbig2/decoder/huffman/StandardTables.java   | 277 ++++++
 .../pdfbox/jbig2/decoder/huffman/ValueNode.java |  59 ++
 .../pdfbox/jbig2/decoder/mmr/MMRConstants.java  | 754 ++++++++++++++
 .../jbig2/decoder/mmr/MMRDecompressor.java      | 612 ++++++++++++
 .../jbig2/err/IntegerMaxValueException.java     |  42 +
 .../jbig2/err/InvalidHeaderValueException.java  |  42 +
 .../apache/pdfbox/jbig2/err/JBIG2Exception.java |  42 +
 .../pdfbox/jbig2/image/BitmapScanline.java      | 127 +++
 .../org/apache/pdfbox/jbig2/image/Bitmaps.java  | 525 ++++++++++
 .../org/apache/pdfbox/jbig2/image/Filter.java   | 457 +++++++++
 .../apache/pdfbox/jbig2/image/FilterType.java   |  50 +
 .../pdfbox/jbig2/image/ParameterizedFilter.java |  69 ++
 .../org/apache/pdfbox/jbig2/image/Resizer.java  | 404 ++++++++
 .../org/apache/pdfbox/jbig2/image/Scanline.java | 558 +++++++++++
 .../apache/pdfbox/jbig2/image/Weighttab.java    | 114 +++
 .../jbig2/io/DefaultInputStreamFactory.java     |  37 +
 .../pdfbox/jbig2/io/InputStreamFactory.java     |  27 +
 .../apache/pdfbox/jbig2/io/SubInputStream.java  | 150 +++
 .../pdfbox/jbig2/segments/EndOfStripe.java      |  49 +
 .../jbig2/segments/GenericRefinementRegion.java | 743 ++++++++++++++
 .../pdfbox/jbig2/segments/GenericRegion.java    | 906 +++++++++++++++++
 .../pdfbox/jbig2/segments/HalftoneRegion.java   | 406 ++++++++
 .../pdfbox/jbig2/segments/PageInformation.java  | 226 +++++
 .../jbig2/segments/PatternDictionary.java       | 220 +++++
 .../apache/pdfbox/jbig2/segments/Profiles.java  |  31 +
 .../segments/RegionSegmentInformation.java      | 107 ++
 .../pdfbox/jbig2/segments/SymbolDictionary.java | 843 ++++++++++++++++
 .../org/apache/pdfbox/jbig2/segments/Table.java |  97 ++
 .../pdfbox/jbig2/segments/TextRegion.java       | 973 +++++++++++++++++++
 .../pdfbox/jbig2/util/CombinationOperator.java  |  40 +
 .../pdfbox/jbig2/util/DictionaryViewer.java     |  59 ++
 .../apache/pdfbox/jbig2/util/ServiceLookup.java |  43 +
 .../org/apache/pdfbox/jbig2/util/Utils.java     | 101 ++
 .../apache/pdfbox/jbig2/util/cache/Cache.java   |  47 +
 .../pdfbox/jbig2/util/cache/CacheBridge.java    |  24 +
 .../pdfbox/jbig2/util/cache/CacheFactory.java   |  55 ++
 .../jbig2/util/cache/SoftReferenceCache.java    |  50 +
 .../util/cache/SoftReferenceCacheBridge.java    |  28 +
 .../apache/pdfbox/jbig2/util/log/JDKLogger.java |  88 ++
 .../pdfbox/jbig2/util/log/JDKLoggerBridge.java  |  26 +
 .../apache/pdfbox/jbig2/util/log/Logger.java    | 135 +++
 .../pdfbox/jbig2/util/log/LoggerBridge.java     |  24 +
 .../pdfbox/jbig2/util/log/LoggerFactory.java    |  55 ++
 .../services/javax.imageio.spi.ImageReaderSpi   |  18 +
 ...g.apache.pdfbox.jbig2.util.cache.CacheBridge |  18 +
 ...rg.apache.pdfbox.jbig2.util.log.LoggerBridge |  18 +
 .../org/apache/pdfbox/jbig2/BitmapTest.java     |  98 ++
 .../apache/pdfbox/jbig2/ChecksumCalculator.java |  60 ++
 .../org/apache/pdfbox/jbig2/ChecksumTest.java   | 175 ++++
 .../apache/pdfbox/jbig2/GithubIssuesTest.java   |  70 ++
 .../pdfbox/jbig2/JBIG2DocumentFacade.java       |  53 +
 .../pdfbox/jbig2/JBIG2ImageReaderDemo.java      |  79 ++
 .../pdfbox/jbig2/JBIG2ImageReaderTest.java      | 141 +++
 .../org/apache/pdfbox/jbig2/JBIG2PageTest.java  | 121 +++
 .../jbig2/PreconfiguredImageReadParam.java      |  56 ++
 .../arithmetic/ArithmeticDecoderTest.java       | 577 +++++++++++
 .../ArithmeticIntegerDecoderTest.java           |  46 +
 .../jbig2/decoder/mmr/MMRDecompressorTest.java  |  60 ++
 .../pdfbox/jbig2/image/BitmapsBlitTest.java     |  78 ++
 .../jbig2/image/BitmapsByteCombinationTest.java |  69 ++
 .../pdfbox/jbig2/image/BitmapsChecksumTest.java | 177 ++++
 .../jbig2/segments/GenericRegionTest.java       | 117 +++
 .../jbig2/segments/HalftoneRegionTest.java      |  61 ++
 .../jbig2/segments/PageInformationTest.java     |  91 ++
 .../jbig2/segments/PatternDictionaryTest.java   |  96 ++
 .../segments/RegionSegmentInformationTest.java  |  50 +
 .../jbig2/segments/SymbolDictionaryTest.java    |  24 +
 .../pdfbox/jbig2/segments/TextRegionTest.java   |  54 +
 .../pdfbox/jbig2/util/CacheFactoryTest.java     |  41 +
 .../pdfbox/jbig2/util/LoggerFactoryTest.java    |  41 +
 .../pdfbox/jbig2/util/ServiceLookupTest.java    |  56 ++
 .../apache/pdfbox/jbig2/util/TestService.java   |  22 +
 .../pdfbox/jbig2/util/TestServiceImpl.java      |  22 +
 .../org.apache.pdfbox.jbig2.util.TestService    |  18 +
 .../resources/com/levigo/jbig2/github/21.glob   | Bin 0 -> 37 bytes
 .../resources/com/levigo/jbig2/github/21.jb2    | Bin 0 -> 11250 bytes
 src/test/resources/images/001.jb2               | Bin 0 -> 66567 bytes
 src/test/resources/images/002.jb2               | Bin 0 -> 155982 bytes
 src/test/resources/images/003.jb2               | Bin 0 -> 8589 bytes
 src/test/resources/images/005.jb2               | Bin 0 -> 11335 bytes
 src/test/resources/images/006.jb2               | Bin 0 -> 150757 bytes
 src/test/resources/images/20123110001.jb2       | Bin 0 -> 36779 bytes
 src/test/resources/images/20123110002.jb2       | Bin 0 -> 347697 bytes
 src/test/resources/images/20123110003.jb2       | Bin 0 -> 624771 bytes
 src/test/resources/images/20123110004.jb2       | Bin 0 -> 86109 bytes
 src/test/resources/images/20123110005.jb2       | Bin 0 -> 41648 bytes
 src/test/resources/images/20123110006.jb2       | Bin 0 -> 97310 bytes
 src/test/resources/images/20123110007.jb2       | Bin 0 -> 57204 bytes
 src/test/resources/images/20123110008.jb2       | Bin 0 -> 58831 bytes
 src/test/resources/images/20123110009.jb2       | Bin 0 -> 60648 bytes
 src/test/resources/images/20123110010.jb2       | Bin 0 -> 60624 bytes
 .../resources/images/arith/decoded testsequence | Bin 0 -> 32 bytes
 .../resources/images/arith/encoded testsequence | Bin 0 -> 30 bytes
 124 files changed, 16329 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7652970
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.idea/
+atlassian-ide-plugin.xml
+levigo-jbig2-imageio.iml
+target/

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..250483c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+language: java
+dist: trusty
+jdk:
+# Disable for now due to https://github.com/travis-ci/travis-ci/issues/7019
+#  - oraclejdk7
+  - oraclejdk8
+  - oraclejdk9
+  - openjdk7

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/LICENSE-HEADER.txt
----------------------------------------------------------------------
diff --git a/LICENSE-HEADER.txt b/LICENSE-HEADER.txt
new file mode 100644
index 0000000..a9ac967
--- /dev/null
+++ b/LICENSE-HEADER.txt
@@ -0,0 +1,14 @@
+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.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/LICENSE.txt
----------------------------------------------------------------------
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..75b5248
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f1abb37
--- /dev/null
+++ b/README.md
@@ -0,0 +1,80 @@
+<!---
+  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.
+--->
+:warning: Please note that this component is currently undergoing migration under the ASF PDFBox umbrella. The new Maven coordinates are not yet working. In the mean time please refer to the [latest released version](https://github.com/levigo/jbig2-imageio/tree/levigo-jbig2-imageio-2.0).
+
+# Welcome to the Java ImageIO plugin for the JBIG2 image format!
+The Java ImageIO plugin for JBIG2 enables access to images encoded using the JBIG2 image compression standard.
+This component is part of the [Apache PDFBox® project](https://pdfbox.apache.org/) 
+
+## Status
+[![Build Status](https://travis-ci.org/levigo/jbig2-imageio.svg?branch=master)](https://travis-ci.org/levigo/jbig2-imageio)
+
+## Features
+The key features of the plugin are:
+
+- Read-only (decode) support for images encoded using the JBIG2 standard, aka *ITU T.88* and *ISO/IEC 14492*.
+- Full support for all features defined in the standard, including arithmetic coding, Huffman coding and MQ coding.
+- Pure Java code. No funny native or JNI stuff required.
+- Secure.
+- Production quality. Robust and well-tested.
+- Reasonable performance.
+- Standard ImageIO API.
+- Support for shared data segments as used by PDF via custom DecodeParams.
+
+## License
+This ImageIO plugin is licensed under the [Apache Software License 2.0](https://www.apache.org/licenses/LICENSE-2.0). Alternatively see [here](LICENSE.txt).
+
+## Release Notes
+Please take a look at the [release notes](release-notes.md).
+
+## Support
+Support is available through the [Apache PDFBox community}(https://pdfbox.apache.org/support.html)
+
+## Usage
+### Introduction
+Please choose the appropriate section below, depending on whether you need to embed the ImageIO decoder inside your application (which would, for example, be the case if you want to support shared data segments) or you just want to add JBIG2 support to an existing ImageIO-enabled application.
+
+### Use within existing Image I/O-based applications
+Using the JBIG2 plugin with an existing application that already supports Java ImageIO is - at least in theory - very simple: just plunk the plugin jar down into your classpath and you're ready to go. What, exactly, you have to do to achieve this, depends on the application in question. Unfortunately, there is no general way to add the plugin to an application. Some general recommendations:
+
+- If you implemented the application yourself: hey, don't look at us. You'll know best what to do. If you build your application using Maven, just pull in the plugin as a dependency. See below.
+- Consult the application's manual (well, duh!).
+- Maybe the application installation has a folder called 'plugins' or something like that. Try putting the jar into it. With some luck, the application will pick it up.
+- Is the application started using a Unix shell script or Windows batch file? Try to identify where the classpath is assembled and add the plugin jar to it.
+- As a last resort, you could try to add the plugin jar to the [lib/ext directory of your JRE installation](http://download.oracle.com/javase/1.4.2/docs/guide/extensions/spec.html). But please be advised that this is not considered to be good style.
+
+### Use dependency management
+The JBIG2 ImageIO-Plugin is available from [Maven Central](http://search.maven.org/). 
+
+#### Maven
+To use the plugin within a Maven POM-based project, simply include a dependency to the following artifact in the appropriate ```pom.xml```:
+
+    <dependency>
+      <groupId>org.apache.pdfbox.jbig2</groupId>
+		<artifactId>pdfbox-jbig2-imageio</artifactId>
+      <version>3.0-SNAPSHOT</version>
+    </dependency>
+
+### How to deal with embedded JBIG2 data
+Several formats allow to embed JBIG2-compressed data in its own structure. PDF, for example, supports JBIG2-compressed data and adds the ability to embed shared data segments. Therefore the `JBIG2ImageReader` can handle `JBIG2Globals`  which are stored separately and can be passed into the reader if neccessary via `setGlobals()`-method.
+
+The reader recognizes if the input data is headless and so embedded. This is assumed if the file header is missing.
+
+You can also specify that the coming input data is embedded by using the special constructor in `JBIG2ImageReader`.
+
+### What if the plugin is on classpath but not seen?
+ImageIO is able to scan the classpath for readers and writers. Call `ImageIO.scanForPlugins()` if the reader is not seen. (Note: Thanks to George Sexton for this tip in context of using ImageIO within Apache Tomcat)

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..16f692a
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,208 @@
+<!--
+
+    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.
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache</groupId>
+        <artifactId>apache</artifactId>
+        <version>18</version>
+        <relativePath/>
+    </parent>
+    
+	<groupId>org.apache.pdfbox</groupId>
+	<artifactId>jbig2-imageio</artifactId>
+	<version>3.0.0-SNAPSHOT</version>
+	
+	<name>PDFBox JBIG2 ImageIO plugin</name>
+	
+	<description>
+		Java Image I/O plugin for reading JBIG2-compressed image data. 
+		Formerly known as the levigo JBig2 ImageIO plugin (com.levigo.jbig2:levigo-jbig2-imageio).
+	</description>
+	
+	<url>https://github.com/levigo/jbig2-imageio</url>
+
+	<developers>
+		<developer>
+			<id>krzikams</id>
+			<name>Matthäus Mayer</name>
+			<email>m.mayer@levigo.de</email>
+			<roles>
+				<role>retired developer</role>
+			</roles>
+		</developer>
+		<developer>
+			<id>hennejg</id>
+			<name>Jörg Henne</name>
+			<email>j.henne@levigo.de</email>
+			<roles>
+				<role>project transition to ASL/ASF</role>
+			</roles>
+		</developer>
+	</developers>
+
+	<distributionManagement>
+		<snapshotRepository>
+			<id>sonatype-nexus-snapshots</id>
+			<name>Sonatype Nexus Snapshot Repository</name>
+			<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
+		</snapshotRepository>
+		<repository>
+			<id>sonatype-nexus-staging</id>
+			<name>Sonatype Nexus Release Staging Repository</name>
+			<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+		</repository>
+	</distributionManagement>
+
+	<scm>
+    	<connection>scm:git:ssh://github.com/levigo/jbig2-imageio.git</connection>
+		<developerConnection>scm:git:ssh://git@github.com/levigo/jbig2-imageio.git</developerConnection>
+    	<url>https://github.com/levigo/jbig2-imageio</url>
+    	<tag>HEAD</tag>
+	</scm>
+
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.10</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.7</source>
+					<target>1.7</target>
+					<debug>false</debug>
+					<optimize>true</optimize>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<inherited>false</inherited>
+				<groupId>com.mycila</groupId>
+				<artifactId>license-maven-plugin</artifactId>
+				<version>3.0</version>
+				<configuration>
+					<header>${basedir}/LICENSE-HEADER.txt</header>
+					<failIfMissing>true</failIfMissing>
+					<aggregate>true</aggregate>
+					<useDefaultExcludes>false</useDefaultExcludes>
+					<excludes>
+						<exclude>**/.classpath</exclude>
+						<exclude>**/.project</exclude>
+						<exclude>**/.settings/**</exclude>
+						<exclude>**/target/**</exclude>
+						<exclude>**/.idea/**</exclude>
+						<exclude>**/atlassian-ide-plugin.xml</exclude>
+					</excludes>
+					<includes>
+						<include>**/*.xml</include>
+						<include>**/*.md</include>
+						<include>**/src/**/*.java</include>
+						<include>**/src/**/*.properties</include>
+						<include>**/META-INF/services/*</include>
+						<include>**/*.yml</include>
+					</includes>
+					<headerDefinitions>
+					   <headerDefinition>src/build/license-maven-plugin/additionalHeaders.xml</headerDefinition>
+					</headerDefinitions>
+					<mapping>
+						<md>MD_STYLE</md>
+						<CacheBridge>SCRIPT_STYLE</CacheBridge>
+						<ReaderSpi>SCRIPT_STYLE</ReaderSpi>
+						<LoggerBridge>SCRIPT_STYLE</LoggerBridge>
+						<TestService>SCRIPT_STYLE</TestService>
+						<ImageReaderSpi>SCRIPT_STYLE</ImageReaderSpi>
+					</mapping>
+				</configuration>
+				<executions>
+					<execution>
+						<id>check-headers</id>
+						<phase>verify</phase>
+						<goals>
+							<goal>check</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+      <plugin>
+        <artifactId>maven-release-plugin</artifactId>
+        <configuration>
+          <autoVersionSubmodules>true</autoVersionSubmodules>
+          <!-- Keep changes in the local repo, push will be done afterwards -->
+          <pushChanges>false</pushChanges>
+          <localCheckout>true</localCheckout>
+          <!-- Use a better name for the tag -->
+          <tagNameFormat>${project.artifactId}-${project.version}</tagNameFormat>
+        </configuration>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.maven.scm</groupId>
+            <artifactId>maven-scm-provider-gitexe</artifactId>
+            <version>1.9</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+		</plugins>
+	</build>
+
+	<profiles>
+		<profile>
+			<id>release-sign-artifacts</id>
+			<activation>
+				<property>
+					<name>performRelease</name>
+					<value>true</value>
+				</property>
+			</activation>
+			<build>
+				<plugins>
+					<plugin>
+						<groupId>org.apache.maven.plugins</groupId>
+						<artifactId>maven-gpg-plugin</artifactId>
+						<version>1.1</version>
+						<configuration>
+							<homedir>${levigo-jbig2-imageio.gpg.homedir}</homedir>
+							<keyname>${levigo-jbig2-imageio.gpg.keyname}</keyname>
+							<passphrase>${levigo-jbig2-imageio.gpg.passphrase}</passphrase>
+						</configuration>
+						<executions>
+							<execution>
+								<id>sign-artifacts</id>
+								<phase>verify</phase>
+								<goals>
+									<goal>sign</goal>
+								</goals>
+							</execution>
+						</executions>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/release-notes.md
----------------------------------------------------------------------
diff --git a/release-notes.md b/release-notes.md
new file mode 100644
index 0000000..b4e9266
--- /dev/null
+++ b/release-notes.md
@@ -0,0 +1,94 @@
+<!---
+  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.
+--->
+# Release notes
+
+## Version 3.0.0 (pending)
+- [Issue #30](https://github.com/levigo/jbig2-imageio/issues/30): Transition project to Apache PDFBox.
+- [Issue #25](https://github.com/levigo/jbig2-imageio/issues/25): Build tests fail if project path has a space.
+- [Issue #26](https://github.com/levigo/jbig2-imageio/issues/26): Huffman user tables in text regions.
+- [Issue #27](https://github.com/levigo/jbig2-imageio/issues/27): Problems in standard Huffman tables.
+- [Issue #32](https://github.com/levigo/jbig2-imageio/issues/32): Newlines printed to stdout.
+
+## Version 2.0.0 (2017-06-02)
+- Java 9 support.
+- [Issue #10](https://github.com/levigo/jbig2-imageio/issues/10): Use general service loading instead of Image I/O specific. See [merge request #18](https://github.com/levigo/jbig2-imageio/pull/18).
+- [Issue #11](https://github.com/levigo/jbig2-imageio/issues/11): Remove @author info from javadocs.
+- [Issue #16](https://github.com/levigo/jbig2-imageio/issues/16): Replace deprecated ```STANDARD_INPUT_TYPE``` constant with self-created array.
+- [Issue #21](https://github.com/levigo/jbig2-imageio/issues/21): Move repetition of previous code length into correct scope. See [merge request #22](https://github.com/levigo/jbig2-imageio/pull/22). 
+
+## Version 1.6.5 (2015-12-29)
+- Issue #5: Deployment to maven central
+
+## Version 1.6.3 (2014-08-04)
+- Issue #1: Discard the request of copying the row above the first row.
+
+## Version 1.6.2-RC1 (2014-01-22)
+- Googlecode Issue 17: Changed computation of result dimension from ceiling to rounding. 
+
+##Version 1.6.1 (2013-04-18)
+- Googlecode Issue 11: Added support for `GRREFERENCE` Release notes
+
+## Version 1.6.2-RC1 (2014-01-22)
+- Googlecode Issue 17: Changed computation of result dimension from ceiling to rounding. 
+
+## Version 1.6.1 (2013-04-18)
+- Googlecode Issue 11: Added support for `GRREFERENCEDX` in generic refinement region coding. 
+
+## Version 1.6.0 (2013-03-25):
+- Googlecode Issue 10: Usability of `CacheFactory` and `LoggerFactory` improved.
+
+## Version 1.5.2 (2012-10-09):
+- Googlecode Issue  9: Transfer of bitmap's data into target raster went wrong if bitmap's line ends with a padded byte. 
+
+## Version 1.5.1 (2012-10-02):
+- Googlecode Issue  8: The default read parameters changed. There will be no source region, no source render size (no scaling) 
+  and subsampling factors of 1 (no subsampling). `Bitmaps.java` can handle this correctly.
+
+## Version 1.5.0 (2012-09-20):
+- Moved Exception-classes to dedicated package `com.levigo.jbig2.err`.
+- Introduced a new utility class `com.levigo.jbig2.image.Bitmaps`. This class provides a bunch of new features operating 
+  on a `Bitmap` instance. For example, extracting a region of interest, scaling with high-quality filters and subsampling
+  in either or both horizontal and vertical direction.
+
+## Version 1.4.1 (2012-04-20):
+- Fixed race condition when parsing documents with multiple pages.
+
+## Version 1.4 (2012-04-10):
+- Googlecode Issue  6 : The returned bitmap was too small in case of only one region. Solution is to check if we have only one
+  region that forms the complete page. Only if width and height of region equals width and height of page use region's
+  bitmap as the page's bitmap. 
+- Googlecode Issue  5: A raster which was too small was created. AWT has thrown a `RasterFormatException`.  
+- Googlecode Issue  4: `IndexOutOfBoundsException` indicates the end of the stream in `JBIG2Document#reachedEndOfStream()`
+- Googlecode Issue  3: Reader recognizes if a file header is present or not.
+
+## Version 1.3 (2011-10-28):
+- Untracked Googlecode Issue : Fixed inverted color model for grayscale images.
+- Untracked Googlecode Issue : Fixed `IndexArrayOutOfBoundException` in handling requests with region of interests. The region of
+  interest is clipped at image boundary.
+
+## Version 1.2 (2011-10-06):
+- Googlecode Issue  1: The default read parameters will return a default image size of 1x1 without claiming the missing input.
+- Untracked Googlecode Issue : A black pixel was represented by 1 and a white pixel by 0. For work with image masks the
+  convention says, a black pixel is the minimum and the white pixel is maximum. This corresponds to an additive
+  colorspace. We turned the representation of white and black pixels for conformity.
+
+## Version 1.1 (2010-12-13):
+- raster creation optimized
+- potential NPE in cache 
+
+## Version 1.0 (2010-07-29):
+- open-source'd  DX in generic refinement region coding. 

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/src/build/license-maven-plugin/additionalHeaders.xml
----------------------------------------------------------------------
diff --git a/src/build/license-maven-plugin/additionalHeaders.xml b/src/build/license-maven-plugin/additionalHeaders.xml
new file mode 100644
index 0000000..7effdc9
--- /dev/null
+++ b/src/build/license-maven-plugin/additionalHeaders.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+
+    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.
+
+-->
+<additionalHeaders>
+    <md_style>
+        <firstLine><![CDATA[<!---]]></firstLine>
+        <beforeEachLine>  </beforeEachLine>
+        <endLine><![CDATA[--->]]></endLine>
+        <firstLineDetectionPattern><![CDATA[(\s|\t)*<!---.*$]]></firstLineDetectionPattern>
+        <lastLineDetectionPattern><![CDATA[.*--->(\s|\t)*$]]></lastLineDetectionPattern>
+        <allowBlankLines>false</allowBlankLines>
+        <isMultiline>true</isMultiline>
+        <padLines>false</padLines>
+    </md_style>
+</additionalHeaders>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/src/main/java/org/apache/pdfbox/jbig2/Bitmap.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/pdfbox/jbig2/Bitmap.java b/src/main/java/org/apache/pdfbox/jbig2/Bitmap.java
new file mode 100644
index 0000000..7dbc38d
--- /dev/null
+++ b/src/main/java/org/apache/pdfbox/jbig2/Bitmap.java
@@ -0,0 +1,198 @@
+/**
+ * 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;
+
+import java.awt.Rectangle;
+
+/**
+ * This class represents a bi-level image that is organized like a bitmap.
+ */
+public class Bitmap {
+
+
+  /** The height of the bitmap in pixels. */
+  private final int height;
+
+  /** The width of the bitmap in pixels. */
+  private final int width;
+
+  /** The amount of bytes used per row. */
+  private final int rowStride;
+
+  /** 8 pixels per byte, 0 for white, 1 for black */
+  private byte[] bitmap;
+
+  /**
+   * Creates an instance of a blank image.<br>
+   * The image data is stored in a byte array. Each pixels is stored as one bit, so that each byte
+   * contains 8 pixel. A pixel has by default the value {@code 0} for white and {@code 1} for black. <br>
+   * Row stride means the amount of bytes per line. It is computed automatically and fills the pad
+   * bits with 0.<br>
+   * 
+   * @param height - The real height of the bitmap in pixels.
+   * @param width - The real width of the bitmap in pixels.
+   */
+  public Bitmap(int width, int height) {
+    this.height = height;
+    this.width = width;
+    this.rowStride = (width + 7) >> 3;
+
+    bitmap = new byte[this.height * this.rowStride];
+  }
+
+  /**
+   * Returns the value of a pixel specified by the given coordinates.
+   * <p>
+   * By default, the value is {@code 0} for a white pixel and {@code 1} for a black pixel. The value
+   * is placed in the rightmost bit in the byte.
+   * 
+   * @param x - The x coordinate of the pixel.
+   * @param y - The y coordinate of the pixel.
+   * @return The value of a pixel.
+   */
+  public byte getPixel(int x, int y) {
+    int byteIndex = this.getByteIndex(x, y);
+    int bitOffset = this.getBitOffset(x);
+
+    int toShift = 7 - bitOffset;
+    return (byte) ((this.getByte(byteIndex) >> toShift) & 0x01);
+  }
+  
+  public void setPixel(int x, int y, byte pixelValue) {
+    final int byteIndex = getByteIndex(x, y);
+    final int bitOffset = getBitOffset(x);
+    
+    final int shift = 7 - bitOffset;
+    
+    final byte src = bitmap[byteIndex];
+    final byte result = (byte) (src | (pixelValue << shift));
+    bitmap[byteIndex] = result;
+  }
+
+  /**
+   * 
+   * <p>
+   * Returns the index of the byte that contains the pixel, specified by the pixel's x and y
+   * coordinates.
+   * 
+   * @param x - The pixel's x coordinate.
+   * @param y - The pixel's y coordinate.
+   * @return The index of the byte that contains the specified pixel.
+   */
+  public int getByteIndex(int x, int y) {
+    return y * this.rowStride + (x >> 3);
+  }
+
+  /**
+   * Simply returns the byte array of this bitmap.
+   * 
+   * @return The byte array of this bitmap.
+   */
+  public byte[] getByteArray() {
+    return bitmap;
+  }
+
+  /**
+   * Simply returns a byte from the bitmap byte array. Throws an {@link IndexOutOfBoundsException}
+   * if the given index is out of bound.
+   * 
+   * @param index - The array index that specifies the position of the wanted byte.
+   * @return The byte at the {@code index}-position.
+   * 
+   * @throws IndexOutOfBoundsException if the index is out of bound.
+   */
+  public byte getByte(int index) {
+    return this.bitmap[index];
+  }
+
+  /**
+   * Simply sets the given value at the given array index position. Throws an
+   * {@link IndexOutOfBoundsException} if the given index is out of bound.
+   * 
+   * @param index - The array index that specifies the position of a byte.
+   * @param value - The byte that should be set.
+   * 
+   * @throws IndexOutOfBoundsException if the index is out of bound.
+   */
+  public void setByte(int index, byte value) {
+    this.bitmap[index] = value;
+  }
+
+  /**
+   * Converts the byte at specified index into an integer and returns the value. Throws an
+   * {@link IndexOutOfBoundsException} if the given index is out of bound.
+   * 
+   * @param index - The array index that specifies the position of the wanted byte.
+   * @return The converted byte at the {@code index}-position as an integer.
+   * 
+   * @throws IndexOutOfBoundsException if the index is out of bound.
+   */
+  public int getByteAsInteger(int index) {
+    return (this.bitmap[index] & 0xff);
+  }
+
+
+  /**
+   * Computes the offset of the given x coordinate in its byte. The method uses optimized modulo
+   * operation for a better performance.
+   * 
+   * @param x - The x coordinate of a pixel.
+   * @return The bit offset of a pixel in its byte.
+   */
+  public int getBitOffset(int x) {
+    // The same like x % 8.
+    // The rightmost three bits are 1. The value masks all bits upon the value "7".
+    return (x & 0x07);
+  }
+
+  /**
+   * Simply returns the height of this bitmap.
+   * 
+   * @return The height of this bitmap.
+   */
+  public int getHeight() {
+    return height;
+  }
+
+  /**
+   * Simply returns the width of this bitmap.
+   * 
+   * @return The width of this bitmap.
+   */
+  public int getWidth() {
+    return width;
+  }
+
+  /**
+   * Simply returns the row stride of this bitmap. <br>
+   * (Row stride means the amount of bytes per line.)
+   * 
+   * @return The row stride of this bitmap.
+   */
+  public int getRowStride() {
+    return rowStride;
+  }
+
+  public Rectangle getBounds() {
+    return new Rectangle(0, 0, width, height);
+  }
+
+  public int getMemorySize() {
+    return bitmap.length;
+  }
+}

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/src/main/java/org/apache/pdfbox/jbig2/Dictionary.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/pdfbox/jbig2/Dictionary.java b/src/main/java/org/apache/pdfbox/jbig2/Dictionary.java
new file mode 100644
index 0000000..89fa888
--- /dev/null
+++ b/src/main/java/org/apache/pdfbox/jbig2/Dictionary.java
@@ -0,0 +1,41 @@
+/**
+ * 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;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.apache.pdfbox.jbig2.err.IntegerMaxValueException;
+import org.apache.pdfbox.jbig2.err.InvalidHeaderValueException;
+
+/**
+ * Interface for all JBIG2 dictionaries segments.
+ */
+public interface Dictionary extends SegmentData {
+
+  /**
+   * Decodes a dictionary segment and returns the result.
+   * 
+   * @return A list of {@link Bitmap}s as a result of the decoding process of dictionary segments.
+   * 
+   * @throws IOException
+   * @throws InvalidHeaderValueException
+   * @throws IntegerMaxValueException
+   */
+  public ArrayList<Bitmap> getDictionary() throws IOException, InvalidHeaderValueException, IntegerMaxValueException;
+}

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/src/main/java/org/apache/pdfbox/jbig2/JBIG2Document.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/pdfbox/jbig2/JBIG2Document.java b/src/main/java/org/apache/pdfbox/jbig2/JBIG2Document.java
new file mode 100644
index 0000000..395c348
--- /dev/null
+++ b/src/main/java/org/apache/pdfbox/jbig2/JBIG2Document.java
@@ -0,0 +1,344 @@
+/**
+ * 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;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.imageio.stream.ImageInputStream;
+
+import org.apache.pdfbox.jbig2.io.SubInputStream;
+import org.apache.pdfbox.jbig2.util.log.Logger;
+import org.apache.pdfbox.jbig2.util.log.LoggerFactory;
+
+/**
+ * This class represents the document structure with its pages and global segments.
+ */
+class JBIG2Document {
+  private static final Logger log = LoggerFactory.getLogger(JBIG2Document.class);
+
+  /** ID string in file header, see ISO/IEC 14492:2001, D.4.1 */
+  private int[] FILE_HEADER_ID = {
+      0x97, 0x4A, 0x42, 0x32, 0x0D, 0x0A, 0x1A, 0x0A
+  };
+
+  /**
+   * This map contains all pages of this document. The key is the number of the page.
+   */
+  private final Map<Integer, JBIG2Page> pages = new TreeMap<Integer, JBIG2Page>();
+
+
+  /** BASIC INFORMATION ABOUT THE CURRENT JBIG2 DOCUMENT */
+
+  /** The length of the file header if exists */
+  private short fileHeaderLength = 9;
+
+  /**
+   * According to D.4.2 - File header bit 0
+   * <p>
+   * This flag contains information about the file organization:
+   * <ul>
+   * <li>{@code 1} for sequential</li>
+   * <li>{@code 0} for random-access</li>
+   * </ul>
+   * You can use the constants {@link #RANDOM} and {@link JBIG2Document#SEQUENTIAL}.
+   */
+  private short organisationType = SEQUENTIAL;
+
+  public static final int RANDOM = 0;
+  public static final int SEQUENTIAL = 1;
+
+  /**
+   * According to D.4.2 - Bit 1<br>
+   * <ul>
+   * <li>{@code true} if amount of pages is unknown, amount of pages field is not present</li>
+   * <li>{@code false} if there is a field in the file header where the amount of pages can be read</li>
+   * </ul>
+   */
+  private boolean amountOfPagesUnknown = true;
+
+  /**
+   * According to D.4.3 - Number of pages field (4 bytes). Only present if
+   * {@link #amountOfPagesUnknown} is {@code false}.
+   */
+  private int amountOfPages;
+
+  /** Defines whether extended Template is used. */
+  private boolean gbUseExtTemplate;
+
+  /**
+   * This is the source data stream wrapped into a {@link SubInputStream}.
+   */
+  private final SubInputStream subInputStream;
+
+  /**
+   * Flag:
+   * <ul>
+   * <li>{@code true} if stream is embedded in another file format and the file header is missing</li>
+   * <li>{@code false} if stream is created of a native jbig2 file and the file header should be
+   * present</li>
+   * </ul>
+   */
+
+  /**
+   * Holds a load of segments, that aren't associated with a page.
+   */
+  private JBIG2Globals globalSegments;
+
+  protected JBIG2Document(ImageInputStream input) throws IOException {
+    this(input, null);
+  }
+
+  protected JBIG2Document(ImageInputStream input, JBIG2Globals globals) throws IOException {
+    if (input == null)
+      throw new IllegalArgumentException("imageInputStream must not be null");
+
+    this.subInputStream = new SubInputStream(input, 0, Long.MAX_VALUE);
+    this.globalSegments = globals;
+
+    mapStream();
+  }
+
+  /**
+   * Retrieves the segment with the given segment number considering only segments that aren't
+   * associated with a page.
+   * 
+   * @param segmentNr - The number of the wanted segment.
+   * @return The requested {@link SegmentHeader}.
+   */
+  SegmentHeader getGlobalSegment(int segmentNr) {
+    if (null != globalSegments) {
+      return globalSegments.getSegment(segmentNr);
+    }
+
+    if (log.isErrorEnabled()) {
+      log.error("Segment not found. Returning null.");
+    }
+
+    return null;
+  }
+
+  /**
+   * Retrieves a {@link JBIG2Page} specified by the given page number.
+   * 
+   * @param pageNumber - The page number of the wanted {@link JBIG2Page}.
+   * 
+   * @return The requested {@link JBIG2Page}.
+   */
+  protected JBIG2Page getPage(int pageNumber) {
+    return pages.get(pageNumber);
+  }
+
+  /**
+   * Retrieves the amount of pages in this JBIG2 document. If the pages are striped, the document
+   * will be completely parsed and the amount of pages will be gathered.
+   * 
+   * @return The amount of pages in this JBIG2 document.
+   * @throws IOException
+   */
+  protected int getAmountOfPages() throws IOException {
+    if (amountOfPagesUnknown || amountOfPages == 0) {
+      if (pages.size() == 0) {
+        mapStream();
+      }
+
+      return pages.size();
+    } else {
+      return amountOfPages;
+    }
+  }
+
+  /**
+   * This method maps the stream and stores all segments.
+   */
+  private void mapStream() throws IOException {
+    final List<SegmentHeader> segments = new LinkedList<SegmentHeader>();
+
+    long offset = 0;
+    int segmentType = 0;
+
+    /*
+     * Parse the file header if there is one.
+     */
+    if (isFileHeaderPresent()) {
+      parseFileHeader();
+      offset += fileHeaderLength;
+    }
+
+    if (globalSegments == null) {
+      globalSegments = new JBIG2Globals();
+    }
+
+    JBIG2Page page = null;
+
+    /*
+     * If organisation type is random-access: walk through the segment headers until EOF segment
+     * appears (specified with segment number 51)
+     */
+    while (segmentType != 51 && !reachedEndOfStream(offset)) {
+      SegmentHeader segment = new SegmentHeader(this, subInputStream, offset, organisationType);
+
+      final int associatedPage = segment.getPageAssociation();
+      segmentType = segment.getSegmentType();
+
+      if (associatedPage != 0) {
+        page = getPage(associatedPage);
+        if (page == null) {
+          page = new JBIG2Page(this, associatedPage);
+          pages.put(associatedPage, page);
+        }
+        page.add(segment);
+      } else {
+        globalSegments.addSegment(segment.getSegmentNr(), segment);
+      }
+      segments.add(segment);
+
+      if (JBIG2ImageReader.DEBUG) {
+        if (log.isDebugEnabled()) {
+          log.debug(segment.toString());
+        }
+      }
+
+      offset = subInputStream.getStreamPosition();
+
+      // Sequential organization skips data part and sets the offset
+      if (organisationType == SEQUENTIAL) {
+        offset += segment.getSegmentDataLength();
+      }
+    }
+
+    /*
+     * Random organization: segment headers are finished. Data part starts and the offset can be
+     * set.
+     */
+    determineRandomDataOffsets(segments, offset);
+  }
+
+  private boolean isFileHeaderPresent() throws IOException {
+    final SubInputStream input = subInputStream;
+    input.mark();
+
+    for (int magicByte : FILE_HEADER_ID) {
+      if (magicByte != input.read()) {
+        input.reset();
+        return false;
+      }
+    }
+
+    input.reset();
+    return true;
+  }
+
+  /**
+   * Determines the start of the data parts and sets the offset.
+   * 
+   * @param segments
+   * @param offset
+   */
+  private void determineRandomDataOffsets(List<SegmentHeader> segments, long offset) {
+    if (organisationType == RANDOM) {
+      for (SegmentHeader s : segments) {
+        s.setSegmentDataStartOffset(offset);
+        offset += s.getSegmentDataLength();
+      }
+    }
+  }
+
+  /**
+   * This method reads the stream and sets variables for information about organization type and
+   * length etc.
+   * 
+   * @return
+   * @throws IOException
+   */
+  private void parseFileHeader() throws IOException {
+    subInputStream.seek(0);
+
+    /* D.4.1 - ID string, read will be skipped */
+    subInputStream.skipBytes(8);
+
+    /*
+     * D.4.2 Header flag (1 byte)
+     */
+
+    // Bit 3-7 are reserved and must be 0
+    subInputStream.readBits(5);
+
+    // Bit 2 - Indicates if extended templates are used
+    if (subInputStream.readBit() == 1) {
+      gbUseExtTemplate = true;
+    }
+
+    // Bit 1 - Indicates if amount of pages are unknown
+    if (subInputStream.readBit() != 1) {
+      amountOfPagesUnknown = false;
+    }
+
+    // Bit 0 - Indicates file organisation type
+    organisationType = (short) subInputStream.readBit();
+
+    // fileHeaderLength = 9;
+
+    /*
+     * D.4.3 Number of pages (field is only present if amount of pages are 'NOT unknown')
+     */
+    if (!amountOfPagesUnknown) {
+      amountOfPages = (int) subInputStream.readUnsignedInt();
+      fileHeaderLength = 13;
+    }
+
+  }
+
+  /**
+   * This method checks, if the stream is at its end to avoid {@link EOFException}s and reads 32
+   * bits.
+   * 
+   * @param offset
+   * @return <li>{@code true} if end of stream reached <li>{@code false} if there are more bytes to
+   *         read
+   * @throws IOException
+   */
+  private boolean reachedEndOfStream(long offset) throws IOException {
+    try {
+      subInputStream.seek(offset);
+      subInputStream.readBits(32);
+      return false;
+    } catch (EOFException e) {
+      return true;
+    } catch (IndexOutOfBoundsException e) {
+      return true;
+    }
+  }
+
+  protected JBIG2Globals getGlobalSegments() {
+    return globalSegments;
+  }
+
+  protected boolean isAmountOfPagesUnknown() {
+    return amountOfPagesUnknown;
+  }
+
+  boolean isGbUseExtTemplate() {
+    return gbUseExtTemplate;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/src/main/java/org/apache/pdfbox/jbig2/JBIG2Globals.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/pdfbox/jbig2/JBIG2Globals.java b/src/main/java/org/apache/pdfbox/jbig2/JBIG2Globals.java
new file mode 100644
index 0000000..1f8f0fe
--- /dev/null
+++ b/src/main/java/org/apache/pdfbox/jbig2/JBIG2Globals.java
@@ -0,0 +1,59 @@
+/**
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.pdfbox.jbig2.util.log.Logger;
+import org.apache.pdfbox.jbig2.util.log.LoggerFactory;
+
+
+/**
+ * This class stores segments, that aren't associated to a page.
+ * 
+ * If the data is embedded in another format, for example PDF, this segments might be stored
+ * separately in the file.
+ * 
+ * This segments will be decoded on demand and all results are stored in the document object and can
+ * be retrieved from there.
+ */
+public class JBIG2Globals {
+  private static final Logger log = LoggerFactory.getLogger(JBIG2Globals.class);
+
+  /**
+   * This map contains all segments, that are not associated with a page. The key is the segment
+   * number.
+   */
+  private Map<Integer, SegmentHeader> globalSegments = new HashMap<Integer, SegmentHeader>();
+
+  protected SegmentHeader getSegment(int segmentNr) {
+    if (globalSegments.size() == 0) {
+      if (log.isErrorEnabled()) {
+        log.error("No global segment added so far. Use JBIG2ImageReader.setGlobals().");
+      }
+    }
+
+    return globalSegments.get(segmentNr);
+  }
+
+  protected void addSegment(Integer segmentNumber, SegmentHeader segment) {
+    globalSegments.put(segmentNumber, segment);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageMetadata.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageMetadata.java b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageMetadata.java
new file mode 100644
index 0000000..a931b10
--- /dev/null
+++ b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageMetadata.java
@@ -0,0 +1,107 @@
+/**
+ * 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;
+
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataFormatImpl;
+import javax.imageio.metadata.IIOMetadataNode;
+
+import org.w3c.dom.Node;
+
+/**
+ * @see IIOMetadata
+ */
+public class JBIG2ImageMetadata extends IIOMetadata {
+
+  static final String IMAGE_METADATA_FORMAT_NAME = "jbig2";
+
+  private final JBIG2Page page;
+
+  public JBIG2ImageMetadata(JBIG2Page page) {
+    super(true, IMAGE_METADATA_FORMAT_NAME, JBIG2ImageMetadataFormat.class.getName(), null, null);
+
+    if (page == null)
+      throw new IllegalArgumentException("page must not be null");
+
+    this.page = page;
+  }
+
+  @Override
+  public boolean isReadOnly() {
+    return true;
+  }
+
+  @Override
+  public Node getAsTree(String formatName) {
+    if (formatName.equals(nativeMetadataFormatName)) {
+      return getNativeTree();
+    } else if (formatName.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
+      return getStandardTree();
+    } else {
+      throw new IllegalArgumentException("Not a recognized format!");
+    }
+  }
+
+  private Node getNativeTree() {
+    IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName);
+    root.appendChild(getStandardDimensionNode());
+    return root;
+  }
+
+  @Override
+  public IIOMetadataNode getStandardDimensionNode() {
+    IIOMetadataNode dimensionNode = new IIOMetadataNode("Dimension");
+    IIOMetadataNode node = null; // scratch node
+
+    node = new IIOMetadataNode("PixelAspectRatio");
+    node.setAttribute("value", "1.0");
+    dimensionNode.appendChild(node);
+
+    node = new IIOMetadataNode("ImageOrientation");
+    node.setAttribute("value", "Normal");
+    dimensionNode.appendChild(node);
+
+    if (page.getResolutionX() != 0) {
+      String pixelResolution = Float.toString(25.4f / (page.getResolutionX() / 39.3701f));
+
+      node = new IIOMetadataNode("HorizontalPixelSize");
+      node.setAttribute("value", pixelResolution);
+      dimensionNode.appendChild(node);
+    }
+
+    if (page.getResolutionY() != 0) {
+      String pixelResolution = Float.toString(25.4f / (page.getResolutionY() / 39.3701f));
+
+      node = new IIOMetadataNode("VerticalPixelSize");
+      node.setAttribute("value", pixelResolution);
+      dimensionNode.appendChild(node);
+    }
+
+    return dimensionNode;
+  }
+
+  @Override
+  public void mergeTree(String formatName, Node root) {
+    throw new IllegalStateException("Metadata is read-only!");
+  }
+
+  @Override
+  public void reset() {
+    throw new IllegalStateException("Metadata is read-only!");
+  }
+}

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageMetadataFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageMetadataFormat.java b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageMetadataFormat.java
new file mode 100644
index 0000000..1dc1ac7
--- /dev/null
+++ b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageMetadataFormat.java
@@ -0,0 +1,53 @@
+/**
+ * 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;
+
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.metadata.IIOMetadataFormat;
+import javax.imageio.metadata.IIOMetadataFormatImpl;
+
+/**
+ * @see IIOMetadataFormat
+ * @see IIOMetadataFormatImpl
+ */
+public class JBIG2ImageMetadataFormat extends IIOMetadataFormatImpl {
+
+  private static IIOMetadataFormat instance = null;
+
+  private JBIG2ImageMetadataFormat() {
+    super(JBIG2ImageMetadata.IMAGE_METADATA_FORMAT_NAME, CHILD_POLICY_SOME);
+
+    // root -> ImageDescriptor
+    addElement("ImageDescriptor", JBIG2ImageMetadata.IMAGE_METADATA_FORMAT_NAME, CHILD_POLICY_EMPTY);
+    addAttribute("ImageDescriptor", "imageWidth", DATATYPE_INTEGER, true, null, "1", "65535", true, true);
+    addAttribute("ImageDescriptor", "imageHeight", DATATYPE_INTEGER, true, null, "1", "65535", true, true);
+    addAttribute("ImageDescriptor", "Xdensity", DATATYPE_FLOAT, true, null, "1", "65535", true, true);
+    addAttribute("ImageDescriptor", "Ydensity", DATATYPE_FLOAT, true, null, "1", "65535", true, true);
+  }
+
+  public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) {
+    return true;
+  }
+
+  public static synchronized IIOMetadataFormat getInstance() {
+    if (instance == null) {
+      instance = new JBIG2ImageMetadataFormat();
+    }
+    return instance;
+  }
+}

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageReader.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageReader.java b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageReader.java
new file mode 100644
index 0000000..db706ab
--- /dev/null
+++ b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageReader.java
@@ -0,0 +1,316 @@
+/**
+ * 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;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.ImageInputStream;
+
+import org.apache.pdfbox.jbig2.err.JBIG2Exception;
+import org.apache.pdfbox.jbig2.image.Bitmaps;
+import org.apache.pdfbox.jbig2.image.FilterType;
+import org.apache.pdfbox.jbig2.util.cache.CacheFactory;
+import org.apache.pdfbox.jbig2.util.log.Logger;
+import org.apache.pdfbox.jbig2.util.log.LoggerFactory;
+
+/**
+ * @see ImageReader
+ */
+public class JBIG2ImageReader extends ImageReader {
+  private static final Logger log = LoggerFactory.getLogger(JBIG2ImageReader.class);
+
+  public static final boolean DEBUG = false;
+  public static final boolean PERFORMANCE_TEST = false;
+
+  /** JBIG2 document to which we delegate current work. */
+  private JBIG2Document document;
+
+  /** Globals are JBIG2 segments for PDF wide use. */
+  private JBIG2Globals globals;
+
+  /**
+   * @see ImageReader#ImageReader(ImageReaderSpi)
+   * 
+   * @param originatingProvider - The {@code ImageReaderSpi} that is invoking this constructor, or
+   *          {@code null}.
+   * @throws IOException if something went wrong while reading the provided stream.
+   */
+  public JBIG2ImageReader(ImageReaderSpi originatingProvider) throws IOException {
+    super(originatingProvider);
+  }
+
+  /**
+   * @see ImageReader#getDefaultReadParam()
+   */
+  @Override
+  public JBIG2ReadParam getDefaultReadParam() {
+    return new JBIG2ReadParam();
+  }
+
+  /**
+   * Returns a default {@linkplain ImageReadParam} object for a specific page.
+   * 
+   * @param imageIndex - The page number.
+   * @return
+   */
+  private JBIG2ReadParam getDefaultReadParam(final int imageIndex) {
+    int width = 1;
+    int height = 1;
+
+    try {
+      final int index = (imageIndex < getDocument().getAmountOfPages()) ? imageIndex : 0;
+      width = getWidth(index);
+      height = getHeight(index);
+    } catch (IOException e) {
+      if (log.isInfoEnabled()) {
+        log.info("Dimensions could not be determined. Returning read params with size " + width + "x" + height);
+      }
+    }
+
+    return new JBIG2ReadParam(1, 1, 0, 0, new Rectangle(0, 0, width, height), new Dimension(width, height));
+  }
+
+  /**
+   * Calculates the width of the specified page.
+   * 
+   * @param imageIndex - The image index. In this case it is the page number.
+   * 
+   * @return The width of the specified page.
+   * 
+   * @throws IOException if an error occurs reading the width information from the input source.
+   */
+  @Override
+  public int getWidth(int imageIndex) throws IOException {
+    return getDocument().getPage(imageIndex + 1).getWidth();
+  }
+
+  /**
+   * Calculates the height of the specified page.
+   * 
+   * @param imageIndex - The image index. In this case it is the page number.
+   * 
+   * @return The height of the specified page or {@code 0} if an error occurred.
+   * 
+   * @throws IOException if an error occurs reading the height information from the input source.
+   */
+  @Override
+  public int getHeight(int imageIndex) throws IOException {
+    try {
+      return getDocument().getPage(imageIndex + 1).getHeight();
+    } catch (JBIG2Exception e) {
+      throw new IOException(e.getMessage());
+    }
+  }
+
+  /**
+   * Simply returns the {@link JBIG2ImageMetadata}.
+   * 
+   * @return The associated {@link JBIG2ImageMetadata}.
+   * 
+   * @throws IOException if an error occurs reading the height information from the input source.
+   */
+  @Override
+  public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
+    return new JBIG2ImageMetadata(getDocument().getPage(imageIndex + 1));
+  }
+
+
+  /**
+   * Returns the iterator for available image types.
+   * 
+   * @param imageIndex - The page number.
+   * 
+   * @return An {@link Iterator} for available image types.
+   * 
+   * @throws IOException if an error occurs reading the height information from the input source.
+   */
+  @Override
+  public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
+    List<ImageTypeSpecifier> l = new ArrayList<ImageTypeSpecifier>();
+
+    l.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_INDEXED));
+
+    return l.iterator();
+  }
+
+  /**
+   * @see ImageReader#getNumImages(boolean)
+   */
+  @Override
+  public int getNumImages(boolean allowSearch) throws IOException {
+    if (allowSearch) {
+      if (getDocument().isAmountOfPagesUnknown()) {
+        log.info("Amount of pages is unknown.");
+      } else {
+        return getDocument().getAmountOfPages();
+      }
+    } else {
+      log.info("Search is not allowed.");
+    }
+    return -1;
+  }
+
+  /**
+   * This ImageIO plugin doesn't record {@link IIOMetadata}.
+   * 
+   * @return {@code null} at every call.
+   */
+  @Override
+  public IIOMetadata getStreamMetadata() {
+    log.info("No metadata recorded");
+    return null;
+  }
+
+  /**
+   * Returns decoded segments that has been set as globals. Globals are jbig2 segments that are used
+   * in embedded case for file wide access. They are not assigned to a specific page.
+   * 
+   * @return Decoded global segments.
+   * 
+   * @throws IOException if an error occurs reading the height information from the input source.
+   */
+  public JBIG2Globals getGlobals() throws IOException {
+    return getDocument().getGlobalSegments();
+  }
+
+  /**
+   * Returns the decoded image of specified page considering the given {@link JBIG2ReadParam}s.
+   * 
+   * @see ImageReader#read(int, ImageReadParam)
+   */
+  @Override
+  public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
+    if (param == null) {
+      log.info("JBIG2ReadParam not specified. Default will be used.");
+      param = (JBIG2ReadParam) getDefaultReadParam(imageIndex);
+    }
+
+    JBIG2Page page = getPage(imageIndex);
+
+    Bitmap pageBitmap = (Bitmap) CacheFactory.getCache().get(page);
+
+    if (pageBitmap == null) {
+      try {
+        pageBitmap = page.getBitmap();
+        CacheFactory.getCache().put(page, pageBitmap, pageBitmap.getMemorySize());
+        page.clearPageData();
+      } catch (JBIG2Exception e) {
+        throw new IOException(e.getMessage());
+      }
+    }
+
+    return Bitmaps.asBufferedImage(pageBitmap, param, FilterType.Gaussian);
+  }
+
+  public boolean canReadRaster() {
+    return true;
+  }
+
+  @Override
+  public Raster readRaster(int imageIndex, ImageReadParam param) throws IOException {
+    if (param == null) {
+      log.info("JBIG2ReadParam not specified. Default will be used.");
+      param = (JBIG2ReadParam) getDefaultReadParam(imageIndex);
+    }
+
+    JBIG2Page page = getPage(imageIndex);
+
+    Bitmap pageBitmap = (Bitmap) CacheFactory.getCache().get(page);
+    if (pageBitmap == null) {
+      try {
+        pageBitmap = page.getBitmap();
+        CacheFactory.getCache().put(page, pageBitmap, pageBitmap.getMemorySize());
+        page.clearPageData();
+      } catch (JBIG2Exception e) {
+        throw new IOException(e.getMessage());
+      }
+    }
+
+    return Bitmaps.asRaster(pageBitmap, param, FilterType.Gaussian);
+  }
+
+  /**
+   * Decodes and returns the global segments.
+   * 
+   * @param globalsInputStream - The input stream of globals data.
+   * 
+   * @return The decoded {@link JBIG2Globals}.
+   * 
+   * @throws IOException if an error occurs reading the height information from the input source.
+   */
+  public JBIG2Globals processGlobals(ImageInputStream globalsInputStream) throws IOException {
+    JBIG2Document doc = new JBIG2Document(globalsInputStream);
+    return doc.getGlobalSegments();
+  }
+
+  /**
+   * Simply sets the globals.
+   * 
+   * @param globals - The globals to set.
+   * @throws IOException
+   */
+  public void setGlobals(JBIG2Globals globals) throws IOException {
+    this.globals = globals;
+    this.document = null;
+  }
+
+  /**
+   * @see ImageReader#setInput(Object, boolean, boolean)
+   */
+  @Override
+  public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) {
+    super.setInput(input, seekForwardOnly, ignoreMetadata);
+    document = null;
+  }
+
+  private JBIG2Document getDocument() throws IOException {
+    if (this.document == null) {
+      if (this.input == null) {
+        throw new IOException("Input not set.");
+      }
+
+      if (this.globals == null) {
+        log.debug("Globals not set.");
+      }
+
+      this.document = new JBIG2Document((ImageInputStream) this.input, this.globals);
+    }
+    return this.document;
+  }
+
+  private JBIG2Page getPage(int imageIndex) throws IOException {
+    JBIG2Page page = getDocument().getPage(imageIndex + 1);
+
+    if (page == null)
+      throw new IndexOutOfBoundsException("Requested page at index=" + imageIndex + " does not exist.");
+
+    return page;
+  }
+}

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/4619d28b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageReaderSpi.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageReaderSpi.java b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageReaderSpi.java
new file mode 100644
index 0000000..04ec211
--- /dev/null
+++ b/src/main/java/org/apache/pdfbox/jbig2/JBIG2ImageReaderSpi.java
@@ -0,0 +1,124 @@
+/**
+ * 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;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.imageio.ImageReader;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.ImageInputStream;
+
+/**
+ * Necessary extension for ImageIO standard.
+ * 
+ * @see ImageReaderSpi
+ */
+public class JBIG2ImageReaderSpi extends ImageReaderSpi {
+
+  private static final String VENDOR = "levigo solutions gmbh";
+  private static final String VERSION = "1.4.1";
+  private static final String READER_CLASS_NAME = "org.apache.pdfbox.jbig2.JBIG2ImageReader";
+  private static final String[] NAMES = {
+      "jbig2", "JBIG2"
+  };
+  private static final String[] SUFFIXES = {
+      "jb2", "jbig2", "JB2", "JBIG2"
+  };
+  private static final String[] MIME_TYPES = {
+      "image/x-jbig2", "image/x-jb2"
+  };
+  private static final Class<?>[] INPUT_TYPES = { ImageInputStream.class };
+
+  /**
+   * According to D.4.1:
+   * <p>
+   * This preamble contains the unique id string for jbig2 files and can be used to check if this
+   * reader plugin can decode the given stream. This can only work with native jbig2 data. If the
+   * stream is embedded in another file format this preamble might be missing.
+   */
+  private static final int[] FILEHEADER_PREAMBLE = {
+      0x97, 0x4A, 0x42, 0x32, 0x0D, 0x0A, 0x1A, 0x0A
+  };
+
+  /* MK: I suppose, there won't be a writer in near future :-) */
+  private static final String[] WRITER_SPI_NAMES = {};
+
+  static final boolean SUPPORTS_STANDARD_STREAM_METADATE_FORMAT = false;
+  static final String NATIVE_STREAM_METADATA_FORMAT_NAME = "JBIG2 Stream Metadata";
+  static final String NATIVE_STREAM_METADATA_FORMAT_CLASSNAME = "JBIG2Metadata";
+  static final String[] EXTRA_STREAM_METADATA_FORMAT_NAME = null;
+  static final String[] EXTRA_STREAM_METADATA_FORMAT_CLASSNAME = null;
+
+  static final boolean SUPPORTS_STANDARD_IMAGE_METADATA_FORMAT = false;
+  static final String NATIVE_IMAGE_METADATA_FORMAT_NAME = "JBIG2 File Metadata";
+  static final String NATIVE_IMAGE_METADATA_FORMAT_CLASSNAME = "JBIG2Metadata";
+  static final String[] EXTRA_IMAGE_METADATA_FORMAT_NAME = null;
+  static final String[] EXTRA_IMAGE_METADATA_FORMAT_CLASSNAME = null;
+
+  public JBIG2ImageReaderSpi() {
+    super(VENDOR, VERSION, NAMES, SUFFIXES, MIME_TYPES, READER_CLASS_NAME, INPUT_TYPES, WRITER_SPI_NAMES,
+        SUPPORTS_STANDARD_STREAM_METADATE_FORMAT, NATIVE_STREAM_METADATA_FORMAT_NAME,
+        NATIVE_STREAM_METADATA_FORMAT_CLASSNAME, EXTRA_STREAM_METADATA_FORMAT_NAME,
+        EXTRA_STREAM_METADATA_FORMAT_CLASSNAME, SUPPORTS_STANDARD_IMAGE_METADATA_FORMAT,
+        NATIVE_IMAGE_METADATA_FORMAT_NAME, NATIVE_IMAGE_METADATA_FORMAT_CLASSNAME, EXTRA_IMAGE_METADATA_FORMAT_NAME,
+        EXTRA_IMAGE_METADATA_FORMAT_CLASSNAME);
+  }
+
+  /*
+   * Checks, if the file header begins with the preamble id string defined in D.4.1, page 100
+   * 
+   * (non-Javadoc)
+   * 
+   * @see javax.imageio.spi.ImageReaderSpi#canDecodeInput(java.lang.Object)
+   */
+  @Override
+  public boolean canDecodeInput(Object source) throws IOException {
+    if (source == null)
+      throw new IllegalArgumentException("source must not be null");
+
+    if (!(source instanceof ImageInputStream)) {
+      System.out.println("source is not an ImageInputStream");
+      return false;
+    }
+
+    ImageInputStream iis = (ImageInputStream) source;
+    iis.mark();
+
+    for (int i = 0; i < FILEHEADER_PREAMBLE.length; i++) {
+      int read = (iis.read() & 0xFF);
+      if (read != FILEHEADER_PREAMBLE[i]) {
+        return false;
+      }
+    }
+
+    iis.reset();
+    return true;
+  }
+
+  @Override
+  public ImageReader createReaderInstance(Object extension) throws IOException {
+    return new JBIG2ImageReader(this);
+  }
+
+  @Override
+  public String getDescription(Locale locale) {
+    return "JBIG2 Image Reader";
+  }
+
+}