mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-30 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 * 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.
201 lines
4.6 KiB
Go
201 lines
4.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 bitmap
|
|
|
|
// Blit blits the source Bitmap 'src' into Destination bitmap: 'dst' on the provided 'x' and 'y' coordinates
|
|
// with respect to the combination operator 'op'.
|
|
func Blit(src *Bitmap, dst *Bitmap, x, y int, op CombinationOperator) error {
|
|
var startLine, srcStartIdx int
|
|
srcEndIdx := src.RowStride - 1
|
|
|
|
// ignore those parts of source bitmap placed outside target bitmap.
|
|
if x < 0 {
|
|
srcStartIdx = -x
|
|
x = 0
|
|
} else if x+src.Width > dst.Width {
|
|
srcEndIdx -= src.Width + x - dst.Width
|
|
}
|
|
|
|
if y < 0 {
|
|
startLine = -y
|
|
y = 0
|
|
srcStartIdx += src.RowStride
|
|
srcEndIdx += src.RowStride
|
|
} else if y+src.Height > dst.Height {
|
|
startLine = src.Height + y - dst.Height
|
|
}
|
|
|
|
var (
|
|
lastLine int
|
|
err error
|
|
)
|
|
shiftVal1 := x & 0x07
|
|
shiftVal2 := 8 - shiftVal1
|
|
padding := src.Width & 0x07
|
|
toShift := shiftVal2 - padding
|
|
useShift := shiftVal2&0x07 != 0
|
|
specialCase := src.Width <= ((srcEndIdx-srcStartIdx)<<3)+shiftVal2
|
|
dstStartIdx := dst.GetByteIndex(x, y)
|
|
|
|
// get math.min()
|
|
temp := startLine + dst.Height
|
|
if src.Height > temp {
|
|
lastLine = temp
|
|
} else {
|
|
lastLine = src.Height
|
|
}
|
|
|
|
switch {
|
|
case !useShift:
|
|
err = blitUnshifted(src, dst, startLine, lastLine, dstStartIdx, srcStartIdx, srcEndIdx, op)
|
|
case specialCase:
|
|
err = blitSpecialShifted(src, dst, startLine, lastLine, dstStartIdx, srcStartIdx, srcEndIdx, toShift, shiftVal1, shiftVal2, op)
|
|
default:
|
|
err = blitShifted(src, dst, startLine, lastLine, dstStartIdx, srcStartIdx, srcEndIdx, toShift, shiftVal1, shiftVal2, op, padding)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func blitUnshifted(
|
|
src, dst *Bitmap,
|
|
startLine, lastLine, dstStartIdx, srcStartIdx, srcEndIdx int,
|
|
op CombinationOperator,
|
|
) error {
|
|
var dstLine int
|
|
increaser := func() {
|
|
dstLine++
|
|
dstStartIdx += dst.RowStride
|
|
srcStartIdx += src.RowStride
|
|
srcEndIdx += src.RowStride
|
|
}
|
|
|
|
for dstLine = startLine; dstLine < lastLine; increaser() {
|
|
dstIdx := dstStartIdx
|
|
for srcIdx := srcStartIdx; srcIdx <= srcEndIdx; srcIdx++ {
|
|
oldByte, err := dst.GetByte(dstIdx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newByte, err := src.GetByte(srcIdx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = dst.SetByte(dstIdx, combineBytes(oldByte, newByte, op)); err != nil {
|
|
return err
|
|
}
|
|
dstIdx++
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func blitShifted(
|
|
src, dst *Bitmap,
|
|
startLine, lastLine, dstStartIdx, srcStartIdx, srcEndIdx, toShift, shiftVal1, shiftVal2 int,
|
|
op CombinationOperator, padding int,
|
|
) error {
|
|
var dstLine int
|
|
increaser := func() {
|
|
dstLine++
|
|
dstStartIdx += dst.RowStride
|
|
srcStartIdx += src.RowStride
|
|
srcEndIdx += src.RowStride
|
|
}
|
|
|
|
for dstLine = startLine; dstLine < lastLine; increaser() {
|
|
var register uint16
|
|
dstIdx := dstStartIdx
|
|
|
|
for srcIdx := srcStartIdx; srcIdx <= srcEndIdx; srcIdx++ {
|
|
oldByte, err := dst.GetByte(dstIdx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newByte, err := src.GetByte(srcIdx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
register = (register | (uint16(newByte) & 0xff)) << uint(shiftVal2)
|
|
|
|
newByte = byte(register >> 8)
|
|
dst.SetByte(dstIdx, combineBytes(oldByte, newByte, op))
|
|
dstIdx++
|
|
|
|
register <<= uint(shiftVal1)
|
|
|
|
if srcIdx == srcEndIdx {
|
|
newByte = byte(register >> (8 - uint8(shiftVal2)))
|
|
|
|
if padding != 0 {
|
|
newByte = unpad(uint(8+toShift), newByte)
|
|
}
|
|
|
|
oldByte, err = dst.GetByte(dstIdx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = dst.SetByte(dstIdx, combineBytes(oldByte, newByte, op)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func blitSpecialShifted(
|
|
src, dst *Bitmap,
|
|
startLine, lastLine, dstStartIdx, srcStartIdx, srcEndIdx, toShift, shiftVal1, shiftVal2 int,
|
|
op CombinationOperator,
|
|
) error {
|
|
var dstLine int
|
|
increaser := func() {
|
|
dstLine++
|
|
dstStartIdx += dst.RowStride
|
|
srcStartIdx += src.RowStride
|
|
srcEndIdx += src.RowStride
|
|
}
|
|
|
|
for dstLine = startLine; dstLine < lastLine; increaser() {
|
|
var register uint16
|
|
dstIdx := dstStartIdx
|
|
|
|
for srcIdx := srcStartIdx; srcIdx <= srcEndIdx; srcIdx++ {
|
|
oldByte, err := dst.GetByte(dstIdx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newByte, err := src.GetByte(srcIdx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
register = (register | uint16(newByte)) << uint(shiftVal2)
|
|
newByte = byte(register >> 8)
|
|
|
|
if srcIdx == srcEndIdx {
|
|
newByte = unpad(uint(toShift), newByte)
|
|
}
|
|
|
|
if err = dst.SetByte(dstIdx, combineBytes(oldByte, newByte, op)); err != nil {
|
|
return err
|
|
}
|
|
dstIdx++
|
|
|
|
register <<= uint(shiftVal1)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func unpad(padding uint, b byte) byte {
|
|
return b >> padding << padding
|
|
}
|