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>
1623 lines
50 KiB
Go
1623 lines
50 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 (
|
|
"math/rand"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/unidoc/unipdf/v3/common"
|
|
)
|
|
|
|
// TestRasterOperation tests the RasterOperation function.
|
|
func TestRasterOperation(t *testing.T) {
|
|
type operatorName struct {
|
|
Operator RasterOperator
|
|
Name string
|
|
}
|
|
t.Run("NilDest", func(t *testing.T) {
|
|
err := RasterOperation(nil, 1, 2, 0, 0, PixSrcXorDst, New(3, 3), 0, 0)
|
|
require.Error(t, err)
|
|
})
|
|
|
|
t.Run("PixDest", func(t *testing.T) {
|
|
dest := New(5, 5)
|
|
err := RasterOperation(dest, 0, 0, 0, 0, PixDst, nil, 0, 0)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("UniLow", func(t *testing.T) {
|
|
t.Run("Dw0", func(t *testing.T) {
|
|
dest := New(5, 5)
|
|
err := RasterOperation(dest, 0, 0, 0, 0, PixSet, nil, 0, 0)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
operators := []operatorName{{PixClr, "Clear"}, {PixSet, "Set"}, {PixNotDst, "NotDst"}}
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
for _, op := range operators {
|
|
t.Run(op.Name, func(t *testing.T) {
|
|
data := []byte{0xff, 0xfd, 0xfa, 0xf3, 0xac, 0xbc, 0xdc, 0xaf}
|
|
tocheck := make([]byte, 8)
|
|
copy(tocheck, data)
|
|
|
|
dest, err := NewWithData(8, 8, data)
|
|
require.NoError(t, err)
|
|
|
|
err = dest.RasterOperation(0, 0, dest.Width, dest.Height, op.Operator, nil, 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
switch op.Operator {
|
|
case PixClr:
|
|
for _, bt := range dest.Data {
|
|
assert.Equal(t, byte(0x00), bt)
|
|
}
|
|
case PixSet:
|
|
for _, bt := range dest.Data {
|
|
assert.Equal(t, byte(0xff), bt)
|
|
}
|
|
case PixNotDst:
|
|
for i, bt := range dest.Data {
|
|
assert.Equal(t, ^tocheck[i], bt)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
t.Run("WithLwBits", func(t *testing.T) {
|
|
for _, op := range operators {
|
|
t.Run(op.Name, func(t *testing.T) {
|
|
data := []byte{0xff, 0xfd, 0xfa, 0xf3, 0xac, 0xbc, 0xdc, 0xaf}
|
|
toCheck := make([]byte, 8)
|
|
copy(toCheck, data)
|
|
|
|
dest, err := NewWithData(7, 8, data)
|
|
require.NoError(t, err)
|
|
|
|
err = dest.RasterOperation(0, 0, dest.Width, dest.Height, op.Operator, nil, 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
// when the width is 7 the last bit is non used.
|
|
// Then the result masked with 11111110 -> 0xfe
|
|
mask := byte(0xfe)
|
|
switch op.Operator {
|
|
case PixClr:
|
|
for i, bt := range dest.Data {
|
|
assert.Equal(t, combinePartial(toCheck[i], 0x00, mask), bt)
|
|
}
|
|
case PixSet:
|
|
for i, bt := range dest.Data {
|
|
assert.Equal(t, combinePartial(toCheck[i], 0xff, mask), bt)
|
|
}
|
|
case PixNotDst:
|
|
for i, bt := range dest.Data {
|
|
assert.Equal(t, combinePartial(toCheck[i], ^toCheck[i], mask), bt)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("WidthLessEqualTo8", func(t *testing.T) {
|
|
for _, op := range operators {
|
|
// check all width sizes from 1 - 7.
|
|
for width := 1; width <= 8; width++ {
|
|
t.Run(op.Name+strconv.Itoa(width), func(t *testing.T) {
|
|
data := []byte{0xff, 0xfd, 0xfa, 0xf3}
|
|
// clear the data with the width bits in mind
|
|
// i.e. data with width 1 should be masked by '10000000'.
|
|
// as the bitmap requires that the row must be at least 1 byte size.
|
|
// with the padding with non used bits.
|
|
for i := 0; i < len(data); i++ {
|
|
data[i] &= lmaskByte[width]
|
|
}
|
|
|
|
tocheck := make([]byte, 4)
|
|
copy(tocheck, data)
|
|
|
|
dest, err := NewWithData(width, 4, data)
|
|
require.NoError(t, err)
|
|
|
|
require.NotPanics(t, func() { err = dest.RasterOperation(0, 0, dest.Width, dest.Height, op.Operator, nil, 0, 0) })
|
|
require.NoError(t, err)
|
|
|
|
switch op.Operator {
|
|
case PixClr:
|
|
for _, bt := range dest.Data {
|
|
assert.Equal(t, byte(0x00), bt)
|
|
}
|
|
case PixSet:
|
|
for _, bt := range dest.Data {
|
|
assert.Equal(t, byte(0xff)&lmaskByte[width], bt)
|
|
}
|
|
case PixNotDst:
|
|
for i, bt := range dest.Data {
|
|
assert.Equal(t, ^tocheck[i]&lmaskByte[width], bt)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("General", func(t *testing.T) {
|
|
t.Run("DoublyPartial", func(t *testing.T) {
|
|
for _, op := range operators {
|
|
t.Run(op.Name, func(t *testing.T) {
|
|
data := []byte{0xff, 0xfd, 0xfa, 0xf3, 0xac, 0xbc, 0xdc, 0xaf}
|
|
tocheck := make([]byte, 8)
|
|
copy(tocheck, data)
|
|
|
|
dest, err := NewWithData(8, 8, data)
|
|
require.NoError(t, err)
|
|
|
|
err = dest.RasterOperation(2, 0, dest.Width-4, dest.Height, op.Operator, nil, 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
switch op.Operator {
|
|
case PixClr:
|
|
for i, bt := range dest.Data {
|
|
assert.Equal(t, combinePartial(data[i], 0x0, 0x3c), bt)
|
|
}
|
|
case PixSet:
|
|
for i, bt := range dest.Data {
|
|
assert.Equal(t, combinePartial(data[i], 0xff, 0x3c), bt)
|
|
}
|
|
case PixNotDst:
|
|
for i, bt := range dest.Data {
|
|
assert.Equal(t, combinePartial(data[i], ^tocheck[i], 0x3c), bt)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|
|
t.Run("Shifted1", func(t *testing.T) {
|
|
for _, op := range operators {
|
|
t.Run(op.Name, func(t *testing.T) {
|
|
data := []byte{0xff, 0xfd, 0xfa, 0xf3, 0xac, 0xbc, 0xdc, 0xaf, 0xff, 0xfd, 0xfa, 0xf3, 0xac, 0xbc, 0xdc, 0xaf}
|
|
tocheck := make([]byte, 16)
|
|
copy(tocheck, data)
|
|
|
|
dest, err := NewWithData(9, 8, data)
|
|
require.NoError(t, err)
|
|
|
|
err = dest.RasterOperation(1, 0, dest.Width, dest.Height, op.Operator, nil, 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
switch op.Operator {
|
|
case PixClr:
|
|
for i, bt := range dest.Data {
|
|
if i%2 == 0 {
|
|
assert.Equal(t, combinePartial(data[i], 0x0, rmaskByte[7]), bt)
|
|
} else {
|
|
assert.Equal(t, combinePartial(data[i], 0x0, lmaskByte[1]), bt)
|
|
}
|
|
}
|
|
case PixSet:
|
|
for i, bt := range dest.Data {
|
|
if i%2 == 0 {
|
|
assert.Equal(t, combinePartial(data[i], 0xff, rmaskByte[7]), bt)
|
|
} else {
|
|
assert.Equal(t, combinePartial(data[i], 0xff, lmaskByte[1]), bt)
|
|
}
|
|
}
|
|
case PixNotDst:
|
|
for i, bt := range dest.Data {
|
|
if i%2 == 0 {
|
|
assert.Equal(t, combinePartial(data[i], ^tocheck[i], rmaskByte[7]), bt)
|
|
} else {
|
|
assert.Equal(t, combinePartial(data[i], ^tocheck[i], lmaskByte[1]), bt)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|
|
t.Run("DoublyPartial", func(t *testing.T) {
|
|
for _, op := range operators {
|
|
t.Run(op.Name, func(t *testing.T) {
|
|
data := []byte{0xff, 0xfd, 0xfa, 0xf3, 0xac, 0xbc, 0xdc, 0xaf, 0xff, 0xfd, 0xfa, 0xf3, 0xac, 0xbc, 0xdc, 0xaf, 0xff, 0xfd, 0xfa, 0xf3, 0xac, 0xbc, 0xdc, 0xaf}
|
|
tocheck := make([]byte, len(data))
|
|
copy(tocheck, data)
|
|
|
|
dest, err := NewWithData(18, 8, data)
|
|
require.NoError(t, err)
|
|
|
|
err = dest.RasterOperation(1, 0, dest.Width-1, dest.Height, op.Operator, nil, 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
switch op.Operator {
|
|
case PixClr:
|
|
for i, bt := range dest.Data {
|
|
ix := i % 3
|
|
switch ix {
|
|
case 0:
|
|
assert.Equal(t, combinePartial(data[i], 0x0, rmaskByte[7]), bt)
|
|
case 1:
|
|
assert.Equal(t, data[i], byte(0x0))
|
|
case 2:
|
|
assert.Equal(t, combinePartial(data[i], 0x0, lmaskByte[2]), bt)
|
|
}
|
|
}
|
|
case PixSet:
|
|
for i, bt := range dest.Data {
|
|
ix := i % 3
|
|
switch ix {
|
|
case 0:
|
|
assert.Equal(t, combinePartial(data[i], 0xff, rmaskByte[7]), bt)
|
|
case 1:
|
|
assert.Equal(t, data[i], byte(0xff))
|
|
case 2:
|
|
assert.Equal(t, combinePartial(data[i], 0xff, lmaskByte[2]), bt)
|
|
}
|
|
}
|
|
case PixNotDst:
|
|
for i, bt := range dest.Data {
|
|
ix := i % 3
|
|
switch ix {
|
|
case 0:
|
|
assert.Equal(t, combinePartial(data[i], ^tocheck[i], rmaskByte[7]), bt)
|
|
case 1:
|
|
assert.Equal(t, data[i], ^tocheck[i])
|
|
case 2:
|
|
assert.Equal(t, combinePartial(data[i], ^tocheck[i], lmaskByte[2]), bt)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|
|
})
|
|
})
|
|
|
|
t.Run("Low", func(t *testing.T) {
|
|
t.Run("NilSrc", func(t *testing.T) {
|
|
dest := New(5, 5)
|
|
err := RasterOperation(dest, 0, 0, 0, 0, PixSrc, nil, 0, 0)
|
|
require.Error(t, err)
|
|
})
|
|
|
|
operators := []operatorName{{PixSrc, "Source"}, {PixNotSrc, "NotSource"}, {PixSrcOrDst, "SourceOrDest"}, {PixSrcAndDst, "SourceAndDest"}, {PixSrcXorDst, "SourceXorDest"}, {PixNotSrcOrDst, "NotSourceOrDest"}, {PixNotSrcAndDst, "NotSourceAndDest"}, {PixSrcOrNotDst, "SourceAndNotDest"}, {PixSrcAndNotDst, "SourceAndNotDest"}, {PixNotPixSrcOrDst, "Not(SourceOrDest)"}, {PixNotPixSrcAndDst, "Not(SourceAndDest)"}, {PixNotPixSrcXorDst, "Not(SourceXorDest)"}}
|
|
|
|
t.Run("ByteAligned", func(t *testing.T) {
|
|
// ByteAligned raster operation occurs when both the resultant 'dx' and 'sx'
|
|
// are divisible by 7 (full byte).
|
|
for _, op := range operators {
|
|
t.Run(op.Name, func(t *testing.T) {
|
|
dest := New(12, 12)
|
|
// generate random bytes for dest
|
|
i, err := rand.Read(dest.Data)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(dest.Data), i)
|
|
|
|
// clear unnecessary bits - the bitmap data have 0th bits at the end of the row.
|
|
for i := 0; i < len(dest.Data); i++ {
|
|
if i%2 != 0 {
|
|
dest.Data[i] &= lmaskByte[4]
|
|
}
|
|
}
|
|
|
|
// create a copy of the dest data for testing purpose
|
|
destDataCopy := make([]byte, len(dest.Data))
|
|
copy(destDataCopy, dest.Data)
|
|
|
|
src := New(14, 16)
|
|
// generate random bytes for source
|
|
i, err = rand.Read(src.Data)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(src.Data), i)
|
|
|
|
for i := 0; i < len(src.Data); i++ {
|
|
if i%2 != 0 {
|
|
src.Data[i] &= lmaskByte[4]
|
|
}
|
|
}
|
|
|
|
// do the raster operations
|
|
err = RasterOperation(dest, 0, 0, dest.Width, dest.Height, op.Operator, src, 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
for i, bt := range dest.Data {
|
|
var shouldBe byte
|
|
if i%2 != 0 {
|
|
// take the mask of the dest.Width % 8
|
|
mask := lmaskByte[4]
|
|
switch op.Operator {
|
|
case PixSrc:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i], mask)
|
|
case PixNotSrc:
|
|
shouldBe = combinePartial(destDataCopy[i], ^src.Data[i], mask)
|
|
case PixSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]|destDataCopy[i], mask)
|
|
case PixSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]&destDataCopy[i], mask)
|
|
case PixSrcXorDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]^destDataCopy[i], mask)
|
|
case PixNotSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], (^src.Data[i])|destDataCopy[i], mask)
|
|
case PixNotSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], (^src.Data[i])&destDataCopy[i], mask)
|
|
case PixSrcOrNotDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]|^destDataCopy[i], mask)
|
|
case PixSrcAndNotDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]&^destDataCopy[i], mask)
|
|
case PixNotPixSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(src.Data[i] | destDataCopy[i]), mask)
|
|
case PixNotPixSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(src.Data[i] & destDataCopy[i]), mask)
|
|
case PixNotPixSrcXorDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(src.Data[i] ^ destDataCopy[i]), mask)
|
|
}
|
|
} else {
|
|
switch op.Operator {
|
|
case PixSrc:
|
|
shouldBe = src.Data[i]
|
|
case PixNotSrc:
|
|
shouldBe = ^src.Data[i]
|
|
case PixSrcOrDst:
|
|
shouldBe = src.Data[i] | destDataCopy[i]
|
|
case PixSrcAndDst:
|
|
shouldBe = src.Data[i] & destDataCopy[i]
|
|
case PixSrcXorDst:
|
|
shouldBe = src.Data[i] ^ destDataCopy[i]
|
|
case PixNotSrcOrDst:
|
|
shouldBe = ^src.Data[i] | destDataCopy[i]
|
|
case PixNotSrcAndDst:
|
|
shouldBe = ^src.Data[i] & destDataCopy[i]
|
|
case PixSrcOrNotDst:
|
|
shouldBe = src.Data[i] | ^destDataCopy[i]
|
|
case PixSrcAndNotDst:
|
|
shouldBe = src.Data[i] & ^destDataCopy[i]
|
|
case PixNotPixSrcOrDst:
|
|
shouldBe = ^(src.Data[i] | destDataCopy[i])
|
|
case PixNotPixSrcAndDst:
|
|
shouldBe = ^(src.Data[i] & destDataCopy[i])
|
|
case PixNotPixSrcXorDst:
|
|
shouldBe = ^(src.Data[i] ^ destDataCopy[i])
|
|
}
|
|
}
|
|
assert.Equal(t, shouldBe, bt, "At i: %d, should be: %08b, is: %08b", i, shouldBe, bt)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("VAligned", func(t *testing.T) {
|
|
// VAligned raster operations occurs when the 'dx' and 'sx' are not byte divisible
|
|
// !(dx&7==0 && sx&7==0) && (dx&7 == sx&7)
|
|
t.Run("WithFullByte", func(t *testing.T) {
|
|
for _, op := range operators {
|
|
t.Run(op.Name, func(t *testing.T) {
|
|
dest := New(18, 12)
|
|
// generate random bytes for dest
|
|
i, err := rand.Read(dest.Data)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(dest.Data), i)
|
|
|
|
// clear unnecessary bits - the bitmap data have 0th bits at the end of the row.
|
|
for i := 0; i < len(dest.Data); i++ {
|
|
if i%2 != 0 {
|
|
dest.Data[i] &= lmaskByte[4]
|
|
}
|
|
}
|
|
|
|
// create a copy of the dest data for testing purpose
|
|
destDataCopy := make([]byte, len(dest.Data))
|
|
copy(destDataCopy, dest.Data)
|
|
|
|
src := New(20, 16)
|
|
// generate random bytes for source
|
|
i, err = rand.Read(src.Data)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(src.Data), i)
|
|
|
|
for i := 0; i < len(src.Data); i++ {
|
|
if i%2 != 0 {
|
|
src.Data[i] &= lmaskByte[4]
|
|
}
|
|
}
|
|
|
|
// do the raster operations
|
|
err = RasterOperation(dest, 2, 0, dest.Width-2, dest.Height, op.Operator, src, 2, 0)
|
|
require.NoError(t, err)
|
|
|
|
for i, bt := range dest.Data {
|
|
var shouldBe, mask byte
|
|
switch i % 3 {
|
|
case 0:
|
|
mask = rmaskByte[6]
|
|
case 1:
|
|
mask = 0xff
|
|
default:
|
|
mask = lmaskByte[2]
|
|
}
|
|
|
|
switch op.Operator {
|
|
case PixSrc:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i], mask)
|
|
case PixNotSrc:
|
|
shouldBe = combinePartial(destDataCopy[i], ^src.Data[i], mask)
|
|
case PixSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]|destDataCopy[i], mask)
|
|
case PixSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]&destDataCopy[i], mask)
|
|
case PixSrcXorDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]^destDataCopy[i], mask)
|
|
case PixNotSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], (^src.Data[i])|destDataCopy[i], mask)
|
|
case PixNotSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], (^src.Data[i])&destDataCopy[i], mask)
|
|
case PixSrcOrNotDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]|^destDataCopy[i], mask)
|
|
case PixSrcAndNotDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]&^destDataCopy[i], mask)
|
|
case PixNotPixSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(src.Data[i] | destDataCopy[i]), mask)
|
|
case PixNotPixSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(src.Data[i] & destDataCopy[i]), mask)
|
|
case PixNotPixSrcXorDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(src.Data[i] ^ destDataCopy[i]), mask)
|
|
}
|
|
assert.Equal(t, shouldBe, bt, "At i: %d, should be: %08b, is: %08b", i, shouldBe, bt)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("DoublyPartial", func(t *testing.T) {
|
|
for _, op := range operators {
|
|
t.Run(op.Name, func(t *testing.T) {
|
|
dest := New(8, 12)
|
|
// generate random bytes for dest
|
|
i, err := rand.Read(dest.Data)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(dest.Data), i)
|
|
|
|
// create a copy of the dest data for testing purpose
|
|
destDataCopy := make([]byte, len(dest.Data))
|
|
copy(destDataCopy, dest.Data)
|
|
|
|
src := New(8, 16)
|
|
// generate random bytes for source
|
|
i, err = rand.Read(src.Data)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(src.Data), i)
|
|
|
|
// do the raster operations
|
|
err = RasterOperation(dest, 2, 0, dest.Width-4, dest.Height, op.Operator, src, 2, 0)
|
|
require.NoError(t, err)
|
|
|
|
mask := rmaskByte[len(rmaskByte)-3] & lmaskByte[len(lmaskByte)-3]
|
|
for i, bt := range dest.Data {
|
|
var shouldBe byte
|
|
|
|
switch op.Operator {
|
|
case PixSrc:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i], mask)
|
|
case PixNotSrc:
|
|
shouldBe = combinePartial(destDataCopy[i], ^src.Data[i], mask)
|
|
case PixSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]|destDataCopy[i], mask)
|
|
case PixSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]&destDataCopy[i], mask)
|
|
case PixSrcXorDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]^destDataCopy[i], mask)
|
|
case PixNotSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], (^src.Data[i])|destDataCopy[i], mask)
|
|
case PixNotSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], (^src.Data[i])&destDataCopy[i], mask)
|
|
case PixSrcOrNotDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]|^destDataCopy[i], mask)
|
|
case PixSrcAndNotDst:
|
|
shouldBe = combinePartial(destDataCopy[i], src.Data[i]&^destDataCopy[i], mask)
|
|
case PixNotPixSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(src.Data[i] | destDataCopy[i]), mask)
|
|
case PixNotPixSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(src.Data[i] & destDataCopy[i]), mask)
|
|
case PixNotPixSrcXorDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(src.Data[i] ^ destDataCopy[i]), mask)
|
|
}
|
|
assert.Equal(t, shouldBe, bt, "At i: %d, should be: %08b, is: %08b", i, shouldBe, bt)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("General", func(t *testing.T) {
|
|
// General raster operations are all other raster operations.
|
|
// !(dx == 0 && sx == 0) && (sx % 7 != dx % 7)
|
|
t.Run("SrcNotAligned", func(t *testing.T) {
|
|
// sx%7 != 0 and dx%7 == 0 -> sHang has some value and dHang has some value
|
|
t.Run("GreaterSrcHang", func(t *testing.T) {
|
|
for _, op := range operators {
|
|
common.SetLogger(common.NewConsoleLogger(common.LogLevelDebug))
|
|
t.Run(op.Name, func(t *testing.T) {
|
|
rd := rand.New(rand.NewSource(123))
|
|
dest := New(18, 12)
|
|
|
|
// generate random bytes for dest
|
|
i, err := rd.Read(dest.Data)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(dest.Data), i)
|
|
|
|
// clear unnecessary bits - the bitmap data have 0th bits at the end of the row.
|
|
for i := 0; i < len(dest.Data); i++ {
|
|
if i%3 == 2 {
|
|
dest.Data[i] &= lmaskByte[2]
|
|
}
|
|
}
|
|
|
|
// create a copy of the dest data for testing purpose
|
|
destDataCopy := make([]byte, len(dest.Data))
|
|
copy(destDataCopy, dest.Data)
|
|
|
|
src := New(20, 16)
|
|
// generate random bytes for source
|
|
i, err = rd.Read(src.Data)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(src.Data), i)
|
|
|
|
for i := 0; i < len(src.Data); i++ {
|
|
if i%3 == 2 {
|
|
src.Data[i] &= lmaskByte[4]
|
|
}
|
|
}
|
|
|
|
// do the raster operations
|
|
err = RasterOperation(dest, 0, 0, dest.Width, dest.Height, op.Operator, src, 2, 0)
|
|
require.NoError(t, err)
|
|
|
|
for i := 0; i < len(dest.Data); i++ {
|
|
var shouldBe, srcByte byte
|
|
mask := byte(0xff)
|
|
// example src.Data
|
|
// 11011000 01101100 11010000 01101001 11010111 11010000
|
|
// in example with PixSrc should be
|
|
// 01100001 10110011 01000000 10100111 01011111 01000000
|
|
switch i % 3 {
|
|
case 0, 1:
|
|
// example srcData
|
|
// src.Data[i]: 11011000, src.Data[i+1] = 01101100
|
|
// the result would be a 11011000 << 2 = 01100000
|
|
// in union with 01101100 >> 6 = 00000001
|
|
// 01100001
|
|
// this means byte values are shifted by 2
|
|
srcByte = src.Data[i]<<2 | src.Data[i+1]>>6
|
|
case 2:
|
|
// example srcData
|
|
// src.Data[i]: 11010000 << 2 = 01100000
|
|
srcByte = src.Data[i] << 2
|
|
mask = lmaskByte[2]
|
|
}
|
|
|
|
switch op.Operator {
|
|
case PixSrc:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte, mask)
|
|
case PixNotSrc:
|
|
shouldBe = combinePartial(destDataCopy[i], ^srcByte, mask)
|
|
case PixSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte|destDataCopy[i], mask)
|
|
case PixSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte&destDataCopy[i], mask)
|
|
case PixSrcXorDst:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte^destDataCopy[i], mask)
|
|
case PixNotSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], (^srcByte)|destDataCopy[i], mask)
|
|
case PixNotSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], (^srcByte)&destDataCopy[i], mask)
|
|
case PixSrcOrNotDst:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte|^destDataCopy[i], mask)
|
|
case PixSrcAndNotDst:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte&^destDataCopy[i], mask)
|
|
case PixNotPixSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(srcByte | destDataCopy[i]), mask)
|
|
case PixNotPixSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(srcByte & destDataCopy[i]), mask)
|
|
case PixNotPixSrcXorDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(srcByte ^ destDataCopy[i]), mask)
|
|
}
|
|
assert.Equal(t, shouldBe, dest.Data[i], "i: %d shouldBe: %08b is: %08b", i, shouldBe, dest.Data[i])
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("GreaterDstHang", func(t *testing.T) {
|
|
for _, op := range operators {
|
|
common.SetLogger(common.NewConsoleLogger(common.LogLevelDebug))
|
|
t.Run(op.Name, func(t *testing.T) {
|
|
rd := rand.New(rand.NewSource(123))
|
|
dest := New(18, 12)
|
|
|
|
// generate random bytes for dest
|
|
i, err := rd.Read(dest.Data)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(dest.Data), i)
|
|
|
|
// clear unnecessary bits - the bitmap data have 0th bits at the end of the row.
|
|
for i := 0; i < len(dest.Data); i++ {
|
|
if i%3 == 2 {
|
|
dest.Data[i] &= lmaskByte[2]
|
|
}
|
|
}
|
|
|
|
// create a copy of the dest data for testing purpose
|
|
destDataCopy := make([]byte, len(dest.Data))
|
|
copy(destDataCopy, dest.Data)
|
|
|
|
src := New(20, 16)
|
|
// generate random bytes for source
|
|
i, err = rd.Read(src.Data)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, len(src.Data), i)
|
|
|
|
for i := 0; i < len(src.Data); i++ {
|
|
if i%3 == 2 {
|
|
src.Data[i] &= lmaskByte[4]
|
|
}
|
|
}
|
|
|
|
// do the raster operations
|
|
err = RasterOperation(dest, 2, 0, dest.Width-2, dest.Height, op.Operator, src, 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
for i := 0; i < len(dest.Data); i++ {
|
|
var shouldBe, srcByte byte
|
|
mask := byte(0x00)
|
|
// example src.Data
|
|
// 11011000 01101100 11010000 01101001 11010111 11010000
|
|
// example dest.Data
|
|
// 10100101 10001011 01000000 01011010 11110101 01000000
|
|
// in example with PixSrc should be where dest is shifted right by 2
|
|
// 10110110 00011011 00000000 01011010 01110101 11000000
|
|
switch i % 3 {
|
|
case 0:
|
|
// example srcData
|
|
// src.Data[0]>>2 = 11011000 >> 2 = 00110110
|
|
// dst.Data[0]&11000000 = 10100101 & 11000000 = 10000000
|
|
// the result would be a union 10110110
|
|
// this means byte values are shifted by 2
|
|
srcByte = src.Data[i] >> 2
|
|
mask = rmaskByte[6]
|
|
case 1:
|
|
// example srcData
|
|
// src.Data[i]: 11010000 << 2 = 01100000
|
|
srcByte = src.Data[i-1]<<6 | src.Data[i]>>2
|
|
mask = 0xff
|
|
case 2:
|
|
// example srcData
|
|
// src.Data[i]: 11010000 << 2 = 01100000
|
|
srcByte = src.Data[i-1]<<6 | src.Data[i]>>2
|
|
mask = lmaskByte[2]
|
|
}
|
|
|
|
switch op.Operator {
|
|
case PixSrc:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte, mask)
|
|
case PixNotSrc:
|
|
shouldBe = combinePartial(destDataCopy[i], ^srcByte, mask)
|
|
case PixSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte|destDataCopy[i], mask)
|
|
case PixSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte&destDataCopy[i], mask)
|
|
case PixSrcXorDst:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte^destDataCopy[i], mask)
|
|
case PixNotSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], (^srcByte)|destDataCopy[i], mask)
|
|
case PixNotSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], (^srcByte)&destDataCopy[i], mask)
|
|
case PixSrcOrNotDst:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte|^destDataCopy[i], mask)
|
|
case PixSrcAndNotDst:
|
|
shouldBe = combinePartial(destDataCopy[i], srcByte&^destDataCopy[i], mask)
|
|
case PixNotPixSrcOrDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(srcByte | destDataCopy[i]), mask)
|
|
case PixNotPixSrcAndDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(srcByte & destDataCopy[i]), mask)
|
|
case PixNotPixSrcXorDst:
|
|
shouldBe = combinePartial(destDataCopy[i], ^(srcByte ^ destDataCopy[i]), mask)
|
|
}
|
|
assert.Equal(t, shouldBe, dest.Data[i], "i: %d shouldBe: %08b is: %08b", i, shouldBe, dest.Data[i])
|
|
}
|
|
})
|
|
}
|
|
})
|
|
})
|
|
|
|
})
|
|
})
|
|
|
|
t.Run("Simple", func(t *testing.T) {
|
|
// having two bitmaps:
|
|
// Dest - width: 18, height: 8 with data:
|
|
//
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 01001111 01000000
|
|
// 10000010 10001001 01000000
|
|
// 10000001 00001001 01000000
|
|
// 10000001 00001111 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
dData := []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x4F, 0x40,
|
|
0x82, 0x89, 0x40,
|
|
0x81, 0x09, 0x40,
|
|
0x81, 0x0F, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}
|
|
|
|
// Source: width 8, height: 4 with data:
|
|
//
|
|
// 01111110
|
|
// 01011001
|
|
// 01010110
|
|
// 01100010
|
|
sData := []byte{0x7E, 0x59, 0x56, 0x62}
|
|
|
|
dst, err := NewWithData(18, 8, dData)
|
|
require.NoError(t, err)
|
|
|
|
src, err := NewWithData(8, 4, sData)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("Dst", func(t *testing.T) {
|
|
t.Run("Clr", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err := dst.RasterOperation(7, 2, 9, 4, PixClr, nil, 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 00000000 01000000
|
|
// 10000010 00000000 01000000
|
|
// 10000000 00000000 01000000
|
|
// 10000000 00000000 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x00, 0x40,
|
|
0x82, 0x00, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
t.Run("Set", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err := dst.RasterOperation(2, 2, 14, 4, PixSet, nil, 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
// should be a:
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10111111 11111111 01000000
|
|
// 10111111 11111111 01000000
|
|
// 10111111 11111111 01000000
|
|
// 10111111 11111111 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0xBF, 0xFF, 0x40,
|
|
0xBF, 0xFF, 0x40,
|
|
0xBF, 0xFF, 0x40,
|
|
0xBF, 0xFF, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
t.Run("NotDst", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err := dst.RasterOperation(5, 3, 11, 4, PixNotDst, nil, 0, 0)
|
|
require.NoError(t, err)
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 01001111 01000000
|
|
// 10000101 01110110 01000000
|
|
// 10000110 11110110 01000000
|
|
// 10000110 11110000 01000000
|
|
// 10000111 11111111 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x4F, 0x40,
|
|
0x85, 0x76, 0x40,
|
|
0x86, 0xF6, 0x40,
|
|
0x86, 0xF0, 0x40,
|
|
0x87, 0xFF, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
})
|
|
|
|
t.Run("WithSrc", func(t *testing.T) {
|
|
t.Run("Src", func(t *testing.T) {
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixSrc, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// 01111110
|
|
// 01011001
|
|
// 01010110
|
|
// 01100010
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 01111110 01000000
|
|
// 10000010 01011001 01000000
|
|
// 10000001 01010110 01000000
|
|
// 10000001 01100010 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x7E, 0x40,
|
|
0x82, 0x59, 0x40,
|
|
0x81, 0x56, 0x40,
|
|
0x81, 0x62, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixSrc, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000101 11111011 01000000
|
|
// 10000001 01100101 01000000
|
|
// 10000001 01011001 01000000
|
|
// 10000001 10001011 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x85, 0xFB, 0x40,
|
|
0x81, 0x65, 0x40,
|
|
0x81, 0x59, 0x40,
|
|
0x81, 0x8B, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
})
|
|
|
|
t.Run("NotSrc", func(t *testing.T) {
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixNotSrc, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 10000001 01000000
|
|
// 10000010 10100110 01000000
|
|
// 10000001 10101001 01000000
|
|
// 10000001 10011101 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x81, 0x40,
|
|
0x82, 0xA6, 0x40,
|
|
0x81, 0xA9, 0x40,
|
|
0x81, 0x9D, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixNotSrc, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// NotSrc: 10000001 10100110 10101001 10011101
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000110 00000111 01000000
|
|
// 10000010 10011001 01000000
|
|
// 10000010 10100101 01000000
|
|
// 10000010 01110111 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x86, 0x07, 0x40,
|
|
0x82, 0x99, 0x40,
|
|
0x82, 0xA5, 0x40,
|
|
0x82, 0x77, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
})
|
|
|
|
t.Run("SrcAndDst", func(t *testing.T) {
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixSrcAndDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 01001111 10001001 00001001 00001111
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// SrcAndDst: 01001110 00001001 00000000 00000010
|
|
// 0x4E 0x09 0x00 0x02
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 01001110 01000000
|
|
// 10000010 00001001 01000000
|
|
// 10000001 00000000 01000000
|
|
// 10000001 00000010 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x4E, 0x40,
|
|
0x82, 0x09, 0x40,
|
|
0x81, 0x00, 0x40,
|
|
0x81, 0x02, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixSrcAndDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// SrcAndDst: 00010010 00000000 01000010 01000010
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 01001011 01000000
|
|
// 10000000 00000001 01000000
|
|
// 10000001 00001001 01000000
|
|
// 10000001 00001011 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x4B, 0x40,
|
|
0x80, 0x01, 0x40,
|
|
0x81, 0x09, 0x40,
|
|
0x81, 0x0B, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}, dst.Data)
|
|
})
|
|
})
|
|
|
|
t.Run("SrcOrDst", func(t *testing.T) {
|
|
t.Run("Algined", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixSrcOrDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 01001111 10001001 00001001 00001111
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// SrcOrDst: 01111111 11011001 01011111 01101111
|
|
// 0xEF 0xD9 0x5F 0x6F
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 01111111 01000000
|
|
// 10000010 11011001 01000000
|
|
// 10000001 01011111 01000000
|
|
// 10000001 01101110 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x7F, 0x40,
|
|
0x82, 0xD9, 0x40,
|
|
0x81, 0x5F, 0x40,
|
|
0x81, 0x6F, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixSrcOrDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// SrcOrDst: 01111111 11111011 01010110 01100011
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000101 11111111 01000000
|
|
// 10000011 11101101 01000000
|
|
// 10000001 01011001 01000000
|
|
// 10000001 10001111 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x85, 0xFF, 0x40,
|
|
0x83, 0xED, 0x40,
|
|
0x81, 0x59, 0x40,
|
|
0x81, 0x8F, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}, dst.Data)
|
|
})
|
|
})
|
|
|
|
t.Run("SrcXorDst", func(t *testing.T) {
|
|
t.Run("Algined", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixSrcXorDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 01001111 10001001 00001001 00001111
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// SrcXorDst: 00110001 11010000 01011111 01101101
|
|
// 0x31 0xD0 0x5F 0x6D
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 00110001 01000000
|
|
// 10000010 11010000 01000000
|
|
// 10000001 01011111 01000000
|
|
// 10000001 01101101 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x31, 0x40,
|
|
0x82, 0xD0, 0x40,
|
|
0x81, 0x5F, 0x40,
|
|
0x81, 0x6D, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixSrcXorDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// SrcXorDst: 01101101 11111011 00010100 00100001
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000101 10110111 01000000
|
|
// 10000011 11101101 01000000
|
|
// 10000000 01010001 01000000
|
|
// 10000000 10000111 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x85, 0xB7, 0x40,
|
|
0x83, 0xED, 0x40,
|
|
0x80, 0x51, 0x40,
|
|
0x80, 0x87, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}, dst.Data)
|
|
})
|
|
})
|
|
|
|
t.Run("SrcAndNotDst", func(t *testing.T) {
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixSrcAndNotDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 01001111 10001001 00001001 00001111
|
|
// ^Dst: 10110000 01110110 11110110 11110000
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// SrcAndNotDst: 00110000 01010000 01010110 01100000
|
|
// 0x30 0x50 0x56 0x60
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 00110000 01000000
|
|
// 10000010 01010000 01000000
|
|
// 10000001 01010110 01000000
|
|
// 10000001 01100000 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x30, 0x40,
|
|
0x82, 0x50, 0x40,
|
|
0x81, 0x56, 0x40,
|
|
0x81, 0x60, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixSrcAndNotDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// ^Dst: 11101100 01011101 10111101 10111100
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// SrcAndNotDst: 01101100 01011001 00010100 00100000
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000101 10110011 01000000
|
|
// 10000001 01100101 01000000
|
|
// 10000000 01010001 01000000
|
|
// 10000000 10000011 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x85, 0xB3, 0x40,
|
|
0x81, 0x65, 0x40,
|
|
0x80, 0x51, 0x40,
|
|
0x80, 0x83, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}, dst.Data)
|
|
})
|
|
})
|
|
|
|
t.Run("SrcOrNotDst", func(t *testing.T) {
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixSrcOrNotDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 01001111 10001001 00001001 00001111
|
|
// ^Dst: 10110000 01110110 11110110 11110000
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// SrcOrNotDst: 11111110 01111111 11110110 11110010
|
|
// 0xFE 0x7F 0xF6 0xF2
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 00110000 01000000
|
|
// 10000010 01010000 01000000
|
|
// 10000001 01010110 01000000
|
|
// 10000001 01100000 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0xFE, 0x40,
|
|
0x82, 0x7F, 0x40,
|
|
0x81, 0xF6, 0x40,
|
|
0x81, 0xF2, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixSrcOrNotDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// ^Dst: 11101100 01011101 10111101 10111100
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// SrcOrNotDst: 11111110 01011101 11111111 11111110
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000111 11111011 01000000
|
|
// 10000001 01110101 01000000
|
|
// 10000011 11111101 01000000
|
|
// 10000011 11111011 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x87, 0xFB, 0x40,
|
|
0x81, 0x75, 0x40,
|
|
0x83, 0xFD, 0x40,
|
|
0x83, 0xFB, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}, dst.Data)
|
|
})
|
|
})
|
|
|
|
t.Run("NotSrcAndDst", func(t *testing.T) {
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixNotSrcAndDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// ^Src: 10000001 10100110 10101001 10011101
|
|
// Dst: 01001111 10001001 00001001 00001111
|
|
// NotSrcAndDst: 00000001 10000000 00001001 00001101
|
|
// 0x01 0x80 0x09 0x0D
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 00000001 01000000
|
|
// 10000010 10000000 01000000
|
|
// 10000001 00001001 01000000
|
|
// 10000001 00001101 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x01, 0x40,
|
|
0x82, 0x80, 0x40,
|
|
0x81, 0x09, 0x40,
|
|
0x81, 0x0D, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixNotSrcAndDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// ^Src: 10000001 10100110 10101001 10011101
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// NotSrcAndDst: 00000001 10100010 00000000 00000001
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 00000111 01000000
|
|
// 10000010 10001001 01000000
|
|
// 10000000 00000001 01000000
|
|
// 10000000 00000111 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x07, 0x40,
|
|
0x82, 0x89, 0x40,
|
|
0x80, 0x01, 0x40,
|
|
0x80, 0x07, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}, dst.Data)
|
|
})
|
|
})
|
|
|
|
t.Run("NotSrcOrDst", func(t *testing.T) {
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixNotSrcOrDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// ^Src: 10000001 10100110 10101001 10011101
|
|
// Dst: 01001111 10001001 00001001 00001111
|
|
// NotSrcOrDst: 11001111 10101111 10101001 10011111
|
|
// 0xCF 0xAF 0xA9 0x9F
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 11001111 01000000
|
|
// 10000010 10101111 01000000
|
|
// 10000001 10101001 01000000
|
|
// 10000001 10011111 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0xCF, 0x40,
|
|
0x82, 0xAF, 0x40,
|
|
0x81, 0xA9, 0x40,
|
|
0x81, 0x9F, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixNotSrcOrDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// ^Src: 10000001 10100110 10101001 10011101
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// NotSrcOrDst: 10010011 10100110 11101011 11011111
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000110 01001111 01000000
|
|
// 10000010 10011001 01000000
|
|
// 10000011 10101101 01000000
|
|
// 10000011 01111111 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x86, 0x4F, 0x40,
|
|
0x82, 0x99, 0x40,
|
|
0x83, 0xAD, 0x40,
|
|
0x83, 0x7F, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}, dst.Data)
|
|
})
|
|
})
|
|
|
|
t.Run("Not(SrcOrDst)", func(t *testing.T) {
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixNotPixSrcOrDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// Dst: 01001111 10001001 00001001 00001111
|
|
|
|
// SrcOrDst: 01111111 11011001 01011111 01101111
|
|
// Not(SrcOrDst): 10000000 00100110 10100000 10010000
|
|
// 0x80 0x26 0xA0 0x90
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 10000000 01000000
|
|
// 10000010 00100110 01000000
|
|
// 10000001 10100000 01000000
|
|
// 10000001 10010000 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0x80, 0x40,
|
|
0x82, 0x26, 0x40,
|
|
0x81, 0xA0, 0x40,
|
|
0x81, 0x90, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixNotPixSrcOrDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// SrcOrDst: 01111111 11111011 01010110 01100011
|
|
// Not(SrcOrDst): 10000000 00000100 10101001 10011100
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000110 00000011 01000000
|
|
// 10000000 00010001 01000000
|
|
// 10000010 10100101 01000000
|
|
// 10000010 01110011 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x86, 0x03, 0x40,
|
|
0x80, 0x11, 0x40,
|
|
0x82, 0xA5, 0x40,
|
|
0x82, 0x73, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}, dst.Data)
|
|
})
|
|
})
|
|
|
|
t.Run("Not(SrcAndDst)", func(t *testing.T) {
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixNotPixSrcAndDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// ^Src: 10000001 10100110 10101001 10011101
|
|
|
|
// SrcAndDst: 01001110 00001001 00000000 00000010
|
|
// Not(SrcAndDst): 10110001 11110110 11111111 11111101
|
|
// 0xB1 0xF6 0xFF 0xFD
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 10110001 01000000
|
|
// 10000010 11110110 01000000
|
|
// 10000001 11111111 01000000
|
|
// 10000001 11111101 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0xB1, 0x40,
|
|
0x82, 0xF6, 0x40,
|
|
0x81, 0xFF, 0x40,
|
|
0x81, 0xFD, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixNotPixSrcAndDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// SrcAndDst: 00010010 00000000 01000010 01000010
|
|
// Not(SrcOrDst): 11101101 11111111 10111101 10111101
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000111 10110111 01000000
|
|
// 10000011 11111101 01000000
|
|
// 10000010 11110101 01000000
|
|
// 10000010 11110111 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x87, 0xB7, 0x40,
|
|
0x83, 0xFD, 0x40,
|
|
0x82, 0xF5, 0x40,
|
|
0x82, 0xF7, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}, dst.Data)
|
|
})
|
|
})
|
|
|
|
t.Run("Not(SrcXorDst)", func(t *testing.T) {
|
|
t.Run("Aligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(8, 2, 8, 4, PixNotPixSrcXorDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// ^Src: 10000001 10100110 10101001 10011101
|
|
|
|
// SrcXorDst: 00110001 11010000 01011111 01101101
|
|
// Not(SrcAndDst): 11001110 00101111 10100000 10010010
|
|
// 0xCE 0x2F 0xA0 0x92
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000100 11001110 01000000
|
|
// 10000010 00101111 01000000
|
|
// 10000001 10100000 01000000
|
|
// 10000001 10010010 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, dst.Data, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x84, 0xCE, 0x40,
|
|
0x82, 0x2F, 0x40,
|
|
0x81, 0xA0, 0x40,
|
|
0x81, 0x92, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
})
|
|
})
|
|
|
|
t.Run("NotAligned", func(t *testing.T) {
|
|
dst := dst.Copy()
|
|
|
|
err = dst.RasterOperation(6, 2, 8, 4, PixNotPixSrcXorDst, src, 0, 0)
|
|
assert.NoError(t, err)
|
|
|
|
// Src: 01111110 01011001 01010110 01100010
|
|
// Dst: 00010011 10100010 01000010 01000011
|
|
// SrcXorDst: 01101101 11111011 00010100 00100001
|
|
// Not(SrcOrDst): 10010010 00000100 11101011 11011110
|
|
|
|
// 11111111 11111111 11000000
|
|
// 10000000 00000000 01000000
|
|
// 10000110 01001011 01000000
|
|
// 10000000 00010001 01000000
|
|
// 10000011 10101101 01000000
|
|
// 10000011 01111011 01000000
|
|
// 10000000 00000000 01000000
|
|
// 11111111 11111111 11000000
|
|
assert.Equal(t, []byte{
|
|
0xFF, 0xFF, 0xC0,
|
|
0x80, 0x00, 0x40,
|
|
0x86, 0x4B, 0x40,
|
|
0x80, 0x11, 0x40,
|
|
0x83, 0xAD, 0x40,
|
|
0x83, 0x7B, 0x40,
|
|
0x80, 0x00, 0x40,
|
|
0xFF, 0xFF, 0xC0,
|
|
}, dst.Data)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|