unipdf/internal/jbig2/segments/generic-region.go
Jacek Kucharczyk 24648f4481 Issue #144 Fix - JBIG2 - Changed integer variables types (#148)
* Fixing platform indepenedent integer size
* Cleared test logs.
* Cleared unnecessary int32
* Defined precise integer size for jbig2 segments.
2019-08-29 19:12:18 +00:00

1102 lines
24 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 (
"fmt"
"strings"
"github.com/unidoc/unipdf/v3/common"
"github.com/unidoc/unipdf/v3/internal/jbig2/bitmap"
"github.com/unidoc/unipdf/v3/internal/jbig2/decoder/arithmetic"
"github.com/unidoc/unipdf/v3/internal/jbig2/decoder/mmr"
"github.com/unidoc/unipdf/v3/internal/jbig2/reader"
)
// GenericRegion represents a generic region segment.
// Parsing is done as described in 7.4.5.
// Decoding procedure is done as described in 6.2.5.7 and 7.4.6.4.
type GenericRegion struct {
r reader.StreamReader
DataHeaderOffset int64
DataHeaderLength int64
DataOffset int64
DataLength int64
// Region segment information field, 7.4.1
RegionSegment *RegionSegment
// Generic region segment flags, 7.4.6.2
UseExtTemplates bool
IsTPGDon bool
GBTemplate byte
IsMMREncoded bool
inlineImage, unknownLength bool
UseMMR bool
// Generic region segment AT flags, 7.4.6.3
GBAtX []int8
GBAtY []int8
GBAtOverride []bool
// override defines if AT pixels are not on their normal location and have to be overwriten.
override bool
// Bitmap is the decoded generic region image.
Bitmap *bitmap.Bitmap
arithDecoder *arithmetic.Decoder
cx *arithmetic.DecoderStats
mmrDecoder *mmr.Decoder
}
// NewGenericRegion creates new GenericRegion segment.
func NewGenericRegion(
r reader.StreamReader,
) *GenericRegion {
return &GenericRegion{RegionSegment: NewRegionSegment(r), r: r}
}
// Init implements Segmenter interface.
func (g *GenericRegion) Init(h *Header, r reader.StreamReader) error {
g.RegionSegment = NewRegionSegment(r)
g.r = r
return g.parseHeader()
}
// GetRegionBitmap gets the bitmap for the generic region segment.
func (g *GenericRegion) GetRegionBitmap() (bm *bitmap.Bitmap, err error) {
if g.Bitmap != nil {
return g.Bitmap, nil
}
// Check how the data is encoded.
if g.IsMMREncoded {
// MMR Decoder Call
if g.mmrDecoder == nil {
g.mmrDecoder, err = mmr.New(g.r, int(g.RegionSegment.BitmapWidth), int(g.RegionSegment.BitmapHeight), g.DataOffset, g.DataLength)
if err != nil {
return nil, err
}
}
// Uncompress the bitmap.
g.Bitmap, err = g.mmrDecoder.UncompressMMR()
return g.Bitmap, err
}
// Arithmetic decoder process for generic region segments.
if err = g.updateOverrideFlags(); err != nil {
return nil, err
}
// 6.2.5.7 - 1)
var ltp int
if g.arithDecoder == nil {
g.arithDecoder, err = arithmetic.New(g.r)
if err != nil {
return nil, err
}
}
if g.cx == nil {
g.cx = arithmetic.NewStats(65536, 1)
}
// 6.2.5.7 - 2)
g.Bitmap = bitmap.New(int(g.RegionSegment.BitmapWidth), int(g.RegionSegment.BitmapHeight))
paddedWidth := int(uint32(g.Bitmap.Width+7) & (^uint32(7)))
// 6.2.5.7 - 3)
for line := 0; line < g.Bitmap.Height; line++ {
// 6.2.5.7 - 3 c)
if g.IsTPGDon {
var temp int
temp, err = g.decodeSLTP()
if err != nil {
return nil, err
}
ltp ^= temp
}
// 6.2.5.7 - 3 d)
if ltp == 1 {
if line > 0 {
if err = g.copyLineAbove(line); err != nil {
return nil, err
}
}
} else {
if err = g.decodeLine(line, g.Bitmap.Width, paddedWidth); err != nil {
return nil, err
}
}
}
return g.Bitmap, nil
}
// GetRegionInfo implements Regioner interface.
func (g *GenericRegion) GetRegionInfo() *RegionSegment {
return g.RegionSegment
}
func (g *GenericRegion) parseHeader() (err error) {
common.Log.Trace("[GENERIC-REGION] ParsingHeader...")
defer func() {
if err != nil {
common.Log.Trace("[GENERIC-REGION] ParsingHeader Finished with error. %v", err)
} else {
common.Log.Trace("[GENERIC-REGION] ParsingHeader Finished Succesfully...")
}
}()
var (
b int
bits uint64
)
if err = g.RegionSegment.parseHeader(); err != nil {
return err
}
// Bit 5-7
if _, err = g.r.ReadBits(3); err != nil {
return err
}
// Bit 4
b, err = g.r.ReadBit()
if err != nil {
return err
}
if b == 1 {
g.UseExtTemplates = true
}
// Bit 3
b, err = g.r.ReadBit()
if err != nil {
return err
}
if b == 1 {
g.IsTPGDon = true
}
// Bit 1-2
bits, err = g.r.ReadBits(2)
if err != nil {
return err
}
g.GBTemplate = byte(bits & 0xf)
// Bit 0
b, err = g.r.ReadBit()
if err != nil {
return err
}
if b == 1 {
g.IsMMREncoded = true
}
if !g.IsMMREncoded {
numberOfGbAt := 1
if g.GBTemplate == 0 {
numberOfGbAt = 4
if g.UseExtTemplates {
numberOfGbAt = 12
}
}
if err = g.readGBAtPixels(numberOfGbAt); err != nil {
return err
}
}
// Segment data structure
if err = g.computeSegmentDataStructure(); err != nil {
return err
}
common.Log.Trace("%s", g)
return nil
}
func (g *GenericRegion) computeSegmentDataStructure() error {
g.DataOffset = g.r.StreamPosition()
g.DataHeaderLength = g.DataOffset - g.DataHeaderOffset
g.DataLength = int64(g.r.Length()) - g.DataHeaderLength
return nil
}
func (g *GenericRegion) copyLineAbove(line int) error {
targetByteIndex := line * g.Bitmap.RowStride
sourceByteIndex := targetByteIndex - g.Bitmap.RowStride
for i := 0; i < g.Bitmap.RowStride; i++ {
b, err := g.Bitmap.GetByte(sourceByteIndex)
if err != nil {
return err
}
sourceByteIndex++
if err = g.Bitmap.SetByte(targetByteIndex, b); err != nil {
return err
}
targetByteIndex++
}
return nil
}
func (g *GenericRegion) decodeSLTP() (int, error) {
switch g.GBTemplate {
case 0:
g.cx.SetIndex(0x9B25)
case 1:
g.cx.SetIndex(0x795)
case 2:
g.cx.SetIndex(0xE5)
case 3:
g.cx.SetIndex(0x195)
}
return g.arithDecoder.DecodeBit(g.cx)
}
func (g *GenericRegion) decodeLine(line, width, paddedWidth int) error {
byteIndex := g.Bitmap.GetByteIndex(0, line)
idx := byteIndex - g.Bitmap.RowStride
switch g.GBTemplate {
case 0:
if !g.UseExtTemplates {
return g.decodeTemplate0a(line, width, paddedWidth, byteIndex, idx)
}
return g.decodeTemplate0b(line, width, paddedWidth, byteIndex, idx)
case 1:
return g.decodeTemplate1(line, width, paddedWidth, byteIndex, idx)
case 2:
return g.decodeTemplate2(line, width, paddedWidth, byteIndex, idx)
case 3:
return g.decodeTemplate3(line, width, paddedWidth, byteIndex, idx)
}
return fmt.Errorf("invalid GBTemplate provided: %d", g.GBTemplate)
}
func (g *GenericRegion) decodeTemplate0a(line, width, paddedWidth int, byteIndex, idx int) (err error) {
var (
context, overriddenContext int
line1, line2 int
temp byte
nextByte int
)
if line >= 1 {
temp, err = g.Bitmap.GetByte(idx)
if err != nil {
return err
}
line1 = int(temp)
}
if line >= 2 {
temp, err = g.Bitmap.GetByte(idx - g.Bitmap.RowStride)
if err != nil {
return err
}
line2 = int(temp) << 6
}
context = (line1 & 0xf0) | (line2 & 0x3800)
for x := 0; x < paddedWidth; x = nextByte {
// 6.2.5.7 3d
var (
result byte
minorWidth int
)
nextByte = x + 8
if d := width - x; d > 8 {
minorWidth = 8
} else {
minorWidth = d
}
if line > 0 {
line1 <<= 8
if nextByte < width {
temp, err = g.Bitmap.GetByte(idx + 1)
if err != nil {
return err
}
line1 |= int(temp)
}
}
if line > 1 {
index := idx - g.Bitmap.RowStride + 1
line2 = line2 << 8
if nextByte < width {
temp, err = g.Bitmap.GetByte(index)
if err != nil {
return err
}
line2 |= (int(temp) << 6)
} else {
line2 |= 0
}
}
for minorX := 0; minorX < minorWidth; minorX++ {
toShift := uint(7 - minorX)
if g.override {
overriddenContext = g.overrideAtTemplate0a(context, x+minorX, line, int(result), minorX, int(toShift))
g.cx.SetIndex(int32(overriddenContext))
} else {
g.cx.SetIndex(int32(context))
}
var bit int
bit, err = g.arithDecoder.DecodeBit(g.cx)
if err != nil {
return err
}
result |= byte(bit) << uint(toShift)
context = ((context & 0x7bf7) << 1) | bit | ((line1 >> toShift) & 0x10) | ((line2 >> toShift) & 0x800)
}
if err := g.Bitmap.SetByte(byteIndex, result); err != nil {
return err
}
byteIndex++
idx++
}
return nil
}
func (g *GenericRegion) decodeTemplate0b(line, width, paddedWidth int, byteIndex, idx int) (err error) {
var (
context, overriddenContext int
line1, line2 int
temp byte
nextByte int
)
if line >= 1 {
temp, err = g.Bitmap.GetByte(idx)
if err != nil {
return err
}
line1 = int(temp)
}
if line >= 2 {
temp, err = g.Bitmap.GetByte(idx - g.Bitmap.RowStride)
if err != nil {
return err
}
line2 = int(temp) << 6
}
context = (line1 & 0xf0) | (line2 & 0x3800)
for x := 0; x < paddedWidth; x = nextByte {
// 6.2.5.7 3d
var (
result byte
minorWidth int
)
nextByte = x + 8
if d := width - x; d > 8 {
minorWidth = 8
} else {
minorWidth = d
}
if line > 0 {
line1 <<= 8
if nextByte < width {
temp, err = g.Bitmap.GetByte(idx + 1)
if err != nil {
return err
}
line1 |= int(temp)
}
}
if line > 1 {
line2 <<= 8
if nextByte < width {
temp, err = g.Bitmap.GetByte(idx - g.Bitmap.RowStride + 1)
if err != nil {
return err
}
line2 |= (int(temp) << 6)
}
}
for minorX := 0; minorX < minorWidth; minorX++ {
toShift := uint(7 - minorX)
if g.override {
overriddenContext = g.overrideAtTemplate0b(context, x+minorX, line, int(result), minorX, int(toShift))
g.cx.SetIndex(int32(overriddenContext))
} else {
g.cx.SetIndex(int32(context))
}
var bit int
bit, err = g.arithDecoder.DecodeBit(g.cx)
if err != nil {
return err
}
result |= byte(bit << uint(toShift))
context = ((context & 0x7bf7) << 1) | bit | ((line1 >> toShift) & 0x10) | ((line2 >> toShift) & 0x800)
}
if err := g.Bitmap.SetByte(byteIndex, result); err != nil {
return err
}
byteIndex++
idx++
}
return nil
}
func (g *GenericRegion) decodeTemplate1(line, width, paddedWidth int, byteIndex, idx int) (err error) {
var (
context, overriddenContext int
line1, line2 int
temp byte
nextByte, bit int
)
if line >= 1 {
temp, err = g.Bitmap.GetByte(idx)
if err != nil {
return err
}
line1 = int(temp)
}
if line >= 2 {
temp, err = g.Bitmap.GetByte(idx - g.Bitmap.RowStride)
if err != nil {
return err
}
line2 = int(temp) << 5
}
context = ((line1 >> 1) & 0x1f8) | ((line2 >> 1) & 0x1e00)
for x := 0; x < paddedWidth; x = nextByte {
// 6.2.5.7 3d
var (
result byte
minorWidth int
)
nextByte = x + 8
if d := width - x; d > 8 {
minorWidth = 8
} else {
minorWidth = d
}
if line > 0 {
line1 <<= 8
if nextByte < width {
temp, err = g.Bitmap.GetByte(idx + 1)
if err != nil {
return err
}
line1 |= int(temp)
}
}
if line > 1 {
line2 <<= 8
if nextByte < width {
temp, err = g.Bitmap.GetByte(idx - g.Bitmap.RowStride + 1)
if err != nil {
return err
}
line2 |= (int(temp) << 5)
}
}
for minorX := 0; minorX < minorWidth; minorX++ {
if g.override {
overriddenContext = g.overrideAtTemplate1(context, x+minorX, line, int(result), minorX)
g.cx.SetIndex(int32(overriddenContext))
} else {
g.cx.SetIndex(int32(context))
}
bit, err = g.arithDecoder.DecodeBit(g.cx)
if err != nil {
return err
}
result |= byte(bit) << uint(7-minorX)
toShift := uint(8 - minorX)
context = ((context & 0xefb) << 1) | bit | ((line1 >> toShift) & 0x8) | ((line2 >> toShift) & 0x200)
}
if err := g.Bitmap.SetByte(byteIndex, result); err != nil {
return err
}
byteIndex++
idx++
}
return nil
}
func (g *GenericRegion) decodeTemplate2(lineNumber, width, paddedWidth int, byteIndex, idx int) (err error) {
var (
context, overriddenContext int
line1, line2 int
temp byte
nextByte, bit int
)
if lineNumber >= 1 {
temp, err = g.Bitmap.GetByte(idx)
if err != nil {
return err
}
line1 = int(temp)
}
if lineNumber >= 2 {
temp, err = g.Bitmap.GetByte(idx - g.Bitmap.RowStride)
if err != nil {
return err
}
line2 = int(temp) << 4
}
context = (line1 >> 3 & 0x7c) | (line2 >> 3 & 0x380)
for x := 0; x < paddedWidth; x = nextByte {
// 6.2.5.7 3d
var (
result byte
minorWidth int
)
nextByte = x + 8
if d := width - x; d > 8 {
minorWidth = 8
} else {
minorWidth = d
}
if lineNumber > 0 {
line1 <<= 8
if nextByte < width {
temp, err = g.Bitmap.GetByte(idx + 1)
if err != nil {
return err
}
line1 |= int(temp)
}
}
if lineNumber > 1 {
line2 <<= 8
if nextByte < width {
temp, err = g.Bitmap.GetByte(idx - g.Bitmap.RowStride + 1)
if err != nil {
return err
}
line2 |= (int(temp) << 4)
}
}
for minorX := 0; minorX < minorWidth; minorX++ {
toShift := uint(10 - minorX)
if g.override {
overriddenContext = g.overrideAtTemplate2(context, x+minorX, lineNumber, int(result), minorX)
g.cx.SetIndex(int32(overriddenContext))
} else {
g.cx.SetIndex(int32(context))
}
bit, err = g.arithDecoder.DecodeBit(g.cx)
if err != nil {
return err
}
result |= byte(bit << uint(7-minorX))
context = ((context & 0x1bd) << 1) | bit | ((line1 >> toShift) & 0x4) | ((line2 >> toShift) & 0x80)
}
if err := g.Bitmap.SetByte(byteIndex, result); err != nil {
return err
}
byteIndex++
idx++
}
return nil
}
func (g *GenericRegion) decodeTemplate3(line, width, paddedWidth int, byteIndex, idx int) (err error) {
var (
context, overriddenContext int
line1 int
temp byte
nextByte, bit int
)
if line >= 1 {
temp, err = g.Bitmap.GetByte(idx)
if err != nil {
return err
}
line1 = int(temp)
}
context = (line1 >> 1) & 0x70
for x := 0; x < paddedWidth; x = nextByte {
// 6.2.5.7 3d
var (
result byte
minorWidth int
)
nextByte = x + 8
if d := width - x; d > 8 {
minorWidth = 8
} else {
minorWidth = d
}
if line >= 1 {
line1 <<= 8
if nextByte < width {
temp, err = g.Bitmap.GetByte(idx + 1)
if err != nil {
return err
}
line1 |= int(temp)
}
}
for minorX := 0; minorX < minorWidth; minorX++ {
if g.override {
overriddenContext = g.overrideAtTemplate3(context, x+minorX, line, int(result), minorX)
g.cx.SetIndex(int32(overriddenContext))
} else {
g.cx.SetIndex(int32(context))
}
bit, err = g.arithDecoder.DecodeBit(g.cx)
if err != nil {
return err
}
result |= byte(bit) << byte(7-minorX)
context = ((context & 0x1f7) << 1) | bit | ((line1 >> uint(8-minorX)) & 0x010)
}
if err := g.Bitmap.SetByte(byteIndex, result); err != nil {
return err
}
byteIndex++
idx++
}
return nil
}
func (g *GenericRegion) getPixel(x, y int) int8 {
if x < 0 || x >= g.Bitmap.Width {
return 0
}
if y < 0 || y >= g.Bitmap.Height {
return 0
}
if g.Bitmap.GetPixel(x, y) {
return 1
}
return 0
}
func (g *GenericRegion) updateOverrideFlags() error {
if g.GBAtX == nil || g.GBAtY == nil {
return nil
}
if len(g.GBAtX) != len(g.GBAtY) {
return fmt.Errorf("incosistent AT pixel. Amount of 'x' pixels: %d, Amount of 'y' pixels: %d", len(g.GBAtX), len(g.GBAtY))
}
g.GBAtOverride = make([]bool, len(g.GBAtX))
switch g.GBTemplate {
case 0:
if !g.UseExtTemplates {
if g.GBAtX[0] != 3 || g.GBAtY[0] != -1 {
g.setOverrideFlag(0)
}
if g.GBAtX[1] != -3 || g.GBAtY[1] != -1 {
g.setOverrideFlag(1)
}
if g.GBAtX[2] != 2 || g.GBAtY[2] != -2 {
g.setOverrideFlag(2)
}
if g.GBAtX[3] != -2 || g.GBAtY[3] != -2 {
g.setOverrideFlag(3)
}
} else {
if g.GBAtX[0] != -2 || g.GBAtY[0] != 0 {
g.setOverrideFlag(0)
}
if g.GBAtX[1] != 0 || g.GBAtY[1] != -2 {
g.setOverrideFlag(1)
}
if g.GBAtX[2] != -2 || g.GBAtY[2] != -1 {
g.setOverrideFlag(2)
}
if g.GBAtX[3] != -1 || g.GBAtY[3] != -2 {
g.setOverrideFlag(3)
}
if g.GBAtX[4] != 1 || g.GBAtY[4] != -2 {
g.setOverrideFlag(4)
}
if g.GBAtX[5] != 2 || g.GBAtY[5] != -1 {
g.setOverrideFlag(5)
}
if g.GBAtX[6] != -3 || g.GBAtY[6] != 0 {
g.setOverrideFlag(6)
}
if g.GBAtX[7] != -4 || g.GBAtY[7] != 0 {
g.setOverrideFlag(7)
}
if g.GBAtX[8] != 2 || g.GBAtY[8] != -2 {
g.setOverrideFlag(8)
}
if g.GBAtX[9] != 3 || g.GBAtY[9] != -1 {
g.setOverrideFlag(9)
}
if g.GBAtX[10] != -2 || g.GBAtY[10] != -2 {
g.setOverrideFlag(10)
}
if g.GBAtX[11] != -3 || g.GBAtY[11] != -1 {
g.setOverrideFlag(11)
}
}
case 1:
if g.GBAtX[0] != 3 || g.GBAtY[0] != -1 {
g.setOverrideFlag(0)
}
case 2:
if g.GBAtX[0] != 2 || g.GBAtY[0] != -1 {
g.setOverrideFlag(0)
}
case 3:
if g.GBAtX[0] != 2 || g.GBAtY[0] != -1 {
g.setOverrideFlag(0)
}
}
return nil
}
func (g *GenericRegion) overrideAtTemplate0a(ctx, x, y, result, minorX, toShift int) int {
if g.GBAtOverride[0] {
ctx &= 0xFFEF
if g.GBAtY[0] == 0 && g.GBAtX[0] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[0]&0x1)) << 4
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[0]), y+int(g.GBAtY[0]))) << 4
}
}
if g.GBAtOverride[1] {
ctx &= 0xFBFF
if g.GBAtY[1] == 0 && g.GBAtX[1] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[1]&0x1)) << 10
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[1]), y+int(g.GBAtY[1]))) << 10
}
}
if g.GBAtOverride[2] {
ctx &= 0xF7FF
if g.GBAtY[2] == 0 && g.GBAtX[2] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[2]&0x1)) << 11
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[2]), y+int(g.GBAtY[2]))) << 11
}
}
if g.GBAtOverride[3] {
ctx &= 0x7FFF
if g.GBAtY[3] == 0 && g.GBAtX[3] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[3]&0x1)) << 15
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[3]), y+int(g.GBAtY[3]))) << 15
}
}
return ctx
}
func (g *GenericRegion) overrideAtTemplate0b(ctx, x, y, result, minorX, toShift int) int {
if g.GBAtOverride[0] {
ctx &= 0xFFFD
if g.GBAtY[0] == 0 && g.GBAtX[0] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[0]&0x1)) << 1
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[0]), y+int(g.GBAtY[0]))) << 1
}
}
if g.GBAtOverride[1] {
ctx &= 0xDFFF
if g.GBAtY[1] == 0 && g.GBAtX[1] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[1]&0x1)) << 13
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[1]), y+int(g.GBAtY[1]))) << 13
}
}
if g.GBAtOverride[2] {
ctx &= 0xFDFF
if g.GBAtY[2] == 0 && g.GBAtX[2] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[2]&0x1)) << 9
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[2]), y+int(g.GBAtY[2]))) << 9
}
}
if g.GBAtOverride[3] {
ctx &= 0xBFFF
if g.GBAtY[3] == 0 && g.GBAtX[3] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[3]&0x1)) << 14
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[3]), y+int(g.GBAtY[3]))) << 14
}
}
if g.GBAtOverride[4] {
ctx &= 0xEFFF
if g.GBAtY[4] == 0 && g.GBAtX[4] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[4]&0x1)) << 12
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[4]), y+int(g.GBAtY[4]))) << 12
}
}
if g.GBAtOverride[5] {
ctx &= 0xFFDF
if g.GBAtY[5] == 0 && g.GBAtX[5] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[5]&0x1)) << 5
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[5]), y+int(g.GBAtY[5]))) << 5
}
}
if g.GBAtOverride[6] {
ctx &= 0xFFFB
if g.GBAtY[6] == 0 && g.GBAtX[6] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[6]&0x1)) << 2
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[6]), y+int(g.GBAtY[6]))) << 2
}
}
if g.GBAtOverride[7] {
ctx &= 0xFFF7
if g.GBAtY[7] == 0 && g.GBAtX[7] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[7]&0x1)) << 3
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[7]), y+int(g.GBAtY[7]))) << 3
}
}
if g.GBAtOverride[8] {
ctx &= 0xF7FF
if g.GBAtY[8] == 0 && g.GBAtX[8] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[8]&0x1)) << 11
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[8]), y+int(g.GBAtY[8]))) << 11
}
}
if g.GBAtOverride[9] {
ctx &= 0xFFEF
if g.GBAtY[9] == 0 && g.GBAtX[9] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[9]&0x1)) << 4
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[9]), y+int(g.GBAtY[9]))) << 4
}
}
if g.GBAtOverride[10] {
ctx &= 0x7FFF
if g.GBAtY[10] == 0 && g.GBAtX[10] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[10]&0x1)) << 15
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[10]), y+int(g.GBAtY[10]))) << 15
}
}
if g.GBAtOverride[11] {
ctx &= 0xFDFF
if g.GBAtY[11] == 0 && g.GBAtX[11] >= -int8(minorX) {
ctx |= (result >> uint(int8(toShift)-g.GBAtX[11]&0x1)) << 10
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[11]), y+int(g.GBAtY[11]))) << 10
}
}
return ctx
}
func (g *GenericRegion) overrideAtTemplate1(ctx, x, y, result, minorX int) int {
ctx &= 0x1FF7
if g.GBAtY[0] == 0 && g.GBAtX[0] >= -int8(minorX) {
ctx |= (result >> uint(7-(int8(minorX)+g.GBAtX[0])) & 0x1) << 3
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[0]), y+int(g.GBAtY[0]))) << 3
}
return ctx
}
func (g *GenericRegion) overrideAtTemplate2(ctx, x, y, result, minorX int) int {
ctx &= 0x3FB
if g.GBAtY[0] == 0 && g.GBAtX[0] >= -int8(minorX) {
ctx |= (result >> uint(7-(int8(minorX)+g.GBAtX[0])) & 0x1) << 2
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[0]), y+int(g.GBAtY[0]))) << 2
}
return ctx
}
func (g *GenericRegion) overrideAtTemplate3(ctx, x, y, result, minorX int) int {
ctx &= 0x3EF
if g.GBAtY[0] == 0 && g.GBAtX[0] >= -int8(minorX) {
ctx |= (result >> uint(7-(int8(minorX)+g.GBAtX[0])) & 0x1) << 4
} else {
ctx |= int(g.getPixel(x+int(g.GBAtX[0]), y+int(g.GBAtY[0]))) << 4
}
return ctx
}
func (g *GenericRegion) readGBAtPixels(numberOfGbAt int) error {
g.GBAtX = make([]int8, numberOfGbAt)
g.GBAtY = make([]int8, numberOfGbAt)
for i := 0; i < numberOfGbAt; i++ {
b, err := g.r.ReadByte()
if err != nil {
return err
}
g.GBAtX[i] = int8(b)
b, err = g.r.ReadByte()
if err != nil {
return err
}
g.GBAtY[i] = int8(b)
}
return nil
}
func (g *GenericRegion) setOverrideFlag(index int) {
g.GBAtOverride[index] = true
g.override = true
}
func (g *GenericRegion) setParameters(isMMREncoded bool, dataOffset, dataLength int64, gbh, gbw uint32) {
g.IsMMREncoded = isMMREncoded
g.DataOffset = dataOffset
g.DataLength = dataLength
g.RegionSegment.BitmapHeight = gbh
g.RegionSegment.BitmapWidth = gbw
g.mmrDecoder = nil
g.Bitmap = nil
}
func (g *GenericRegion) setParametersWithAt(
isMMREncoded bool,
SDTemplate byte,
isTPGDon, useSkip bool,
sDAtX, sDAtY []int8,
symWidth, hcHeight uint32,
cx *arithmetic.DecoderStats, a *arithmetic.Decoder,
) {
g.IsMMREncoded = isMMREncoded
g.GBTemplate = SDTemplate
g.IsTPGDon = isTPGDon
g.GBAtX = sDAtX
g.GBAtY = sDAtY
g.RegionSegment.BitmapHeight = hcHeight
g.RegionSegment.BitmapWidth = symWidth
g.mmrDecoder = nil
g.Bitmap = nil
if cx != nil {
g.cx = cx
}
if a != nil {
g.arithDecoder = a
}
common.Log.Trace("[GENERIC-REGION] setParameters SDAt: %s", g)
}
func (g *GenericRegion) setParametersMMR(
isMMREncoded bool,
dataOffset, dataLength int64,
gbh, gbw uint32,
gbTemplate byte,
isTPGDon, useSkip bool,
gbAtX, gbAtY []int8,
) {
g.DataOffset = dataOffset
g.DataLength = dataLength
g.RegionSegment = &RegionSegment{}
g.RegionSegment.BitmapHeight = gbh
g.RegionSegment.BitmapWidth = gbw
g.GBTemplate = gbTemplate
g.IsMMREncoded = isMMREncoded
g.IsTPGDon = isTPGDon
g.GBAtX = gbAtX
g.GBAtY = gbAtY
}
// String implements Stringer interface
func (g *GenericRegion) String() string {
sb := &strings.Builder{}
sb.WriteString("\n[GENERIC REGION]\n")
sb.WriteString(g.RegionSegment.String() + "\n")
sb.WriteString(fmt.Sprintf("\t- UseExtTemplates: %v\n", g.UseExtTemplates))
sb.WriteString(fmt.Sprintf("\t- IsTPGDon: %v\n", g.IsTPGDon))
sb.WriteString(fmt.Sprintf("\t- GBTemplate: %d\n", g.GBTemplate))
sb.WriteString(fmt.Sprintf("\t- IsMMREncoded: %v\n", g.IsMMREncoded))
sb.WriteString(fmt.Sprintf("\t- GBAtX: %v\n", g.GBAtX))
sb.WriteString(fmt.Sprintf("\t- GBAtY: %v\n", g.GBAtY))
sb.WriteString(fmt.Sprintf("\t- GBAtOverride: %v\n", g.GBAtOverride))
return sb.String()
}