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 * Decoded full document * 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 * 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. * Integrate jbig2 tests with build system * Added jbig2 integration test golden files. * Minor jbig2 integration test fix * Removed jbig2 integration image assertions * Fixed jbig2 rowstride issue. Implemented jbig2 bit writer * Changed golden files logic. Fixes r13 issues.
159 lines
3.5 KiB
Go
159 lines
3.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 bitmap
|
|
|
|
import (
|
|
"image"
|
|
|
|
"github.com/unidoc/unipdf/v3/common"
|
|
)
|
|
|
|
// CombineBytes combines the provided bytes with respect to the CombinationOperator.
|
|
func CombineBytes(oldByte, newByte byte, op CombinationOperator) byte {
|
|
return combineBytes(oldByte, newByte, op)
|
|
}
|
|
|
|
// Extract extracts the rectangle of given size from the source 'src' Bitmap.
|
|
func Extract(roi image.Rectangle, src *Bitmap) (*Bitmap, error) {
|
|
dst := New(roi.Dx(), roi.Dy())
|
|
upShift := roi.Min.X & 0x07
|
|
downShift := 8 - upShift
|
|
padding := uint(8 - dst.Width&0x07)
|
|
srcLineStartIdx := src.GetByteIndex(roi.Min.X, roi.Min.Y)
|
|
srcLineEndIdx := src.GetByteIndex(roi.Max.X-1, roi.Min.Y)
|
|
usePadding := dst.RowStride == srcLineEndIdx+1-srcLineStartIdx
|
|
|
|
var dstLineStartIdx int
|
|
|
|
for y := roi.Min.Y; y < roi.Max.Y; y++ {
|
|
srcIdx := srcLineStartIdx
|
|
dstIdx := dstLineStartIdx
|
|
|
|
if srcLineStartIdx == srcLineEndIdx {
|
|
pixels, err := src.GetByte(srcIdx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pixels <<= uint(upShift)
|
|
|
|
err = dst.SetByte(dstIdx, unpad(padding, pixels))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else if upShift == 0 {
|
|
for x := srcLineStartIdx; x <= srcLineEndIdx; x++ {
|
|
value, err := src.GetByte(srcIdx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
srcIdx++
|
|
|
|
if x == srcLineEndIdx && usePadding {
|
|
value = unpad(padding, value)
|
|
}
|
|
|
|
err = dst.SetByte(dstIdx, value)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dstIdx++
|
|
}
|
|
} else {
|
|
err := copyLine(src, dst, uint(upShift), uint(downShift), padding, srcLineStartIdx, srcLineEndIdx, usePadding, srcIdx, dstIdx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
srcLineStartIdx += src.RowStride
|
|
srcLineEndIdx += src.RowStride
|
|
dstLineStartIdx += dst.RowStride
|
|
}
|
|
return dst, nil
|
|
}
|
|
|
|
func combineBytes(oldByte, newByte byte, op CombinationOperator) byte {
|
|
switch op {
|
|
case CmbOpOr:
|
|
return newByte | oldByte
|
|
case CmbOpAnd:
|
|
return newByte & oldByte
|
|
case CmbOpXor:
|
|
return newByte ^ oldByte
|
|
case CmbOpXNor:
|
|
return ^(newByte ^ oldByte)
|
|
case CmbOpNot:
|
|
return ^(newByte)
|
|
default:
|
|
return newByte
|
|
}
|
|
}
|
|
|
|
func copyLine(
|
|
src, dst *Bitmap,
|
|
sourceUpShift, sourceDownShift, padding uint,
|
|
firstSourceByteOfLine, lastSourceByteOfLine int,
|
|
usePadding bool, sourceOffset, targetOffset int,
|
|
) error {
|
|
for x := firstSourceByteOfLine; x < lastSourceByteOfLine; x++ {
|
|
if sourceOffset+1 < len(src.Data) {
|
|
isLastByte := x+1 == lastSourceByteOfLine
|
|
v1, err := src.GetByte(sourceOffset)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sourceOffset++
|
|
v1 <<= sourceUpShift
|
|
|
|
v2, err := src.GetByte(sourceOffset)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
v2 >>= sourceDownShift
|
|
value := v1 | v2
|
|
|
|
if isLastByte && !usePadding {
|
|
value = unpad(padding, value)
|
|
}
|
|
|
|
err = dst.SetByte(targetOffset, value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
targetOffset++
|
|
|
|
if isLastByte && usePadding {
|
|
temp, err := src.GetByte(sourceOffset)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
temp <<= sourceUpShift
|
|
value = unpad(padding, temp)
|
|
|
|
if err = dst.SetByte(targetOffset, value); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
value, err := src.GetByte(sourceOffset)
|
|
if err != nil {
|
|
common.Log.Debug("Getting the value at: %d failed: %s", sourceOffset, err)
|
|
return err
|
|
}
|
|
value <<= sourceUpShift
|
|
sourceOffset++
|
|
err = dst.SetByte(targetOffset, value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
targetOffset++
|
|
}
|
|
return nil
|
|
}
|