mirror of
https://github.com/unidoc/unipdf.git
synced 2025-05-02 22:17:06 +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>
221 lines
4.5 KiB
Go
221 lines
4.5 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 (
|
|
"errors"
|
|
"image"
|
|
"math"
|
|
|
|
"github.com/unidoc/unipdf/v3/common"
|
|
|
|
"github.com/unidoc/unipdf/v3/internal/jbig2/bitmap"
|
|
"github.com/unidoc/unipdf/v3/internal/jbig2/reader"
|
|
)
|
|
|
|
// PatternDictionary is the jbig2 model for the pattern dictionary segment - 7.4.4.
|
|
type PatternDictionary struct {
|
|
r reader.StreamReader
|
|
|
|
DataHeaderOffset int64
|
|
DataHeaderLength int64
|
|
DataOffset int64
|
|
DataLength int64
|
|
|
|
GBAtX []int8
|
|
GBAtY []int8
|
|
|
|
// Flags 7.4.4.1.1
|
|
IsMMREncoded bool
|
|
HDTemplate byte
|
|
|
|
// Width of the patterns in the pattern dictionary
|
|
HdpWidth byte
|
|
// Height of the patterns in the pattern dictionary
|
|
HdpHeight byte
|
|
|
|
// Decoded bitmaps stored to be used by segments that refer to it
|
|
Patterns []*bitmap.Bitmap
|
|
|
|
// Largest gray-scale value 7.4.4.1.4
|
|
GrayMax uint32
|
|
}
|
|
|
|
// GetDictionary gets the PatternDictionary segment Dictionary bitmaps.
|
|
func (p *PatternDictionary) GetDictionary() ([]*bitmap.Bitmap, error) {
|
|
if p.Patterns != nil {
|
|
return p.Patterns, nil
|
|
}
|
|
|
|
if !p.IsMMREncoded {
|
|
p.setGbAtPixels()
|
|
}
|
|
|
|
genericRegion := NewGenericRegion(p.r)
|
|
genericRegion.setParametersMMR(p.IsMMREncoded, p.DataOffset, p.DataLength, uint32(p.HdpHeight), (p.GrayMax+1)*uint32(p.HdpWidth), p.HDTemplate, false, false, p.GBAtX, p.GBAtY)
|
|
|
|
collectiveBitmap, err := genericRegion.GetRegionBitmap()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err = p.extractPatterns(collectiveBitmap); err != nil {
|
|
return nil, err
|
|
}
|
|
return p.Patterns, nil
|
|
}
|
|
|
|
// Init implements Segmenter interface.
|
|
func (p *PatternDictionary) Init(h *Header, r reader.StreamReader) error {
|
|
p.r = r
|
|
return p.parseHeader()
|
|
}
|
|
|
|
func (p *PatternDictionary) checkInput() error {
|
|
if p.HdpHeight < 1 || p.HdpWidth < 1 {
|
|
return errors.New("invalid Header Value: Width/Height must be greater than zero")
|
|
}
|
|
|
|
if p.IsMMREncoded {
|
|
if p.HDTemplate != 0 {
|
|
common.Log.Debug("variable HDTemplate should not contain the value 0")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *PatternDictionary) computeSegmentDataStructure() error {
|
|
p.DataOffset = p.r.StreamPosition()
|
|
p.DataHeaderLength = p.DataOffset - p.DataHeaderOffset
|
|
p.DataLength = int64(p.r.Length()) - p.DataHeaderLength
|
|
return nil
|
|
}
|
|
|
|
func (p *PatternDictionary) extractPatterns(collectiveBitmap *bitmap.Bitmap) error {
|
|
// 3)
|
|
var gray int
|
|
patterns := make([]*bitmap.Bitmap, p.GrayMax+1)
|
|
|
|
// 4
|
|
for gray <= int(p.GrayMax) {
|
|
// 4 a)
|
|
x0 := int(p.HdpWidth) * gray
|
|
roi := image.Rect(x0, 0, x0+int(p.HdpWidth), int(p.HdpHeight))
|
|
patternBitmap, err := bitmap.Extract(roi, collectiveBitmap)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
patterns[gray] = patternBitmap
|
|
|
|
// 4 b)
|
|
gray++
|
|
}
|
|
|
|
p.Patterns = patterns
|
|
return nil
|
|
}
|
|
|
|
func (p *PatternDictionary) parseHeader() error {
|
|
common.Log.Trace("[PATTERN-DICTIONARY][parseHeader] begin")
|
|
defer func() {
|
|
common.Log.Trace("[PATTERN-DICTIONARY][parseHeader] finished")
|
|
}()
|
|
|
|
// Bit 3-7 dirty read
|
|
_, err := p.r.ReadBits(5)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Bit 1-2
|
|
if err = p.readTemplate(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Bit 0
|
|
if err = p.readIsMMREncoded(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = p.readPatternWidthAndHeight(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = p.readGrayMax(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = p.computeSegmentDataStructure(); err != nil {
|
|
return err
|
|
}
|
|
return p.checkInput()
|
|
}
|
|
|
|
func (p *PatternDictionary) readTemplate() error {
|
|
temp, err := p.r.ReadBits(2)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p.HDTemplate = byte(temp)
|
|
return nil
|
|
}
|
|
|
|
func (p *PatternDictionary) readIsMMREncoded() error {
|
|
bit, err := p.r.ReadBit()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if bit != 0 {
|
|
p.IsMMREncoded = true
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *PatternDictionary) readPatternWidthAndHeight() error {
|
|
temp, err := p.r.ReadByte()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p.HdpWidth = temp
|
|
|
|
temp, err = p.r.ReadByte()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p.HdpHeight = temp
|
|
return nil
|
|
}
|
|
|
|
func (p *PatternDictionary) readGrayMax() error {
|
|
temp, err := p.r.ReadBits(32)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p.GrayMax = uint32(temp & math.MaxUint32)
|
|
return nil
|
|
}
|
|
|
|
func (p *PatternDictionary) setGbAtPixels() {
|
|
if p.HDTemplate == 0 {
|
|
p.GBAtX = make([]int8, 4)
|
|
p.GBAtY = make([]int8, 4)
|
|
|
|
p.GBAtX[0] = -int8(p.HdpWidth)
|
|
p.GBAtY[0] = 0
|
|
|
|
p.GBAtX[1] = -3
|
|
p.GBAtY[1] = -1
|
|
|
|
p.GBAtX[2] = 2
|
|
p.GBAtY[2] = -2
|
|
|
|
p.GBAtX[3] = -2
|
|
p.GBAtY[3] = -2
|
|
} else {
|
|
p.GBAtX = []int8{-int8(p.HdpWidth)}
|
|
p.GBAtY = []int8{0}
|
|
}
|
|
}
|