| // Copyright 2025 The Wuffs Authors. | |
| // | |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
| // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
| // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your | |
| // option. This file may not be copied, modified, or distributed | |
| // except according to those terms. | |
| // | |
| // SPDX-License-Identifier: Apache-2.0 OR MIT | |
| // ---------------- | |
| //go:generate go run gen.go | |
| // Package lowleveljpeg provides a JPEG encoder that takes in-DCT-space | |
| // coefficients instead of in-XY-space pixels. | |
| // | |
| // It can be useful for experimenting with or visualizing in-DCT-space | |
| // transformations, such as quantization, extrapolation and progressive-like | |
| // reduction. Or for learning about how the JPEG file format works. But most | |
| // programmers should use the Go standard library's image/jpeg package instead. | |
| package lowleveljpeg | |
| // See "the spec", also known as "the JPEG specification" or "ITU/CCITT T.81": | |
| // https://www.w3.org/Graphics/JPEG/itu-t81.pdf | |
| import ( | |
| "errors" | |
| "io" | |
| ) | |
| var ( | |
| ErrBadAddNForColorType = errors.New("lowleveljpeg: bad AddN for ColorType") | |
| ErrBadArgument = errors.New("lowleveljpeg: bad argument") | |
| ErrInvalidBlockI16 = errors.New("lowleveljpeg: invalid BlockI16") | |
| ErrNilReceiver = errors.New("lowleveljpeg: nil receiver") | |
| ErrPreviouslyReturnedError = errors.New("lowleveljpeg: previously returned error") | |
| ErrTooManyAddNCalls = errors.New("lowleveljpeg: too many AddN calls") | |
| ) | |
| // ColorType is a JPEG image's color type. | |
| type ColorType byte | |
| const ( | |
| // ColorTypeInvalid, the zero value, is invalid. | |
| ColorTypeInvalid = ColorType(0) | |
| // ColorTypeGray means a single channel (Gray). | |
| ColorTypeGray = ColorType(1) | |
| // ColorTypeYCbCr444 means three channels (Luma, Chroma-blue, Chroma-red), | |
| // using 4:4:4 Chroma subsampling. | |
| ColorTypeYCbCr444 = ColorType(3) | |
| // ColorTypeYCbCr420 means three channels (Luma, Chroma-blue, Chroma-red), | |
| // using 4:2:0 Chroma subsampling. | |
| // | |
| // This is the most popular color type for colorful (not gray) JPEG images. | |
| ColorTypeYCbCr420 = ColorType(6) | |
| // As an implementation detail, the constants' numerical value is the | |
| // number of blocks in a JPEG MCU (Mininum Coded Unit). | |
| ) | |
| // MCUDimensions returns the width and height of a Mininum Coded Unit. | |
| func (c ColorType) MCUDimensions() (width int, height int) { | |
| switch c { | |
| case ColorTypeGray, ColorTypeYCbCr444: | |
| return 8, 8 | |
| case ColorTypeYCbCr420: | |
| return 16, 16 | |
| } | |
| return 0, 0 | |
| } | |
| func (c ColorType) isValid() bool { | |
| switch c { | |
| case ColorTypeGray, ColorTypeYCbCr444, ColorTypeYCbCr420: | |
| return true | |
| } | |
| return false | |
| } | |
| // EncoderOptions are optional arguments to Encoder.Reset. The zero value is | |
| // valid and means to use the default configuration. | |
| type EncoderOptions struct { | |
| // QuantizationFactors are the BlockI16 quantization factors. A nil pointer | |
| // is equivalent to using DefaultQuality. | |
| QuantizationFactors *Array2QuantizationFactors | |
| // There may be other fields added in the future. | |
| } | |
| // Encoder writes JPEG-formatted bytes to an io.Writer. | |
| // | |
| // Call Reset and then AddN multiple times (N depends on the ColorType). Each | |
| // AddN call encodes a Minimum Coded Unit (an 8×8 or 16×16 group of pixels, | |
| // depending on the ColorType). Add MCUs in left-to-right top-to-bottom order. | |
| // The final AddN call also writes the JPEG footer. | |
| // | |
| // AddN takes ArrayNBlockI16 arguments, which are post-FDCT (when encoding) or | |
| // pre-IDCT (when decoding) coefficients. | |
| // | |
| // To get ArrayNBlockI16 values from pixels, use ExtractYCbCrFrom on an | |
| // image.Image (to get an array of BlockU8 values) and then FowardDCTFrom (to | |
| // get an array of BlockI16 values). See Example_basic for an example. | |
| // | |
| // An Encoder makes no allocations, other than the Encoder struct itself and | |
| // any allocations that the passed io.Writer makes. | |
| // | |
| // An Encoder can be re-used, by calling Reset. | |
| type Encoder struct { | |
| hasReturnedError bool | |
| colorType ColorType | |
| prevDC [3]int16 | |
| numAddsRemaining uint32 | |
| bitsV uint32 | |
| bitsN uint32 | |
| quants Array2QuantizationFactors | |
| // The fields above occupy 148 bytes. Each Reset or AddN call, in the worst | |
| // case, emits not much more than 2688 bytes. We round sizeof(Encoder) up | |
| // to be 3072, which is 1.5 times a power of 2. | |
| buf [3072 - 148]byte | |
| } | |
| // Reset makes an Encoder ready to use (ready to make AddN calls), for encoding | |
| // a JPEG with the given colorType, width and height. | |
| // | |
| // colorType should be ColorTypeGray, ColorTypeYCbCr444 or ColorTypeYCbCr420. | |
| // | |
| // width and height should both be positive but no larger than 0xFFFF, since a | |
| // JPEG image cannot represent anything larger. | |
| // | |
| // options may be nil, which means to use the default configuration. | |
| func (e *Encoder) Reset(w io.Writer, colorType ColorType, width int, height int, options *EncoderOptions) error { | |
| if e == nil { | |
| return ErrNilReceiver | |
| } else if (width <= 0) || (0xFFFF < width) || (height <= 0) || (0xFFFF < height) || !colorType.isValid() { | |
| e.hasReturnedError = true | |
| return ErrBadArgument | |
| } | |
| if (options == nil) || (options.QuantizationFactors == nil) { | |
| e.quants.SetToStandardValues(DefaultQuality) | |
| } else { | |
| q := options.QuantizationFactors | |
| if !q[0].IsValid() || !q[1].IsValid() { | |
| e.hasReturnedError = true | |
| return ErrBadArgument | |
| } | |
| e.quants = *q | |
| } | |
| e.hasReturnedError = false | |
| e.colorType = colorType | |
| e.prevDC[0] = 0 | |
| e.prevDC[1] = 0 | |
| e.prevDC[2] = 0 | |
| if colorType != ColorTypeYCbCr420 { | |
| e.numAddsRemaining = uint32((width+7)/8) * uint32((height+7)/8) | |
| } else { | |
| e.numAddsRemaining = uint32((width+15)/16) * uint32((height+15)/16) | |
| } | |
| e.bitsV = 0 | |
| e.bitsN = 0 | |
| e.buf[0] = 0xFF // SOI marker. | |
| e.buf[1] = 0xD8 | |
| bufIndex := 2 | |
| bufIndex = e.encodeDQT(bufIndex) | |
| bufIndex = e.encodeSOF0(bufIndex, width, height) | |
| bufIndex = e.encodeDHT(bufIndex) | |
| bufIndex = e.encodeSOSHeader(bufIndex) | |
| if _, err := w.Write(e.buf[:bufIndex]); err != nil { | |
| e.hasReturnedError = true | |
| return err | |
| } | |
| return nil | |
| } | |
| // Add1 adds an 8×8 group of pixels to a ColorTypeGray image. | |
| func (e *Encoder) Add1(w io.Writer, b *Array1BlockI16) error { | |
| if e == nil { | |
| return ErrNilReceiver | |
| } else if e.hasReturnedError { | |
| return ErrPreviouslyReturnedError | |
| } else if e.colorType != ColorTypeGray { | |
| e.hasReturnedError = true | |
| return ErrBadAddNForColorType | |
| } else if b == nil { | |
| e.hasReturnedError = true | |
| return ErrBadArgument | |
| } | |
| return e.addN(w, b[:]) | |
| } | |
| // Add3 adds an 8×8 group of pixels to a ColorTypeYCbCr444 image. | |
| func (e *Encoder) Add3(w io.Writer, b *Array3BlockI16) error { | |
| if e == nil { | |
| return ErrNilReceiver | |
| } else if e.hasReturnedError { | |
| return ErrPreviouslyReturnedError | |
| } else if e.colorType != ColorTypeYCbCr444 { | |
| e.hasReturnedError = true | |
| return ErrBadAddNForColorType | |
| } else if b == nil { | |
| e.hasReturnedError = true | |
| return ErrBadArgument | |
| } | |
| return e.addN(w, b[:]) | |
| } | |
| // Add6 adds a 16×16 group of pixels to a ColorTypeYCbCr420 image. | |
| func (e *Encoder) Add6(w io.Writer, b *Array6BlockI16) error { | |
| if e == nil { | |
| return ErrNilReceiver | |
| } else if e.hasReturnedError { | |
| return ErrPreviouslyReturnedError | |
| } else if e.colorType != ColorTypeYCbCr420 { | |
| e.hasReturnedError = true | |
| return ErrBadAddNForColorType | |
| } else if b == nil { | |
| e.hasReturnedError = true | |
| return ErrBadArgument | |
| } | |
| return e.addN(w, b[:]) | |
| } | |
| func (e *Encoder) addN(w io.Writer, blocks []BlockI16) error { | |
| for i := range blocks { | |
| if !blocks[i].IsValid() { | |
| e.hasReturnedError = true | |
| return ErrInvalidBlockI16 | |
| } | |
| } | |
| if e.numAddsRemaining <= 0 { | |
| e.hasReturnedError = true | |
| return ErrTooManyAddNCalls | |
| } | |
| e.numAddsRemaining-- | |
| // In terms of worst case number of bytes emitted, the up-to-six | |
| // encodeBlock calls can emit 2688 bytes (6 * 448 bytes). | |
| whichComponents := "" | |
| switch ColorType(len(blocks)) { | |
| case ColorTypeGray: | |
| whichComponents = "\x00" | |
| case ColorTypeYCbCr444: | |
| whichComponents = "\x00\x01\x02" | |
| case ColorTypeYCbCr420: | |
| whichComponents = "\x00\x00\x00\x00\x01\x02" | |
| } | |
| bufIndex := 0 | |
| for i := range blocks { | |
| bufIndex = e.encodeBlock(bufIndex, whichComponents[i], &blocks[i]) | |
| } | |
| if e.numAddsRemaining == 0 { | |
| bufIndex = e.emitBits(bufIndex, 0x7F, 7) | |
| e.buf[bufIndex+0] = 0xFF // EOI marker. | |
| e.buf[bufIndex+1] = 0xD9 | |
| bufIndex += 2 | |
| } | |
| if _, err := w.Write(e.buf[:bufIndex]); err != nil { | |
| e.hasReturnedError = true | |
| return err | |
| } | |
| return nil | |
| } | |
| func (e *Encoder) encodeDQT(bufIndex int) int { | |
| e.buf[bufIndex+0] = 0xFF | |
| e.buf[bufIndex+1] = 0xDB | |
| e.buf[bufIndex+2] = 0x00 | |
| if e.colorType == ColorTypeGray { | |
| e.buf[bufIndex+3] = 0x43 | |
| } else { | |
| e.buf[bufIndex+3] = 0x84 | |
| } | |
| bufIndex += 4 | |
| for i := range e.quants { | |
| e.buf[bufIndex+0] = uint8(i) | |
| bufIndex += 1 | |
| q := &e.quants[i] | |
| for z := 0; z < 64; z++ { | |
| e.buf[bufIndex+z] = q[zigzag[z]] | |
| } | |
| bufIndex += 64 | |
| if e.colorType == ColorTypeGray { | |
| break | |
| } | |
| } | |
| return bufIndex | |
| } | |
| func (e *Encoder) encodeSOF0(bufIndex int, width int, height int) int { | |
| numComponents := byte(1) | |
| if e.colorType != ColorTypeGray { | |
| numComponents = byte(3) | |
| } | |
| e.buf[bufIndex+0] = 0xFF | |
| e.buf[bufIndex+1] = 0xC0 | |
| e.buf[bufIndex+2] = 0x00 | |
| e.buf[bufIndex+3] = 0x08 + (3 * numComponents) // Payload length. | |
| e.buf[bufIndex+4] = 0x08 // 8-bit depth. | |
| e.buf[bufIndex+5] = byte(height >> 8) | |
| e.buf[bufIndex+6] = byte(height >> 0) | |
| e.buf[bufIndex+7] = byte(width >> 8) | |
| e.buf[bufIndex+8] = byte(width >> 0) | |
| e.buf[bufIndex+9] = numComponents | |
| if e.colorType == ColorTypeGray { | |
| e.buf[bufIndex+10] = 0x01 // Component ID 1. | |
| e.buf[bufIndex+11] = 0x11 // Subsampling. | |
| e.buf[bufIndex+12] = 0x00 // Quant selector 0. | |
| return bufIndex + 13 | |
| } | |
| lumaComponentSubsampling := byte(0x11) | |
| if e.colorType == ColorTypeYCbCr420 { | |
| lumaComponentSubsampling = byte(0x22) | |
| } | |
| // 4:4:4 subsampling. Luma and Chroma select Quant tables 0 and 1. | |
| e.buf[bufIndex+10] = 0x01 // Component ID 1. | |
| e.buf[bufIndex+11] = lumaComponentSubsampling | |
| e.buf[bufIndex+12] = 0x00 // Quant selector 0. | |
| e.buf[bufIndex+13] = 0x02 // Component ID 2. | |
| e.buf[bufIndex+14] = 0x11 // Subsampling. | |
| e.buf[bufIndex+15] = 0x01 // Quant selector 1. | |
| e.buf[bufIndex+16] = 0x03 // Component ID 3. | |
| e.buf[bufIndex+17] = 0x11 // Subsampling. | |
| e.buf[bufIndex+18] = 0x01 // Quant selector 1. | |
| return bufIndex + 19 | |
| } | |
| func (e *Encoder) encodeDHT(bufIndex int) int { | |
| s := "" | |
| if e.colorType == ColorTypeGray { | |
| s = hardCodedDHTSegments[:len(hardCodedDHTSegments)/2] | |
| } else { | |
| s = hardCodedDHTSegments | |
| } | |
| n := copy(e.buf[bufIndex:], s) | |
| return bufIndex + n | |
| } | |
| func (e *Encoder) encodeSOSHeader(bufIndex int) int { | |
| s := "" | |
| if e.colorType == ColorTypeGray { | |
| s = "\xFF\xDA" + // SOS marker. | |
| "\x00\x08" + // Payload length. | |
| "\x01" + // Number of components. | |
| "\x01\x00" + // Component ID 1, Huffman selectors 0 (DC) and 0 (AC). | |
| "\x00\x3F\x00" // Ss=0, Se=63, Ah=0, Al=0. | |
| } else { | |
| s = "\xFF\xDA" + // SOS marker. | |
| "\x00\x0C" + // Payload length. | |
| "\x03" + // Number of components. | |
| "\x01\x00" + // Component ID 1, Huffman selectors 0 (DC) and 0 (AC). | |
| "\x02\x11" + // Component ID 2, Huffman selectors 1 (DC) and 1 (AC). | |
| "\x03\x11" + // Component ID 3, Huffman selectors 1 (DC) and 1 (AC). | |
| "\x00\x3F\x00" // Ss=0, Se=63, Ah=0, Al=0. | |
| } | |
| n := copy(e.buf[bufIndex:], s) | |
| return bufIndex + n | |
| } | |
| // In terms of worst case number of bytes emitted, encodeBlock can emit 448 | |
| // bytes (64 * 7 bytes), since there are 64 elements and each element could | |
| // emit 7 bytes. | |
| func (e *Encoder) encodeBlock(bufIndex int, whichComponent byte, b *BlockI16) int { | |
| whichHuffmanBase := 0 | |
| if whichComponent > 0 { | |
| whichHuffmanBase = 2 | |
| } | |
| dc := div(b[0], int16(e.quants[whichHuffmanBase>>1][0])) | |
| deltaDC := dc - e.prevDC[whichComponent] | |
| e.prevDC[whichComponent] = dc | |
| bufIndex = e.emitHuffmanRun(bufIndex, whichHuffmanBase+0, 0, int32(deltaDC)) | |
| zeroesRunLength := uint32(0) | |
| for z := 1; z < 64; z++ { | |
| zz := zigzag[z] | |
| ac := div(b[zz], int16(e.quants[whichHuffmanBase>>1][zz])) | |
| if ac == 0 { | |
| zeroesRunLength++ | |
| continue | |
| } | |
| for ; zeroesRunLength >= 16; zeroesRunLength -= 16 { | |
| bufIndex = e.emitHuffman(bufIndex, whichHuffmanBase+1, 0xF0) | |
| } | |
| bufIndex = e.emitHuffmanRun(bufIndex, whichHuffmanBase+1, zeroesRunLength, int32(ac)) | |
| zeroesRunLength = 0 | |
| } | |
| if zeroesRunLength > 0 { | |
| bufIndex = e.emitHuffman(bufIndex, whichHuffmanBase+1, 0x00) | |
| } | |
| return bufIndex | |
| } | |
| // emitHuffmanRun emits (zeroesRunLength, value) as two bitstrings. The first | |
| // bitstring combines zeroesRunLength (also called RRRR) and the "category" | |
| // part of value (also called SSSS). The second bitstring holds the "adjusted | |
| // diff" part of value. | |
| // | |
| // The breakdown from value (a signed integer) into category and adjusted diff | |
| // is a little complicated. Category is an unsigned integer less than 12 and | |
| // smaller category mean values closer to zero. Adjusted diff is an unsigned | |
| // integer less than (1 << category). | |
| // | |
| // Value Category Adjusted Diff | |
| // 0 0 0 | |
| // -1, +1 1 0, 1 | |
| // -3, -2, +2, +3 2 0, 1, 2, 3 | |
| // -7, -6, -5, -4, +4, +5, +6, +7 3 0, 1, 2, 3, 4, 5, 6, 7 | |
| // -15, -14, ..., -8, +8, ..., +14, +15 4 0, 1, ..., 7, 8, ..., 14, 15 | |
| // etc etc | |
| // -2047, ..., -1024, +1024, ..., +2047 11 0, ..., 1023, 1024, ..., 2047 | |
| // | |
| // Compare with the JPEG spec, Tables F.1 and F.2, for the distinction between | |
| // "diff" and "adjusted diff". | |
| // | |
| // For example, if value is -5 then category is 3 and adjDiff is 2 (0b010). | |
| // | |
| // For example, if value is -13 then category is 4 and adjDiff is 2 (0b0010). | |
| // | |
| // For example, if value is +15 then category is 4 and adjDiff is 15 (0b1111). | |
| // | |
| // At the bit level, the combined number ((zeroesRunLength << 4) | category), | |
| // also known as ((RRRR << 4) | SSSS) in the spec, is Huffman-encoded. After | |
| // that comes the adjDiff's bits, a bitstring whose length equals category. | |
| // | |
| // For DC values, zeroesRunLength is always zero and what's passed to this | |
| // method is the delta from the previous DC value. | |
| // | |
| // For AC values, zeroesRunLength ranges from 0 up to 15 (inclusive). Category | |
| // 11 is unused. Category 0 is also unused for AC values (as zeroes are run- | |
| // length encoded), other than ((RRRR << 4) | SSSS) values of 0x00 and 0xF0 | |
| // being special cases: | |
| // | |
| // - 0x00 means that all remaining AC coefficients are zero. | |
| // - 0xF0 means that the next 16 AC coefficients are zero. | |
| // | |
| // Pre-condition: value is in the range [-2047, +2047]. BlockI16.IsValid checks | |
| // for [-1024, +1023] for DC and [-1023, +1023] for AC values. For DC values, | |
| // what's then passed to this method is the delta from the previous DC value. | |
| // | |
| // In terms of worst case number of bytes emitted, emitHuffmanRun can emit 54 | |
| // bits, which rounds up to 7 bytes. To calculate that: category can range up | |
| // to 11, so that emitHuffman + emitBits can emit 16 + 11 = 27 bits. Doubling | |
| // that, because of 0xFF 0x00 byte stuffing, produces a worst case of 54. | |
| func (e *Encoder) emitHuffmanRun(bufIndex int, whichHuffman int, zeroesRunLength uint32, value int32) int { | |
| absValue, adjDiffBeforeMasking := uint32(value), uint32(value) | |
| if value < 0 { | |
| absValue, adjDiffBeforeMasking = uint32(-value), uint32(value-1) | |
| } | |
| category := uint32(0) | |
| if absValue < 0x100 { | |
| category = uint32(bitCount[absValue]) | |
| } else { | |
| category = uint32(bitCount[absValue>>8]) + 8 | |
| } | |
| combined := (zeroesRunLength << 4) | category | |
| bufIndex = e.emitHuffman(bufIndex, whichHuffman, uint8(combined)) | |
| // At this point, we could say | |
| // | |
| // adjDiff := adjDiffBeforeMasking & ((1 << category) - 1) | |
| // | |
| // but it's equivalent to pass adjDiffBeforeMasking (instead of adjDiff) to | |
| // emitBits, which does "v &= (1 << n) - 1" early in its function body. | |
| bufIndex = e.emitBits(bufIndex, adjDiffBeforeMasking, category) | |
| return bufIndex | |
| } | |
| // emitHuffman emits the Huffman-coded bits for value. | |
| func (e *Encoder) emitHuffman(bufIndex int, whichHuffman int, value uint8) int { | |
| x := huffmanBitWriters[whichHuffman][value] | |
| return e.emitBits(bufIndex, x&0xFFFF, x>>16) | |
| } | |
| // emitBits emits the low n bits of v. | |
| func (e *Encoder) emitBits(bufIndex int, v uint32, n uint32) int { | |
| if n <= 0 { | |
| return bufIndex | |
| } | |
| v &= (1 << n) - 1 | |
| n += e.bitsN | |
| v <<= 32 - n | |
| v |= e.bitsV | |
| for ; n >= 8; n -= 8 { | |
| vByte := byte(v >> 24) | |
| e.buf[bufIndex] = vByte | |
| bufIndex++ | |
| if vByte == 0xFF { | |
| e.buf[bufIndex] = 0x00 | |
| bufIndex++ | |
| } | |
| v <<= 8 | |
| } | |
| e.bitsV = v | |
| e.bitsN = n | |
| return bufIndex | |
| } | |
| // div returns a/b rounded to the nearest integer, instead of rounded to zero. | |
| // | |
| // Pre-condition: b > 0. | |
| func div(a, b int16) int16 { | |
| if a >= 0 { | |
| return (a + (b >> 1)) / b | |
| } | |
| return -((-a + (b >> 1)) / b) | |
| } | |
| // zigzag represents JPEG's zig-zag order for visiting coefficients. If b is a | |
| // BlockI16 then b[zigzag[1]], b[zigzag[2]], b[zigzag[3]], ..., b[zigzag[63]] | |
| // are its AC coefficients ordered from lowest to highest frequency, roughly | |
| // speaking. b[0], which is also b[zigzag[0]], is the DC coefficient. | |
| // | |
| // https://en.wikipedia.org/wiki/File:JPEG_ZigZag.svg | |
| var zigzag = [64]uint8{ | |
| 0o00, 0o01, 0o10, 0o20, 0o11, 0o02, 0o03, 0o12, // 0, 1, 8, 16, 9, 2, 3, 10, | |
| 0o21, 0o30, 0o40, 0o31, 0o22, 0o13, 0o04, 0o05, // 17, 24, 32, 25, 18, 11, 4, 5, | |
| 0o14, 0o23, 0o32, 0o41, 0o50, 0o60, 0o51, 0o42, // 12, 19, 26, 33, 40, 48, 41, 34, | |
| 0o33, 0o24, 0o15, 0o06, 0o07, 0o16, 0o25, 0o34, // 27, 20, 13, 6, 7, 14, 21, 28, | |
| 0o43, 0o52, 0o61, 0o70, 0o71, 0o62, 0o53, 0o44, // 35, 42, 49, 56, 57, 50, 43, 36, | |
| 0o35, 0o26, 0o17, 0o27, 0o36, 0o45, 0o54, 0o63, // 29, 22, 15, 23, 30, 37, 44, 51, | |
| 0o72, 0o73, 0o64, 0o55, 0o46, 0o37, 0o47, 0o56, // 58, 59, 52, 45, 38, 31, 39, 46, | |
| 0o65, 0o74, 0o75, 0o66, 0o57, 0o67, 0o76, 0o77, // 53, 60, 61, 54, 47, 55, 62, 63, | |
| } | |
| // bitCount[i] is the smallest n such that i < (1 << n). | |
| var bitCount = [256]byte{ | |
| 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, | |
| 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, | |
| 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, | |
| 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, | |
| 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | |
| 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | |
| 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | |
| 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | |
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | |
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | |
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | |
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | |
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | |
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | |
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | |
| 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | |
| } |