// Copyright 2012 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.package jpegimport ()// makeImg allocates and initializes the destination image.func ( *decoder) (, int) {if .nComp == 1 { := image.NewGray(image.Rect(0, 0, 8*, 8*)) .img1 = .SubImage(image.Rect(0, 0, .width, .height)).(*image.Gray)return } := .comp[0].h := .comp[0].v := / .comp[1].h := / .comp[1].vvarimage.YCbCrSubsampleRatioswitch <<4 | {case0x11: = image.YCbCrSubsampleRatio444case0x12: = image.YCbCrSubsampleRatio440case0x21: = image.YCbCrSubsampleRatio422case0x22: = image.YCbCrSubsampleRatio420case0x41: = image.YCbCrSubsampleRatio411case0x42: = image.YCbCrSubsampleRatio410default:panic("unreachable") } := image.NewYCbCr(image.Rect(0, 0, 8**, 8**), ) .img3 = .SubImage(image.Rect(0, 0, .width, .height)).(*image.YCbCr)if .nComp == 4 { , := .comp[3].h, .comp[3].v .blackPix = make([]byte, 8***8**) .blackStride = 8 * * }}// Specified in section B.2.3.func ( *decoder) ( int) error {if .nComp == 0 {returnFormatError("missing SOF marker") }if < 6 || 4+2*.nComp < || %2 != 0 {returnFormatError("SOS has wrong length") }if := .readFull(.tmp[:]); != nil {return } := int(.tmp[0])if != 4+2* {returnFormatError("SOS length inconsistent with number of components") }var [maxComponents]struct {uint8uint8// DC table selector.uint8// AC table selector. } := 0for := 0; < ; ++ { := .tmp[1+2*] // Component selector. := -1for , := range .comp[:.nComp] {if == .c { = } }if < 0 {returnFormatError("unknown component selector") } []. = uint8()// Section B.2.3 states that "the value of Cs_j shall be different from // the values of Cs_1 through Cs_(j-1)". Since we have previously // verified that a frame's component identifiers (C_i values in section // B.2.2) are unique, it suffices to check that the implicit indexes // into d.comp are unique.for := 0; < ; ++ {if []. == []. {returnFormatError("repeated component selector") } } += .comp[].h * .comp[].v// The baseline t <= 1 restriction is specified in table B.3. []. = .tmp[2+2*] >> 4if := [].; > maxTh || (.baseline && > 1) {returnFormatError("bad Td value") } []. = .tmp[2+2*] & 0x0fif := [].; > maxTh || (.baseline && > 1) {returnFormatError("bad Ta value") } }// Section B.2.3 states that if there is more than one component then the // total H*V values in a scan must be <= 10.if .nComp > 1 && > 10 {returnFormatError("total sampling factors too large") }// zigStart and zigEnd are the spectral selection bounds. // ah and al are the successive approximation high and low values. // The spec calls these values Ss, Se, Ah and Al. // // For progressive JPEGs, these are the two more-or-less independent // aspects of progression. Spectral selection progression is when not // all of a block's 64 DCT coefficients are transmitted in one pass. // For example, three passes could transmit coefficient 0 (the DC // component), coefficients 1-5, and coefficients 6-63, in zig-zag // order. Successive approximation is when not all of the bits of a // band of coefficients are transmitted in one pass. For example, // three passes could transmit the 6 most significant bits, followed // by the second-least significant bit, followed by the least // significant bit. // // For sequential JPEGs, these parameters are hard-coded to 0/63/0/0, as // per table B.3. , , , := int32(0), int32(blockSize-1), uint32(0), uint32(0)if .progressive { = int32(.tmp[1+2*]) = int32(.tmp[2+2*]) = uint32(.tmp[3+2*] >> 4) = uint32(.tmp[3+2*] & 0x0f)if ( == 0 && != 0) || > || blockSize <= {returnFormatError("bad spectral selection bounds") }if != 0 && != 1 {returnFormatError("progressive AC coefficients for more than one component") }if != 0 && != +1 {returnFormatError("bad successive approximation values") } }// mxx and myy are the number of MCUs (Minimum Coded Units) in the image. , := .comp[0].h, .comp[0].v// The h and v values from the Y components. := (.width + 8* - 1) / (8 * ) := (.height + 8* - 1) / (8 * )if .img1 == nil && .img3 == nil { .makeImg(, ) }if .progressive {for := 0; < ; ++ { := [].if .progCoeffs[] == nil { .progCoeffs[] = make([]block, **.comp[].h*.comp[].v) } } } .bits = bits{} , := 0, uint8(rst0Marker)var (// b is the decoded coefficients, in natural (not zig-zag) order.block [maxComponents]int32// bx and by are the location of the current block, in units of 8x8 // blocks: the third block in the first row has (bx, by) = (2, 0). , intint )for := 0; < ; ++ {for := 0; < ; ++ {for := 0; < ; ++ { := []. := .comp[].h := .comp[].vfor := 0; < *; ++ {// The blocks are traversed one MCU at a time. For 4:2:0 chroma // subsampling, there are four Y 8x8 blocks in every 16x16 MCU. // // For a sequential 32x16 pixel image, the Y blocks visiting order is: // 0 1 4 5 // 2 3 6 7 // // For progressive images, the interleaved scans (those with nComp > 1) // are traversed as above, but non-interleaved scans are traversed left // to right, top to bottom: // 0 1 2 3 // 4 5 6 7 // Only DC scans (zigStart == 0) can be interleaved. AC scans must have // only one component. // // To further complicate matters, for non-interleaved scans, there is no // data for any blocks that are inside the image at the MCU level but // outside the image at the pixel level. For example, a 24x16 pixel 4:2:0 // progressive image consists of two 16x16 MCUs. The interleaved scans // will process 8 Y blocks: // 0 1 4 5 // 2 3 6 7 // The non-interleaved scans will process only 6 Y blocks: // 0 1 2 // 3 4 5if != 1 { = * + % = * + / } else { := * = % = / ++if *8 >= .width || *8 >= .height {continue } }// Load the previous partially decoded coefficients, if applicable.if .progressive { = .progCoeffs[][**+] } else { = block{} }if != 0 {if := .refine(&, &.huff[acTable][[].], , , 1<<); != nil {return } } else { := if == 0 { ++// Decode the DC coefficient, as specified in section F.2.2.1. , := .decodeHuffman(&.huff[dcTable][[].])if != nil {return }if > 16 {returnUnsupportedError("excessive DC component") } , := .receiveExtend()if != nil {return } [] += [0] = [] << }if <= && .eobRun > 0 { .eobRun-- } else {// Decode the AC coefficients, as specified in section F.2.2.2. := &.huff[acTable][[].]for ; <= ; ++ { , := .decodeHuffman()if != nil {return } := >> 4 := & 0x0fif != 0 { += int32()if > {break } , := .receiveExtend()if != nil {return } [unzig[]] = << } else {if != 0x0f { .eobRun = uint16(1 << )if != 0 { , := .decodeBits(int32())if != nil {return } .eobRun |= uint16() } .eobRun--break } += 0x0f } } } }if .progressive {// Save the coefficients. .progCoeffs[][**+] = // At this point, we could call reconstructBlock to dequantize and perform the // inverse DCT, to save early stages of a progressive image to the *image.YCbCr // buffers (the whole point of progressive encoding), but in Go, the jpeg.Decode // function does not return until the entire image is decoded, so we "continue" // here to avoid wasted computation. Instead, reconstructBlock is called on each // accumulated block by the reconstructProgressiveImage method after all of the // SOS markers are processed.continue }if := .reconstructBlock(&, , , int()); != nil {return } } // for j } // for i ++if .ri > 0 && %.ri == 0 && < * {// For well-formed input, the RST[0-7] restart marker follows // immediately. For corrupt input, call findRST to try to // resynchronize.if := .readFull(.tmp[:2]); != nil {return } elseif .tmp[0] != 0xff || .tmp[1] != {if := .findRST(); != nil {return } } ++if == rst7Marker+1 { = rst0Marker }// Reset the Huffman decoder. .bits = bits{}// Reset the DC components, as per section F.2.1.3.1. = [maxComponents]int32{}// Reset the progressive decoder state, as per section G.1.2.2. .eobRun = 0 } } // for mx } // for myreturnnil}// refine decodes a successive approximation refinement block, as specified in// section G.1.2.func ( *decoder) ( *block, *huffman, , , int32) error {// Refining a DC component is trivial.if == 0 {if != 0 {panic("unreachable") } , := .decodeBit()if != nil {return }if { [0] |= }returnnil }// Refining AC components is more complicated; see sections G.1.2.2 and G.1.2.3. := if .eobRun == 0 { :for ; <= ; ++ { := int32(0) , := .decodeHuffman()if != nil {return } := >> 4 := & 0x0fswitch {case0:if != 0x0f { .eobRun = uint16(1 << )if != 0 { , := .decodeBits(int32())if != nil {return } .eobRun |= uint16() }break }case1: = , := .decodeBit()if != nil {return }if ! { = - }default:returnFormatError("unexpected Huffman code") } , = .refineNonZeroes(, , , int32(), )if != nil {return }if > {returnFormatError("too many coefficients") }if != 0 { [unzig[]] = } } }if .eobRun > 0 { .eobRun--if , := .refineNonZeroes(, , , -1, ); != nil {return } }returnnil}// refineNonZeroes refines non-zero entries of b in zig-zag order. If nz >= 0,// the first nz zero entries are skipped over.func ( *decoder) ( *block, , , , int32) (int32, error) {for ; <= ; ++ { := unzig[]if [] == 0 {if == 0 {break } --continue } , := .decodeBit()if != nil {return0, }if ! {continue }if [] >= 0 { [] += } else { [] -= } }return , nil}func ( *decoder) () error {// The h0, mxx, by and bx variables have the same meaning as in the // processSOS method. := .comp[0].h := (.width + 8* - 1) / (8 * )for := 0; < .nComp; ++ {if .progCoeffs[] == nil {continue } := 8 * .comp[0].v / .comp[].v := 8 * .comp[0].h / .comp[].h := * .comp[].hfor := 0; * < .height; ++ {for := 0; * < .width; ++ {if := .reconstructBlock(&.progCoeffs[][*+], , , ); != nil {return } } } }returnnil}// reconstructBlock dequantizes, performs the inverse DCT and stores the block// to the image.func ( *decoder) ( *block, , , int) error { := &.quant[.comp[].tq]for := 0; < blockSize; ++ { [unzig[]] *= [] }idct() , := []byte(nil), 0if .nComp == 1 { , = .img1.Pix[8*(*.img1.Stride+):], .img1.Stride } else {switch {case0: , = .img3.Y[8*(*.img3.YStride+):], .img3.YStridecase1: , = .img3.Cb[8*(*.img3.CStride+):], .img3.CStridecase2: , = .img3.Cr[8*(*.img3.CStride+):], .img3.CStridecase3: , = .blackPix[8*(*.blackStride+):], .blackStridedefault:returnUnsupportedError("too many components") } }// Level shift by +128, clip to [0, 255], and write to dst.for := 0; < 8; ++ { := * 8 := * for := 0; < 8; ++ { := [+]if < -128 { = 0 } elseif > 127 { = 255 } else { += 128 } [+] = uint8() } }returnnil}// findRST advances past the next RST restart marker that matches expectedRST.// Other than I/O errors, it is also an error if we encounter an {0xFF, M}// two-byte marker sequence where M is not 0x00, 0xFF or the expectedRST.//// This is similar to libjpeg's jdmarker.c's next_marker function.// https://github.com/libjpeg-turbo/libjpeg-turbo/blob/2dfe6c0fe9e18671105e94f7cbf044d4a1d157e6/jdmarker.c#L892-L935//// Precondition: d.tmp[:2] holds the next two bytes of JPEG-encoded input// (input in the d.readFull sense).func ( *decoder) ( uint8) error {for {// i is the index such that, at the bottom of the loop, we read 2-i // bytes into d.tmp[i:2], maintaining the invariant that d.tmp[:2] // holds the next two bytes of JPEG-encoded input. It is either 0 or 1, // so that each iteration advances by 1 or 2 bytes (or returns). := 0if .tmp[0] == 0xff {if .tmp[1] == {returnnil } elseif .tmp[1] == 0xff { = 1 } elseif .tmp[1] != 0x00 {// libjpeg's jdmarker.c's jpeg_resync_to_restart does something // fancy here, treating RST markers within two (modulo 8) of // expectedRST differently from RST markers that are 'more // distant'. Until we see evidence that recovering from such // cases is frequent enough to be worth the complexity, we take // a simpler approach for now. Any marker that's not 0x00, 0xff // or expectedRST is a fatal FormatError.returnFormatError("bad RST marker") } } elseif .tmp[1] == 0xff { .tmp[0] = 0xff = 1 }if := .readFull(.tmp[:2]); != nil {return } }}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.