123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795 |
- // Copyright 2019 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- //go:generate go run gen.go
- // Package ccitt implements a CCITT (fax) image decoder.
- package ccitt
- import (
- "encoding/binary"
- "errors"
- "image"
- "io"
- "math/bits"
- )
- var (
- errIncompleteCode = errors.New("ccitt: incomplete code")
- errInvalidBounds = errors.New("ccitt: invalid bounds")
- errInvalidCode = errors.New("ccitt: invalid code")
- errInvalidMode = errors.New("ccitt: invalid mode")
- errInvalidOffset = errors.New("ccitt: invalid offset")
- errMissingEOL = errors.New("ccitt: missing End-of-Line")
- errRunLengthOverflowsWidth = errors.New("ccitt: run length overflows width")
- errRunLengthTooLong = errors.New("ccitt: run length too long")
- errUnsupportedMode = errors.New("ccitt: unsupported mode")
- errUnsupportedSubFormat = errors.New("ccitt: unsupported sub-format")
- errUnsupportedWidth = errors.New("ccitt: unsupported width")
- )
- // Order specifies the bit ordering in a CCITT data stream.
- type Order uint32
- const (
- // LSB means Least Significant Bits first.
- LSB Order = iota
- // MSB means Most Significant Bits first.
- MSB
- )
- // SubFormat represents that the CCITT format consists of a number of
- // sub-formats. Decoding or encoding a CCITT data stream requires knowing the
- // sub-format context. It is not represented in the data stream per se.
- type SubFormat uint32
- const (
- Group3 SubFormat = iota
- Group4
- )
- // AutoDetectHeight is passed as the height argument to NewReader to indicate
- // that the image height (the number of rows) is not known in advance.
- const AutoDetectHeight = -1
- // Options are optional parameters.
- type Options struct {
- // Align means that some variable-bit-width codes are byte-aligned.
- Align bool
- // Invert means that black is the 1 bit or 0xFF byte, and white is 0.
- Invert bool
- }
- // maxWidth is the maximum (inclusive) supported width. This is a limitation of
- // this implementation, to guard against integer overflow, and not anything
- // inherent to the CCITT format.
- const maxWidth = 1 << 20
- func invertBytes(b []byte) {
- for i, c := range b {
- b[i] = ^c
- }
- }
- func reverseBitsWithinBytes(b []byte) {
- for i, c := range b {
- b[i] = bits.Reverse8(c)
- }
- }
- // highBits writes to dst (1 bit per pixel, most significant bit first) the
- // high (0x80) bits from src (1 byte per pixel). It returns the number of bytes
- // written and read such that dst[:d] is the packed form of src[:s].
- //
- // For example, if src starts with the 8 bytes [0x7D, 0x7E, 0x7F, 0x80, 0x81,
- // 0x82, 0x00, 0xFF] then 0x1D will be written to dst[0].
- //
- // If src has (8 * len(dst)) or more bytes then only len(dst) bytes are
- // written, (8 * len(dst)) bytes are read, and invert is ignored.
- //
- // Otherwise, if len(src) is not a multiple of 8 then the final byte written to
- // dst is padded with 1 bits (if invert is true) or 0 bits. If inverted, the 1s
- // are typically temporary, e.g. they will be flipped back to 0s by an
- // invertBytes call in the highBits caller, reader.Read.
- func highBits(dst []byte, src []byte, invert bool) (d int, s int) {
- // Pack as many complete groups of 8 src bytes as we can.
- n := len(src) / 8
- if n > len(dst) {
- n = len(dst)
- }
- dstN := dst[:n]
- for i := range dstN {
- src8 := src[i*8 : i*8+8]
- dstN[i] = ((src8[0] & 0x80) >> 0) |
- ((src8[1] & 0x80) >> 1) |
- ((src8[2] & 0x80) >> 2) |
- ((src8[3] & 0x80) >> 3) |
- ((src8[4] & 0x80) >> 4) |
- ((src8[5] & 0x80) >> 5) |
- ((src8[6] & 0x80) >> 6) |
- ((src8[7] & 0x80) >> 7)
- }
- d, s = n, 8*n
- dst, src = dst[d:], src[s:]
- // Pack up to 7 remaining src bytes, if there's room in dst.
- if (len(dst) > 0) && (len(src) > 0) {
- dstByte := byte(0)
- if invert {
- dstByte = 0xFF >> uint(len(src))
- }
- for n, srcByte := range src {
- dstByte |= (srcByte & 0x80) >> uint(n)
- }
- dst[0] = dstByte
- d, s = d+1, s+len(src)
- }
- return d, s
- }
- type bitReader struct {
- r io.Reader
- // readErr is the error returned from the most recent r.Read call. As the
- // io.Reader documentation says, when r.Read returns (n, err), "always
- // process the n > 0 bytes returned before considering the error err".
- readErr error
- // order is whether to process r's bytes LSB first or MSB first.
- order Order
- // The high nBits bits of the bits field hold upcoming bits in MSB order.
- bits uint64
- nBits uint32
- // bytes[br:bw] holds bytes read from r but not yet loaded into bits.
- br uint32
- bw uint32
- bytes [1024]uint8
- }
- func (b *bitReader) alignToByteBoundary() {
- n := b.nBits & 7
- b.bits <<= n
- b.nBits -= n
- }
- // nextBitMaxNBits is the maximum possible value of bitReader.nBits after a
- // bitReader.nextBit call, provided that bitReader.nBits was not more than this
- // value before that call.
- //
- // Note that the decode function can unread bits, which can temporarily set the
- // bitReader.nBits value above nextBitMaxNBits.
- const nextBitMaxNBits = 31
- func (b *bitReader) nextBit() (uint64, error) {
- for {
- if b.nBits > 0 {
- bit := b.bits >> 63
- b.bits <<= 1
- b.nBits--
- return bit, nil
- }
- if available := b.bw - b.br; available >= 4 {
- // Read 32 bits, even though b.bits is a uint64, since the decode
- // function may need to unread up to maxCodeLength bits, putting
- // them back in the remaining (64 - 32) bits. TestMaxCodeLength
- // checks that the generated maxCodeLength constant fits.
- //
- // If changing the Uint32 call, also change nextBitMaxNBits.
- b.bits = uint64(binary.BigEndian.Uint32(b.bytes[b.br:])) << 32
- b.br += 4
- b.nBits = 32
- continue
- } else if available > 0 {
- b.bits = uint64(b.bytes[b.br]) << (7 * 8)
- b.br++
- b.nBits = 8
- continue
- }
- if b.readErr != nil {
- return 0, b.readErr
- }
- n, err := b.r.Read(b.bytes[:])
- b.br = 0
- b.bw = uint32(n)
- b.readErr = err
- if b.order != MSB {
- reverseBitsWithinBytes(b.bytes[:b.bw])
- }
- }
- }
- func decode(b *bitReader, decodeTable [][2]int16) (uint32, error) {
- nBitsRead, bitsRead, state := uint32(0), uint64(0), int32(1)
- for {
- bit, err := b.nextBit()
- if err != nil {
- if err == io.EOF {
- err = errIncompleteCode
- }
- return 0, err
- }
- bitsRead |= bit << (63 - nBitsRead)
- nBitsRead++
- // The "&1" is redundant, but can eliminate a bounds check.
- state = int32(decodeTable[state][bit&1])
- if state < 0 {
- return uint32(^state), nil
- } else if state == 0 {
- // Unread the bits we've read, then return errInvalidCode.
- b.bits = (b.bits >> nBitsRead) | bitsRead
- b.nBits += nBitsRead
- return 0, errInvalidCode
- }
- }
- }
- // decodeEOL decodes the 12-bit EOL code 0000_0000_0001.
- func decodeEOL(b *bitReader) error {
- nBitsRead, bitsRead := uint32(0), uint64(0)
- for {
- bit, err := b.nextBit()
- if err != nil {
- if err == io.EOF {
- err = errMissingEOL
- }
- return err
- }
- bitsRead |= bit << (63 - nBitsRead)
- nBitsRead++
- if nBitsRead < 12 {
- if bit&1 == 0 {
- continue
- }
- } else if bit&1 != 0 {
- return nil
- }
- // Unread the bits we've read, then return errMissingEOL.
- b.bits = (b.bits >> nBitsRead) | bitsRead
- b.nBits += nBitsRead
- return errMissingEOL
- }
- }
- type reader struct {
- br bitReader
- subFormat SubFormat
- // width is the image width in pixels.
- width int
- // rowsRemaining starts at the image height in pixels, when the reader is
- // driven through the io.Reader interface, and decrements to zero as rows
- // are decoded. Alternatively, it may be negative if the image height is
- // not known in advance at the time of the NewReader call.
- //
- // When driven through DecodeIntoGray, this field is unused.
- rowsRemaining int
- // curr and prev hold the current and previous rows. Each element is either
- // 0x00 (black) or 0xFF (white).
- //
- // prev may be nil, when processing the first row.
- curr []byte
- prev []byte
- // ri is the read index. curr[:ri] are those bytes of curr that have been
- // passed along via the Read method.
- //
- // When the reader is driven through DecodeIntoGray, instead of through the
- // io.Reader interface, this field is unused.
- ri int
- // wi is the write index. curr[:wi] are those bytes of curr that have
- // already been decoded via the decodeRow method.
- //
- // What this implementation calls wi is roughly equivalent to what the spec
- // calls the a0 index.
- wi int
- // These fields are copied from the *Options (which may be nil).
- align bool
- invert bool
- // atStartOfRow is whether we have just started the row. Some parts of the
- // spec say to treat this situation as if "wi = -1".
- atStartOfRow bool
- // penColorIsWhite is whether the next run is black or white.
- penColorIsWhite bool
- // seenStartOfImage is whether we've called the startDecode method.
- seenStartOfImage bool
- // truncated is whether the input is missing the final 6 consecutive EOL's
- // (for Group3) or 2 consecutive EOL's (for Group4). Omitting that trailer
- // (but otherwise padding to a byte boundary, with either all 0 bits or all
- // 1 bits) is invalid according to the spec, but happens in practice when
- // exporting from Adobe Acrobat to TIFF + CCITT. This package silently
- // ignores the format error for CCITT input that has been truncated in that
- // fashion, returning the full decoded image.
- //
- // Detecting trailer truncation (just after the final row of pixels)
- // requires knowing which row is the final row, and therefore does not
- // trigger if the image height is not known in advance.
- truncated bool
- // readErr is a sticky error for the Read method.
- readErr error
- }
- func (z *reader) Read(p []byte) (int, error) {
- if z.readErr != nil {
- return 0, z.readErr
- }
- originalP := p
- for len(p) > 0 {
- // Allocate buffers (and decode any start-of-image codes), if
- // processing the first or second row.
- if z.curr == nil {
- if !z.seenStartOfImage {
- if z.readErr = z.startDecode(); z.readErr != nil {
- break
- }
- z.atStartOfRow = true
- }
- z.curr = make([]byte, z.width)
- }
- // Decode the next row, if necessary.
- if z.atStartOfRow {
- if z.rowsRemaining < 0 {
- // We do not know the image height in advance. See if the next
- // code is an EOL. If it is, it is consumed. If it isn't, the
- // bitReader shouldn't advance along the bit stream, and we
- // simply decode another row of pixel data.
- //
- // For the Group4 subFormat, we may need to align to a byte
- // boundary. For the Group3 subFormat, the previous z.decodeRow
- // call (or z.startDecode call) has already consumed one of the
- // 6 consecutive EOL's. The next EOL is actually the second of
- // 6, in the middle, and we shouldn't align at that point.
- if z.align && (z.subFormat == Group4) {
- z.br.alignToByteBoundary()
- }
- if err := z.decodeEOL(); err == errMissingEOL {
- // No-op. It's another row of pixel data.
- } else if err != nil {
- z.readErr = err
- break
- } else {
- if z.readErr = z.finishDecode(true); z.readErr != nil {
- break
- }
- z.readErr = io.EOF
- break
- }
- } else if z.rowsRemaining == 0 {
- // We do know the image height in advance, and we have already
- // decoded exactly that many rows.
- if z.readErr = z.finishDecode(false); z.readErr != nil {
- break
- }
- z.readErr = io.EOF
- break
- } else {
- z.rowsRemaining--
- }
- if z.readErr = z.decodeRow(z.rowsRemaining == 0); z.readErr != nil {
- break
- }
- }
- // Pack from z.curr (1 byte per pixel) to p (1 bit per pixel).
- packD, packS := highBits(p, z.curr[z.ri:], z.invert)
- p = p[packD:]
- z.ri += packS
- // Prepare to decode the next row, if necessary.
- if z.ri == len(z.curr) {
- z.ri, z.curr, z.prev = 0, z.prev, z.curr
- z.atStartOfRow = true
- }
- }
- n := len(originalP) - len(p)
- if z.invert {
- invertBytes(originalP[:n])
- }
- return n, z.readErr
- }
- func (z *reader) penColor() byte {
- if z.penColorIsWhite {
- return 0xFF
- }
- return 0x00
- }
- func (z *reader) startDecode() error {
- switch z.subFormat {
- case Group3:
- if err := z.decodeEOL(); err != nil {
- return err
- }
- case Group4:
- // No-op.
- default:
- return errUnsupportedSubFormat
- }
- z.seenStartOfImage = true
- return nil
- }
- func (z *reader) finishDecode(alreadySeenEOL bool) error {
- numberOfEOLs := 0
- switch z.subFormat {
- case Group3:
- if z.truncated {
- return nil
- }
- // The stream ends with a RTC (Return To Control) of 6 consecutive
- // EOL's, but we should have already just seen an EOL, either in
- // z.startDecode (for a zero-height image) or in z.decodeRow.
- numberOfEOLs = 5
- case Group4:
- autoDetectHeight := z.rowsRemaining < 0
- if autoDetectHeight {
- // Aligning to a byte boundary was already handled by reader.Read.
- } else if z.align {
- z.br.alignToByteBoundary()
- }
- // The stream ends with two EOL's. If the first one is missing, and we
- // had an explicit image height, we just assume that the trailing two
- // EOL's were truncated and return a nil error.
- if err := z.decodeEOL(); err != nil {
- if (err == errMissingEOL) && !autoDetectHeight {
- z.truncated = true
- return nil
- }
- return err
- }
- numberOfEOLs = 1
- default:
- return errUnsupportedSubFormat
- }
- if alreadySeenEOL {
- numberOfEOLs--
- }
- for ; numberOfEOLs > 0; numberOfEOLs-- {
- if err := z.decodeEOL(); err != nil {
- return err
- }
- }
- return nil
- }
- func (z *reader) decodeEOL() error {
- return decodeEOL(&z.br)
- }
- func (z *reader) decodeRow(finalRow bool) error {
- z.wi = 0
- z.atStartOfRow = true
- z.penColorIsWhite = true
- if z.align {
- z.br.alignToByteBoundary()
- }
- switch z.subFormat {
- case Group3:
- for ; z.wi < len(z.curr); z.atStartOfRow = false {
- if err := z.decodeRun(); err != nil {
- return err
- }
- }
- err := z.decodeEOL()
- if finalRow && (err == errMissingEOL) {
- z.truncated = true
- return nil
- }
- return err
- case Group4:
- for ; z.wi < len(z.curr); z.atStartOfRow = false {
- mode, err := decode(&z.br, modeDecodeTable[:])
- if err != nil {
- return err
- }
- rm := readerMode{}
- if mode < uint32(len(readerModes)) {
- rm = readerModes[mode]
- }
- if rm.function == nil {
- return errInvalidMode
- }
- if err := rm.function(z, rm.arg); err != nil {
- return err
- }
- }
- return nil
- }
- return errUnsupportedSubFormat
- }
- func (z *reader) decodeRun() error {
- table := blackDecodeTable[:]
- if z.penColorIsWhite {
- table = whiteDecodeTable[:]
- }
- total := 0
- for {
- n, err := decode(&z.br, table)
- if err != nil {
- return err
- }
- if n > maxWidth {
- panic("unreachable")
- }
- total += int(n)
- if total > maxWidth {
- return errRunLengthTooLong
- }
- // Anything 0x3F or below is a terminal code.
- if n <= 0x3F {
- break
- }
- }
- if total > (len(z.curr) - z.wi) {
- return errRunLengthOverflowsWidth
- }
- dst := z.curr[z.wi : z.wi+total]
- penColor := z.penColor()
- for i := range dst {
- dst[i] = penColor
- }
- z.wi += total
- z.penColorIsWhite = !z.penColorIsWhite
- return nil
- }
- // The various modes' semantics are based on determining a row of pixels'
- // "changing elements": those pixels whose color differs from the one on its
- // immediate left.
- //
- // The row above the first row is implicitly all white. Similarly, the column
- // to the left of the first column is implicitly all white.
- //
- // For example, here's Figure 1 in "ITU-T Recommendation T.6", where the
- // current and previous rows contain black (B) and white (w) pixels. The a?
- // indexes point into curr, the b? indexes point into prev.
- //
- // b1 b2
- // v v
- // prev: BBBBBwwwwwBBBwwwww
- // curr: BBBwwwwwBBBBBBwwww
- // ^ ^ ^
- // a0 a1 a2
- //
- // a0 is the "reference element" or current decoder position, roughly
- // equivalent to what this implementation calls reader.wi.
- //
- // a1 is the next changing element to the right of a0, on the "coding line"
- // (the current row).
- //
- // a2 is the next changing element to the right of a1, again on curr.
- //
- // b1 is the first changing element on the "reference line" (the previous row)
- // to the right of a0 and of opposite color to a0.
- //
- // b2 is the next changing element to the right of b1, again on prev.
- //
- // The various modes calculate a1 (and a2, for modeH):
- // - modePass calculates that a1 is at or to the right of b2.
- // - modeH calculates a1 and a2 without considering b1 or b2.
- // - modeV* calculates a1 to be b1 plus an adjustment (between -3 and +3).
- const (
- findB1 = false
- findB2 = true
- )
- // findB finds either the b1 or b2 value.
- func (z *reader) findB(whichB bool) int {
- // The initial row is a special case. The previous row is implicitly all
- // white, so that there are no changing pixel elements. We return b1 or b2
- // to be at the end of the row.
- if len(z.prev) != len(z.curr) {
- return len(z.curr)
- }
- i := z.wi
- if z.atStartOfRow {
- // a0 is implicitly at -1, on a white pixel. b1 is the first black
- // pixel in the previous row. b2 is the first white pixel after that.
- for ; (i < len(z.prev)) && (z.prev[i] == 0xFF); i++ {
- }
- if whichB == findB2 {
- for ; (i < len(z.prev)) && (z.prev[i] == 0x00); i++ {
- }
- }
- return i
- }
- // As per figure 1 above, assume that the current pen color is white.
- // First, walk past every contiguous black pixel in prev, starting at a0.
- oppositeColor := ^z.penColor()
- for ; (i < len(z.prev)) && (z.prev[i] == oppositeColor); i++ {
- }
- // Then walk past every contiguous white pixel.
- penColor := ^oppositeColor
- for ; (i < len(z.prev)) && (z.prev[i] == penColor); i++ {
- }
- // We're now at a black pixel (or at the end of the row). That's b1.
- if whichB == findB2 {
- // If we're looking for b2, walk past every contiguous black pixel
- // again.
- oppositeColor := ^penColor
- for ; (i < len(z.prev)) && (z.prev[i] == oppositeColor); i++ {
- }
- }
- return i
- }
- type readerMode struct {
- function func(z *reader, arg int) error
- arg int
- }
- var readerModes = [...]readerMode{
- modePass: {function: readerModePass},
- modeH: {function: readerModeH},
- modeV0: {function: readerModeV, arg: +0},
- modeVR1: {function: readerModeV, arg: +1},
- modeVR2: {function: readerModeV, arg: +2},
- modeVR3: {function: readerModeV, arg: +3},
- modeVL1: {function: readerModeV, arg: -1},
- modeVL2: {function: readerModeV, arg: -2},
- modeVL3: {function: readerModeV, arg: -3},
- modeExt: {function: readerModeExt},
- }
- func readerModePass(z *reader, arg int) error {
- b2 := z.findB(findB2)
- if (b2 < z.wi) || (len(z.curr) < b2) {
- return errInvalidOffset
- }
- dst := z.curr[z.wi:b2]
- penColor := z.penColor()
- for i := range dst {
- dst[i] = penColor
- }
- z.wi = b2
- return nil
- }
- func readerModeH(z *reader, arg int) error {
- // The first iteration finds a1. The second finds a2.
- for i := 0; i < 2; i++ {
- if err := z.decodeRun(); err != nil {
- return err
- }
- }
- return nil
- }
- func readerModeV(z *reader, arg int) error {
- a1 := z.findB(findB1) + arg
- if (a1 < z.wi) || (len(z.curr) < a1) {
- return errInvalidOffset
- }
- dst := z.curr[z.wi:a1]
- penColor := z.penColor()
- for i := range dst {
- dst[i] = penColor
- }
- z.wi = a1
- z.penColorIsWhite = !z.penColorIsWhite
- return nil
- }
- func readerModeExt(z *reader, arg int) error {
- return errUnsupportedMode
- }
- // DecodeIntoGray decodes the CCITT-formatted data in r into dst.
- //
- // It returns an error if dst's width and height don't match the implied width
- // and height of CCITT-formatted data.
- func DecodeIntoGray(dst *image.Gray, r io.Reader, order Order, sf SubFormat, opts *Options) error {
- bounds := dst.Bounds()
- if (bounds.Dx() < 0) || (bounds.Dy() < 0) {
- return errInvalidBounds
- }
- if bounds.Dx() > maxWidth {
- return errUnsupportedWidth
- }
- z := reader{
- br: bitReader{r: r, order: order},
- subFormat: sf,
- align: (opts != nil) && opts.Align,
- invert: (opts != nil) && opts.Invert,
- width: bounds.Dx(),
- }
- if err := z.startDecode(); err != nil {
- return err
- }
- width := bounds.Dx()
- for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
- p := (y - bounds.Min.Y) * dst.Stride
- z.curr = dst.Pix[p : p+width]
- if err := z.decodeRow(y+1 == bounds.Max.Y); err != nil {
- return err
- }
- z.curr, z.prev = nil, z.curr
- }
- if err := z.finishDecode(false); err != nil {
- return err
- }
- if z.invert {
- for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
- p := (y - bounds.Min.Y) * dst.Stride
- invertBytes(dst.Pix[p : p+width])
- }
- }
- return nil
- }
- // NewReader returns an io.Reader that decodes the CCITT-formatted data in r.
- // The resultant byte stream is one bit per pixel (MSB first), with 1 meaning
- // white and 0 meaning black. Each row in the result is byte-aligned.
- //
- // A negative height, such as passing AutoDetectHeight, means that the image
- // height is not known in advance. A negative width is invalid.
- func NewReader(r io.Reader, order Order, sf SubFormat, width int, height int, opts *Options) io.Reader {
- readErr := error(nil)
- if width < 0 {
- readErr = errInvalidBounds
- } else if width > maxWidth {
- readErr = errUnsupportedWidth
- }
- return &reader{
- br: bitReader{r: r, order: order},
- subFormat: sf,
- align: (opts != nil) && opts.Align,
- invert: (opts != nil) && opts.Invert,
- width: width,
- rowsRemaining: height,
- readErr: readErr,
- }
- }
|