mirror of
https://github.com/unidoc/unipdf.git
synced 2025-04-30 13:48:51 +08:00
Make requested changes according to the PR comments
Add default parameters to the NewCCITTFaxEncoder. Default values are taken from the PDF specification. ccittfaxdecode was moved to pdf/internal and renamed to ccittfax. ccittfax package errors were unexported.
This commit is contained in:
parent
54443dab7f
commit
6ffb78b093
@ -34,7 +34,7 @@ import (
|
|||||||
lzw1 "golang.org/x/image/tiff/lzw"
|
lzw1 "golang.org/x/image/tiff/lzw"
|
||||||
|
|
||||||
"github.com/unidoc/unidoc/common"
|
"github.com/unidoc/unidoc/common"
|
||||||
"github.com/unidoc/unidoc/pdf/core/ccittfaxdecode"
|
"github.com/unidoc/unidoc/pdf/internal/ccittfax"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -1633,7 +1633,10 @@ type CCITTFaxEncoder struct {
|
|||||||
|
|
||||||
// NewCCITTFaxEncoder makes a new CCITTFax encoder.
|
// NewCCITTFaxEncoder makes a new CCITTFax encoder.
|
||||||
func NewCCITTFaxEncoder() *CCITTFaxEncoder {
|
func NewCCITTFaxEncoder() *CCITTFaxEncoder {
|
||||||
return &CCITTFaxEncoder{}
|
return &CCITTFaxEncoder{
|
||||||
|
Columns: 1728,
|
||||||
|
EndOfBlock: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFilterName gets the filter name.
|
// GetFilterName gets the filter name.
|
||||||
@ -1842,7 +1845,7 @@ func (enc *CCITTFaxEncoder) UpdateParams(params *PdfObjectDictionary) {
|
|||||||
|
|
||||||
// DecodeBytes decodes the CCITTFax encoded image data.
|
// DecodeBytes decodes the CCITTFax encoded image data.
|
||||||
func (enc *CCITTFaxEncoder) DecodeBytes(encoded []byte) ([]byte, error) {
|
func (enc *CCITTFaxEncoder) DecodeBytes(encoded []byte) ([]byte, error) {
|
||||||
encoder := &ccittfaxdecode.Encoder{
|
encoder := &ccittfax.Encoder{
|
||||||
K: enc.K,
|
K: enc.K,
|
||||||
Columns: enc.Columns,
|
Columns: enc.Columns,
|
||||||
EndOfLine: enc.EndOfLine,
|
EndOfLine: enc.EndOfLine,
|
||||||
@ -1913,7 +1916,7 @@ func (enc *CCITTFaxEncoder) EncodeBytes(data []byte) ([]byte, error) {
|
|||||||
pixels = append(pixels, pixelsRow)
|
pixels = append(pixels, pixelsRow)
|
||||||
}
|
}
|
||||||
|
|
||||||
encoder := &ccittfaxdecode.Encoder{
|
encoder := &ccittfax.Encoder{
|
||||||
K: enc.K,
|
K: enc.K,
|
||||||
Columns: enc.Columns,
|
Columns: enc.Columns,
|
||||||
EndOfLine: enc.EndOfLine,
|
EndOfLine: enc.EndOfLine,
|
||||||
|
@ -59,6 +59,7 @@ const testImageFile2 = "./testdata/signature.png"
|
|||||||
const testRobotoRegularTTFFile = "./testdata/roboto/Roboto-Regular.ttf"
|
const testRobotoRegularTTFFile = "./testdata/roboto/Roboto-Regular.ttf"
|
||||||
const testRobotoBoldTTFFile = "./testdata/roboto/Roboto-Bold.ttf"
|
const testRobotoBoldTTFFile = "./testdata/roboto/Roboto-Bold.ttf"
|
||||||
const testWts11TTFFile = "./testdata/wts11.ttf"
|
const testWts11TTFFile = "./testdata/wts11.ttf"
|
||||||
|
const testImageFileCCITT = "./testdata/p3_0.png"
|
||||||
|
|
||||||
// TODO(peterwilliams97): /tmp/2_p_multi.pdf which is created in this test gives an error message
|
// TODO(peterwilliams97): /tmp/2_p_multi.pdf which is created in this test gives an error message
|
||||||
// when opened in Adobe Reader: The font FreeSans contains bad Widths.
|
// when opened in Adobe Reader: The font FreeSans contains bad Widths.
|
||||||
@ -166,6 +167,58 @@ func TestImageWithEncoder(t *testing.T) {
|
|||||||
testWriteAndRender(t, creator, "1_dct.pdf")
|
testWriteAndRender(t, creator, "1_dct.pdf")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestImageWithCCITTFaxEncoder(t *testing.T) {
|
||||||
|
creator := New()
|
||||||
|
|
||||||
|
file, err := os.Open(testImageFileCCITT)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error opening test image file: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
imgF, _, err := goimage.Decode(file)
|
||||||
|
if err != nil {
|
||||||
|
file.Close()
|
||||||
|
t.Errorf("Error decoding test image file: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file.Close()
|
||||||
|
|
||||||
|
modelImg, err := model.ImageHandling.NewImageFromGoImage(imgF)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error creating image from go image: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
modelImg.BitsPerComponent = 1
|
||||||
|
modelImg.ColorComponents = 1
|
||||||
|
|
||||||
|
img, err := creator.NewImage(modelImg)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error creating image: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder := core.NewCCITTFaxEncoder()
|
||||||
|
encoder.Columns = int(img.Width())
|
||||||
|
img.SetEncoder(encoder)
|
||||||
|
|
||||||
|
img.SetPos(0, 0)
|
||||||
|
img.ScaleToWidth(612.0)
|
||||||
|
height := 612.0 * img.Height() / img.Width()
|
||||||
|
creator.SetPageSize(PageSize{612, height})
|
||||||
|
creator.NewPage()
|
||||||
|
|
||||||
|
err = creator.Draw(img)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Fail: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testWriteAndRender(t, creator, "1_ccitt.pdf")
|
||||||
|
}
|
||||||
|
|
||||||
func TestShapes1(t *testing.T) {
|
func TestShapes1(t *testing.T) {
|
||||||
creator := New()
|
creator := New()
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 220 KiB |
@ -3,9 +3,10 @@
|
|||||||
* file 'LICENSE.md', which is part of this source code package.
|
* file 'LICENSE.md', which is part of this source code package.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ccittfaxdecode
|
package ccittfax
|
||||||
|
|
||||||
// map pixel run lengths to the encoded bit sequences
|
// map pixel run lengths to the encoded bit sequences
|
||||||
|
// all the bit sequences for all groups could be found here https://www.itu.int/rec/T-REC-T.6-198811-I/en
|
||||||
var (
|
var (
|
||||||
bTerms map[int]code
|
bTerms map[int]code
|
||||||
wTerms map[int]code
|
wTerms map[int]code
|
@ -3,29 +3,31 @@
|
|||||||
* file 'LICENSE.md', which is part of this source code package.
|
* file 'LICENSE.md', which is part of this source code package.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ccittfaxdecode
|
package ccittfax
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrEOFBCorrupt is returned when the corrupt EOFB (end-of-block) code is found.
|
// errEOFBCorrupt is returned when the corrupt EOFB (end-of-block) code is found.
|
||||||
ErrEOFBCorrupt = errors.New("EOFB code is corrupted")
|
errEOFBCorrupt = errors.New("EOFB code is corrupted")
|
||||||
// ErrRTCCorrupt is returned when the corrupt RTC (return-the-carriage) code is found.
|
// errRTCCorrupt is returned when the corrupt RTC (return-the-carriage) code is found.
|
||||||
ErrRTCCorrupt = errors.New("RTC code is corrupted")
|
errRTCCorrupt = errors.New("RTC code is corrupted")
|
||||||
// ErrWrongCodeInHorizontalMode is returned when entered the horizontal mode and unknown bit
|
// errWrongCodeInHorizontalMode is returned when entered the horizontal mode and unknown bit
|
||||||
// sequence met.
|
// sequence met.
|
||||||
ErrWrongCodeInHorizontalMode = errors.New("wrong code in horizontal mode")
|
errWrongCodeInHorizontalMode = errors.New("wrong code in horizontal mode")
|
||||||
// ErrNoEOLFound is returned when the EndOfLine parameter is true in filter but no EOL (end-of-line) met.
|
// errNoEOLFound is returned when the EndOfLine parameter is true in filter but no EOL (end-of-line) met.
|
||||||
ErrNoEOLFound = errors.New("no EOL found while the EndOfLine parameter is true")
|
errNoEOLFound = errors.New("no EOL found while the EndOfLine parameter is true")
|
||||||
// ErrInvalidEOL is returned when the EOL code is corrupt.
|
// errInvalidEOL is returned when the EOL code is corrupt.
|
||||||
ErrInvalidEOL = errors.New("invalid EOL")
|
errInvalidEOL = errors.New("invalid EOL")
|
||||||
// ErrInvalid2DCode is returned when the invalid 2 dimensional code is met. 2 dimensional code
|
// errInvalid2DCode is returned when the invalid 2 dimensional code is met. 2 dimensional code
|
||||||
// according to the CCITT reccommendations is one of the following: H, P, V0, V1L, V2L, V3L, V1R, V2R, V3R.
|
// according to the CCITT reccommendations is one of the following: H, P, V0, V1L, V2L, V3L, V1R, V2R, V3R.
|
||||||
ErrInvalid2DCode = errors.New("invalid 2D code")
|
errInvalid2DCode = errors.New("invalid 2D code")
|
||||||
|
)
|
||||||
|
|
||||||
// trees represent the finite state machine for parsing bit sequences and fetching pixel run lengths
|
// trees represent the finite state machine for parsing bit sequences and fetching pixel run lengths
|
||||||
|
var (
|
||||||
whiteTree = &decodingTreeNode{
|
whiteTree = &decodingTreeNode{
|
||||||
Val: 255,
|
Val: 255,
|
||||||
}
|
}
|
||||||
@ -112,7 +114,7 @@ func (e *Encoder) decodeG31D(encoded []byte) ([][]byte, error) {
|
|||||||
gotEOL, bitPos = tryFetchEOL(encoded, bitPos)
|
gotEOL, bitPos = tryFetchEOL(encoded, bitPos)
|
||||||
if !gotEOL {
|
if !gotEOL {
|
||||||
if e.EndOfLine {
|
if e.EndOfLine {
|
||||||
return nil, ErrNoEOLFound
|
return nil, errNoEOLFound
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 5 EOLs left to fill RTC
|
// 5 EOLs left to fill RTC
|
||||||
@ -124,7 +126,7 @@ func (e *Encoder) decodeG31D(encoded []byte) ([][]byte, error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, ErrInvalidEOL
|
return nil, errInvalidEOL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +178,7 @@ byteLoop:
|
|||||||
|
|
||||||
if !gotEOL {
|
if !gotEOL {
|
||||||
if e.EndOfLine {
|
if e.EndOfLine {
|
||||||
return nil, ErrNoEOLFound
|
return nil, errNoEOLFound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +214,7 @@ byteLoop:
|
|||||||
break byteLoop
|
break byteLoop
|
||||||
} else {
|
} else {
|
||||||
if e.EndOfLine {
|
if e.EndOfLine {
|
||||||
return nil, ErrNoEOLFound
|
return nil, errNoEOLFound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,31 +240,24 @@ byteLoop:
|
|||||||
}
|
}
|
||||||
case v0:
|
case v0:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 0)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 0)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v1r:
|
case v1r:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 1)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 1)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v2r:
|
case v2r:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 2)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 2)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v3r:
|
case v3r:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 3)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 3)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v1l:
|
case v1l:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -1)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -1)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v2l:
|
case v2l:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -2)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -2)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v3l:
|
case v3l:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -3)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -3)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,7 +322,7 @@ func (e *Encoder) decodeG4(encoded []byte) ([][]byte, error) {
|
|||||||
for a0 < e.Columns {
|
for a0 < e.Columns {
|
||||||
twoDimCode, bitPos, ok = fetchNext2DCode(encoded, bitPos)
|
twoDimCode, bitPos, ok = fetchNext2DCode(encoded, bitPos)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrInvalid2DCode
|
return nil, errInvalid2DCode
|
||||||
}
|
}
|
||||||
|
|
||||||
switch twoDimCode {
|
switch twoDimCode {
|
||||||
@ -342,31 +337,24 @@ func (e *Encoder) decodeG4(encoded []byte) ([][]byte, error) {
|
|||||||
}
|
}
|
||||||
case v0:
|
case v0:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 0)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 0)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v1r:
|
case v1r:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 1)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 1)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v2r:
|
case v2r:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 2)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 2)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v3r:
|
case v3r:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 3)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, 3)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v1l:
|
case v1l:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -1)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -1)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v2l:
|
case v2l:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -2)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -2)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
case v3l:
|
case v3l:
|
||||||
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -3)
|
pixelsRow, a0 = decodeVerticalMode(pixels, pixelsRow, isWhite, a0, -3)
|
||||||
|
|
||||||
isWhite = !isWhite
|
isWhite = !isWhite
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,7 +444,7 @@ func decodeHorizontalMode(encoded, pixelsRow []byte, bitPos int, isWhite bool, a
|
|||||||
|
|
||||||
// decodeNextRunLen decodes tries to decode the next part of data using the Group3 1-dimensional code.
|
// decodeNextRunLen decodes tries to decode the next part of data using the Group3 1-dimensional code.
|
||||||
// Returns moved bit position and the pixels row filled with the decoded pixels. The returned bit position
|
// Returns moved bit position and the pixels row filled with the decoded pixels. The returned bit position
|
||||||
// is not moved if the error occurs. Returns `ErrWrongCodeInHorizontalMode` if none of the 1-dimensional codes found.
|
// is not moved if the error occurs. Returns `errWrongCodeInHorizontalMode` if none of the 1-dimensional codes found.
|
||||||
func decodeNextRunLen(encoded, pixelsRow []byte, bitPos int, isWhite bool) ([]byte, int, error) {
|
func decodeNextRunLen(encoded, pixelsRow []byte, bitPos int, isWhite bool) ([]byte, int, error) {
|
||||||
startingBitPos := bitPos
|
startingBitPos := bitPos
|
||||||
|
|
||||||
@ -472,7 +460,7 @@ func decodeNextRunLen(encoded, pixelsRow []byte, bitPos int, isWhite bool) ([]by
|
|||||||
}
|
}
|
||||||
|
|
||||||
if runLen == -1 {
|
if runLen == -1 {
|
||||||
return pixelsRow, startingBitPos, ErrWrongCodeInHorizontalMode
|
return pixelsRow, startingBitPos, errWrongCodeInHorizontalMode
|
||||||
}
|
}
|
||||||
|
|
||||||
return pixelsRow, bitPos, nil
|
return pixelsRow, bitPos, nil
|
||||||
@ -480,7 +468,7 @@ func decodeNextRunLen(encoded, pixelsRow []byte, bitPos int, isWhite bool) ([]by
|
|||||||
|
|
||||||
// tryFetchRTC2D tries to fetch the RTC code (0000000000011 X 6) for Group3 mixed (1D/2D) dimensional encoding from
|
// tryFetchRTC2D tries to fetch the RTC code (0000000000011 X 6) for Group3 mixed (1D/2D) dimensional encoding from
|
||||||
// the encoded data. Returns the moved bit position if the code was found. The other way returns the
|
// the encoded data. Returns the moved bit position if the code was found. The other way returns the
|
||||||
// the original bit position. The `ErrRTCCorrupt` is returned if the RTC code is corrupt. The RTC code is considered
|
// the original bit position. The `errRTCCorrupt` is returned if the RTC code is corrupt. The RTC code is considered
|
||||||
// corrupt if there are more than one EOL1 code (0000000000011) is met.
|
// corrupt if there are more than one EOL1 code (0000000000011) is met.
|
||||||
func tryFetchRTC2D(encoded []byte, bitPos int) (bool, int, error) {
|
func tryFetchRTC2D(encoded []byte, bitPos int) (bool, int, error) {
|
||||||
startingBitPos := bitPos
|
startingBitPos := bitPos
|
||||||
@ -492,7 +480,7 @@ func tryFetchRTC2D(encoded []byte, bitPos int) (bool, int, error) {
|
|||||||
|
|
||||||
if !gotEOL {
|
if !gotEOL {
|
||||||
if i > 1 {
|
if i > 1 {
|
||||||
return false, startingBitPos, ErrRTCCorrupt
|
return false, startingBitPos, errRTCCorrupt
|
||||||
} else {
|
} else {
|
||||||
bitPos = startingBitPos
|
bitPos = startingBitPos
|
||||||
|
|
||||||
@ -506,7 +494,7 @@ func tryFetchRTC2D(encoded []byte, bitPos int) (bool, int, error) {
|
|||||||
|
|
||||||
// tryFetchEOFB tries to fetch the EOFB code (000000000001 X 2) for Group4 encoding from
|
// tryFetchEOFB tries to fetch the EOFB code (000000000001 X 2) for Group4 encoding from
|
||||||
// the encoded data. Returns the moved bit position if the code was found. The other way returns the
|
// the encoded data. Returns the moved bit position if the code was found. The other way returns the
|
||||||
// the original bit position. The `ErrEOFBCorrupt` is returned if the EOFB code is corrupt. The EOFB code is considered
|
// the original bit position. The `errEOFBCorrupt` is returned if the EOFB code is corrupt. The EOFB code is considered
|
||||||
// corrupt if there is a single EOL code (000000000001).
|
// corrupt if there is a single EOL code (000000000001).
|
||||||
func tryFetchEOFB(encoded []byte, bitPos int) (bool, int, error) {
|
func tryFetchEOFB(encoded []byte, bitPos int) (bool, int, error) {
|
||||||
startingBitPos := bitPos
|
startingBitPos := bitPos
|
||||||
@ -520,7 +508,7 @@ func tryFetchEOFB(encoded []byte, bitPos int) (bool, int, error) {
|
|||||||
if gotEOL {
|
if gotEOL {
|
||||||
return true, bitPos, nil
|
return true, bitPos, nil
|
||||||
} else {
|
} else {
|
||||||
return false, startingBitPos, ErrEOFBCorrupt
|
return false, startingBitPos, errEOFBCorrupt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
|||||||
* file 'LICENSE.md', which is part of this source code package.
|
* file 'LICENSE.md', which is part of this source code package.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ccittfaxdecode
|
package ccittfax
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
@ -32,6 +32,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want testResult
|
Want testResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculated test data based on the reference documentation.
|
||||||
tests := []testData{
|
tests := []testData{
|
||||||
{
|
{
|
||||||
Encoded: []byte{1, 28, 2},
|
Encoded: []byte{1, 28, 2},
|
||||||
@ -179,7 +180,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -190,7 +191,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -201,7 +202,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -212,7 +213,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -223,7 +224,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -234,7 +235,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -245,7 +246,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -256,7 +257,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -267,7 +268,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -278,7 +279,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -289,7 +290,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -300,7 +301,7 @@ func TestDecodeNextRunLen(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -415,7 +416,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
A0: 0,
|
A0: 0,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -428,7 +429,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
A0: 120,
|
A0: 120,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -441,7 +442,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
A0: 10,
|
A0: 10,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -454,7 +455,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
A0: 13,
|
A0: 13,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -467,7 +468,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
A0: 23,
|
A0: 23,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -480,7 +481,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
A0: 34,
|
A0: 34,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -493,7 +494,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
A0: 134,
|
A0: 134,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -506,7 +507,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
A0: 35,
|
A0: 35,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -519,7 +520,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
A0: 876,
|
A0: 876,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -532,7 +533,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
A0: 738,
|
A0: 738,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -545,7 +546,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
A0: 283,
|
A0: 283,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -558,7 +559,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
PixelsRow: nil,
|
PixelsRow: nil,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
A0: 29,
|
A0: 29,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -573,7 +574,7 @@ func TestDecodeHorizontalMode(t *testing.T) {
|
|||||||
white, white, white},
|
white, white, white},
|
||||||
BitPos: 16,
|
BitPos: 16,
|
||||||
A0: 0,
|
A0: 0,
|
||||||
Err: ErrWrongCodeInHorizontalMode,
|
Err: errWrongCodeInHorizontalMode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -2005,7 +2006,7 @@ func TestTryFetchEOFB(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
OK: false,
|
OK: false,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrEOFBCorrupt,
|
Err: errEOFBCorrupt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2099,7 +2100,7 @@ func TestTryFetchRTC2D(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
OK: false,
|
OK: false,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrRTCCorrupt,
|
Err: errRTCCorrupt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2108,7 +2109,7 @@ func TestTryFetchRTC2D(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
OK: false,
|
OK: false,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
Err: ErrRTCCorrupt,
|
Err: errRTCCorrupt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2117,7 +2118,7 @@ func TestTryFetchRTC2D(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
OK: false,
|
OK: false,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrRTCCorrupt,
|
Err: errRTCCorrupt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2126,7 +2127,7 @@ func TestTryFetchRTC2D(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
OK: false,
|
OK: false,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
Err: ErrRTCCorrupt,
|
Err: errRTCCorrupt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2135,7 +2136,7 @@ func TestTryFetchRTC2D(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
OK: false,
|
OK: false,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrRTCCorrupt,
|
Err: errRTCCorrupt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2144,7 +2145,7 @@ func TestTryFetchRTC2D(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
OK: false,
|
OK: false,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
Err: ErrRTCCorrupt,
|
Err: errRTCCorrupt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2153,7 +2154,7 @@ func TestTryFetchRTC2D(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
OK: false,
|
OK: false,
|
||||||
BitPos: 0,
|
BitPos: 0,
|
||||||
Err: ErrRTCCorrupt,
|
Err: errRTCCorrupt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2162,7 +2163,7 @@ func TestTryFetchRTC2D(t *testing.T) {
|
|||||||
Want: testResult{
|
Want: testResult{
|
||||||
OK: false,
|
OK: false,
|
||||||
BitPos: 2,
|
BitPos: 2,
|
||||||
Err: ErrRTCCorrupt,
|
Err: errRTCCorrupt,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
@ -3,7 +3,7 @@
|
|||||||
* file 'LICENSE.md', which is part of this source code package.
|
* file 'LICENSE.md', which is part of this source code package.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ccittfaxdecode
|
package ccittfax
|
||||||
|
|
||||||
// decodingTreeNode is a node of a tree which represents the finite state machine for
|
// decodingTreeNode is a node of a tree which represents the finite state machine for
|
||||||
// searching the decoded pixel run lengths having the bit sequence. `Val` is a single bit
|
// searching the decoded pixel run lengths having the bit sequence. `Val` is a single bit
|
@ -3,7 +3,7 @@
|
|||||||
* file 'LICENSE.md', which is part of this source code package.
|
* file 'LICENSE.md', which is part of this source code package.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ccittfaxdecode
|
package ccittfax
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
@ -3,7 +3,7 @@
|
|||||||
* file 'LICENSE.md', which is part of this source code package.
|
* file 'LICENSE.md', which is part of this source code package.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Package ccittfaxdecode defines and implements the Group3 and Group4
|
// Package ccittfax defines and implements the Group3 and Group4
|
||||||
// facsimile (fax) encoding and decoding according to the CCITT recommendations
|
// facsimile (fax) encoding and decoding according to the CCITT recommendations
|
||||||
// T.4 and T.6.
|
// T.4 and T.6.
|
||||||
package ccittfaxdecode
|
package ccittfax
|
@ -3,7 +3,7 @@
|
|||||||
* file 'LICENSE.md', which is part of this source code package.
|
* file 'LICENSE.md', which is part of this source code package.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ccittfaxdecode
|
package ccittfax
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
@ -68,7 +68,6 @@ func (e *Encoder) encodeG31D(pixels [][]byte) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
encodedRow, bitPos := encodeRow1D(pixels[i], prevBitPos, eol)
|
encodedRow, bitPos := encodeRow1D(pixels[i], prevBitPos, eol)
|
||||||
|
|
||||||
encoded = e.appendEncodedRow(encoded, encodedRow, prevBitPos)
|
encoded = e.appendEncodedRow(encoded, encodedRow, prevBitPos)
|
||||||
|
|
||||||
if e.EncodedByteAlign {
|
if e.EncodedByteAlign {
|
||||||
@ -82,7 +81,6 @@ func (e *Encoder) encodeG31D(pixels [][]byte) []byte {
|
|||||||
if e.EndOfBlock {
|
if e.EndOfBlock {
|
||||||
// put RTC
|
// put RTC
|
||||||
encodedRTC, _ := encodeRTC(prevBitPos)
|
encodedRTC, _ := encodeRTC(prevBitPos)
|
||||||
|
|
||||||
encoded = e.appendEncodedRow(encoded, encodedRTC, prevBitPos)
|
encoded = e.appendEncodedRow(encoded, encodedRTC, prevBitPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +208,6 @@ func (e *Encoder) encodeG4(pixelsToEncode [][]byte) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
encoded = e.appendEncodedRow(encoded, encodedRow, prevBitPos)
|
encoded = e.appendEncodedRow(encoded, encodedRow, prevBitPos)
|
||||||
|
|
||||||
if e.EncodedByteAlign {
|
if e.EncodedByteAlign {
|
||||||
// align to byte border
|
// align to byte border
|
||||||
bitPos = 0
|
bitPos = 0
|
||||||
@ -222,7 +219,6 @@ func (e *Encoder) encodeG4(pixelsToEncode [][]byte) []byte {
|
|||||||
if e.EndOfBlock {
|
if e.EndOfBlock {
|
||||||
// put EOFB
|
// put EOFB
|
||||||
encodedEOFB, _ := encodeEOFB(prevBitPos)
|
encodedEOFB, _ := encodeEOFB(prevBitPos)
|
||||||
|
|
||||||
encoded = e.appendEncodedRow(encoded, encodedEOFB, prevBitPos)
|
encoded = e.appendEncodedRow(encoded, encodedEOFB, prevBitPos)
|
||||||
}
|
}
|
||||||
|
|
@ -3,11 +3,10 @@
|
|||||||
* file 'LICENSE.md', which is part of this source code package.
|
* file 'LICENSE.md', which is part of this source code package.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ccittfaxdecode
|
package ccittfax
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
_ "image/png"
|
||||||
"image/png"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
@ -20,8 +19,6 @@ func TestEncode(t *testing.T) {
|
|||||||
WantFilePath string
|
WantFilePath string
|
||||||
}
|
}
|
||||||
|
|
||||||
image.RegisterFormat("png", "png", png.Decode, png.DecodeConfig)
|
|
||||||
|
|
||||||
pixels, err := getPixels(testDataPath + "p3_0.png")
|
pixels, err := getPixels(testDataPath + "p3_0.png")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error getting pixels from image: %v\n", err)
|
t.Fatalf("Error getting pixels from image: %v\n", err)
|
BIN
pdf/internal/ccittfax/testdata/p3_0.png
vendored
Normal file
BIN
pdf/internal/ccittfax/testdata/p3_0.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 220 KiB |
Loading…
x
Reference in New Issue
Block a user