mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-27 13:48:51 +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>
170 lines
3.9 KiB
Go
170 lines
3.9 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
|
|
|
|
switch {
|
|
case 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
|
|
}
|
|
case 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++
|
|
}
|
|
default:
|
|
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
|
|
}
|
|
|
|
// combineBitmap combines two bitmaps with respect to the 'op' combination operator and returns result as new Bitmap.
|
|
func combineBitmap(first, second *Bitmap, op CombinationOperator) *Bitmap {
|
|
result := New(first.Width, first.Height)
|
|
|
|
for i := 0; i < len(result.Data); i++ {
|
|
result.Data[i] = combineBytes(first.Data[i], second.Data[i], op)
|
|
}
|
|
return result
|
|
}
|
|
|
|
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
|
|
}
|