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

* Fixing platform indepenedent integer size * Cleared test logs. * Cleared unnecessary int32 * Defined precise integer size for jbig2 segments.
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|