mirror of
https://github.com/unidoc/unipdf.git
synced 2025-05-04 22:17:22 +08:00

* Prepared skeleton and basic component implementations for the jbig2 encoding. * Added Bitset. Implemented Bitmap. * Decoder with old Arithmetic Decoder * Partly working arithmetic * Working arithmetic decoder. * MMR patched. * rebuild to apache. * Working generic * Working generic * Decoded full document * Update Jenkinsfile go version [master] (#398) * Update Jenkinsfile go version * Decoded AnnexH document * Minor issues fixed. * Update README.md * Fixed generic region errors. Added benchmark. Added bitmap unpadder. Added Bitmap toImage method. * Fixed endofpage error * Added integration test. * Decoded all test files without errors. Implemented JBIG2Global. * Merged with v3 version * Fixed the EOF in the globals issue * Fixed the JBIG2 ChocolateData Decode * JBIG2 Added license information * Minor fix in jbig2 encoding. * Applied the logging convention * Cleaned unnecessary imports * Go modules clear unused imports * checked out the README.md * Moved trace to Debug. Fixed the build integrate tag in the document_decode_test.go * Initial encoder skeleton * Applied UniPDF Developer Guide. Fixed lint issues. * Cleared documentation, fixed style issues. * Added jbig2 doc.go files. Applied unipdf guide style. * Minor code style changes. * Minor naming and style issues fixes. * Minor naming changes. Style issues fixed. * Review r11 fixes. * Added JBIG2 Encoder skeleton. * Moved Document and Page to jbig2/document package. Created decoder package responsible for decoding jbig2 stream. * Implemented raster functions. * Added raster uni low test funcitons. * Added raster low test functions * untracked files on jbig2-encoder: c869089 Added raster low test functions * index on jbig2-encoder: c869089 Added raster low test functions * Added morph files. * implemented jbig2 encoder basics * JBIG2 Encoder - Generic method * Added jbig2 image encode ttests, black/white image tests * cleaned and tested jbig2 package * unfinished jbig2 classified encoder * jbig2 minor style changes * minor jbig2 encoder changes * prepared JBIG2 Encoder * Style and lint fixes * Minor changes and lints * Fixed shift unsinged value build errors * Minor naming change * Added jbig2 encode, image gondels. Fixed jbig2 decode bug. * Provided jbig2 core.DecodeGlobals function. * Fixed JBIG2Encoder `r6` revision issues. * Removed public JBIG2Encoder document. * Minor style changes * added NewJBIG2Encoder function. * fixed JBIG2Encoder 'r9' revision issues. * Cleared 'r9' commented code. * Updated ACKNOWLEDGEMENETS. Fixed JBIG2Encoder 'r10' revision issues. Co-authored-by: Gunnsteinn Hall <gunnsteinn.hall@gmail.com>
333 lines
7.6 KiB
Go
333 lines
7.6 KiB
Go
/*
|
|
* This file is subject to the terms and conditions defined in
|
|
* file 'LICENSE.md', which is part of this source code package.
|
|
*/
|
|
|
|
package segments
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/unidoc/unipdf/v3/common"
|
|
|
|
"github.com/unidoc/unipdf/v3/internal/jbig2/bitmap"
|
|
"github.com/unidoc/unipdf/v3/internal/jbig2/reader"
|
|
)
|
|
|
|
// TestSymbolDictionaryDecode tests the symbol dictionary decode process.
|
|
func TestSymbolDictionaryDecode(t *testing.T) {
|
|
setLogger()
|
|
|
|
t.Run("1st", func(t *testing.T) {
|
|
data := []byte{
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18,
|
|
// Data part
|
|
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xE9, 0xCB,
|
|
0xF4, 0x00, 0x26, 0xAF, 0x04, 0xBF, 0xF0, 0x78, 0x2F, 0xE0, 0x00, 0x40,
|
|
}
|
|
r := reader.New(data)
|
|
d := &document{}
|
|
h, err := NewHeader(d, r, 0, OSequential)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, TSymbolDictionary, h.Type)
|
|
assert.Equal(t, false, h.PageAssociationFieldSize)
|
|
assert.Equal(t, false, h.RetainFlag)
|
|
assert.Equal(t, 0, len(h.RTSegments))
|
|
assert.Equal(t, uint64(24), h.SegmentDataLength)
|
|
|
|
sg, err := h.GetSegmentData()
|
|
require.NoError(t, err)
|
|
|
|
s, ok := sg.(*SymbolDictionary)
|
|
require.True(t, ok)
|
|
|
|
assert.True(t, s.IsHuffmanEncoded)
|
|
assert.False(t, s.UseRefinementAggregation)
|
|
assert.Equal(t, uint32(1), s.NumberOfExportedSymbols)
|
|
assert.Equal(t, uint32(1), s.NumberOfNewSymbols)
|
|
|
|
bm, err := s.GetDictionary()
|
|
require.NoError(t, err)
|
|
|
|
assert.NotEmpty(t, bm)
|
|
if assert.Len(t, bm, 1) {
|
|
isLetterP(t, bm[0])
|
|
}
|
|
})
|
|
|
|
t.Run("3rd", func(t *testing.T) {
|
|
data := []byte{
|
|
// Header
|
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1C,
|
|
|
|
// Data part
|
|
0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0xE5, 0xCD,
|
|
0xF8, 0x00, 0x79, 0xE0, 0x84, 0x10, 0x81, 0xF0, 0x82, 0x10, 0x86, 0x10,
|
|
0x79, 0xF0, 0x00, 0x80,
|
|
}
|
|
r := reader.New(data)
|
|
d := &document{}
|
|
h, err := NewHeader(d, r, 0, OSequential)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, TSymbolDictionary, h.Type)
|
|
assert.Equal(t, false, h.PageAssociationFieldSize)
|
|
assert.Equal(t, false, h.RetainFlag)
|
|
assert.Equal(t, 0, len(h.RTSegments))
|
|
assert.Equal(t, uint64(28), h.SegmentDataLength)
|
|
|
|
sg, err := h.GetSegmentData()
|
|
require.NoError(t, err)
|
|
|
|
s, ok := sg.(*SymbolDictionary)
|
|
require.True(t, ok)
|
|
|
|
assert.True(t, s.IsHuffmanEncoded)
|
|
assert.False(t, s.UseRefinementAggregation)
|
|
assert.Equal(t, uint32(2), s.NumberOfExportedSymbols)
|
|
assert.Equal(t, uint32(2), s.NumberOfNewSymbols)
|
|
|
|
bm, err := s.GetDictionary()
|
|
require.NoError(t, err)
|
|
|
|
if assert.Len(t, bm, 2) {
|
|
// first letter should be a 'c'
|
|
isLetterC(t, bm[0])
|
|
isLetterA(t, bm[1])
|
|
}
|
|
})
|
|
|
|
t.Run("10th", func(t *testing.T) {
|
|
data := []byte{
|
|
// Header
|
|
0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x1B,
|
|
|
|
// Segment data
|
|
0x08, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02,
|
|
0x4F, 0xE7, 0x8C, 0x20, 0x0E, 0x1D, 0xC7, 0xCF, 0x01, 0x11, 0xC4, 0xB2,
|
|
0x6F, 0xFF, 0xAC,
|
|
}
|
|
r := reader.New(data)
|
|
d := &document{}
|
|
h, err := NewHeader(d, r, 0, OSequential)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, TSymbolDictionary, h.Type)
|
|
assert.Equal(t, false, h.PageAssociationFieldSize)
|
|
assert.Equal(t, false, h.RetainFlag)
|
|
assert.Equal(t, 0, len(h.RTSegments))
|
|
assert.Equal(t, uint64(27), h.SegmentDataLength)
|
|
|
|
sg, err := h.GetSegmentData()
|
|
require.NoError(t, err)
|
|
|
|
s, ok := sg.(*SymbolDictionary)
|
|
require.True(t, ok)
|
|
|
|
assert.False(t, s.IsHuffmanEncoded)
|
|
assert.Equal(t, int8(2), s.SdTemplate)
|
|
assert.Equal(t, false, s.isCodingContextUsed)
|
|
assert.Equal(t, false, s.isCodingContextRetained)
|
|
|
|
assert.Equal(t, int8(2), s.SdATX[0])
|
|
assert.Equal(t, int8(-1), s.SdATY[0])
|
|
|
|
assert.Equal(t, uint32(2), s.NumberOfExportedSymbols)
|
|
assert.Equal(t, uint32(2), s.NumberOfNewSymbols)
|
|
|
|
bm, err := s.GetDictionary()
|
|
require.NoError(t, err)
|
|
|
|
if assert.Len(t, bm, 2) {
|
|
isLetterC(t, bm[0])
|
|
isLetterA(t, bm[1])
|
|
}
|
|
})
|
|
|
|
t.Run("17th", func(t *testing.T) {
|
|
data := []byte{
|
|
// 17th segment
|
|
// Header
|
|
0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16,
|
|
|
|
// Data Part
|
|
0x08, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
|
0x01, 0x4F, 0xE7, 0x8D, 0x68, 0x1B, 0x14, 0x2F, 0x3F, 0xFF, 0xAC,
|
|
|
|
// 18th segment
|
|
// Header
|
|
0x00, 0x00, 0x00, 0x11, 0x00, 0x21, 0x10, 0x03, 0x00, 0x00, 0x00, 0x20,
|
|
|
|
// Data Part
|
|
0x08, 0x02, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03,
|
|
0x00, 0x00, 0x00, 0x02, 0x4F, 0xE9, 0xD7, 0xD5, 0x90, 0xC3, 0xB5, 0x26,
|
|
0xA7, 0xFB, 0x6D, 0x14, 0x98, 0x3F, 0xFF, 0xAC,
|
|
}
|
|
|
|
r := reader.New(data)
|
|
p3 := &page{segments: []*Header{}}
|
|
d := &document{pages: []Pager{nil, nil, p3}}
|
|
h, err := NewHeader(d, r, 0, OSequential)
|
|
require.NoError(t, err)
|
|
|
|
p3.setSegment(h)
|
|
|
|
assert.Equal(t, TSymbolDictionary, h.Type)
|
|
assert.Equal(t, false, h.PageAssociationFieldSize)
|
|
|
|
assert.Equal(t, false, h.RetainFlag)
|
|
assert.Equal(t, 0, len(h.RTSegments))
|
|
assert.Equal(t, uint64(22), h.SegmentDataLength)
|
|
|
|
sg, err := h.GetSegmentData()
|
|
require.NoError(t, err)
|
|
|
|
s, ok := sg.(*SymbolDictionary)
|
|
require.True(t, ok)
|
|
|
|
assert.False(t, s.IsHuffmanEncoded)
|
|
assert.False(t, s.UseRefinementAggregation)
|
|
assert.Equal(t, int8(2), s.SdTemplate)
|
|
assert.False(t, s.isCodingContextUsed)
|
|
assert.False(t, s.isCodingContextRetained)
|
|
|
|
if assert.Len(t, s.SdATX, 1) {
|
|
assert.Equal(t, s.SdATX[0], int8(2))
|
|
}
|
|
|
|
if assert.Len(t, s.SdATY, 1) {
|
|
assert.Equal(t, s.SdATY[0], int8(-1))
|
|
}
|
|
|
|
assert.Equal(t, uint32(1), s.NumberOfExportedSymbols)
|
|
assert.Equal(t, uint32(1), s.NumberOfNewSymbols)
|
|
|
|
bm, err := s.GetDictionary()
|
|
require.NoError(t, err)
|
|
|
|
if assert.Len(t, bm, 1) {
|
|
isLetterA(t, bm[0])
|
|
}
|
|
})
|
|
}
|
|
|
|
var alreadySet bool
|
|
|
|
func setLogger() {
|
|
if testing.Verbose() && !alreadySet {
|
|
common.SetLogger(common.NewConsoleLogger(common.LogLevelDebug))
|
|
}
|
|
}
|
|
|
|
func isLetterP(t *testing.T, b *bitmap.Bitmap) {
|
|
if b.Width != 5 || b.Height != 8 {
|
|
t.Fail()
|
|
return
|
|
}
|
|
|
|
for y := 0; y < b.Height; y++ {
|
|
for x := 0; x < b.Width; x++ {
|
|
pix := b.GetPixel(x, y)
|
|
|
|
switch y {
|
|
case 0, 4:
|
|
if x != 4 {
|
|
assert.True(t, pix)
|
|
} else {
|
|
assert.False(t, pix)
|
|
}
|
|
case 1, 2, 3:
|
|
if x == 0 || x == 4 {
|
|
assert.True(t, pix)
|
|
} else {
|
|
assert.False(t, pix)
|
|
}
|
|
case 5, 6, 7:
|
|
if x == 0 {
|
|
assert.True(t, pix)
|
|
} else {
|
|
assert.False(t, pix)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func isLetterC(t *testing.T, b *bitmap.Bitmap) {
|
|
if b.Width != 6 || b.Height != 6 {
|
|
t.Fail()
|
|
return
|
|
}
|
|
|
|
for y := 0; y < b.Height; y++ {
|
|
for x := 0; x < b.Width; x++ {
|
|
pix := b.GetPixel(x, y)
|
|
|
|
switch y {
|
|
case 0, 5:
|
|
if x == 0 || x == 5 {
|
|
assert.False(t, pix)
|
|
} else {
|
|
assert.True(t, pix)
|
|
}
|
|
case 1, 4:
|
|
if x == 0 || x == 5 {
|
|
assert.True(t, pix)
|
|
} else {
|
|
assert.False(t, pix)
|
|
}
|
|
default:
|
|
if x == 0 {
|
|
assert.True(t, pix)
|
|
} else {
|
|
assert.False(t, pix)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func isLetterA(t *testing.T, b *bitmap.Bitmap) {
|
|
if b.Width != 6 || b.Height != 6 {
|
|
t.Fail()
|
|
return
|
|
}
|
|
|
|
for y := 0; y < b.Height; y++ {
|
|
for x := 0; x < b.Width; x++ {
|
|
pix := b.GetPixel(x, y)
|
|
|
|
switch y {
|
|
case 0:
|
|
if x == 0 || x == 5 {
|
|
assert.False(t, pix)
|
|
} else {
|
|
assert.True(t, pix)
|
|
}
|
|
case 1:
|
|
if x == 5 {
|
|
assert.True(t, pix)
|
|
} else {
|
|
assert.False(t, pix)
|
|
}
|
|
case 2, 5:
|
|
if x == 0 {
|
|
assert.False(t, pix)
|
|
} else {
|
|
assert.True(t, pix)
|
|
}
|
|
default:
|
|
if x == 0 || x == 5 {
|
|
assert.True(t, pix)
|
|
} else {
|
|
assert.False(t, pix)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|