Update with comments @EliotJones, rename Bitmap(s) to Jbig2Bitmap(s) and replace System.Drawing.rectangle by Jbig2Rectangle and update NOTICE with JBig2

This commit is contained in:
BobLD 2023-02-06 19:40:04 +00:00 committed by BobLd
parent 301fdb8c01
commit 1132cfc95d
54 changed files with 208 additions and 183 deletions

View File

@ -10,4 +10,12 @@ Includes the Adobe Glyph List
Copyright 1997, 1998, 2002, 2007, 2010 Adobe Systems Incorporated.
Includes the Zapf Dingbats Glyph List
Copyright 2002, 2010 Adobe Systems Incorporated.
Copyright 2002, 2010 Adobe Systems Incorporated.
------------------------------------------------------------------
Apache JBig2 ImageIO Plugin
Copyright 2017 The Apache Software Foundation
Based on source code originally developed in the JBig2 project.
Copyright (C) 1995-2017 levigo holding GmbH

View File

@ -9,7 +9,7 @@
[Fact]
public void GetPixelAndSetPixelTest()
{
var bitmap = new Bitmap(37, 49);
var bitmap = new Jbig2Bitmap(37, 49);
Assert.Equal(0, bitmap.GetPixel(3, 19));
bitmap.SetPixel(3, 19, (byte)1);
@ -20,7 +20,7 @@
[Fact]
public void GetByteAndSetByteTest()
{
var bitmap = new Bitmap(16, 16);
var bitmap = new Jbig2Bitmap(16, 16);
byte value = (byte)4;
bitmap.SetByte(0, value);
@ -33,7 +33,7 @@
[Fact]
public void GetByteThrowsExceptionTest()
{
var bitmap = new Bitmap(16, 16);
var bitmap = new Jbig2Bitmap(16, 16);
Action action = () => bitmap.GetByte(32);
@ -43,7 +43,7 @@
[Fact]
public void SetByteThrowsExceptionTest()
{
var bitmap = new Bitmap(16, 16);
var bitmap = new Jbig2Bitmap(16, 16);
Action action = () => bitmap.SetByte(32, (byte)0);
@ -53,7 +53,7 @@
[Fact]
public void GetByteAsIntegerTest()
{
var bitmap = new Bitmap(16, 16);
var bitmap = new Jbig2Bitmap(16, 16);
var byteValue = (byte)4;
int integerValue = byteValue;
@ -69,7 +69,7 @@
public void GetHeightTest()
{
int height = 16;
var bitmap = new Bitmap(1, height);
var bitmap = new Jbig2Bitmap(1, height);
Assert.Equal(height, bitmap.Height);
}
@ -78,7 +78,7 @@
public void GetWidthTest()
{
int width = 16;
var bitmap = new Bitmap(width, 1);
var bitmap = new Jbig2Bitmap(width, 1);
Assert.Equal(width, bitmap.Width);
}

View File

@ -46,10 +46,10 @@
new[] { "005.jb2", "712610586-1224021396100112-102-77-1177851" },
new[] { "006.jb2", "-8719-116-83-83-35-3425-64-528667602154-25" },
new[] { "007.jb2", "6171-125-109-20-128-71925295955793-127-41-122" },
new[] { "sampledata.jb2", "104-68-555325117-4757-48527676-9775-8432" },
new[] { "sampledata_page1.jb2", "104-68-555325117-4757-48527676-9775-8432" },
new[] { "sampledata_page2.jb2", "104-68-555325117-4757-48527676-9775-8432" },
new[] { "sampledata_page3.jb2", "-7825-56-41-30-19-719536-3678580-61-2586" },
//new[] { "sampledata.jb2", "104-68-555325117-4757-48527676-9775-8432" },
//new[] { "sampledata_page1.jb2", "104-68-555325117-4757-48527676-9775-8432" },
//new[] { "sampledata_page2.jb2", "104-68-555325117-4757-48527676-9775-8432" },
//new[] { "sampledata_page3.jb2", "-7825-56-41-30-19-719536-3678580-61-2586" },
new[] { "20123110001.jb2", "60-96-101-2458-3335024-5468-5-11068-78-80" },
new[] { "20123110002.jb2", "-28-921048181-117-48-96126-110-9-2865611113" },
new[] { "20123110003.jb2", "-3942-239351-28-56-729169-5839122-439231" },
@ -71,7 +71,7 @@
var iis = new ImageInputStream(ImageHelpers.LoadFileBytes(filename));
var doc = new Jbig2Document(iis);
Bitmap b = doc.GetPage(1).GetBitmap();
Jbig2Bitmap b = doc.GetPage(1).GetBitmap();
byte[] digest = Hash(b.GetByteArray());
var stringBuilder = new StringBuilder();

View File

@ -6,7 +6,7 @@
public class GenericRegionTest
{
[Fact]
[Fact(Skip = "File removed")]
public void ParseHeaderTest()
{
var iis = new ImageInputStream(ImageHelpers.LoadFileBytes("sampledata.jb2"));

View File

@ -6,7 +6,7 @@
public class HalftoneRegionTest
{
[Fact]
[Fact(Skip = "File removed")]
public void ParseHeaderTest()
{
var iis = new ImageInputStream(ImageHelpers.LoadFileBytes("sampledata.jb2"));

View File

@ -6,7 +6,7 @@
public class MMRDecompressorTest
{
[Fact]
[Fact(Skip = "File removed")]
public void MmrDecodingTest()
{
var expected = new byte[]
@ -20,7 +20,7 @@
// Sixth Segment (number 5)
var sis = new SubInputStream(iis, 252, 38);
var mmrd = new MMRDecompressor(16 * 4, 4, sis);
Bitmap b = mmrd.Uncompress();
Jbig2Bitmap b = mmrd.Uncompress();
byte[] actual = b.GetByteArray();
Assert.Equal(expected, actual);

View File

@ -6,7 +6,7 @@
public class PatternDictionaryTest
{
[Fact]
[Fact(Skip = "File removed")]
public void ParseHeaderTest()
{
var iis = new ImageInputStream(ImageHelpers.LoadFileBytes("sampledata.jb2"));

View File

@ -5,8 +5,8 @@
using Xunit;
public class RegionSegmentInformationTest
{
[Fact]
{
[Fact(Skip = "File removed")]
public void ParseHeaderTest()
{
var iis = new ImageInputStream(ImageHelpers.LoadFileBytes("sampledata.jb2"));

View File

@ -8,7 +8,7 @@ namespace UglyToad.PdfPig.Tests.Filters
{
public class Jbig2DecodeFilterTests
{
[Fact]
[Fact(Skip = "File removed")]
public void CanDecodeJbig2CompressedImageData_WithoutGlobalSegments()
{
var encodedImageBytes = ImageHelpers.LoadFileBytes("sampledata_page1.jb2");

View File

@ -1,21 +0,0 @@
============================================================================
The files sampledata_pageN.jb2 and sampledata.jb are included subject to the
following terms:
============================================================================
The compliance checking files provided with this package contain
information which has been extracted from Recommendation ITU-T T.88
"Information technology Lossy/lossless coding of bi-level images"
(2000/02) of the International Telecommunication Union (“ITU Information”),
as found in http://www.itu.int/rec/T-REC-T.88-200002-I/en.
The extraction and use of ITU Information has been made under license
from International Telecommunication Union (“ITU”), which owns all property
rights (including intellectual property rights) to Recommendation ITU-T
T.88 (2000/02). This ITU Information is made available to everyone for free
and may be used for non-commercial purposes; for any other use please
contact ITU at sales@itu.int. The sole responsibility for extracting the
ITU Information and the responsibility for any errors or deficiencies in
the package lies exclusively with the PdfPig project. ITU is not
involved in the development of the package or the extraction and use of
ITU Information contained therein.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 893 B

View File

@ -258,7 +258,7 @@
Assert.True(ImageHelpers.ImagesAreEqual(LoadImage("calgray.png"), bytes));
}
[Fact]
[Fact(Skip = "File removed")]
public void CanGeneratePngFromJbig2DecodedImageData()
{
var decodedBytes = ImageHelpers.LoadFileBytes("sampledata_page1.jb2-decoded.bin");

View File

@ -3,7 +3,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// This class represents the arithmetic decoder, described in ISO/IEC 14492:2001 in E.3
/// </summary>
internal class ArithmeticDecoder
internal sealed class ArithmeticDecoder
{
private static readonly int[][] QE = new[]{
new []{ 0x5601, 01, 01, 1 }, new []{ 0x3401, 02, 06, 0 }, new []{ 0x1801, 03, 09, 0 },

View File

@ -3,7 +3,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// This class represents the arithmetic integer decoder, described in ISO/IEC 14492:2001 (Annex A).
/// </summary>
internal class ArithmeticIntegerDecoder
internal sealed class ArithmeticIntegerDecoder
{
private readonly ArithmeticDecoder decoder;

View File

@ -4,7 +4,7 @@
/// CX represents the context used by arithmetic decoding and arithmetic integer decoding. It selects the probability
/// estimate and statistics used during decoding procedure.
/// </summary>
internal class CX
internal sealed class CX
{
private readonly byte[] cx;
private readonly byte[] mps;

View File

@ -5,7 +5,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// This class represents a encoded huffman table.
/// </summary>
internal class EncodedTable : HuffmanTable
internal sealed class EncodedTable : HuffmanTable
{
private readonly Table table;

View File

@ -3,7 +3,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// This segment flags an end of stripe (see JBIG2 ISO standard, 7.4.9).
/// </summary>
internal class EndOfStripe : ISegmentData
internal sealed class EndOfStripe : ISegmentData
{
private SubInputStream subInputStream;
private int lineNumber;

View File

@ -5,7 +5,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// This class represents a fixed size huffman table.
/// </summary>
internal class FixedSizeTable : HuffmanTable
internal sealed class FixedSizeTable : HuffmanTable
{
public FixedSizeTable(List<Code> runCodeTable)
{

View File

@ -6,7 +6,7 @@
/// This class represents a generic refinement region and implements the procedure described in JBIG2 ISO standard, 6.3
/// and 7.4.7.
/// </summary>
internal class GenericRefinementRegion : IRegion
internal sealed class GenericRefinementRegion : IRegion
{
public abstract class Template
{
@ -63,10 +63,10 @@
private short[] grAtY;
// Decoded data as pixel values (use row stride/width to wrap line)
private Bitmap regionBitmap;
private Jbig2Bitmap regionBitmap;
// Variables for decoding
private Bitmap referenceBitmap;
private Jbig2Bitmap referenceBitmap;
private int referenceDX;
private int referenceDY;
@ -147,11 +147,11 @@
/// <summary>
/// Decode using a template and arithmetic coding, as described in 6.3.5.6
/// </summary>
/// <returns>The decoded <see cref="Bitmap"/>.</returns>
/// <returns>The decoded <see cref="Jbig2Bitmap"/>.</returns>
/// <exception cref="System.IO.IOException">if an underlying IO operation fails</exception>
/// <exception cref="InvalidHeaderValueException">if a segment header value is invalid</exception>
/// <exception cref="IntegerMaxValueException"> if the maximum value limit of an integer is exceeded</exception>
public Bitmap GetRegionBitmap()
public Jbig2Bitmap GetRegionBitmap()
{
if (null == regionBitmap)
{
@ -175,7 +175,7 @@
}
// 6.3.5.6 - 2)
regionBitmap = new Bitmap(RegionInfo.BitmapWidth, RegionInfo.BitmapHeight);
regionBitmap = new Jbig2Bitmap(RegionInfo.BitmapWidth, RegionInfo.BitmapHeight);
if (templateID == 0)
{
@ -221,7 +221,7 @@
return arithDecoder.Decode(cx);
}
private Bitmap GetGrReference()
private Jbig2Bitmap GetGrReference()
{
SegmentHeader[] segments = segmentHeader.GetRtSegments();
IRegion region = (IRegion)segments[0].GetSegmentData();
@ -824,7 +824,7 @@
return context;
}
private static byte GetPixel(Bitmap b, int x, int y)
private static byte GetPixel(Jbig2Bitmap b, int x, int y)
{
if (x < 0 || x >= b.Width)
{
@ -848,7 +848,7 @@
internal void SetParameters(CX cx, ArithmeticDecoder arithmeticDecoder,
short grTemplate, int regionWidth, int regionHeight,
Bitmap grReference, int grReferenceDX, int grReferenceDY,
Jbig2Bitmap grReference, int grReferenceDX, int grReferenceDY,
bool isTPGRon, short[] grAtX, short[] grAtY)
{

View File

@ -5,7 +5,7 @@
/// Parsing is done as described in 7.4.5.
/// Decoding procedure is done as described in 6.2.5.7 and 7.4.6.4.
/// </summary>
internal class GenericRegion : IRegion
internal sealed class GenericRegion : IRegion
{
private SubInputStream subInputStream;
private long dataHeaderOffset = 0;
@ -28,7 +28,7 @@
private bool @override;
// Decoded data as pixel values (use row stride/width to wrap line)
private Bitmap regionBitmap;
private Jbig2Bitmap regionBitmap;
private ArithmeticDecoder arithDecoder;
private CX cx;
@ -123,8 +123,8 @@
/// <summary>
/// The procedure is described in 6.2.5.7, page 17.
/// </summary>
/// <returns>The decoded <see cref="Bitmap"/>.</returns>
public Bitmap GetRegionBitmap()
/// <returns>The decoded <see cref="Jbig2Bitmap"/>.</returns>
public Jbig2Bitmap GetRegionBitmap()
{
if (null == regionBitmap)
{
@ -160,7 +160,7 @@
}
// 6.2.5.7 - 2)
regionBitmap = new Bitmap(RegionInfo.BitmapWidth,
regionBitmap = new Jbig2Bitmap(RegionInfo.BitmapWidth,
RegionInfo.BitmapHeight);
int paddedWidth = (regionBitmap.Width + 7) & -8;

View File

@ -8,7 +8,7 @@
/// This class represents the data of segment type "Halftone region". Parsing is described in 7.4.5, page 67. Decoding
/// procedure in 6.6.5 and 7.4.5.2.
/// </summary>
internal class HalftoneRegion : IRegion
internal sealed class HalftoneRegion : IRegion
{
private SubInputStream subInputStream;
private SegmentHeader segmentHeader;
@ -18,10 +18,10 @@
private long dataLength;
// Decoded data
private Bitmap halftoneRegionBitmap;
private Jbig2Bitmap halftoneRegionBitmap;
// Previously decoded data from other regions or dictionaries, stored to use as patterns in this region.
private List<Bitmap> patterns;
private List<Jbig2Bitmap> patterns;
// Region segment information field, 7.4.1
public RegionSegmentInformation RegionInfo { get; private set; }
@ -114,14 +114,14 @@
/// <summary>
/// The procedure is described in JBIG2 ISO standard, 6.6.5.
/// </summary>
/// <returns>The decoded <see cref="Bitmap"/></returns>
public Bitmap GetRegionBitmap()
/// <returns>The decoded <see cref="Jbig2Bitmap"/></returns>
public Jbig2Bitmap GetRegionBitmap()
{
if (null == halftoneRegionBitmap)
{
// 6.6.5, page 40
// 1)
halftoneRegionBitmap = new Bitmap(RegionInfo.BitmapWidth,
halftoneRegionBitmap = new Jbig2Bitmap(RegionInfo.BitmapWidth,
RegionInfo.BitmapHeight);
if (patterns == null)
@ -176,16 +176,16 @@
y = ComputeY(m, n);
// ii)
Bitmap patternBitmap = patterns[grayScaleValues[m][n]];
Bitmaps.Blit(patternBitmap, halftoneRegionBitmap, (x + HGridX), (y + HGridY),
Jbig2Bitmap patternBitmap = patterns[grayScaleValues[m][n]];
Jbig2Bitmaps.Blit(patternBitmap, halftoneRegionBitmap, (x + HGridX), (y + HGridY),
HCombinationOperator);
}
}
}
private List<Bitmap> GetPatterns()
private List<Jbig2Bitmap> GetPatterns()
{
var patterns = new List<Bitmap>();
var patterns = new List<Jbig2Bitmap>();
foreach (SegmentHeader s in segmentHeader.GetRtSegments())
{
@ -229,7 +229,7 @@
gbAtY[3] = -2;
}
var grayScalePlanes = new Bitmap[bitsPerValue];
var grayScalePlanes = new Jbig2Bitmap[bitsPerValue];
// 1)
var genericRegion = new GenericRegion(subInputStream);
@ -255,7 +255,7 @@
return ComputeGrayScaleValues(grayScalePlanes, bitsPerValue);
}
private Bitmap[] CombineGrayScalePlanes(Bitmap[] grayScalePlanes, int j)
private Jbig2Bitmap[] CombineGrayScalePlanes(Jbig2Bitmap[] grayScalePlanes, int j)
{
int byteIndex = 0;
for (int y = 0; y < grayScalePlanes[j].Height; y++)
@ -267,13 +267,13 @@
byte oldValue = grayScalePlanes[j].GetByte(byteIndex);
grayScalePlanes[j].SetByte(byteIndex++,
Bitmaps.CombineBytes(oldValue, newValue, CombinationOperator.XOR));
Jbig2Bitmaps.CombineBytes(oldValue, newValue, CombinationOperator.XOR));
}
}
return grayScalePlanes;
}
private int[][] ComputeGrayScaleValues(Bitmap[] grayScalePlanes, int bitsPerValue)
private int[][] ComputeGrayScaleValues(Jbig2Bitmap[] grayScalePlanes, int bitsPerValue)
{
// Gray-scale decoding procedure, page 98
int[][] grayScaleValues = new int[HGridHeight][];

View File

@ -33,7 +33,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
public override sealed string ToString()
{
return (Value != -1 ? ValueNode.bitPattern(Value, PrefixLength) : "?") + "/"
return (Value != -1 ? ValueNode.BitPattern(Value, PrefixLength) : "?") + "/"
+ PrefixLength + "/" + RangeLength + "/" + RangeLow;
}
}

View File

@ -5,15 +5,15 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// Interface for all JBIG2 dictionaries segments.
/// </summary>
internal interface IDictionary : ISegmentData
internal interface IJbigDictionary : ISegmentData
{
/// <summary>
/// Decodes a dictionary segment and returns the result.
/// </summary>
/// <returns>A list of <see cref="Bitmap"/>s as a result of the decoding process of dictionary segments.</returns>
/// <returns>A list of <see cref="Jbig2Bitmap"/>s as a result of the decoding process of dictionary segments.</returns>
/// <exception cref="InvalidHeaderValueException">if the segment header value is invalid.</exception>
/// <exception cref="IntegerMaxValueException">if the maximum value limit of an integer is exceeded.</exception>
/// <exception cref="System.IO.IOException">if an underlying IO operation fails.</exception>
List<Bitmap> GetDictionary();
List<Jbig2Bitmap> GetDictionary();
}
}

View File

@ -13,10 +13,10 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// Decodes and returns a regions content.
/// </summary>
/// <returns>The decoded region as <see cref="Bitmap"/>.</returns>
/// <returns>The decoded region as <see cref="Jbig2Bitmap"/>.</returns>
/// <exception cref="InvalidHeaderValueException">if the segment header value is invalid.</exception>
/// <exception cref="IntegerMaxValueException">if the maximum value limit of an integer is exceeded.</exception>
/// <exception cref="System.IO.IOException">if an underlying IO operation fails.</exception>
Bitmap GetRegionBitmap();
Jbig2Bitmap GetRegionBitmap();
}
}

View File

@ -3,7 +3,7 @@
using System;
using System.IO;
internal class ImageInputStream : AbstractImageInputStream
internal sealed class ImageInputStream : AbstractImageInputStream
{
private readonly Stream inner;

View File

@ -5,7 +5,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// Can be used if the maximum value limit of an integer is exceeded.
/// </summary>
internal class IntegerMaxValueException : Jbig2Exception
internal sealed class IntegerMaxValueException : Jbig2Exception
{
public IntegerMaxValueException()
{

View File

@ -7,7 +7,7 @@
/// <summary>
/// This class represents an internal node of a Huffman tree. It contains two child nodes.
/// </summary>
internal class InternalNode : Node
internal sealed class InternalNode : Node
{
private readonly int depth;

View File

@ -3,7 +3,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// This class represents a bi-level image that is organized like a bitmap.
/// </summary>
internal class Bitmap
internal sealed class Jbig2Bitmap
{
// 8 pixels per byte, 0 for white, 1 for black
private readonly byte[] bitmap;
@ -31,7 +31,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
public Bitmap(int width, int height)
public Jbig2Bitmap(int width, int height)
{
Height = height;
Width = width;

View File

@ -1,19 +1,18 @@
namespace UglyToad.PdfPig.Filters.Jbig2
{
using System;
using System.Drawing;
internal static class Bitmaps
internal static class Jbig2Bitmaps
{
/// <summary>
/// Returns the specified rectangle area of the bitmap.
/// </summary>
/// <param name="roi">A <see cref="System.Drawing.Rectangle"/> that specifies the requested image section.</param>
/// <param name="roi">A <see cref="Jbig2Rectangle"/> that specifies the requested image section.</param>
/// <param name="src">src the given bitmap</param>
/// <returns>A <see cref="Bitmap"/> that represents the requested image section.</returns>
public static Bitmap Extract(Rectangle roi, Bitmap src)
/// <returns>A <see cref="Jbig2Bitmap"/> that represents the requested image section.</returns>
public static Jbig2Bitmap Extract(Jbig2Rectangle roi, Jbig2Bitmap src)
{
var dst = new Bitmap(roi.Width, roi.Height);
var dst = new Jbig2Bitmap(roi.Width, roi.Height);
int upShift = roi.X & 0x07;
int downShift = 8 - upShift;
@ -24,7 +23,8 @@ namespace UglyToad.PdfPig.Filters.Jbig2
int srcLineEndIdx = src.GetByteIndex(roi.X + roi.Width - 1, roi.Y);
bool usePadding = dst.RowStride == srcLineEndIdx + 1 - srcLineStartIdx;
for (int y = roi.Y; y < roi.GetMaxY(); y++)
int maxY = roi.GetMaxY();
for (int y = roi.Y; y < maxY; y++)
{
int srcIdx = srcLineStartIdx;
int dstIdx = dstLineStartIdx;
@ -104,7 +104,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <param name="x">The x coordinate where the upper left corner of the bitmap to blit should be positioned.</param>
/// <param name="y">The y coordinate where the upper left corner of the bitmap to blit should be positioned.</param>
/// <param name="combinationOperator">The combination operator for combining two pixels.</param>
public static void Blit(Bitmap src, Bitmap dst, int x, int y, CombinationOperator combinationOperator)
public static void Blit(Jbig2Bitmap src, Jbig2Bitmap dst, int x, int y, CombinationOperator combinationOperator)
{
int startLine = 0;
int srcStartIdx = 0;
@ -163,7 +163,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
}
}
private static void CopyLine(Bitmap src, Bitmap dst, int sourceUpShift, int sourceDownShift,
private static void CopyLine(Jbig2Bitmap src, Jbig2Bitmap dst, int sourceUpShift, int sourceDownShift,
int padding, int firstSourceByteOfLine, int lastSourceByteOfLine, bool usePadding,
int sourceOffset, int targetOffset)
{
@ -210,7 +210,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
return (byte)(value >> padding << padding);
}
private static void BlitUnshifted(Bitmap src, Bitmap dst, int startLine, int lastLine,
private static void BlitUnshifted(Jbig2Bitmap src, Jbig2Bitmap dst, int startLine, int lastLine,
int dstStartIdx, int srcStartIdx, int srcEndIdx, CombinationOperator op)
{
@ -229,7 +229,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
}
}
private static void BlitSpecialShifted(Bitmap src, Bitmap dst, int startLine, int lastLine,
private static void BlitSpecialShifted(Jbig2Bitmap src, Jbig2Bitmap dst, int startLine, int lastLine,
int dstStartIdx, int srcStartIdx, int srcEndIdx, int toShift, int shiftVal1,
int shiftVal2, CombinationOperator op)
{
@ -258,7 +258,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
}
}
private static void BlitShifted(Bitmap src, Bitmap dst, int startLine, int lastLine,
private static void BlitShifted(Jbig2Bitmap src, Jbig2Bitmap dst, int startLine, int lastLine,
int dstStartIdx, int srcStartIdx, int srcEndIdx, int toShift, int shiftVal1,
int shiftVal2, CombinationOperator op, int padding)
{

View File

@ -7,7 +7,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// This class represents the document structure with its pages and global segments.
/// </summary>
internal class Jbig2Document : IDisposable
internal sealed class Jbig2Document : IDisposable
{
// ID string in file header, see ISO/IEC 14492:2001, D.4.1
private static readonly int[] FILE_HEADER_ID = { 0x97, 0x4A, 0x42, 0x32, 0x0D, 0x0A, 0x1A, 0x0A };

View File

@ -8,7 +8,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// This segments will be decoded on demand and all results are stored in the document object and can be retrieved from
/// there.
/// </summary>
internal class Jbig2Globals
internal sealed class Jbig2Globals
{
// This map contains all segments, that are not associated with a page. The key is the segment number.
private readonly Dictionary<int, SegmentHeader> globalSegments = new Dictionary<int, SegmentHeader>();

View File

@ -6,7 +6,7 @@
/// <summary>
/// This class represents a JBIG2 page.
/// </summary>
internal class Jbig2Page
internal sealed class Jbig2Page
{
// This list contains all segments of this page, sorted by segment number in ascending order.
private readonly SortedDictionary<int, SegmentHeader> segments = new SortedDictionary<int, SegmentHeader>();
@ -15,7 +15,7 @@
private readonly int pageNumber;
// The page bitmap that represents the page buffer
private Bitmap pageBitmap;
private Jbig2Bitmap pageBitmap;
private int finalHeight;
private int finalWidth;
@ -74,7 +74,7 @@
/// <returns>The result of decoding a page</returns>
/// <exception cref="Jbig2Exception"/>
/// <exception cref="System.IO.IOException"/>
public Bitmap GetBitmap()
public Jbig2Bitmap GetBitmap()
{
if (null == pageBitmap)
{
@ -84,7 +84,7 @@
}
/// <summary>
/// This method composes the bitmaps of segments to a page and stores the page as a <see cref="Bitmap"/>.
/// This method composes the bitmaps of segments to a page and stores the page as a <see cref="Jbig2Bitmap"/>.
/// </summary>
/// <exception cref="Jbig2Exception"/>
/// <exception cref="System.IO.IOException"/>
@ -115,7 +115,7 @@
private void CreateNormalPage(PageInformation pageInformation)
{
pageBitmap = new Bitmap(pageInformation.BitmapWidth, pageInformation.BitmapHeight);
pageBitmap = new Jbig2Bitmap(pageInformation.BitmapWidth, pageInformation.BitmapHeight);
// Page 79, 3)
// If default pixel value is not 0, byte will be filled with 0xff
@ -139,7 +139,7 @@
case 43: // Immediate lossless generic refinement region
IRegion r = (IRegion)s.GetSegmentData();
Bitmap regionBitmap = r.GetRegionBitmap();
Jbig2Bitmap regionBitmap = r.GetRegionBitmap();
if (FitsPage(pageInformation, regionBitmap))
{
@ -150,7 +150,7 @@
RegionSegmentInformation regionInfo = r.RegionInfo;
CombinationOperator op = GetCombinationOperator(pageInformation,
regionInfo.CombinationOperator);
Bitmaps.Blit(regionBitmap, pageBitmap, regionInfo.X,
Jbig2Bitmaps.Blit(regionBitmap, pageBitmap, regionInfo.X,
regionInfo.Y, op);
}
@ -164,7 +164,7 @@
/// the region's bitmap as the page's bitmap. Otherwise we have to blit the smaller region's bitmap into the page's
/// bitmap.
/// </summary>
private bool FitsPage(PageInformation pageInformation, Bitmap regionBitmap)
private bool FitsPage(PageInformation pageInformation, Jbig2Bitmap regionBitmap)
{
return CountRegions() == 1 && pageInformation.DefaultPixelValue == 0
&& pageInformation.BitmapWidth == regionBitmap.Width
@ -175,7 +175,7 @@
{
List<ISegmentData> pageStripes = CollectPageStripes();
pageBitmap = new Bitmap(pageInformation.BitmapWidth, finalHeight);
pageBitmap = new Jbig2Bitmap(pageInformation.BitmapWidth, finalHeight);
int startLine = 0;
foreach (ISegmentData sd in pageStripes)
@ -190,7 +190,7 @@
RegionSegmentInformation regionInfo = r.RegionInfo;
CombinationOperator op = GetCombinationOperator(pageInformation,
regionInfo.CombinationOperator);
Bitmaps.Blit(r.GetRegionBitmap(), pageBitmap, regionInfo.X, startLine,
Jbig2Bitmaps.Blit(r.GetRegionBitmap(), pageBitmap, regionInfo.X, startLine,
op);
}
}

View File

@ -0,0 +1,40 @@
namespace UglyToad.PdfPig.Filters.Jbig2
{
internal readonly struct Jbig2Rectangle
{
/// <summary>
/// The x-coordinate of the upper-left corner of the rectangle.
/// </summary>
public int X { get; }
/// <summary>
/// The y-coordinate of the upper-left corner of the rectangle.
/// </summary>
public int Y { get; }
/// <summary>
/// The width of the rectangle.
/// </summary>
public int Width { get; }
/// <summary>
/// The height of the rectangle.
/// </summary>
public int Height { get; }
/// <summary>
/// Create a new <see cref="Jbig2Rectangle"/>.
/// </summary>
/// <param name="x">The x-coordinate of the upper-left corner of the rectangle.</param>
/// <param name="y">The y-coordinate of the upper-left corner of the rectangle.</param>
/// <param name="width">The width of the rectangle.</param>
/// <param name="height">The height of the rectangle.</param>
public Jbig2Rectangle(int x, int y, int width, int height)
{
X = x;
Y = y;
Width = width;
Height = height;
}
}
}

View File

@ -3,7 +3,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// Constants for MMR (de)compression.
/// </summary>
internal class MMRConstants
internal static class MMRConstants
{
public const int COMP_FAXG3 = 0;
public const int COMP_FAXG4 = 1;

View File

@ -8,7 +8,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// A decompressor for MMR compression.
/// </summary>
internal class MMRDecompressor
internal sealed class MMRDecompressor
{
private readonly int width;
private readonly int height;
@ -490,9 +490,9 @@ namespace UglyToad.PdfPig.Filters.Jbig2
InitTables();
}
public Bitmap Uncompress()
public Jbig2Bitmap Uncompress()
{
Bitmap result = new Bitmap(width, height);
Jbig2Bitmap result = new Jbig2Bitmap(width, height);
int[] currentOffsets = new int[width + 5];
int[] referenceOffsets = new int[width + 5];
@ -545,7 +545,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
}
}
private void FillBitmap(Bitmap result, int line, int[] currentOffsets, int count)
private void FillBitmap(Jbig2Bitmap result, int line, int[] currentOffsets, int count)
{
int x = 0;
int targetByte = result.GetByteIndex(0, line);

View File

@ -5,7 +5,7 @@
/// <summary>
/// Represents a out of band node in a Huffman tree.
/// </summary>
internal class OutOfBandNode : Node
internal sealed class OutOfBandNode : Node
{
public OutOfBandNode(Code c)
{

View File

@ -3,7 +3,7 @@
/// <summary>
/// This class represents the segment type "Page information", 7.4.8 (page 73).
/// </summary>
internal class PageInformation : ISegmentData
internal sealed class PageInformation : ISegmentData
{
private SubInputStream subInputStream;

View File

@ -1,12 +1,11 @@
namespace UglyToad.PdfPig.Filters.Jbig2
{
using System.Collections.Generic;
using System.Drawing;
/// <summary>
/// This class represents the segment type "Pattern dictionary", 7.4.4.
/// </summary>
internal class PatternDictionary : IDictionary
internal sealed class PatternDictionary : IJbigDictionary
{
private SubInputStream subInputStream;
@ -20,7 +19,7 @@
private short[] gbAtY = null;
// Decoded bitmaps, stored to be used by segments, that refer to it
private List<Bitmap> patterns;
private List<Jbig2Bitmap> patterns;
// Pattern dictionary flags, 7.4.4.1.1
public bool IsMMREncoded { get; private set; }
@ -99,11 +98,11 @@
/// <summary>
/// This method decodes a pattern dictionary segment and returns an array of
/// <see cref="Bitmap"/>s. Each <see cref="Bitmap"/> is a pattern.
/// <see cref="Jbig2Bitmap"/>s. Each <see cref="Jbig2Bitmap"/> is a pattern.
/// The procedure is described in 6.7.5 (page 43).
/// </summary>
/// <returns>An array of <see cref="Bitmap"/>s as result of the decoding procedure.</returns>
public List<Bitmap> GetDictionary()
/// <returns>An array of <see cref="Jbig2Bitmap"/>s as result of the decoding procedure.</returns>
public List<Jbig2Bitmap> GetDictionary()
{
if (null == patterns)
{
@ -117,7 +116,7 @@
genericRegion.SetParameters(IsMMREncoded, dataOffset, dataLength, HdpHeight,
(GrayMax + 1) * HdpWidth, HdTemplate, false, false, gbAtX, gbAtY);
Bitmap collectiveBitmap = genericRegion.GetRegionBitmap();
Jbig2Bitmap collectiveBitmap = genericRegion.GetRegionBitmap();
// 4)
ExtractPatterns(collectiveBitmap);
@ -126,18 +125,18 @@
return patterns;
}
private void ExtractPatterns(Bitmap collectiveBitmap)
private void ExtractPatterns(Jbig2Bitmap collectiveBitmap)
{
// 3)
int gray = 0;
patterns = new List<Bitmap>(GrayMax + 1);
patterns = new List<Jbig2Bitmap>(GrayMax + 1);
// 4)
while (gray <= GrayMax)
{
// 4) a) Retrieve a pattern bitmap by extracting it out of the collective bitmap
Rectangle roi = new Rectangle(HdpWidth * gray, 0, HdpWidth, HdpHeight);
Bitmap patternBitmap = Bitmaps.Extract(roi, collectiveBitmap);
Jbig2Rectangle roi = new Jbig2Rectangle(HdpWidth * gray, 0, HdpWidth, HdpHeight);
Jbig2Bitmap patternBitmap = Jbig2Bitmaps.Extract(roi, collectiveBitmap);
patterns.Add(patternBitmap);
// 4) b)

View File

@ -3,7 +3,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// This class is not implemented yet and empty. Wait for use cases.
/// </summary>
internal class Profiles : ISegmentData
internal sealed class Profiles : ISegmentData
{
public void Init(SegmentHeader header, SubInputStream sis)
{

View File

@ -4,7 +4,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// This class represents the "Region segment information" field, 7.4.1(page 50).
/// Every region segment data starts with this part.
/// </summary>
internal class RegionSegmentInformation : ISegmentData
internal sealed class RegionSegmentInformation : ISegmentData
{
private readonly SubInputStream subInputStream;

View File

@ -7,7 +7,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// The basic class for all JBIG2 segments.
/// </summary>
internal class SegmentHeader
internal sealed class SegmentHeader
{
private static readonly Dictionary<int, Type> SEGMENT_TYPE_MAP = new Dictionary<int, Type>
{

View File

@ -2,7 +2,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
{
using System.Collections.Generic;
internal class StandardTables
internal static class StandardTables
{
class StandardTable : HuffmanTable
{

View File

@ -7,7 +7,7 @@
/// Read accesses to the wrapped stream are synchronized, so that users of this stream need to deal with synchronization
/// against other users of the same instance, but not against other users of the wrapped stream.
/// </summary>
internal class SubInputStream : AbstractImageInputStream
internal sealed class SubInputStream : AbstractImageInputStream
{
private readonly IImageInputStream wrappedStream;

View File

@ -2,13 +2,12 @@
{
using System;
using System.Collections.Generic;
using System.Drawing;
/// <summary>
/// This class represents the data of segment type "Symbol dictionary". Parsing is described in
/// 7.4.2.1.1 - 7.4.1.1.5 and decoding procedure is described in 6.5.
/// </summary>
internal class SymbolDictionary : IDictionary
internal sealed class SymbolDictionary : IJbigDictionary
{
private SubInputStream subInputStream;
@ -41,9 +40,9 @@
// Further parameters
private SegmentHeader segmentHeader;
private int amountOfImportedSymbolss;
private List<Bitmap> importSymbols;
private List<Jbig2Bitmap> importSymbols;
private int amountOfDecodedSymbols;
private Bitmap[] newSymbols;
private Jbig2Bitmap[] newSymbols;
// User-supplied tables
private HuffmanTable dhTable;
@ -52,8 +51,8 @@
private HuffmanTable aggInstTable;
// Return value of that segment
private List<Bitmap> exportSymbols;
private List<Bitmap> sbSymbols;
private List<Jbig2Bitmap> exportSymbols;
private List<Jbig2Bitmap> sbSymbols;
private ArithmeticDecoder arithmeticDecoder;
private ArithmeticIntegerDecoder iDecoder;
@ -230,7 +229,7 @@
}
else
{
importSymbols = new List<Bitmap>();
importSymbols = new List<Jbig2Bitmap>();
}
}
@ -309,7 +308,7 @@
/// 6.5.5 Decoding the symbol dictionary.
/// </summary>
/// <returns>List of decoded symbol bitmaps.</returns>
public List<Bitmap> GetDictionary()
public List<Jbig2Bitmap> GetDictionary()
{
if (null == exportSymbols)
{
@ -324,7 +323,7 @@
}
// 6.5.5 1)
newSymbols = new Bitmap[amountOfNewSymbols];
newSymbols = new Jbig2Bitmap[amountOfNewSymbols];
// 6.5.5 2)
int[] newSymbolsWidths = null;
@ -408,7 +407,7 @@
subInputStream.SkipBits();
Bitmap heightClassCollectiveBitmap =
Jbig2Bitmap heightClassCollectiveBitmap =
DecodeHeightClassCollectiveBitmap(bmSize, heightClassHeight, totalWidth);
subInputStream.SkipBits();
@ -479,7 +478,7 @@
}
}
private void DecodeHeightClassBitmap(Bitmap heightClassCollectiveBitmap,
private void DecodeHeightClassBitmap(Jbig2Bitmap heightClassCollectiveBitmap,
int heightClassFirstSymbol, int heightClassHeight,
int[] newSymbolsWidths)
{
@ -492,8 +491,8 @@
startColumn += newSymbolsWidths[j];
}
var roi = new Rectangle(startColumn, 0, newSymbolsWidths[i], heightClassHeight);
var symbolBitmap = Bitmaps.Extract(roi, heightClassCollectiveBitmap);
var roi = new Jbig2Rectangle(startColumn, 0, newSymbolsWidths[i], heightClassHeight);
var symbolBitmap = Jbig2Bitmaps.Extract(roi, heightClassCollectiveBitmap);
newSymbols[i] = symbolBitmap;
sbSymbols.Add(symbolBitmap);
}
@ -619,7 +618,7 @@
// 6)
SetSymbolsArray();
Bitmap ibo = sbSymbols[id];
Jbig2Bitmap ibo = sbSymbols[id];
DecodeNewSymbols(symbolWidth, heightClassHeight, ibo, rdx, rdy);
// 7)
@ -630,7 +629,7 @@
}
}
private void DecodeNewSymbols(int symWidth, int hcHeight, Bitmap ibo, int rdx, int rdy)
private void DecodeNewSymbols(int symWidth, int hcHeight, Jbig2Bitmap ibo, int rdx, int rdy)
{
if (genericRefinementRegion == null)
{
@ -670,7 +669,7 @@
private void AddSymbol(IRegion region)
{
Bitmap symbol = region.GetRegionBitmap();
Jbig2Bitmap symbol = region.GetRegionBitmap();
newSymbols[amountOfDecodedSymbols] = symbol;
sbSymbols.Add(symbol);
}
@ -747,12 +746,12 @@
return 0;
}
private Bitmap DecodeHeightClassCollectiveBitmap(long bmSize,
private Jbig2Bitmap DecodeHeightClassCollectiveBitmap(long bmSize,
int heightClassHeight, int totalWidth)
{
if (bmSize == 0)
{
Bitmap heightClassCollectiveBitmap = new Bitmap(totalWidth, heightClassHeight);
Jbig2Bitmap heightClassCollectiveBitmap = new Jbig2Bitmap(totalWidth, heightClassHeight);
for (int i = 0; i < heightClassCollectiveBitmap.GetByteArray().Length; i++)
{
@ -777,7 +776,7 @@
private void SetExportedSymbols(int[] toExportFlags)
{
exportSymbols = new List<Bitmap>(amountOfExportSymbolss);
exportSymbols = new List<Jbig2Bitmap>(amountOfExportSymbolss);
for (int i = 0; i < amountOfImportedSymbolss + amountOfNewSymbols; i++)
{
@ -881,7 +880,7 @@
if (sbSymbols == null)
{
sbSymbols = new List<Bitmap>();
sbSymbols = new List<Jbig2Bitmap>();
sbSymbols.AddRange(importSymbols);
}
}
@ -891,7 +890,7 @@
/// </summary>
private void RetrieveImportSymbols()
{
importSymbols = new List<Bitmap>();
importSymbols = new List<Jbig2Bitmap>();
foreach (SegmentHeader referredToSegmentHeader in segmentHeader.GetRtSegments())
{
if (referredToSegmentHeader.SegmentType == 0)

View File

@ -3,7 +3,7 @@ namespace UglyToad.PdfPig.Filters.Jbig2
/// <summary>
/// This class represents a "Table" segment. It handles custom tables, see Annex B.
/// </summary>
internal class Table : ISegmentData
internal sealed class Table : ISegmentData
{
private SubInputStream subInputStream;

View File

@ -8,7 +8,7 @@
/// <summary>
/// This class represented the segment type "Text region", 7.4.3, page 56.
/// </summary>
internal class TextRegion : IRegion
internal sealed class TextRegion : IRegion
{
private SubInputStream subInputStream;
@ -45,8 +45,8 @@
private int sbStrips;
private int amountOfSymbols;
private Bitmap regionBitmap;
private List<Bitmap> symbols = new List<Bitmap>();
private Jbig2Bitmap regionBitmap;
private List<Jbig2Bitmap> symbols = new List<Jbig2Bitmap>();
private ArithmeticDecoder arithmeticDecoder;
private ArithmeticIntegerDecoder integerDecoder;
@ -283,7 +283,7 @@
}
}
public Bitmap GetRegionBitmap()
public Jbig2Bitmap GetRegionBitmap()
{
if (!isHuffmanEncoded)
{
@ -363,7 +363,7 @@
private void CreateRegionBitmap()
{
// 6.4.5
regionBitmap = new Bitmap(RegionInfo.BitmapWidth, RegionInfo.BitmapHeight);
regionBitmap = new Jbig2Bitmap(RegionInfo.BitmapWidth, RegionInfo.BitmapHeight);
// 1)
if (defaultPixel != 0)
@ -472,7 +472,7 @@
// 3 c) v)
long r = DecodeRI();
// 6.4.11
Bitmap ib = DecodeIb(r, id);
Jbig2Bitmap ib = DecodeIb(r, id);
// vi)
Blit(ib, t);
@ -609,9 +609,9 @@
return 0;
}
private Bitmap DecodeIb(long r, long id)
private Jbig2Bitmap DecodeIb(long r, long id)
{
Bitmap ib;
Jbig2Bitmap ib;
if (r == 0)
{
@ -635,7 +635,7 @@
}
// 6)
Bitmap ibo = symbols[(int)id];
Jbig2Bitmap ibo = symbols[(int)id];
int wo = ibo.Width;
int ho = ibo.Height;
@ -904,7 +904,7 @@
}
private void Blit(Bitmap ib, long t)
private void Blit(Jbig2Bitmap ib, long t)
{
if (isTransposed == 0 && (referenceCorner == 2 || referenceCorner == 3))
{
@ -946,7 +946,7 @@
}
}
Bitmaps.Blit(ib, regionBitmap, (int)s, (int)t, combinationOperator);
Jbig2Bitmaps.Blit(ib, regionBitmap, (int)s, (int)t, combinationOperator);
// x)
if (isTransposed == 0 && (referenceCorner == 0 || referenceCorner == 1))
@ -1105,7 +1105,7 @@
short sbCombinationOperator, short transposed, short refCorner, short sbdsOffset,
short sbHuffFS, short sbHuffDS, short sbHuffDT, short sbHuffRDWidth,
short sbHuffRDHeight, short sbHuffRDX, short sbHuffRDY, short sbHuffRSize,
short sbrTemplate, short[] sbrATX, short[] sbrATY, List<Bitmap> sbSyms,
short sbrTemplate, short[] sbrATX, short[] sbrATY, List<Jbig2Bitmap> sbSyms,
int sbSymCodeLen)
{

View File

@ -1,7 +1,6 @@
namespace UglyToad.PdfPig.Filters.Jbig2
{
using System;
using System.Drawing;
internal static class Utils
{
@ -10,22 +9,22 @@ namespace UglyToad.PdfPig.Filters.Jbig2
return (int)Math.Pow(2, Convert.ToString(number, 2).Length - 1);
}
public static int GetMinY(this Rectangle r)
public static int GetMinY(this Jbig2Rectangle r)
{
return r.Y;
}
public static int GetMaxY(this Rectangle r)
public static int GetMaxY(this Jbig2Rectangle r)
{
return r.Y + r.Height;
}
public static int GetMaxX(this Rectangle r)
public static int GetMaxX(this Jbig2Rectangle r)
{
return r.X + r.Width;
}
public static int GetMinX(this Rectangle r)
public static int GetMinX(this Jbig2Rectangle r)
{
return r.X;
}

View File

@ -1,12 +1,11 @@
namespace UglyToad.PdfPig.Filters.Jbig2
{
using System;
using static HuffmanTable;
/// <summary>
/// Represents a value node in a Huffman tree. It is a leaf of a tree.
/// </summary>
internal class ValueNode : Node
internal sealed class ValueNode : Node
{
private readonly int rangeLength;
private readonly int rangeLow;
@ -33,13 +32,15 @@
}
}
internal static string bitPattern(int v, int len)
internal static string BitPattern(int v, int len)
{
var result = new char[len];
for (int i = 1; i <= len; i++)
{
result[i - 1] = (v >> (len - i) & 1) != 0 ? '1' : '0';
}
return new String(result);
return new string(result);
}
}
}

View File

@ -33,8 +33,8 @@
var bounds = xObject.AppliedTransformation.Transform(new PdfRectangle(new PdfPoint(0, 0), new PdfPoint(1, 1)));
var width = dictionary.Get<NumericToken>(NameToken.Width).Int;
var height = dictionary.Get<NumericToken>(NameToken.Height).Int;
var width = dictionary.Get<NumericToken>(NameToken.Width, pdfScanner).Int;
var height = dictionary.Get<NumericToken>(NameToken.Height, pdfScanner).Int;
var isImageMask = dictionary.TryGet(NameToken.ImageMask, out BooleanToken isMaskToken)
&& isMaskToken.Data;
@ -65,11 +65,11 @@
}
var interpolate = dictionary.TryGet(NameToken.Interpolate, out BooleanToken interpolateToken)
&& interpolateToken.Data;
&& interpolateToken.Data;
var supportsFilters = true;
var filters = filterProvider.GetFilters(dictionary, pdfScanner);
foreach (var filter in filters)
{